react-native-webview / react-native-webview

React Native Cross-Platform WebView
https://github.com/react-native-community/discussions-and-proposals/pull/3
MIT License
6.3k stars 2.95k forks source link

Support deviceOrientationAndMotionGrantType #3408

Open artola opened 1 month ago

artola commented 1 month ago

It would be awesome to support deviceOrientationAndMotionGrantType as it is done with mediaCapturePermissionGrantType, otherwise every single time that you open/close the app the permit is required.

See: https://developer.apple.com/documentation/webkit/wkuidelegate/3795606-webview

If you don’t implement this method in your delegate, the system returns WKPermissionDecision.prompt.

This was already reported in the issue "Motion sensor permissions are asked repetitively": https://github.com/react-native-webview/react-native-webview/issues/2942

That issue was closed including a PR with a "solution" that was not merged: https://github.com/react-native-webview/react-native-webview/pull/2944

I can confirm that a patch for RNCWebViewImpl.m with the PR code works and the if we pass "grant", the popup is not shown.

I would like to know what was missing (there is some note of the author about using same prop mediaCapturePermissionGrantType) or something else?

Should be revive that and push forward?

CC @ThorstenBux

Posible implementation:

#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 150000 /* iOS 15 */
/**
 * Media capture permissions (prevent multiple prompts)
 */
- (void)                         webView:(WKWebView *)webView
  requestMediaCapturePermissionForOrigin:(WKSecurityOrigin *)origin
                        initiatedByFrame:(WKFrameInfo *)frame
                                    type:(WKMediaCaptureType)type
                         decisionHandler:(void (^)(WKPermissionDecision decision))decisionHandler {
  [self webView:webView requestPermissionForOrigin:origin initiatedByFrame:frame grantType:_mediaCapturePermissionGrantType decisionHandler:decisionHandler];
}

/**
 * Device Orientation and Motion permissions (prevent multiple prompts)
 */
- (void)                         webView:(WKWebView *)webView
  requestDeviceOrientationAndMotionPermissionForOrigin:(WKSecurityOrigin *)origin
                        initiatedByFrame:(WKFrameInfo *)frame
                         decisionHandler:(void (^)(WKPermissionDecision decision))decisionHandler {
  [self webView:webView requestPermissionForOrigin:origin initiatedByFrame:frame grantType:_deviceOrientationAndMotionPermissionGrantType decisionHandler:decisionHandler];
}

- (void)                         webView:(WKWebView *)webView
  requestPermissionForOrigin:(WKSecurityOrigin *)origin
                        initiatedByFrame:(WKFrameInfo *)frame
                               grantType:(RNCWebViewPermissionGrantType)grantType
                         decisionHandler:(void (^)(WKPermissionDecision decision))decisionHandler {
  if (grantType == RNCWebViewPermissionGrantType_GrantIfSameHost_ElsePrompt || grantType == RNCWebViewPermissionGrantType_GrantIfSameHost_ElseDeny) {
    if ([origin.host isEqualToString:webView.URL.host]) {
      decisionHandler(WKPermissionDecisionGrant);
    } else {
      WKPermissionDecision decision = grantType == RNCWebViewPermissionGrantType_GrantIfSameHost_ElsePrompt ? WKPermissionDecisionPrompt : WKPermissionDecisionDeny;
      decisionHandler(decision);
    }
  } else if (grantType == RNCWebViewPermissionGrantType_Deny) {
    decisionHandler(WKPermissionDecisionDeny);
  } else if (grantType == RNCWebViewPermissionGrantType_Grant) {
    decisionHandler(WKPermissionDecisionGrant);
  } else {
    decisionHandler(WKPermissionDecisionPrompt);
  }
}
#endif