From 8aed88e0c5154a6ea799d1e004f9917401808606 Mon Sep 17 00:00:00 2001 From: Konstantin Gornichnov Date: Tue, 2 Jul 2019 09:36:44 +0400 Subject: [PATCH 01/13] Add onReceiveError feature to android code. --- .../webviewflutter/FlutterWebViewClient.java | 38 ++++++++++++++++++- .../webview_flutter/lib/webview_flutter.dart | 7 ++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java index e7b10ce2257b..340cce511671 100644 --- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java +++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java @@ -7,15 +7,20 @@ import android.annotation.TargetApi; import android.os.Build; import android.util.Log; +import android.webkit.WebResourceError; import android.webkit.WebResourceRequest; import android.webkit.WebView; import android.webkit.WebViewClient; + import androidx.annotation.NonNull; +import androidx.webkit.WebResourceErrorCompat; import androidx.webkit.WebViewClientCompat; -import io.flutter.plugin.common.MethodChannel; + import java.util.HashMap; import java.util.Map; +import io.flutter.plugin.common.MethodChannel; + // We need to use WebViewClientCompat to get // shouldOverrideUrlLoading(WebView view, WebResourceRequest request) // invoked by the webview on older Android devices, without it pages that use iframes will @@ -85,6 +90,14 @@ private void notifyOnNavigationRequest( } } + private void onReceiveError(WebView view, int code, String description, String url) { + Map args = new HashMap<>(); + args.put("url", url); + args.put("code", code); + args.put("description", description); + methodChannel.invokeMethod("onPageReceiveError", args); + } + // This method attempts to avoid using WebViewClientCompat due to bug // https://bugs.chromium.org/p/chromium/issues/detail?id=925887. Also, see // https://github.com/flutter/flutter/issues/29446. @@ -110,6 +123,17 @@ public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request public void onPageFinished(WebView view, String url) { FlutterWebViewClient.this.onPageFinished(view, url); } + + @TargetApi(Build.VERSION_CODES.M) + @Override + public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { + FlutterWebViewClient.this.onReceiveError(view, error.getErrorCode(), error.getDescription().toString(), request.getUrl().toString()); + } + + @Override + public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { + FlutterWebViewClient.this.onReceiveError(view, errorCode, description, failingUrl); + } }; } @@ -130,6 +154,18 @@ public boolean shouldOverrideUrlLoading(WebView view, String url) { public void onPageFinished(WebView view, String url) { FlutterWebViewClient.this.onPageFinished(view, url); } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + @Override + public void onReceivedError(@NonNull WebView view, @NonNull WebResourceRequest request, @NonNull WebResourceErrorCompat error) { + //TODO: is really need to check WebViewFeature.isFeatureSupported() and api version. + FlutterWebViewClient.this.onReceiveError(view, error.getErrorCode(), error.getDescription().toString(), request.getUrl().toString()); + } + + @Override + public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { + FlutterWebViewClient.this.onReceiveError(view, errorCode, description, failingUrl); + } }; } diff --git a/packages/webview_flutter/lib/webview_flutter.dart b/packages/webview_flutter/lib/webview_flutter.dart index 3c0175e2f22b..a67830620a6a 100644 --- a/packages/webview_flutter/lib/webview_flutter.dart +++ b/packages/webview_flutter/lib/webview_flutter.dart @@ -72,6 +72,10 @@ typedef NavigationDecision NavigationDelegate(NavigationRequest navigation); /// Signature for when a [WebView] has finished loading a page. typedef void PageFinishedCallback(String url); +/// Signature for when a [WebView] receive error. +/// Code must be NSURLErrorDomain code or const from WebViewClient. +typedef void PageReceiveErrorCallback(String url, int code, String description); + final RegExp _validChannelNames = RegExp('^[a-zA-Z_][a-zA-Z0-9]*\$'); /// A named channel for receiving messaged from JavaScript code running inside a web view. @@ -121,6 +125,7 @@ class WebView extends StatefulWidget { this.gestureRecognizers, this.onPageFinished, this.debuggingEnabled = false, + this.onPageReceiveError }) : assert(javascriptMode != null), super(key: key); @@ -255,6 +260,8 @@ class WebView extends StatefulWidget { /// By default `debuggingEnabled` is false. final bool debuggingEnabled; + final PageReceiveErrorCallback onPageReceiveError; + @override State createState() => _WebViewState(); } From a3b3a2489990677ebc29243bfdf250c9cd3e9217 Mon Sep 17 00:00:00 2001 From: Konstantin Gornichnov Date: Tue, 2 Jul 2019 11:21:48 +0400 Subject: [PATCH 02/13] Implement onReceiveHttpError. --- .../webviewflutter/FlutterWebViewClient.java | 18 ++++++++++++++++++ .../lib/platform_interface.dart | 2 ++ .../lib/src/webview_method_channel.dart | 7 +++++++ .../webview_flutter/lib/webview_flutter.dart | 7 +++++++ 4 files changed, 34 insertions(+) diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java index 340cce511671..9f5c894b83a5 100644 --- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java +++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java @@ -9,6 +9,7 @@ import android.util.Log; import android.webkit.WebResourceError; import android.webkit.WebResourceRequest; +import android.webkit.WebResourceResponse; import android.webkit.WebView; import android.webkit.WebViewClient; @@ -130,10 +131,20 @@ public void onReceivedError(WebView view, WebResourceRequest request, WebResourc FlutterWebViewClient.this.onReceiveError(view, error.getErrorCode(), error.getDescription().toString(), request.getUrl().toString()); } + @TargetApi(Build.VERSION_CODES.M) + @Override + public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) { + FlutterWebViewClient.this.onReceiveError(view, errorResponse.getStatusCode(), null, request.getUrl().toString()); + } + + @SuppressWarnings("deprecation") @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { FlutterWebViewClient.this.onReceiveError(view, errorCode, description, failingUrl); } + + + }; } @@ -155,6 +166,12 @@ public void onPageFinished(WebView view, String url) { FlutterWebViewClient.this.onPageFinished(view, url); } + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + @Override + public void onReceivedHttpError(@NonNull WebView view, @NonNull WebResourceRequest request, @NonNull WebResourceResponse errorResponse) { + FlutterWebViewClient.this.onReceiveError(view, errorResponse.getStatusCode(), null, request.getUrl().toString()); + } + @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public void onReceivedError(@NonNull WebView view, @NonNull WebResourceRequest request, @NonNull WebResourceErrorCompat error) { @@ -162,6 +179,7 @@ public void onReceivedError(@NonNull WebView view, @NonNull WebResourceRequest r FlutterWebViewClient.this.onReceiveError(view, error.getErrorCode(), error.getDescription().toString(), request.getUrl().toString()); } + @SuppressWarnings("deprecation") @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { FlutterWebViewClient.this.onReceiveError(view, errorCode, description, failingUrl); diff --git a/packages/webview_flutter/lib/platform_interface.dart b/packages/webview_flutter/lib/platform_interface.dart index bfb5b6255421..21d4d0651fde 100644 --- a/packages/webview_flutter/lib/platform_interface.dart +++ b/packages/webview_flutter/lib/platform_interface.dart @@ -25,6 +25,8 @@ abstract class WebViewPlatformCallbacksHandler { /// Invoked by [WebViewPlatformController] when a page has finished loading. void onPageFinished(String url); + + void onPageReceiveError({String url, int code, String description}); } /// Interface for talking to the webview's platform implementation. diff --git a/packages/webview_flutter/lib/src/webview_method_channel.dart b/packages/webview_flutter/lib/src/webview_method_channel.dart index ce9988743853..cbe5eab8985c 100644 --- a/packages/webview_flutter/lib/src/webview_method_channel.dart +++ b/packages/webview_flutter/lib/src/webview_method_channel.dart @@ -38,6 +38,13 @@ class MethodChannelWebViewPlatform implements WebViewPlatformController { case 'onPageFinished': _platformCallbacksHandler.onPageFinished(call.arguments['url']); return null; + case 'onPageReceiveError': + _platformCallbacksHandler.onPageReceiveError( + url: call.arguments['url'], + code: call.arguments['code'], + description: call.arguments['description'] + ); + return null; } throw MissingPluginException( '${call.method} was invoked but has no handler'); diff --git a/packages/webview_flutter/lib/webview_flutter.dart b/packages/webview_flutter/lib/webview_flutter.dart index a67830620a6a..eadaee9c848e 100644 --- a/packages/webview_flutter/lib/webview_flutter.dart +++ b/packages/webview_flutter/lib/webview_flutter.dart @@ -404,6 +404,13 @@ class _PlatformCallbacksHandler implements WebViewPlatformCallbacksHandler { } } + @override + void onPageReceiveError({String url, int code, String description}) { + if (_widget.onPageReceiveError != null) { + _widget.onPageReceiveError(url, code, description); + } + } + void _updateJavascriptChannelsFromSet(Set channels) { _javascriptChannels.clear(); if (channels == null) { From 13d1d3ff07f3eddfad97cc7fbd06b19158ff8f5f Mon Sep 17 00:00:00 2001 From: Konstantin Gornichnov Date: Tue, 2 Jul 2019 11:35:00 +0400 Subject: [PATCH 03/13] Flutter tests. --- .../test/webview_flutter_test.dart | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/packages/webview_flutter/test/webview_flutter_test.dart b/packages/webview_flutter/test/webview_flutter_test.dart index d451a86b19c8..51b3f1def966 100644 --- a/packages/webview_flutter/test/webview_flutter_test.dart +++ b/packages/webview_flutter/test/webview_flutter_test.dart @@ -807,6 +807,73 @@ void main() { expect(platform.lastRequestHeaders, headers); }); }); + + group('$PageReceiveErrorCallback', () { + testWidgets('onPageReceiveError is not null', (WidgetTester tester) async { + String returnedUrl; + int returnedCode; + String returnedDescription; + + await tester.pumpWidget(WebView( + initialUrl: 'https://youtube.com', + onPageReceiveError: (String url, int code, String description) { + returnedUrl = url; + returnedCode = code; + returnedDescription = description; + }, + )); + + final FakePlatformWebView platformWebView = + fakePlatformViewsController.lastCreatedView; + + platformWebView.fakeOnPageReceiveErrorCallback(404, "description"); + + expect(platformWebView.currentUrl, returnedUrl); + expect(404, returnedCode); + expect("description", returnedDescription); + }); + + testWidgets('onPageReceiveError is null', (WidgetTester tester) async { + await tester.pumpWidget(const WebView( + initialUrl: 'https://youtube.com', + onPageReceiveError: null, + )); + + final FakePlatformWebView platformWebView = + fakePlatformViewsController.lastCreatedView; + + platformWebView.fakeOnPageReceiveErrorCallback(404, "description"); + }); + + testWidgets('onPageReceiveError changed', (WidgetTester tester) async { + String returnedUrl; + int returnedCode; + String returnedDescription; + + await tester.pumpWidget(WebView( + initialUrl: 'https://youtube.com', + onPageReceiveError: (String url, int code, String description) {}, + )); + + await tester.pumpWidget(WebView( + initialUrl: 'https://youtube.com', + onPageReceiveError: (String url, int code, String description) { + returnedUrl = url; + returnedCode = code; + returnedDescription = description; + }, + )); + + final FakePlatformWebView platformWebView = + fakePlatformViewsController.lastCreatedView; + + platformWebView.fakeOnPageReceiveErrorCallback(404, "description"); + + expect(platformWebView.currentUrl, returnedUrl); + expect(404, returnedCode); + expect("description", returnedDescription); + }); + }); } class FakePlatformWebView { @@ -961,6 +1028,28 @@ class FakePlatformWebView { ); } + void fakeOnPageReceiveErrorCallback(int code, String description) { + final StandardMethodCodec codec = const StandardMethodCodec(); + + final ByteData data = codec.encodeMethodCall(MethodCall( + 'onPageReceiveError', + { + 'url': currentUrl, + 'code': code, + 'description': description + }, + )); + + // TODO(hterkelsen): Remove this when defaultBinaryMessages is in stable. + // https://github.com/flutter/flutter/issues/33446 + // ignore: deprecated_member_use + BinaryMessages.handlePlatformMessage( + channel.name, + data, + (ByteData data) {}, + ); + } + void _loadUrl(String url) { history = history.sublist(0, currentPosition + 1); history.add(url); From 52e57ff7dbdf5c6425360cd7850b28d3924653ed Mon Sep 17 00:00:00 2001 From: Konstantin Gornichnov Date: Tue, 2 Jul 2019 11:39:39 +0400 Subject: [PATCH 04/13] Add description. --- packages/webview_flutter/lib/webview_flutter.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/webview_flutter/lib/webview_flutter.dart b/packages/webview_flutter/lib/webview_flutter.dart index eadaee9c848e..9d68e05afa6f 100644 --- a/packages/webview_flutter/lib/webview_flutter.dart +++ b/packages/webview_flutter/lib/webview_flutter.dart @@ -73,7 +73,8 @@ typedef NavigationDecision NavigationDelegate(NavigationRequest navigation); typedef void PageFinishedCallback(String url); /// Signature for when a [WebView] receive error. -/// Code must be NSURLErrorDomain code or const from WebViewClient. +/// Code may be NSURLErrorDomain code or const from Android WebViewClient or http status code. +/// Description is optional typedef void PageReceiveErrorCallback(String url, int code, String description); final RegExp _validChannelNames = RegExp('^[a-zA-Z_][a-zA-Z0-9]*\$'); From 0affc517df3d0e0707021fa50048eb64e40eef9f Mon Sep 17 00:00:00 2001 From: Konstantin Gornichnov Date: Tue, 2 Jul 2019 13:05:28 +0400 Subject: [PATCH 05/13] Implement IOS error delegate. --- .../ios/Classes/FLTWKNavigationDelegate.m | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m b/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m index abcca0a5e8a9..4d61258350de 100644 --- a/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m +++ b/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m @@ -59,4 +59,37 @@ - (void)webView:(WKWebView*)webView - (void)webView:(WKWebView*)webView didFinishNavigation:(WKNavigation*)navigation { [_methodChannel invokeMethod:@"onPageFinished" arguments:@{@"url" : webView.URL.absoluteString}]; } + +- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error { + [_methodChannel invokeMethod:@"onPageReceiveError" + arguments:@{@"url" : webView.URL.absoluteString, + @"code" : [NSNumber numberWithLong: error.code], + @"description" : [error localizedDescription], + }]; +} + +- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error { + [_methodChannel invokeMethod:@"onPageReceiveError" + arguments:@{@"url" : error.userInfo[NSURLErrorFailingURLStringErrorKey], + @"code" : [NSNumber numberWithLong: error.code], + @"description" : [error localizedDescription], + }]; +} + +- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler { + if ([navigationResponse.response isKindOfClass:[NSHTTPURLResponse class]]) { + NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response; + if (response.statusCode >= 400 && response.statusCode < 600) { +// @throw([NSException exceptionWithName: @"e" reason:@"E" userInfo:nil]); + [_methodChannel invokeMethod:@"onPageReceiveError" + arguments:@{@"url" : response.URL.absoluteString, + @"code" : [NSNumber numberWithLong: response.statusCode], + @"description" : [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], + }]; + } + } + + decisionHandler(WKNavigationResponsePolicyAllow); +} + @end From 01b34e7ff590533b9524224d0386832841b92b75 Mon Sep 17 00:00:00 2001 From: Konstantin Gornichnov Date: Tue, 2 Jul 2019 14:00:07 +0400 Subject: [PATCH 06/13] Implement onPageStarted callback in ios. --- .../ios/Classes/FLTWKNavigationDelegate.m | 41 +++++++++++-------- .../lib/platform_interface.dart | 2 + .../lib/src/webview_method_channel.dart | 3 ++ .../webview_flutter/lib/webview_flutter.dart | 17 +++++++- 4 files changed, 45 insertions(+), 18 deletions(-) diff --git a/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m b/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m index 4d61258350de..08cc64442d36 100644 --- a/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m +++ b/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m @@ -61,35 +61,44 @@ - (void)webView:(WKWebView*)webView didFinishNavigation:(WKNavigation*)navigatio } - (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error { - [_methodChannel invokeMethod:@"onPageReceiveError" - arguments:@{@"url" : webView.URL.absoluteString, - @"code" : [NSNumber numberWithLong: error.code], - @"description" : [error localizedDescription], - }]; + NSDictionary* arguments = @{ + @"url" : webView.URL.absoluteString ?: [NSNull null], + @"code" : [NSNumber numberWithLong: error.code], + @"description" : [error localizedDescription], + }; + + [_methodChannel invokeMethod:@"onPageReceiveError" arguments: arguments]; } - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error { - [_methodChannel invokeMethod:@"onPageReceiveError" - arguments:@{@"url" : error.userInfo[NSURLErrorFailingURLStringErrorKey], - @"code" : [NSNumber numberWithLong: error.code], - @"description" : [error localizedDescription], - }]; + NSDictionary* arguments = @{ + @"url" : error.userInfo[NSURLErrorFailingURLStringErrorKey], + @"code" : [NSNumber numberWithLong: error.code], + @"description" : [error localizedDescription], + }; + + [_methodChannel invokeMethod:@"onPageReceiveError" arguments:arguments]; } - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler { if ([navigationResponse.response isKindOfClass:[NSHTTPURLResponse class]]) { NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response; if (response.statusCode >= 400 && response.statusCode < 600) { -// @throw([NSException exceptionWithName: @"e" reason:@"E" userInfo:nil]); - [_methodChannel invokeMethod:@"onPageReceiveError" - arguments:@{@"url" : response.URL.absoluteString, - @"code" : [NSNumber numberWithLong: response.statusCode], - @"description" : [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], - }]; + NSDictionary* arguments = @{ + @"url" : response.URL.absoluteString ?: [NSNull null], + @"code" : [NSNumber numberWithLong: response.statusCode], + @"description" : [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], + }; + + [_methodChannel invokeMethod:@"onPageReceiveError" arguments: arguments]; } } decisionHandler(WKNavigationResponsePolicyAllow); } +- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation { + [_methodChannel invokeMethod:@"onPageStarted" arguments:@{@"url" : webView.URL.absoluteString ?: [NSNull null],}]; +} + @end diff --git a/packages/webview_flutter/lib/platform_interface.dart b/packages/webview_flutter/lib/platform_interface.dart index 21d4d0651fde..9bc58de404b9 100644 --- a/packages/webview_flutter/lib/platform_interface.dart +++ b/packages/webview_flutter/lib/platform_interface.dart @@ -27,6 +27,8 @@ abstract class WebViewPlatformCallbacksHandler { void onPageFinished(String url); void onPageReceiveError({String url, int code, String description}); + + void onPageStarted(String url); } /// Interface for talking to the webview's platform implementation. diff --git a/packages/webview_flutter/lib/src/webview_method_channel.dart b/packages/webview_flutter/lib/src/webview_method_channel.dart index cbe5eab8985c..fcbee44e179a 100644 --- a/packages/webview_flutter/lib/src/webview_method_channel.dart +++ b/packages/webview_flutter/lib/src/webview_method_channel.dart @@ -45,6 +45,9 @@ class MethodChannelWebViewPlatform implements WebViewPlatformController { description: call.arguments['description'] ); return null; + case 'onPageStarted': + _platformCallbacksHandler.onPageStarted(call.arguments['url']); + return null; } throw MissingPluginException( '${call.method} was invoked but has no handler'); diff --git a/packages/webview_flutter/lib/webview_flutter.dart b/packages/webview_flutter/lib/webview_flutter.dart index 9d68e05afa6f..073ecdc413d4 100644 --- a/packages/webview_flutter/lib/webview_flutter.dart +++ b/packages/webview_flutter/lib/webview_flutter.dart @@ -72,11 +72,14 @@ typedef NavigationDecision NavigationDelegate(NavigationRequest navigation); /// Signature for when a [WebView] has finished loading a page. typedef void PageFinishedCallback(String url); -/// Signature for when a [WebView] receive error. +/// Signature for when a [WebView] receive a error. /// Code may be NSURLErrorDomain code or const from Android WebViewClient or http status code. /// Description is optional typedef void PageReceiveErrorCallback(String url, int code, String description); +/// Signature for when a [WebView] has started loading a page. +typedef void PageStartedCallback(String url); + final RegExp _validChannelNames = RegExp('^[a-zA-Z_][a-zA-Z0-9]*\$'); /// A named channel for receiving messaged from JavaScript code running inside a web view. @@ -126,7 +129,8 @@ class WebView extends StatefulWidget { this.gestureRecognizers, this.onPageFinished, this.debuggingEnabled = false, - this.onPageReceiveError + this.onPageReceiveError, + this.onPageStarted, }) : assert(javascriptMode != null), super(key: key); @@ -263,6 +267,8 @@ class WebView extends StatefulWidget { final PageReceiveErrorCallback onPageReceiveError; + final PageStartedCallback onPageStarted; + @override State createState() => _WebViewState(); } @@ -412,6 +418,13 @@ class _PlatformCallbacksHandler implements WebViewPlatformCallbacksHandler { } } + @override + void onPageStarted(String url) { + if (_widget.onPageStarted != null) { + _widget.onPageStarted(url); + } + } + void _updateJavascriptChannelsFromSet(Set channels) { _javascriptChannels.clear(); if (channels == null) { From 7cc039f903dcc0763376f7941ca2a82eac2869ed Mon Sep 17 00:00:00 2001 From: Konstantin Gornichnov Date: Tue, 2 Jul 2019 14:07:07 +0400 Subject: [PATCH 07/13] OnPageStarted android callbacks and dart tests. --- .../webviewflutter/FlutterWebViewClient.java | 18 ++++- .../test/webview_flutter_test.dart | 73 +++++++++++++++++++ 2 files changed, 89 insertions(+), 2 deletions(-) diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java index 9f5c894b83a5..550a309a90f8 100644 --- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java +++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java @@ -5,6 +5,7 @@ package io.flutter.plugins.webviewflutter; import android.annotation.TargetApi; +import android.graphics.Bitmap; import android.os.Build; import android.util.Log; import android.webkit.WebResourceError; @@ -99,6 +100,12 @@ private void onReceiveError(WebView view, int code, String description, String u methodChannel.invokeMethod("onPageReceiveError", args); } + private void onPageStarted(WebView view, String url) { + Map args = new HashMap<>(); + args.put("url", url); + methodChannel.invokeMethod("onPageStarted", args); + } + // This method attempts to avoid using WebViewClientCompat due to bug // https://bugs.chromium.org/p/chromium/issues/detail?id=925887. Also, see // https://github.com/flutter/flutter/issues/29446. @@ -143,8 +150,10 @@ public void onReceivedError(WebView view, int errorCode, String description, Str FlutterWebViewClient.this.onReceiveError(view, errorCode, description, failingUrl); } - - + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) { + FlutterWebViewClient.this.onPageStarted(view, url); + } }; } @@ -184,6 +193,11 @@ public void onReceivedError(@NonNull WebView view, @NonNull WebResourceRequest r public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { FlutterWebViewClient.this.onReceiveError(view, errorCode, description, failingUrl); } + + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) { + FlutterWebViewClient.this.onPageStarted(view, url); + } }; } diff --git a/packages/webview_flutter/test/webview_flutter_test.dart b/packages/webview_flutter/test/webview_flutter_test.dart index 51b3f1def966..7db1feada80d 100644 --- a/packages/webview_flutter/test/webview_flutter_test.dart +++ b/packages/webview_flutter/test/webview_flutter_test.dart @@ -874,6 +874,61 @@ void main() { expect("description", returnedDescription); }); }); + + group('$PageStartedCallback', () { + testWidgets('onPageStarted is not null', (WidgetTester tester) async { + String returnedUrl; + + await tester.pumpWidget(WebView( + initialUrl: 'https://youtube.com', + onPageStarted: (String url) { + returnedUrl = url; + }, + )); + + final FakePlatformWebView platformWebView = + fakePlatformViewsController.lastCreatedView; + + platformWebView.fakeOnPageStartedCallback(); + + expect(platformWebView.currentUrl, returnedUrl); + }); + + testWidgets('onPageStarted is null', (WidgetTester tester) async { + await tester.pumpWidget(const WebView( + initialUrl: 'https://youtube.com', + onPageStarted: null, + )); + + final FakePlatformWebView platformWebView = + fakePlatformViewsController.lastCreatedView; + + platformWebView.fakeOnPageStartedCallback(); + }); + + testWidgets('onPageStarted changed', (WidgetTester tester) async { + String returnedUrl; + + await tester.pumpWidget(WebView( + initialUrl: 'https://youtube.com', + onPageStarted: (String url) {}, + )); + + await tester.pumpWidget(WebView( + initialUrl: 'https://youtube.com', + onPageStarted: (String url) { + returnedUrl = url; + }, + )); + + final FakePlatformWebView platformWebView = + fakePlatformViewsController.lastCreatedView; + + platformWebView.fakeOnPageStartedCallback(); + + expect(platformWebView.currentUrl, returnedUrl); + }); + }); } class FakePlatformWebView { @@ -1050,6 +1105,24 @@ class FakePlatformWebView { ); } + void fakeOnPageStartedCallback() { + final StandardMethodCodec codec = const StandardMethodCodec(); + + final ByteData data = codec.encodeMethodCall(MethodCall( + 'onPageStarted', + {'url': currentUrl}, + )); + + // TODO(hterkelsen): Remove this when defaultBinaryMessages is in stable. + // https://github.com/flutter/flutter/issues/33446 + // ignore: deprecated_member_use + BinaryMessages.handlePlatformMessage( + channel.name, + data, + (ByteData data) {}, + ); + } + void _loadUrl(String url) { history = history.sublist(0, currentPosition + 1); history.add(url); From c65c100705711e45cfb1c2b5a910c921ff191ae7 Mon Sep 17 00:00:00 2001 From: Konstantin Gornichnov Date: Tue, 2 Jul 2019 15:03:34 +0400 Subject: [PATCH 08/13] Format flutter files. --- packages/webview_flutter/lib/src/webview_method_channel.dart | 3 +-- packages/webview_flutter/test/webview_flutter_test.dart | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/webview_flutter/lib/src/webview_method_channel.dart b/packages/webview_flutter/lib/src/webview_method_channel.dart index fcbee44e179a..0e471b28f7ef 100644 --- a/packages/webview_flutter/lib/src/webview_method_channel.dart +++ b/packages/webview_flutter/lib/src/webview_method_channel.dart @@ -42,8 +42,7 @@ class MethodChannelWebViewPlatform implements WebViewPlatformController { _platformCallbacksHandler.onPageReceiveError( url: call.arguments['url'], code: call.arguments['code'], - description: call.arguments['description'] - ); + description: call.arguments['description']); return null; case 'onPageStarted': _platformCallbacksHandler.onPageStarted(call.arguments['url']); diff --git a/packages/webview_flutter/test/webview_flutter_test.dart b/packages/webview_flutter/test/webview_flutter_test.dart index 7db1feada80d..fd5e61e4e1ac 100644 --- a/packages/webview_flutter/test/webview_flutter_test.dart +++ b/packages/webview_flutter/test/webview_flutter_test.dart @@ -1101,7 +1101,7 @@ class FakePlatformWebView { BinaryMessages.handlePlatformMessage( channel.name, data, - (ByteData data) {}, + (ByteData data) {}, ); } @@ -1119,7 +1119,7 @@ class FakePlatformWebView { BinaryMessages.handlePlatformMessage( channel.name, data, - (ByteData data) {}, + (ByteData data) {}, ); } From e5a52f7152d199ccb21af6467fbb3087b0b773fe Mon Sep 17 00:00:00 2001 From: Konstantin Gornichnov Date: Wed, 3 Jul 2019 09:15:00 +0400 Subject: [PATCH 09/13] Format Objective-C and Java files. --- .../webviewflutter/FlutterWebViewClient.java | 45 +++++++--- .../ios/Classes/FLTWKNavigationDelegate.m | 85 ++++++++++--------- 2 files changed, 78 insertions(+), 52 deletions(-) diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java index 550a309a90f8..4402284d29aa 100644 --- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java +++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java @@ -13,16 +13,13 @@ import android.webkit.WebResourceResponse; import android.webkit.WebView; import android.webkit.WebViewClient; - import androidx.annotation.NonNull; import androidx.webkit.WebResourceErrorCompat; import androidx.webkit.WebViewClientCompat; - +import io.flutter.plugin.common.MethodChannel; import java.util.HashMap; import java.util.Map; -import io.flutter.plugin.common.MethodChannel; - // We need to use WebViewClientCompat to get // shouldOverrideUrlLoading(WebView view, WebResourceRequest request) // invoked by the webview on older Android devices, without it pages that use iframes will @@ -134,19 +131,27 @@ public void onPageFinished(WebView view, String url) { @TargetApi(Build.VERSION_CODES.M) @Override - public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { - FlutterWebViewClient.this.onReceiveError(view, error.getErrorCode(), error.getDescription().toString(), request.getUrl().toString()); + public void onReceivedError( + WebView view, WebResourceRequest request, WebResourceError error) { + FlutterWebViewClient.this.onReceiveError( + view, + error.getErrorCode(), + error.getDescription().toString(), + request.getUrl().toString()); } @TargetApi(Build.VERSION_CODES.M) @Override - public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) { - FlutterWebViewClient.this.onReceiveError(view, errorResponse.getStatusCode(), null, request.getUrl().toString()); + public void onReceivedHttpError( + WebView view, WebResourceRequest request, WebResourceResponse errorResponse) { + FlutterWebViewClient.this.onReceiveError( + view, errorResponse.getStatusCode(), null, request.getUrl().toString()); } @SuppressWarnings("deprecation") @Override - public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { + public void onReceivedError( + WebView view, int errorCode, String description, String failingUrl) { FlutterWebViewClient.this.onReceiveError(view, errorCode, description, failingUrl); } @@ -177,20 +182,32 @@ public void onPageFinished(WebView view, String url) { @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override - public void onReceivedHttpError(@NonNull WebView view, @NonNull WebResourceRequest request, @NonNull WebResourceResponse errorResponse) { - FlutterWebViewClient.this.onReceiveError(view, errorResponse.getStatusCode(), null, request.getUrl().toString()); + public void onReceivedHttpError( + @NonNull WebView view, + @NonNull WebResourceRequest request, + @NonNull WebResourceResponse errorResponse) { + FlutterWebViewClient.this.onReceiveError( + view, errorResponse.getStatusCode(), null, request.getUrl().toString()); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override - public void onReceivedError(@NonNull WebView view, @NonNull WebResourceRequest request, @NonNull WebResourceErrorCompat error) { + public void onReceivedError( + @NonNull WebView view, + @NonNull WebResourceRequest request, + @NonNull WebResourceErrorCompat error) { //TODO: is really need to check WebViewFeature.isFeatureSupported() and api version. - FlutterWebViewClient.this.onReceiveError(view, error.getErrorCode(), error.getDescription().toString(), request.getUrl().toString()); + FlutterWebViewClient.this.onReceiveError( + view, + error.getErrorCode(), + error.getDescription().toString(), + request.getUrl().toString()); } @SuppressWarnings("deprecation") @Override - public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { + public void onReceivedError( + WebView view, int errorCode, String description, String failingUrl) { FlutterWebViewClient.this.onReceiveError(view, errorCode, description, failingUrl); } diff --git a/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m b/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m index 08cc64442d36..5f7a313424ed 100644 --- a/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m +++ b/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m @@ -5,10 +5,10 @@ #import "FLTWKNavigationDelegate.h" @implementation FLTWKNavigationDelegate { - FlutterMethodChannel* _methodChannel; + FlutterMethodChannel *_methodChannel; } -- (instancetype)initWithChannel:(FlutterMethodChannel*)channel { +- (instancetype)initWithChannel:(FlutterMethodChannel *)channel { self = [super init]; if (self) { _methodChannel = channel; @@ -16,14 +16,14 @@ - (instancetype)initWithChannel:(FlutterMethodChannel*)channel { return self; } -- (void)webView:(WKWebView*)webView - decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction +- (void)webView:(WKWebView *)webView + decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { if (!self.hasDartNavigationDelegate) { decisionHandler(WKNavigationActionPolicyAllow); return; } - NSDictionary* arguments = @{ + NSDictionary *arguments = @{ @"url" : navigationAction.request.URL.absoluteString, @"isForMainFrame" : @(navigationAction.targetFrame.isMainFrame) }; @@ -50,55 +50,64 @@ - (void)webView:(WKWebView*)webView decisionHandler(WKNavigationActionPolicyAllow); return; } - NSNumber* typedResult = result; + NSNumber *typedResult = result; decisionHandler([typedResult boolValue] ? WKNavigationActionPolicyAllow : WKNavigationActionPolicyCancel); }]; } -- (void)webView:(WKWebView*)webView didFinishNavigation:(WKNavigation*)navigation { +- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { [_methodChannel invokeMethod:@"onPageFinished" arguments:@{@"url" : webView.URL.absoluteString}]; } -- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error { - NSDictionary* arguments = @{ - @"url" : webView.URL.absoluteString ?: [NSNull null], - @"code" : [NSNumber numberWithLong: error.code], - @"description" : [error localizedDescription], - }; - - [_methodChannel invokeMethod:@"onPageReceiveError" arguments: arguments]; +- (void)webView:(WKWebView *)webView + didFailNavigation:(WKNavigation *)navigation + withError:(NSError *)error { + NSDictionary *arguments = @{ + @"url" : webView.URL.absoluteString ?: [NSNull null], + @"code" : [NSNumber numberWithLong:error.code], + @"description" : [error localizedDescription], + }; + + [_methodChannel invokeMethod:@"onPageReceiveError" arguments:arguments]; } -- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error { - NSDictionary* arguments = @{ - @"url" : error.userInfo[NSURLErrorFailingURLStringErrorKey], - @"code" : [NSNumber numberWithLong: error.code], - @"description" : [error localizedDescription], - }; - - [_methodChannel invokeMethod:@"onPageReceiveError" arguments:arguments]; +- (void)webView:(WKWebView *)webView + didFailProvisionalNavigation:(WKNavigation *)navigation + withError:(NSError *)error { + NSDictionary *arguments = @{ + @"url" : error.userInfo[NSURLErrorFailingURLStringErrorKey], + @"code" : [NSNumber numberWithLong:error.code], + @"description" : [error localizedDescription], + }; + + [_methodChannel invokeMethod:@"onPageReceiveError" arguments:arguments]; } -- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler { - if ([navigationResponse.response isKindOfClass:[NSHTTPURLResponse class]]) { - NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response; - if (response.statusCode >= 400 && response.statusCode < 600) { - NSDictionary* arguments = @{ - @"url" : response.URL.absoluteString ?: [NSNull null], - @"code" : [NSNumber numberWithLong: response.statusCode], - @"description" : [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], - }; - - [_methodChannel invokeMethod:@"onPageReceiveError" arguments: arguments]; - } +- (void)webView:(WKWebView *)webView + decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse + decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler { + if ([navigationResponse.response isKindOfClass:[NSHTTPURLResponse class]]) { + NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response; + if (response.statusCode >= 400 && response.statusCode < 600) { + NSDictionary *arguments = @{ + @"url" : response.URL.absoluteString ?: [NSNull null], + @"code" : [NSNumber numberWithLong:response.statusCode], + @"description" : [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], + }; + + [_methodChannel invokeMethod:@"onPageReceiveError" arguments:arguments]; } - - decisionHandler(WKNavigationResponsePolicyAllow); + } + + decisionHandler(WKNavigationResponsePolicyAllow); } - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation { - [_methodChannel invokeMethod:@"onPageStarted" arguments:@{@"url" : webView.URL.absoluteString ?: [NSNull null],}]; + [_methodChannel invokeMethod:@"onPageStarted" + arguments:@{ + @"url" : webView.URL.absoluteString ?: [NSNull null], + }]; } @end From 8ad5b2c1c687aceb4d67c7ebca999f1b70907f39 Mon Sep 17 00:00:00 2001 From: isaprykin Date: Fri, 13 Dec 2019 11:41:06 +0500 Subject: [PATCH 10/13] Add DartDoc, fix merge --- .../webviewflutter/FlutterWebViewClient.java | 10 ---------- packages/webview_flutter/example/lib/main.dart | 9 ++++++++- .../lib/platform_interface.dart | 3 +-- .../webview_flutter/lib/webview_flutter.dart | 7 ++----- .../test/webview_flutter_test.dart | 18 ------------------ 5 files changed, 11 insertions(+), 36 deletions(-) diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java index a3d8d8a7fd9b..ea556d567cdb 100644 --- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java +++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java @@ -167,11 +167,6 @@ public void onReceivedError( WebView view, int errorCode, String description, String failingUrl) { FlutterWebViewClient.this.onReceiveError(view, errorCode, description, failingUrl); } - - @Override - public void onPageStarted(WebView view, String url, Bitmap favicon) { - FlutterWebViewClient.this.onPageStarted(view, url); - } }; } @@ -234,11 +229,6 @@ public void onReceivedError( WebView view, int errorCode, String description, String failingUrl) { FlutterWebViewClient.this.onReceiveError(view, errorCode, description, failingUrl); } - - @Override - public void onPageStarted(WebView view, String url, Bitmap favicon) { - FlutterWebViewClient.this.onPageStarted(view, url); - } }; } diff --git a/packages/webview_flutter/example/lib/main.dart b/packages/webview_flutter/example/lib/main.dart index 59c87a25dedf..e97e577baa5a 100644 --- a/packages/webview_flutter/example/lib/main.dart +++ b/packages/webview_flutter/example/lib/main.dart @@ -50,7 +50,7 @@ class _WebViewExampleState extends State { // to allow calling Scaffold.of(context) so we can show a snackbar. body: Builder(builder: (BuildContext context) { return WebView( - initialUrl: 'https://flutter.dev', + initialUrl: 'https://google.com', javascriptMode: JavascriptMode.unrestricted, onWebViewCreated: (WebViewController webViewController) { _controller.complete(webViewController); @@ -74,6 +74,13 @@ class _WebViewExampleState extends State { onPageFinished: (String url) { print('Page finished loading: $url'); }, + onPageReceiveError: (String url, int code, String message) { + Scaffold.of(context).showSnackBar(SnackBar( + content: Text( + 'Code: $code, Url: $url, Message: $message', + ), + )); + }, gestureNavigationEnabled: true, ); }), diff --git a/packages/webview_flutter/lib/platform_interface.dart b/packages/webview_flutter/lib/platform_interface.dart index 37272b4d99e5..4398adf159f1 100644 --- a/packages/webview_flutter/lib/platform_interface.dart +++ b/packages/webview_flutter/lib/platform_interface.dart @@ -29,9 +29,8 @@ abstract class WebViewPlatformCallbacksHandler { /// Invoked by [WebViewPlatformController] when a page has finished loading. void onPageFinished(String url); + /// Invoked by [WebViewPlatformController] when platform's webview return error. void onPageReceiveError({String url, int code, String description}); - - void onPageStarted(String url); } /// Interface for talking to the webview's platform implementation. diff --git a/packages/webview_flutter/lib/webview_flutter.dart b/packages/webview_flutter/lib/webview_flutter.dart index 6fd439b0524b..87dd1c042cd9 100644 --- a/packages/webview_flutter/lib/webview_flutter.dart +++ b/packages/webview_flutter/lib/webview_flutter.dart @@ -84,9 +84,6 @@ typedef void PageFinishedCallback(String url); /// Description is optional typedef void PageReceiveErrorCallback(String url, int code, String description); -/// Signature for when a [WebView] has started loading a page. -typedef void PageStartedCallback(String url); - final RegExp _validChannelNames = RegExp('^[a-zA-Z_][a-zA-Z0-9]*\$'); /// Specifies possible restrictions on automatic media playback. @@ -108,8 +105,6 @@ enum AutoMediaPlaybackPolicy { always_allow, } -final RegExp _validChannelNames = RegExp('^[a-zA-Z_][a-zA-Z0-9_]*\$'); - /// A named channel for receiving messaged from JavaScript code running inside a web view. class JavascriptChannel { /// Constructs a Javascript channel. @@ -301,6 +296,8 @@ class WebView extends StatefulWidget { /// By default `debuggingEnabled` is false. final bool debuggingEnabled; + + /// Invoked when a webview return error. final PageReceiveErrorCallback onPageReceiveError; /// The value used for the HTTP User-Agent: request header. diff --git a/packages/webview_flutter/test/webview_flutter_test.dart b/packages/webview_flutter/test/webview_flutter_test.dart index 3a245e8c30c4..7591b0e102a6 100644 --- a/packages/webview_flutter/test/webview_flutter_test.dart +++ b/packages/webview_flutter/test/webview_flutter_test.dart @@ -1207,24 +1207,6 @@ class FakePlatformWebView { ); } - void fakeOnPageStartedCallback() { - final StandardMethodCodec codec = const StandardMethodCodec(); - - final ByteData data = codec.encodeMethodCall(MethodCall( - 'onPageStarted', - {'url': currentUrl}, - )); - - // TODO(hterkelsen): Remove this when defaultBinaryMessages is in stable. - // https://github.com/flutter/flutter/issues/33446 - // ignore: deprecated_member_use - BinaryMessages.handlePlatformMessage( - channel.name, - data, - (ByteData data) {}, - ); - } - void _loadUrl(String url) { history = history.sublist(0, currentPosition + 1); history.add(url); From 2e4384e2b13216f3c4d9293da4ce57b7aa2d9b2d Mon Sep 17 00:00:00 2001 From: Ivan Saprykin Date: Fri, 13 Dec 2019 12:58:35 +0500 Subject: [PATCH 11/13] ios merge fix --- .../webview_flutter/ios/Classes/FLTWKNavigationDelegate.m | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m b/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m index 305f70959a5f..58dd089c0d54 100644 --- a/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m +++ b/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m @@ -109,11 +109,5 @@ - (void)webView:(WKWebView *)webView decisionHandler(WKNavigationResponsePolicyAllow); } -- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation { - [_methodChannel invokeMethod:@"onPageStarted" - arguments:@{ - @"url" : webView.URL.absoluteString ?: [NSNull null], - }]; -} @end From bce8c834f0353f9be62cf39731659de998fe3a8f Mon Sep 17 00:00:00 2001 From: Ivan Saprykin Date: Fri, 13 Dec 2019 14:35:42 +0500 Subject: [PATCH 12/13] _validChannelNames fix --- packages/webview_flutter/lib/webview_flutter.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webview_flutter/lib/webview_flutter.dart b/packages/webview_flutter/lib/webview_flutter.dart index 87dd1c042cd9..4d2520afbe31 100644 --- a/packages/webview_flutter/lib/webview_flutter.dart +++ b/packages/webview_flutter/lib/webview_flutter.dart @@ -84,7 +84,7 @@ typedef void PageFinishedCallback(String url); /// Description is optional typedef void PageReceiveErrorCallback(String url, int code, String description); -final RegExp _validChannelNames = RegExp('^[a-zA-Z_][a-zA-Z0-9]*\$'); +final RegExp _validChannelNames = RegExp('^[a-zA-Z_][a-zA-Z0-9_]*\$'); /// Specifies possible restrictions on automatic media playback. /// From e0bd82a81f5c06adc869a0a612115d22bb3484d0 Mon Sep 17 00:00:00 2001 From: Ivan Saprykin Date: Fri, 13 Dec 2019 15:17:59 +0500 Subject: [PATCH 13/13] format --- .../webviewflutter/FlutterWebViewClient.java | 2 +- .../ios/Classes/FLTWKNavigationDelegate.m | 23 ++++++++++--------- .../webview_flutter/lib/webview_flutter.dart | 1 - 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java index ea556d567cdb..fb114e27d5fc 100644 --- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java +++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java @@ -8,8 +8,8 @@ import android.graphics.Bitmap; import android.os.Build; import android.util.Log; -import android.webkit.WebResourceError; import android.view.KeyEvent; +import android.webkit.WebResourceError; import android.webkit.WebResourceRequest; import android.webkit.WebResourceResponse; import android.webkit.WebView; diff --git a/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m b/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m index 58dd089c0d54..e60b36769f3e 100644 --- a/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m +++ b/packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m @@ -5,10 +5,10 @@ #import "FLTWKNavigationDelegate.h" @implementation FLTWKNavigationDelegate { - FlutterMethodChannel* _methodChannel; + FlutterMethodChannel *_methodChannel; } -- (instancetype)initWithChannel:(FlutterMethodChannel*)channel { +- (instancetype)initWithChannel:(FlutterMethodChannel *)channel { self = [super init]; if (self) { _methodChannel = channel; @@ -18,18 +18,18 @@ - (instancetype)initWithChannel:(FlutterMethodChannel*)channel { #pragma mark - WKNavigationDelegate conformance -- (void)webView:(WKWebView*)webView didStartProvisionalNavigation:(WKNavigation*)navigation { +- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation { [_methodChannel invokeMethod:@"onPageStarted" arguments:@{@"url" : webView.URL.absoluteString}]; } -- (void)webView:(WKWebView*)webView - decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction +- (void)webView:(WKWebView *)webView + decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { if (!self.hasDartNavigationDelegate) { decisionHandler(WKNavigationActionPolicyAllow); return; } - NSDictionary* arguments = @{ + NSDictionary *arguments = @{ @"url" : navigationAction.request.URL.absoluteString, @"isForMainFrame" : @(navigationAction.targetFrame.isMainFrame) }; @@ -37,7 +37,8 @@ - (void)webView:(WKWebView*)webView arguments:arguments result:^(id _Nullable result) { if ([result isKindOfClass:[FlutterError class]]) { - NSLog(@"navigationRequest has unexpectedly completed with an error, " + NSLog(@"navigationRequest has unexpectedly completed with an " + @"error, " @"allowing navigation."); decisionHandler(WKNavigationActionPolicyAllow); return; @@ -50,19 +51,20 @@ - (void)webView:(WKWebView*)webView return; } if (![result isKindOfClass:[NSNumber class]]) { - NSLog(@"navigationRequest unexpectedly returned a non boolean value: " + NSLog(@"navigationRequest unexpectedly returned a non boolean " + @"value: " @"%@, allowing navigation.", result); decisionHandler(WKNavigationActionPolicyAllow); return; } - NSNumber* typedResult = result; + NSNumber *typedResult = result; decisionHandler([typedResult boolValue] ? WKNavigationActionPolicyAllow : WKNavigationActionPolicyCancel); }]; } -- (void)webView:(WKWebView*)webView didFinishNavigation:(WKNavigation*)navigation { +- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { [_methodChannel invokeMethod:@"onPageFinished" arguments:@{@"url" : webView.URL.absoluteString}]; } @@ -109,5 +111,4 @@ - (void)webView:(WKWebView *)webView decisionHandler(WKNavigationResponsePolicyAllow); } - @end diff --git a/packages/webview_flutter/lib/webview_flutter.dart b/packages/webview_flutter/lib/webview_flutter.dart index 4d2520afbe31..c026db3d2355 100644 --- a/packages/webview_flutter/lib/webview_flutter.dart +++ b/packages/webview_flutter/lib/webview_flutter.dart @@ -296,7 +296,6 @@ class WebView extends StatefulWidget { /// By default `debuggingEnabled` is false. final bool debuggingEnabled; - /// Invoked when a webview return error. final PageReceiveErrorCallback onPageReceiveError;