From 481ad47ad4546435531a41918ecdc229af7c0a5e Mon Sep 17 00:00:00 2001 From: Amir Hardon Date: Thu, 7 Mar 2019 13:20:43 -0800 Subject: [PATCH 1/3] Allow specifying a navigation delegate (iOS implementation). --- .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++++ .../xcshareddata/WorkspaceSettings.xcsettings | 8 ++++ .../ios/Classes/FLTWKNavigationDelegate.h | 21 ++++++++++ .../ios/Classes/FLTWKNavigationDelegate.m | 39 +++++++++++++++++++ .../ios/Classes/FlutterWebView.m | 7 ++++ 5 files changed, 83 insertions(+) create mode 100644 packages/webview_flutter/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/webview_flutter/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.h create mode 100644 packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m diff --git a/packages/webview_flutter/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/webview_flutter/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000000..18d981003d68 --- /dev/null +++ b/packages/webview_flutter/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/webview_flutter/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/webview_flutter/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000000..949b67898200 --- /dev/null +++ b/packages/webview_flutter/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + BuildSystemType + Original + + diff --git a/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.h b/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.h new file mode 100644 index 000000000000..f96065e278f1 --- /dev/null +++ b/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.h @@ -0,0 +1,21 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FLTWKNavigationDelegate : NSObject + +- (instancetype)initWithChannel:(FlutterMethodChannel*)channel; + +/** + * Whether to delegate navigation decisions over the method channel. + */ +@property(nonatomic, assign) BOOL hasDartNavigationDelegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m b/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m new file mode 100644 index 000000000000..1be973d95caa --- /dev/null +++ b/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m @@ -0,0 +1,39 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "FLTWKNavigationDelegate.h" + +@implementation FLTWKNavigationDelegate { + FlutterMethodChannel* _methodChannel; +} + +- (instancetype)initWithChannel:(FlutterMethodChannel*)channel { + self = [super init]; + if (self) { + _methodChannel = channel; + } + return self; +} + +- (void)webView:(WKWebView*)webView + decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction + decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { + if (!self.hasDartNavigationDelegate) { + decisionHandler(WKNavigationActionPolicyAllow); + return; + } + NSDictionary* arguments = @{ + @"url" : navigationAction.request.URL.absoluteString, + @"isMainFrame" : [NSNumber numberWithBool:navigationAction.targetFrame.isMainFrame] + }; + [_methodChannel invokeMethod:@"navigationRequest" + arguments:arguments + result:^(id _Nullable result) { + NSNumber* typedResult = result; + decisionHandler([typedResult boolValue] ? WKNavigationActionPolicyAllow + : WKNavigationActionPolicyCancel); + }]; +} + +@end diff --git a/packages/webview_flutter/ios/Classes/FlutterWebView.m b/packages/webview_flutter/ios/Classes/FlutterWebView.m index 87d4d25bd9dc..ea3b192f47ff 100644 --- a/packages/webview_flutter/ios/Classes/FlutterWebView.m +++ b/packages/webview_flutter/ios/Classes/FlutterWebView.m @@ -3,6 +3,7 @@ // found in the LICENSE file. #import "FlutterWebView.h" +#import "FLTWKNavigationDelegate.h" #import "JavaScriptChannelHandler.h" @implementation FLTWebViewFactory { @@ -40,6 +41,7 @@ @implementation FLTWebViewController { NSString* _currentUrl; // The set of registered JavaScript channel names. NSMutableSet* _javaScriptChannelNames; + FLTWKNavigationDelegate* _navigationDelegate; } - (instancetype)initWithFrame:(CGRect)frame @@ -64,6 +66,8 @@ - (instancetype)initWithFrame:(CGRect)frame configuration.userContentController = userContentController; _webView = [[WKWebView alloc] initWithFrame:frame configuration:configuration]; + _navigationDelegate = [[FLTWKNavigationDelegate alloc] initWithChannel:_channel]; + _webView.navigationDelegate = _navigationDelegate; __weak __typeof__(self) weakSelf = self; [_channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { [weakSelf onMethodCall:call result:result]; @@ -229,6 +233,9 @@ - (void)applySettings:(NSDictionary*)settings { if ([key isEqualToString:@"jsMode"]) { NSNumber* mode = settings[key]; [self updateJsMode:mode]; + } else if ([key isEqualToString:@"hasNavigationDelegate"]) { + NSNumber* hasDartNavigationDelegate = settings[key]; + _navigationDelegate.hasDartNavigationDelegate = [hasDartNavigationDelegate boolValue]; } else { NSLog(@"webview_flutter: unknown setting key: %@", key); } From 8d4fe3cc214f6fe8fc6a9d62d215fbfce5d661b2 Mon Sep 17 00:00:00 2001 From: Amir Hardon Date: Thu, 7 Mar 2019 15:27:19 -0800 Subject: [PATCH 2/3] review comments followup --- .../ios/Classes/FLTWKNavigationDelegate.h | 2 +- .../ios/Classes/FLTWKNavigationDelegate.m | 24 +++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.h b/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.h index f96065e278f1..1625c4999bd2 100644 --- a/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.h +++ b/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.h @@ -1,4 +1,4 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. +// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. diff --git a/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m b/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m index 1be973d95caa..5c3b55592969 100644 --- a/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m +++ b/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m @@ -1,4 +1,4 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. +// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -25,11 +25,31 @@ - (void)webView:(WKWebView*)webView } NSDictionary* arguments = @{ @"url" : navigationAction.request.URL.absoluteString, - @"isMainFrame" : [NSNumber numberWithBool:navigationAction.targetFrame.isMainFrame] + @"isMainFrame" : @(navigationAction.targetFrame.isMainFrame) }; [_methodChannel invokeMethod:@"navigationRequest" arguments:arguments result:^(id _Nullable result) { + if ([result isKindOfClass:[FlutterError class]]) { + NSLog(@"navigationRequest has unexpectedly completed with an error, " + @"allowing navigation."); + decisionHandler(WKNavigationActionPolicyAllow); + return; + } + if (result == FlutterMethodNotImplemented) { + NSLog(@"navigationRequest was unexepectedly not implemented: %@, " + @"allowing navigation.", + result); + decisionHandler(WKNavigationActionPolicyAllow); + return; + } + if (![result isKindOfClass:[NSNumber class]]) { + NSLog(@"navigationRequest unexpectedly returned a non boolean value: " + @"%@, allowing navigation.", + result); + decisionHandler(WKNavigationActionPolicyAllow); + return; + } NSNumber* typedResult = result; decisionHandler([typedResult boolValue] ? WKNavigationActionPolicyAllow : WKNavigationActionPolicyCancel); From ff417e7e9b4e42e7b727b17d82b23ce273158f7a Mon Sep 17 00:00:00 2001 From: Amir Hardon Date: Fri, 8 Mar 2019 15:31:32 -0800 Subject: [PATCH 3/3] rename isMainFrame to isForMainFrame --- packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m b/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m index 5c3b55592969..3638ddcda117 100644 --- a/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m +++ b/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m @@ -25,7 +25,7 @@ - (void)webView:(WKWebView*)webView } NSDictionary* arguments = @{ @"url" : navigationAction.request.URL.absoluteString, - @"isMainFrame" : @(navigationAction.targetFrame.isMainFrame) + @"isForMainFrame" : @(navigationAction.targetFrame.isMainFrame) }; [_methodChannel invokeMethod:@"navigationRequest" arguments:arguments