From 0fd43ae64438a00bc0289aa2f7373bbff0c469fa Mon Sep 17 00:00:00 2001 From: Dave Alden Date: Wed, 21 Nov 2018 18:04:04 +0000 Subject: [PATCH] Fixes loadAfterBeforeload on iOS. Resolves #349. (#350) For both UIWebView and WKWebView implementations on iOS. ### Platforms affected iOS ### What does this PR do? Fixes `beforeload` event (introduced by #276) for iOS ### What testing has been done on this change? Tested both allow & deny loading of URL with both iOS implementations in [test container app](https://github.com/dpa99c/cordova-plugin-inappbrowser-wkwebview-test) (ignore its README). - To test with UIWebView use options: `beforeload=yes,usewkwebview=no` - To test with WKWebView use options: `beforeload=yes,usewkwebview=yes` ### Checklist - [x] [Reported an issue](http://cordova.apache.org/contribute/issues.html) in the JIRA database - [x] Commit message follows the format: "CB-3232: (android) Fix bug with resolving file paths", where CB-xxxx is the JIRA ID & "android" is the platform affected. - [x] Added automated test coverage as appropriate for this change. closes #349 --- src/ios/CDVInAppBrowser.h | 1 + src/ios/CDVInAppBrowser.m | 9 ++++++ src/ios/CDVWKInAppBrowser.h | 4 +++ src/ios/CDVWKInAppBrowser.m | 64 +++++++++++++++++++++++++++++++------ 4 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/ios/CDVInAppBrowser.h b/src/ios/CDVInAppBrowser.h index d40e92b1b..2ca6704b6 100644 --- a/src/ios/CDVInAppBrowser.h +++ b/src/ios/CDVInAppBrowser.h @@ -30,6 +30,7 @@ - (void)injectScriptCode:(CDVInvokedUrlCommand*)command; - (void)show:(CDVInvokedUrlCommand*)command; - (void)hide:(CDVInvokedUrlCommand*)command; +- (void)loadAfterBeforeload:(CDVInvokedUrlCommand*)command; @end diff --git a/src/ios/CDVInAppBrowser.m b/src/ios/CDVInAppBrowser.m index ad30b2323..5b7dc0e97 100644 --- a/src/ios/CDVInAppBrowser.m +++ b/src/ios/CDVInAppBrowser.m @@ -121,5 +121,14 @@ - (void)injectStyleFile:(CDVInvokedUrlCommand*)command } } +- (void)loadAfterBeforeload:(CDVInvokedUrlCommand*)command +{ + if(self.usewkwebview){ + [[CDVWKInAppBrowser getInstance] loadAfterBeforeload:command]; + }else{ + [[CDVUIInAppBrowser getInstance] loadAfterBeforeload:command]; + } +} + @end diff --git a/src/ios/CDVWKInAppBrowser.h b/src/ios/CDVWKInAppBrowser.h index 4de7824d8..8b5925e81 100644 --- a/src/ios/CDVWKInAppBrowser.h +++ b/src/ios/CDVWKInAppBrowser.h @@ -27,6 +27,9 @@ @class CDVWKInAppBrowserViewController; @interface CDVWKInAppBrowser : CDVPlugin { + @private + BOOL _useBeforeload; + BOOL _waitForBeforeload; } @property (nonatomic, retain) CDVWKInAppBrowser* instance; @@ -40,6 +43,7 @@ - (void)injectScriptCode:(CDVInvokedUrlCommand*)command; - (void)show:(CDVInvokedUrlCommand*)command; - (void)hide:(CDVInvokedUrlCommand*)command; +- (void)loadAfterBeforeload:(CDVInvokedUrlCommand*)command; @end diff --git a/src/ios/CDVWKInAppBrowser.m b/src/ios/CDVWKInAppBrowser.m index b7c2f3f73..6c1b51a9a 100644 --- a/src/ios/CDVWKInAppBrowser.m +++ b/src/ios/CDVWKInAppBrowser.m @@ -60,6 +60,8 @@ - (void)pluginInitialize instance = self; _previousStatusBarStyle = -1; _callbackIdPattern = nil; + _useBeforeload = NO; + _waitForBeforeload = NO; } - (id)settingForKey:(NSString*)key @@ -263,6 +265,9 @@ - (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options } } + // use of beforeload event + _useBeforeload = browserOptions.beforeload; + _waitForBeforeload = browserOptions.beforeload; [self.inAppBrowserViewController navigateTo:url]; [self show:nil withNoAnimate:browserOptions.hidden]; @@ -370,6 +375,27 @@ - (void)openInSystem:(NSURL*)url [[UIApplication sharedApplication] openURL:url]; } +- (void)loadAfterBeforeload:(CDVInvokedUrlCommand*)command +{ + NSString* urlStr = [command argumentAtIndex:0]; + + if (!_useBeforeload) { + NSLog(@"unexpected loadAfterBeforeload called without feature beforeload=yes"); + } + if (self.inAppBrowserViewController == nil) { + NSLog(@"Tried to invoke loadAfterBeforeload on IAB after it was closed."); + return; + } + if (urlStr == nil) { + NSLog(@"loadAfterBeforeload called with nil argument, ignoring."); + return; + } + + NSURL* url = [NSURL URLWithString:urlStr]; + _waitForBeforeload = NO; + [self.inAppBrowserViewController navigateTo:url]; +} + // This is a helper method for the inject{Script|Style}{Code|File} API calls, which // provides a consistent method for injecting JavaScript code into the document. // @@ -480,16 +506,29 @@ - (BOOL)isValidCallbackId:(NSString *)callbackId * to the InAppBrowser plugin. Care has been taken that other callbacks cannot be triggered, and that no * other code execution is possible. */ -- (BOOL)webView:(WKWebView*)theWebView decidePolicyForNavigationAction:(NSURLRequest*)request -{ - NSURL* url = request.URL; - BOOL isTopLevelNavigation = [request.URL isEqual:[request mainDocumentURL]]; +- (void)webView:(WKWebView *)theWebView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { + + NSURL* url = navigationAction.request.URL; + NSURL* mainDocumentURL = navigationAction.request.mainDocumentURL; + BOOL isTopLevelNavigation = [url isEqual:mainDocumentURL]; + BOOL shouldStart = YES; + + // When beforeload=yes, on first URL change, initiate JS callback. Only after the beforeload event, continue. + if (_waitForBeforeload && isTopLevelNavigation) { + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK + messageAsDictionary:@{@"type":@"beforeload", @"url":[url absoluteString]}]; + [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]]; + + [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId]; + decisionHandler(WKNavigationActionPolicyCancel); + return; + } //if is an app store link, let the system handle it, otherwise it fails to load it if ([[ url scheme] isEqualToString:@"itms-appss"] || [[ url scheme] isEqualToString:@"itms-apps"]) { [theWebView stopLoading]; [self openInSystem:url]; - return NO; + shouldStart = NO; } else if ((self.callbackId != nil) && isTopLevelNavigation) { // Send a loadstart event for each top-level navigation (includes redirects). @@ -499,8 +538,16 @@ - (BOOL)webView:(WKWebView*)theWebView decidePolicyForNavigationAction:(NSURLReq [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId]; } + + if (_useBeforeload && isTopLevelNavigation) { + _waitForBeforeload = YES; + } - return YES; + if(shouldStart){ + decisionHandler(WKNavigationActionPolicyAllow); + }else{ + decisionHandler(WKNavigationActionPolicyCancel); + } } #pragma mark WKScriptMessageHandler delegate @@ -1072,10 +1119,7 @@ - (void)webView:(WKWebView *)theWebView decidePolicyForNavigationAction:(WKNavig self.currentURL = url; } - [self.navigationDelegate webView:theWebView decidePolicyForNavigationAction:navigationAction.request]; - - decisionHandler(WKNavigationActionPolicyAllow); - + [self.navigationDelegate webView:theWebView decidePolicyForNavigationAction:navigationAction decisionHandler:decisionHandler]; } - (void)webView:(WKWebView *)theWebView didFinishNavigation:(WKNavigation *)navigation