From 60fc5862e0a3fcee0318736455d365534a6855f4 Mon Sep 17 00:00:00 2001 From: Aslau Mario-Daniel Date: Mon, 26 Feb 2024 16:41:44 -0600 Subject: [PATCH] fix: #1408 Native Alert Patch for Webview (#8515) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** Currently on iOS when the user is promted with an alert to grant permissions for a website that has a big domain, it will hide the entire Alert message that the website is requesting. ## **Related issues** https://github.com/MetaMask/mobile-planning/issues/1408 Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **e2e Testing** https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/abb68302-f423-4084-9cd5-3fef3a0a5c7c ## **Screenshots/Recordings** Before: This is the website we can use for debugging purposes: https://nfttoks.crypto.comsssssssss.go.f-secure.com.egghunter.in/camera.html After: Screenshot 2024-02-02 at 16 10 13 ### **Before** ### **After** ## **Pre-merge author checklist** - [ ] I’ve followed [MetaMask Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've clearly explained what problem this PR is solving and how it is solved. - [ ] I've linked related issues - [ ] I've included manual testing steps - [ ] I've included screenshots/recordings if applicable - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. - [ ] I’ve properly set the pull request status: - [ ] In case it's not yet "ready for review", I've set it to "draft". - [ ] In case it's "ready for review", I've changed it from "draft" to "non-draft". ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: Cal Leung --- patches/react-native-webview+11.13.0.patch | 74 ++++++++++++++++++---- 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/patches/react-native-webview+11.13.0.patch b/patches/react-native-webview+11.13.0.patch index 6168b3ed384..81140f13f02 100644 --- a/patches/react-native-webview+11.13.0.patch +++ b/patches/react-native-webview+11.13.0.patch @@ -1171,10 +1171,10 @@ index 0000000..b9581ac +} \ No newline at end of file diff --git a/node_modules/react-native-webview/apple/RNCWebView.m b/node_modules/react-native-webview/apple/RNCWebView.m -index 28c078a..6f7d0b7 100644 +index 28c078a..9bb5368 100644 --- a/node_modules/react-native-webview/apple/RNCWebView.m +++ b/node_modules/react-native-webview/apple/RNCWebView.m -@@ -105,6 +105,7 @@ static NSDictionary* customCertificatesForHost; +@@ -105,6 +105,7 @@ @implementation RNCWebView UIStatusBarStyle _savedStatusBarStyle; #endif // !TARGET_OS_OSX BOOL _savedStatusBarHidden; @@ -1182,7 +1182,7 @@ index 28c078a..6f7d0b7 100644 #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */ UIScrollViewContentInsetAdjustmentBehavior _savedContentInsetAdjustmentBehavior; -@@ -139,6 +140,7 @@ static NSDictionary* customCertificatesForHost; +@@ -139,6 +140,7 @@ - (instancetype)initWithFrame:(CGRect)frame _injectedJavaScriptForMainFrameOnly = YES; _injectedJavaScriptBeforeContentLoaded = nil; _injectedJavaScriptBeforeContentLoadedForMainFrameOnly = YES; @@ -1190,7 +1190,7 @@ index 28c078a..6f7d0b7 100644 #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */ _savedContentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; -@@ -417,6 +419,7 @@ static NSDictionary* customCertificatesForHost; +@@ -417,6 +419,7 @@ -(void)keyboardDisplacementFix - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ if ([keyPath isEqual:@"estimatedProgress"] && object == self.webView) { if(_onLoadingProgress){ @@ -1198,7 +1198,7 @@ index 28c078a..6f7d0b7 100644 NSMutableDictionary *event = [self baseEvent]; [event addEntriesFromDictionary:@{@"progress":[NSNumber numberWithDouble:self.webView.estimatedProgress]}]; _onLoadingProgress(event); -@@ -492,6 +495,7 @@ static NSDictionary* customCertificatesForHost; +@@ -492,6 +495,7 @@ - (void)userContentController:(WKUserContentController *)userContentController NSMutableDictionary *event = [self baseEvent]; [event addEntriesFromDictionary: @{@"navigationType": message.body}]; _onLoadingFinish(event); @@ -1206,7 +1206,7 @@ index 28c078a..6f7d0b7 100644 } } else if ([message.name isEqualToString:MessageHandlerName]) { if (_onMessage) { -@@ -851,11 +855,13 @@ static NSDictionary* customCertificatesForHost; +@@ -851,11 +855,13 @@ - (void) webView:(WKWebView *)webView - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler { #if !TARGET_OS_OSX @@ -1225,7 +1225,59 @@ index 28c078a..6f7d0b7 100644 #else NSAlert *alert = [[NSAlert alloc] init]; [alert setMessageText:message]; -@@ -894,44 +900,49 @@ static NSDictionary* customCertificatesForHost; +@@ -868,6 +874,51 @@ - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSStrin + /** + * confirm + */ ++// This patch made to overridde the restrictions that webView is imposing to the native Alert, by restricting its size. ++- (void)webView:(WKWebView *)webView requestMediaCapturePermissionForOrigin:(WKSecurityOrigin *)origin initiatedByFrame:(WKFrameInfo *)frame type:(WKMediaCaptureType)type decisionHandler:(void (^)(WKPermissionDecision decision))decisionHandler API_AVAILABLE(ios(15.0)){ ++ ++ NSString *deviceType; ++ ++ switch (type) { ++ case WKMediaCaptureTypeCamera: ++ deviceType = @"camera"; ++ break; ++ case WKMediaCaptureTypeMicrophone: ++ deviceType = @"microphone"; ++ break; ++ case WKMediaCaptureTypeCameraAndMicrophone: ++ deviceType = @"camera and microphone"; ++ break; ++ default: ++ deviceType = @"unknown device"; ++ } ++ ++ NSString *message = [NSString stringWithFormat:@"The webpage %@ is requesting access to your %@. Do you want to allow this?", origin.host, deviceType]; ++ ++ UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Permission Request" ++ message:message ++ preferredStyle:UIAlertControllerStyleAlert]; ++ ++ UIAlertAction *allowAction = [UIAlertAction actionWithTitle:@"Allow" ++ style:UIAlertActionStyleDefault ++ handler:^(UIAlertAction * _Nonnull action) { ++ decisionHandler(WKPermissionDecisionGrant); ++ } ++ ]; ++ ++ UIAlertAction *denyAction = [UIAlertAction actionWithTitle:@"Deny" ++ style:UIAlertActionStyleCancel ++ handler:^(UIAlertAction * _Nonnull action) { ++ decisionHandler(WKPermissionDecisionDeny); ++ } ++ ]; ++ ++ [alertController addAction:allowAction]; ++ [alertController addAction:denyAction]; ++ ++ [[self topViewController] presentViewController:alertController animated:YES completion:NULL]; ++} ++ + - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{ + #if !TARGET_OS_OSX + UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:message preferredStyle:UIAlertControllerStyleAlert]; +@@ -894,44 +945,49 @@ - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSStr * prompt */ - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *))completionHandler{ @@ -1247,7 +1299,7 @@ index 28c078a..6f7d0b7 100644 -#else - NSAlert *alert = [[NSAlert alloc] init]; - [alert setMessageText:prompt]; - +- - const NSRect RCTSingleTextFieldFrame = NSMakeRect(0.0, 0.0, 275.0, 22.0); - NSTextField *textField = [[NSTextField alloc] initWithFrame:RCTSingleTextFieldFrame]; - textField.cell.scrollable = YES; @@ -1256,7 +1308,7 @@ index 28c078a..6f7d0b7 100644 - } - textField.stringValue = defaultText; - [alert setAccessoryView:textField]; -- + - [alert addButtonWithTitle:NSLocalizedString(@"OK", @"OK button")]; - [alert addButtonWithTitle:NSLocalizedString(@"Cancel", @"Cancel button")]; - [alert beginSheetModalForWindow:[NSApp keyWindow] completionHandler:^(NSModalResponse response) { @@ -1310,7 +1362,7 @@ index 28c078a..6f7d0b7 100644 } #if !TARGET_OS_OSX -@@ -1157,6 +1168,7 @@ static NSDictionary* customCertificatesForHost; +@@ -1157,6 +1213,7 @@ - (void)webView:(WKWebView *)webView } if (_onLoadingFinish) { @@ -1318,7 +1370,7 @@ index 28c078a..6f7d0b7 100644 _onLoadingFinish([self baseEvent]); } } -@@ -1446,3 +1458,4 @@ static NSDictionary* customCertificatesForHost; +@@ -1446,3 +1503,4 @@ - (void)userContentController:(WKUserContentController *)userContentController d } @end