Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit 45cc819

Browse files
authored
Allow specifying a navigation delegate (iOS implementation). (#1323)
This is the iOS implementation of the navigation delegate method channel. The Dart and Android implementations are in #1236 Splitting off the iOS to keep a reasonable change size. This PR will be merged first. flutter/flutter#25329
1 parent 7951279 commit 45cc819

File tree

5 files changed

+103
-0
lines changed

5 files changed

+103
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>IDEDidComputeMac32BitWarning</key>
6+
<true/>
7+
</dict>
8+
</plist>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>BuildSystemType</key>
6+
<string>Original</string>
7+
</dict>
8+
</plist>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2019 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#import <Flutter/Flutter.h>
6+
#import <WebKit/WebKit.h>
7+
8+
NS_ASSUME_NONNULL_BEGIN
9+
10+
@interface FLTWKNavigationDelegate : NSObject <WKNavigationDelegate>
11+
12+
- (instancetype)initWithChannel:(FlutterMethodChannel*)channel;
13+
14+
/**
15+
* Whether to delegate navigation decisions over the method channel.
16+
*/
17+
@property(nonatomic, assign) BOOL hasDartNavigationDelegate;
18+
19+
@end
20+
21+
NS_ASSUME_NONNULL_END
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright 2019 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#import "FLTWKNavigationDelegate.h"
6+
7+
@implementation FLTWKNavigationDelegate {
8+
FlutterMethodChannel* _methodChannel;
9+
}
10+
11+
- (instancetype)initWithChannel:(FlutterMethodChannel*)channel {
12+
self = [super init];
13+
if (self) {
14+
_methodChannel = channel;
15+
}
16+
return self;
17+
}
18+
19+
- (void)webView:(WKWebView*)webView
20+
decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction
21+
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
22+
if (!self.hasDartNavigationDelegate) {
23+
decisionHandler(WKNavigationActionPolicyAllow);
24+
return;
25+
}
26+
NSDictionary* arguments = @{
27+
@"url" : navigationAction.request.URL.absoluteString,
28+
@"isForMainFrame" : @(navigationAction.targetFrame.isMainFrame)
29+
};
30+
[_methodChannel invokeMethod:@"navigationRequest"
31+
arguments:arguments
32+
result:^(id _Nullable result) {
33+
if ([result isKindOfClass:[FlutterError class]]) {
34+
NSLog(@"navigationRequest has unexpectedly completed with an error, "
35+
@"allowing navigation.");
36+
decisionHandler(WKNavigationActionPolicyAllow);
37+
return;
38+
}
39+
if (result == FlutterMethodNotImplemented) {
40+
NSLog(@"navigationRequest was unexepectedly not implemented: %@, "
41+
@"allowing navigation.",
42+
result);
43+
decisionHandler(WKNavigationActionPolicyAllow);
44+
return;
45+
}
46+
if (![result isKindOfClass:[NSNumber class]]) {
47+
NSLog(@"navigationRequest unexpectedly returned a non boolean value: "
48+
@"%@, allowing navigation.",
49+
result);
50+
decisionHandler(WKNavigationActionPolicyAllow);
51+
return;
52+
}
53+
NSNumber* typedResult = result;
54+
decisionHandler([typedResult boolValue] ? WKNavigationActionPolicyAllow
55+
: WKNavigationActionPolicyCancel);
56+
}];
57+
}
58+
59+
@end

packages/webview_flutter/ios/Classes/FlutterWebView.m

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// found in the LICENSE file.
44

55
#import "FlutterWebView.h"
6+
#import "FLTWKNavigationDelegate.h"
67
#import "JavaScriptChannelHandler.h"
78

89
@implementation FLTWebViewFactory {
@@ -40,6 +41,7 @@ @implementation FLTWebViewController {
4041
NSString* _currentUrl;
4142
// The set of registered JavaScript channel names.
4243
NSMutableSet* _javaScriptChannelNames;
44+
FLTWKNavigationDelegate* _navigationDelegate;
4345
}
4446

4547
- (instancetype)initWithFrame:(CGRect)frame
@@ -64,6 +66,8 @@ - (instancetype)initWithFrame:(CGRect)frame
6466
configuration.userContentController = userContentController;
6567

6668
_webView = [[WKWebView alloc] initWithFrame:frame configuration:configuration];
69+
_navigationDelegate = [[FLTWKNavigationDelegate alloc] initWithChannel:_channel];
70+
_webView.navigationDelegate = _navigationDelegate;
6771
__weak __typeof__(self) weakSelf = self;
6872
[_channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
6973
[weakSelf onMethodCall:call result:result];
@@ -229,6 +233,9 @@ - (void)applySettings:(NSDictionary<NSString*, id>*)settings {
229233
if ([key isEqualToString:@"jsMode"]) {
230234
NSNumber* mode = settings[key];
231235
[self updateJsMode:mode];
236+
} else if ([key isEqualToString:@"hasNavigationDelegate"]) {
237+
NSNumber* hasDartNavigationDelegate = settings[key];
238+
_navigationDelegate.hasDartNavigationDelegate = [hasDartNavigationDelegate boolValue];
232239
} else {
233240
NSLog(@"webview_flutter: unknown setting key: %@", key);
234241
}

0 commit comments

Comments
 (0)