From 710be6789491905140de99abfdb129cba5cd317c Mon Sep 17 00:00:00 2001 From: Lorenzo Pichilli Date: Tue, 30 Jun 2020 10:58:59 +0200 Subject: [PATCH] added disableDefaultErrorPage Android-specific webview option, updated onCreateWindow event implementation --- CHANGELOG.md | 1 + README.md | 1 + .../InAppWebView/FlutterWebView.java | 6 +-- .../InAppWebViewChromeClient.java | 19 +++++++- .../InAppWebView/InAppWebViewClient.java | 33 +++++++++---- .../InAppWebView/InAppWebViewOptions.java | 5 ++ .../JavaScriptBridgeInterface.java | 18 +++++++ example/.flutter-plugins-dependencies | 2 +- ios/Classes/InAppWebView.swift | 20 ++++++-- lib/src/headless_in_app_webview.dart | 2 +- lib/src/in_app_browser.dart | 9 ++-- lib/src/in_app_webview.dart | 2 +- lib/src/in_app_webview_controller.dart | 48 ++++--------------- lib/src/webview.dart | 11 ++--- lib/src/webview_options.dart | 21 +++++--- 15 files changed, 122 insertions(+), 76 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cc4fbe9..4ee2db04 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - Updated `onCreateWindow`, `onJsAlert`, `onJsConfirm`, `onJsPrompt` webview events - Added `onCloseWindow`, `onTitleChanged`, `onWindowFocus`, `onWindowBlur` webview events - Added `androidOnRequestFocus`, `androidOnReceivedIcon`, `androidOnReceivedTouchIconUrl`, `androidOnJsBeforeUnload`, `androidOnReceivedLoginRequest` Android-specific webview events +- Added `disableDefaultErrorPage` Android-specific webview option - Fixed "SFSafariViewController doesn't open like a native iOS modal" [#403](https://github.com/pichillilorenzo/flutter_inappwebview/issues/403) ### BREAKING CHANGES diff --git a/README.md b/README.md index d8bde937..492c51b7 100755 --- a/README.md +++ b/README.md @@ -583,6 +583,7 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly: * `scrollbarFadingEnabled`: Define whether scrollbars will fade when the view is not scrolling. The default value is `true`. * `scrollBarFadeDuration`: Define the scrollbar fade duration in milliseconds. * `rendererPriorityPolicy`: Set the renderer priority policy for this WebView. +* `disableDefaultErrorPage`: Sets whether the default Android error page should be disabled. The default value is `false`. ##### `InAppWebView` iOS-specific options diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/FlutterWebView.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/FlutterWebView.java index 59e1e3fa..39d1c68c 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/FlutterWebView.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/FlutterWebView.java @@ -518,9 +518,9 @@ public class FlutterWebView implements PlatformView, MethodCallHandler { public void dispose() { channel.setMethodCallHandler(null); if (webView != null) { - if (Shared.activityPluginBinding != null) { - Shared.activityPluginBinding.removeActivityResultListener(webView.inAppWebViewChromeClient); - } + webView.inAppWebViewChromeClient.dispose(); + webView.inAppWebViewClient.dispose(); + webView.javaScriptBridgeInterface.dispose(); webView.setWebChromeClient(new WebChromeClient()); webView.setWebViewClient(new WebViewClient() { @Override diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewChromeClient.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewChromeClient.java index 62ac5087..4bcc60da 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewChromeClient.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewChromeClient.java @@ -602,7 +602,11 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR channel.invokeMethod("onCreateWindow", obj, new MethodChannel.Result() { @Override public void success(@Nullable Object result) { - if (result == null && InAppWebViewChromeClient.windowWebViewMessages.containsKey(windowId)) { + boolean handledByClient = false; + if (result instanceof Boolean) { + handledByClient = (boolean) result; + } + if (!handledByClient && InAppWebViewChromeClient.windowWebViewMessages.containsKey(windowId)) { InAppWebViewChromeClient.windowWebViewMessages.remove(windowId); } } @@ -1132,4 +1136,17 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR }); } } + + public void dispose() { + channel.setMethodCallHandler(null); + if (Shared.activityPluginBinding != null) { + Shared.activityPluginBinding.removeActivityResultListener(this); + } + if (inAppBrowserActivity != null) { + inAppBrowserActivity = null; + } + if (flutterWebView != null) { + flutterWebView = null; + } + } } diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java index b8155298..324220d7 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java @@ -66,6 +66,7 @@ public class InAppWebViewClient extends WebViewClient { if (webView.options.useShouldOverrideUrlLoading) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { onShouldOverrideUrlLoading( + webView, request.getUrl().toString(), request.getMethod(), request.getRequestHeaders(), @@ -74,6 +75,7 @@ public class InAppWebViewClient extends WebViewClient { request.isRedirect()); } else { onShouldOverrideUrlLoading( + webView, request.getUrl().toString(), request.getMethod(), request.getRequestHeaders(), @@ -102,14 +104,16 @@ public class InAppWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView webView, String url) { - if (((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView).options.useShouldOverrideUrlLoading) { - onShouldOverrideUrlLoading(url, "GET", null,true, false, false); + InAppWebView inAppWebView = (InAppWebView) webView; + if (inAppWebView.options.useShouldOverrideUrlLoading) { + onShouldOverrideUrlLoading(inAppWebView, url, "GET", null,true, false, false); return true; } return false; } - public void onShouldOverrideUrlLoading(final String url, final String method, final Map headers, final boolean isForMainFrame, boolean hasGesture, boolean isRedirect) { + public void onShouldOverrideUrlLoading(final InAppWebView webView, final String url, final String method, final Map headers, + final boolean isForMainFrame, boolean hasGesture, boolean isRedirect) { Map obj = new HashMap<>(); if (inAppBrowserActivity != null) obj.put("uuid", inAppBrowserActivity.uuid); @@ -132,7 +136,6 @@ public class InAppWebViewClient extends WebViewClient { if (isForMainFrame) { // There isn't any way to load an URL for a frame that is not the main frame, // so call this only on main frame. - InAppWebView webView = ((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) webView.loadUrl(url, headers); else @@ -250,11 +253,15 @@ public class InAppWebViewClient extends WebViewClient { @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { -// // Used to show instantly a custom error page -// view.stopLoading(); -// view.loadUrl("about:blank"); - ((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView).isLoading = false; + final InAppWebView webView = (InAppWebView) view; + + if (webView.options.disableDefaultErrorPage) { + webView.stopLoading(); + webView.loadUrl("about:blank"); + } + + webView.isLoading = false; previousAuthRequestFailureCount = 0; credentialsProposed = null; @@ -830,4 +837,14 @@ public class InAppWebViewClient extends WebViewClient { public void onUnhandledKeyEvent(WebView view, KeyEvent event) { } + + public void dispose() { + channel.setMethodCallHandler(null); + if (inAppBrowserActivity != null) { + inAppBrowserActivity = null; + } + if (flutterWebView != null) { + flutterWebView = null; + } + } } diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewOptions.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewOptions.java index e6a8702c..a40098fa 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewOptions.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewOptions.java @@ -96,6 +96,7 @@ public class InAppWebViewOptions implements Options { public Map rendererPriorityPolicy = new HashMap<>(); public Boolean useShouldInterceptRequest = false; public Boolean useOnRenderProcessGone = false; + public Boolean disableDefaultErrorPage = false; @Override public InAppWebViewOptions parse(Map options) { @@ -335,6 +336,9 @@ public class InAppWebViewOptions implements Options { case "useOnRenderProcessGone": useOnRenderProcessGone = (Boolean) value; break; + case "disableDefaultErrorPage": + disableDefaultErrorPage = (Boolean) value; + break; } } @@ -420,6 +424,7 @@ public class InAppWebViewOptions implements Options { options.put("rendererPriorityPolicy", rendererPriorityPolicy); options.put("useShouldInterceptRequest", useShouldInterceptRequest); options.put("useOnRenderProcessGone", useOnRenderProcessGone); + options.put("disableDefaultErrorPage", disableDefaultErrorPage); return options; } diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/JavaScriptBridgeInterface.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/JavaScriptBridgeInterface.java index b1095706..69f3cb25 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/JavaScriptBridgeInterface.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/JavaScriptBridgeInterface.java @@ -46,6 +46,10 @@ public class JavaScriptBridgeInterface { @JavascriptInterface public void _hideContextMenu() { + if (flutterWebView == null && inAppBrowserActivity == null) { + return; + } + final InAppWebView webView = (inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView; final Handler handler = new Handler(Looper.getMainLooper()); @@ -61,6 +65,10 @@ public class JavaScriptBridgeInterface { @JavascriptInterface public void _callHandler(final String handlerName, final String _callHandlerID, final String args) { + if (flutterWebView == null && inAppBrowserActivity == null) { + return; + } + final InAppWebView webView = (inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView; final Map obj = new HashMap<>(); @@ -108,4 +116,14 @@ public class JavaScriptBridgeInterface { } }); } + + public void dispose() { + channel.setMethodCallHandler(null); + if (inAppBrowserActivity != null) { + inAppBrowserActivity = null; + } + if (flutterWebView != null) { + flutterWebView = null; + } + } } diff --git a/example/.flutter-plugins-dependencies b/example/.flutter-plugins-dependencies index 092a5a51..98d606d2 100755 --- a/example/.flutter-plugins-dependencies +++ b/example/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.10/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1/","dependencies":[]}],"android":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.10/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+3/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+1/","dependencies":[]}],"windows":[],"web":[]},"dependencyGraph":[{"name":"e2e","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"permission_handler","dependencies":[]}],"date_created":"2020-06-29 16:24:39.876196","version":"1.17.4"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.10/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1/","dependencies":[]}],"android":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.10/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+3/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+1/","dependencies":[]}],"windows":[],"web":[]},"dependencyGraph":[{"name":"e2e","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"permission_handler","dependencies":[]}],"date_created":"2020-06-29 17:43:40.301350","version":"1.17.4"} \ No newline at end of file diff --git a/ios/Classes/InAppWebView.swift b/ios/Classes/InAppWebView.swift index eb4c47f2..7e59336d 100755 --- a/ios/Classes/InAppWebView.swift +++ b/ios/Classes/InAppWebView.swift @@ -1906,7 +1906,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi if (options?.useOnDownloadStart)! { let mimeType = navigationResponse.response.mimeType - if let url = navigationResponse.response.url { + if let url = navigationResponse.response.url, navigationResponse.isForMainFrame { if mimeType != nil && !mimeType!.starts(with: "text/") { onDownloadStart(url: url.absoluteString) decisionHandler(.cancel) @@ -1959,7 +1959,17 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi public func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { InAppWebView.credentialsProposed = [] - onLoadError(url: url?.absoluteString, error: error) + var urlError = url?.absoluteString + if let info = error._userInfo as? [String: Any] { + if let failingUrl = info[NSURLErrorFailingURLErrorKey] as? URL { + urlError = failingUrl.absoluteString + } + if let failingUrlString = info[NSURLErrorFailingURLStringErrorKey] as? String { + urlError = failingUrlString + } + } + + onLoadError(url: urlError, error: error) if IABController != nil { IABController!.backButton.isEnabled = canGoBack @@ -2439,7 +2449,11 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi return } else { - if result == nil, InAppWebView.windowWebViews[windowId] != nil { + var handledByClient = false + if result != nil, result is Bool { + handledByClient = result as! Bool + } + if !handledByClient, InAppWebView.windowWebViews[windowId] != nil { InAppWebView.windowWebViews.removeValue(forKey: windowId) } } diff --git a/lib/src/headless_in_app_webview.dart b/lib/src/headless_in_app_webview.dart index 3e2094de..108e087e 100644 --- a/lib/src/headless_in_app_webview.dart +++ b/lib/src/headless_in_app_webview.dart @@ -197,7 +197,7 @@ class HeadlessInAppWebView implements WebView { onConsoleMessage; @override - final Future Function(InAppWebViewController controller, + final Future Function(InAppWebViewController controller, CreateWindowRequest onCreateWindowRequest) onCreateWindow; @override diff --git a/lib/src/in_app_browser.dart b/lib/src/in_app_browser.dart index 58cb7e4a..e7b9a73d 100755 --- a/lib/src/in_app_browser.dart +++ b/lib/src/in_app_browser.dart @@ -341,10 +341,9 @@ class InAppBrowser { ///Event fired when the [InAppBrowser] webview requests the host application to create a new window, ///for example when trying to open a link with `target="_blank"` or when `window.open()` is called by JavaScript side. - ///The return type should be an [InAppBrowser] instance, a [HeadlessInAppWebView] instance or `null`. If it returns `null`, then nothing will happen. - ///If it returns an [InAppBrowser] instance, the new [InAppBrowser] will be immediately opened. - ///If it returns a [HeadlessInAppWebView] instance, the [HeadlessInAppWebView.run] method will be immediately called. - ///Remember to use the [CreateWindowRequest.windowId] to create the new WebView instance. + ///If the host application chooses to honor this request, it should return `true` from this method, create a new WebView to host the window. + ///If the host application chooses not to honor the request, it should return `false` from this method. + ///The default implementation of this method does nothing and hence returns `false`. /// ///[createWindowRequest] represents the request. /// @@ -369,7 +368,7 @@ class InAppBrowser { /// ///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1536907-webview // ignore: missing_return - Future onCreateWindow(CreateWindowRequest createWindowRequest) {} + Future onCreateWindow(CreateWindowRequest createWindowRequest) {} ///Event fired when the host application should close the given WebView and remove it from the view system if necessary. ///At this point, WebCore has stopped any loading in this window and has removed any cross-scripting ability in javascript. diff --git a/lib/src/in_app_webview.dart b/lib/src/in_app_webview.dart index 44d567c3..2b3eb56c 100755 --- a/lib/src/in_app_webview.dart +++ b/lib/src/in_app_webview.dart @@ -161,7 +161,7 @@ class InAppWebView extends StatefulWidget implements WebView { onConsoleMessage; @override - final Future Function(InAppWebViewController controller, + final Future Function(InAppWebViewController controller, CreateWindowRequest onCreateWindowRequest) onCreateWindow; @override diff --git a/lib/src/in_app_webview_controller.dart b/lib/src/in_app_webview_controller.dart index 2405fc4c..900dc362 100644 --- a/lib/src/in_app_webview_controller.dart +++ b/lib/src/in_app_webview_controller.dart @@ -222,50 +222,15 @@ class InAppWebViewController { IOSWKNavigationType.fromValue(iosWKNavigationType), iosIsForMainFrame: iosIsForMainFrame); - WebView webView; - dynamic inAppBrowserWindow; + bool result = false; if (_webview != null && _webview.onCreateWindow != null) - webView = await _webview.onCreateWindow(this, createWindowRequest); + result = await _webview.onCreateWindow(this, createWindowRequest); else if (_inAppBrowser != null) { - inAppBrowserWindow = - await _inAppBrowser.onCreateWindow(createWindowRequest); - assert( - inAppBrowserWindow is InAppBrowser || - inAppBrowserWindow is HeadlessInAppWebView, - "InAppBrowser.onCreateWindow should return an \"InAppBrowser\" instance or a \"HeadlessInAppWebView\" instance."); + result = await _inAppBrowser.onCreateWindow(createWindowRequest); } - int webViewWindowId; - - if (webView != null) { - webViewWindowId = webView.windowId; - assert( - webViewWindowId != null, - "If you are returning a WebView, then WebView.windowId should be not null. To set the " + - "WebView.windowId property, you should use the CreateWindowRequest.windowId property."); - if (webView is HeadlessInAppWebView) { - webView.run(); - } - } else if (inAppBrowserWindow != null) { - if (inAppBrowserWindow is InAppBrowser) { - webViewWindowId = inAppBrowserWindow.windowId; - assert( - webViewWindowId != null, - "If you are returning an InAppBrowser, then InAppBrowser.windowId should be not null. To set the " + - "InAppBrowser.windowId property, you should use the CreateWindowRequest.windowId property."); - inAppBrowserWindow.openUrl(url: "about:blank"); - } else if (inAppBrowserWindow is HeadlessInAppWebView) { - webViewWindowId = inAppBrowserWindow.windowId; - assert( - webViewWindowId != null, - "If you are returning a HeadlessInAppWebView, then HeadlessInAppWebView.windowId should be not null. To set the " + - "HeadlessInAppWebView.windowId property, you should use the CreateWindowRequest.windowId property."); - inAppBrowserWindow.run(); - } - } - - return webViewWindowId; + return result; case "onCloseWindow": if (_webview != null && _webview.onCloseWindow != null) _webview.onCloseWindow(this); @@ -1222,7 +1187,10 @@ class InAppWebViewController { String encoding = "utf8", String baseUrl = "about:blank", String androidHistoryUrl = "about:blank"}) async { - assert(data != null); + assert(data != null && + mimeType != null && + encoding != null && + baseUrl != null); Map args = {}; args.putIfAbsent('data', () => data); args.putIfAbsent('mimeType', () => mimeType); diff --git a/lib/src/webview.dart b/lib/src/webview.dart index ef81d8d1..b9947e60 100644 --- a/lib/src/webview.dart +++ b/lib/src/webview.dart @@ -132,10 +132,9 @@ abstract class WebView { ///Event fired when the [WebView] requests the host application to create a new window, ///for example when trying to open a link with `target="_blank"` or when `window.open()` is called by JavaScript side. - ///The return value should be a [WebView] instance or `null`. If it returns `null`, then nothing will happen. - ///If it returns an [InAppWebView] instance, when it will be added to the widget tree, it will load the request. - ///If it returns a [HeadlessInAppWebView] instance, the [HeadlessInAppWebView.run] method will be immediately called. - ///Remember to use the [CreateWindowRequest.windowId] to create the new WebView instance. + ///If the host application chooses to honor this request, it should return `true` from this method, create a new WebView to host the window. + ///If the host application chooses not to honor the request, it should return `false` from this method. + ///The default implementation of this method does nothing and hence returns `false`. /// ///[createWindowRequest] represents the request. /// @@ -150,7 +149,7 @@ abstract class WebView { ///[IOSInAppWebViewOptions.allowsPictureInPictureMediaPlayback], [IOSInAppWebViewOptions.isFraudulentWebsiteWarningEnabled], ///[IOSInAppWebViewOptions.allowsInlineMediaPlayback], [IOSInAppWebViewOptions.suppressesIncrementalRendering], [IOSInAppWebViewOptions.selectionGranularity], ///[IOSInAppWebViewOptions.ignoresViewportScaleLimits], - ///will have no effect due to a `WKWebView` limitation when creating a new window WebView: it's impossible to return a new `WKWebView` + ///will have no effect due to a `WKWebView` limitation when creating the new window WebView: it's impossible to return the new `WKWebView` ///with a different `WKWebViewConfiguration` instance (see https://developer.apple.com/documentation/webkit/wkuidelegate/1536907-webview). ///So, these options will be inherited from the caller WebView. ///Also, note that calling [InAppWebViewController.setOptions] method using the controller of the new created WebView, @@ -159,7 +158,7 @@ abstract class WebView { ///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onCreateWindow(android.webkit.WebView,%20boolean,%20boolean,%20android.os.Message) /// ///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1536907-webview - final Future Function(InAppWebViewController controller, + final Future Function(InAppWebViewController controller, CreateWindowRequest createWindowRequest) onCreateWindow; ///Event fired when the host application should close the given WebView and remove it from the view system if necessary. diff --git a/lib/src/webview_options.dart b/lib/src/webview_options.dart index 4add12bc..506dd7c0 100755 --- a/lib/src/webview_options.dart +++ b/lib/src/webview_options.dart @@ -462,7 +462,7 @@ class AndroidInAppWebViewOptions ///The default value is `true`. bool hardwareAcceleration; - ///Sets whether the WebView whether supports multiple windows. + ///Sets whether the WebView supports multiple windows. ///If set to `true`, [onCreateWindow] event must be implemented by the host application. The default value is `false`. bool supportMultipleWindows; @@ -485,7 +485,7 @@ class AndroidInAppWebViewOptions ///This is used to set the JavaScript property `window.navigator.isOnline` and generates the online/offline event as specified in HTML5, sec. 5.7.7. bool networkAvailable; - ///Specify the style of the scrollbars. The scrollbars can be overlaid or inset. + ///Specifies the style of the scrollbars. The scrollbars can be overlaid or inset. ///When inset, they add to the padding of the view. And the scrollbars can be drawn inside the padding area or on the edge of the view. ///For example, if a view has a background drawable and you want to draw the scrollbars inside the padding specified by the drawable, ///you can use SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to appear at the edge of the view, ignoring the padding, @@ -493,23 +493,27 @@ class AndroidInAppWebViewOptions ///The default value is [AndroidScrollBarStyle.SCROLLBARS_INSIDE_OVERLAY]. AndroidScrollBarStyle scrollBarStyle; - ///Set the position of the vertical scroll bar. + ///Sets the position of the vertical scroll bar. ///The default value is [AndroidVerticalScrollbarPosition.SCROLLBAR_POSITION_DEFAULT]. AndroidVerticalScrollbarPosition verticalScrollbarPosition; ///Defines the delay in milliseconds that a scrollbar waits before fade out. int scrollBarDefaultDelayBeforeFade; - ///Define whether scrollbars will fade when the view is not scrolling. + ///Defines whether scrollbars will fade when the view is not scrolling. ///The default value is `true`. bool scrollbarFadingEnabled; - ///Define the scrollbar fade duration in milliseconds. + ///Defines the scrollbar fade duration in milliseconds. int scrollBarFadeDuration; - ///Set the renderer priority policy for this WebView. + ///Sets the renderer priority policy for this WebView. RendererPriorityPolicy rendererPriorityPolicy; + ///Sets whether the default Android error page should be disabled. + ///The default value is `false`. + bool disableDefaultErrorPage; + AndroidInAppWebViewOptions({ this.textZoom = 100, this.clearSessionCache = false, @@ -563,6 +567,7 @@ class AndroidInAppWebViewOptions this.scrollbarFadingEnabled = true, this.scrollBarFadeDuration, this.rendererPriorityPolicy, + this.disableDefaultErrorPage, }); @override @@ -618,7 +623,8 @@ class AndroidInAppWebViewOptions "scrollBarDefaultDelayBeforeFade": scrollBarDefaultDelayBeforeFade, "scrollbarFadingEnabled": scrollbarFadingEnabled, "scrollBarFadeDuration": scrollBarFadeDuration, - "rendererPriorityPolicy": rendererPriorityPolicy?.toMap() + "rendererPriorityPolicy": rendererPriorityPolicy?.toMap(), + "disableDefaultErrorPage": disableDefaultErrorPage }; } @@ -686,6 +692,7 @@ class AndroidInAppWebViewOptions options.scrollBarFadeDuration = map["scrollBarFadeDuration"]; options.rendererPriorityPolicy = RendererPriorityPolicy.fromMap( map["rendererPriorityPolicy"]?.cast()); + options.disableDefaultErrorPage = map["disableDefaultErrorPage"]; return options; }