From ebdcef63935248dab4ee4eb756d1d1879a462797 Mon Sep 17 00:00:00 2001 From: Lorenzo Pichilli Date: Sun, 8 May 2022 15:08:34 +0200 Subject: [PATCH] deprecated onLoadResourceCustomScheme for onLoadResourceWithCustomScheme event --- .../webview/WebViewChannelDelegate.java | 20 +-- .../in_app_webview/InAppWebViewClient.java | 125 ++++++--------- .../integration_test/in_app_webview/main.dart | 4 +- ... on_load_resource_with_custom_scheme.dart} | 10 +- .../InAppWebView/CustomSchemeHandler.swift | 39 +++-- ios/Classes/InAppWebView/InAppWebView.swift | 11 +- .../InAppWebView/WebViewChannelDelegate.swift | 8 +- ios/Classes/Types/WebResourceRequest.swift | 14 ++ ios/Classes/Types/WebResourceResponse.swift | 9 ++ lib/src/in_app_browser/in_app_browser.dart | 146 +++++++++++++----- .../headless_in_app_webview.dart | 11 +- lib/src/in_app_webview/in_app_webview.dart | 9 +- .../in_app_webview_controller.dart | 41 +++-- lib/src/in_app_webview/webview.dart | 15 +- 14 files changed, 276 insertions(+), 186 deletions(-) rename example/integration_test/in_app_webview/{on_load_resource_custom_scheme.dart => on_load_resource_with_custom_scheme.dart} (86%) diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/WebViewChannelDelegate.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/WebViewChannelDelegate.java index 3a3f4a79..1285ec00 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/WebViewChannelDelegate.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/WebViewChannelDelegate.java @@ -1102,7 +1102,7 @@ public class WebViewChannelDelegate extends ChannelDelegateImpl { channel.invokeMethod("onReceivedLoginRequest", obj); } - public static class LoadResourceCustomSchemeCallback extends BaseCallbackResultImpl { + public static class LoadResourceWithCustomSchemeCallback extends BaseCallbackResultImpl { @Nullable @Override public CustomSchemeResponse decodeResult(@Nullable Object obj) { @@ -1110,33 +1110,33 @@ public class WebViewChannelDelegate extends ChannelDelegateImpl { } } - public void onLoadResourceCustomScheme(String url, @NonNull LoadResourceCustomSchemeCallback callback) { + public void onLoadResourceWithCustomScheme(WebResourceRequestExt request, @NonNull LoadResourceWithCustomSchemeCallback callback) { MethodChannel channel = getChannel(); if (channel == null) { callback.defaultBehaviour(null); return; } Map obj = new HashMap<>(); - obj.put("url", url); - channel.invokeMethod("onLoadResourceCustomScheme", obj, callback); + obj.put("request", request.toMap()); + channel.invokeMethod("onLoadResourceWithCustomScheme", obj, callback); } - public static class SyncLoadResourceCustomSchemeCallback extends SyncBaseCallbackResultImpl { + public static class SyncLoadResourceWithCustomSchemeCallback extends SyncBaseCallbackResultImpl { @Nullable @Override public CustomSchemeResponse decodeResult(@Nullable Object obj) { - return (new LoadResourceCustomSchemeCallback()).decodeResult(obj); + return (new LoadResourceWithCustomSchemeCallback()).decodeResult(obj); } } @Nullable - public CustomSchemeResponse onLoadResourceCustomScheme(String url) throws InterruptedException { + public CustomSchemeResponse onLoadResourceWithCustomScheme(WebResourceRequestExt request) throws InterruptedException { MethodChannel channel = getChannel(); if (channel == null) return null; final Map obj = new HashMap<>(); - obj.put("url", url); - final SyncLoadResourceCustomSchemeCallback callback = new SyncLoadResourceCustomSchemeCallback(); - return Util.invokeMethodAndWaitResult(channel, "onLoadResourceCustomScheme", obj, callback); + obj.put("request", request.toMap()); + final SyncLoadResourceWithCustomSchemeCallback callback = new SyncLoadResourceWithCustomSchemeCallback(); + return Util.invokeMethodAndWaitResult(channel, "onLoadResourceWithCustomScheme", obj, callback); } public static class ShouldInterceptRequestCallback extends BaseCallbackResultImpl { diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/InAppWebViewClient.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/InAppWebViewClient.java index ec952190..62bf88ed 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/InAppWebViewClient.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/InAppWebViewClient.java @@ -52,7 +52,6 @@ import com.pichillilorenzo.flutter_inappwebview.webview.WebViewChannelDelegate; import java.io.ByteArrayInputStream; import java.net.URI; import java.net.URISyntaxException; -import java.net.URL; import java.util.List; import java.util.Map; import java.util.regex.Matcher; @@ -442,10 +441,9 @@ public class InAppWebViewClient extends WebViewClient { final String host = uri.getHost(); final String protocol = uri.getScheme(); - final String realm = null; final int port = uri.getPort(); - URLProtectionSpace protectionSpace = new URLProtectionSpace(host, protocol, realm, port, sslError.getCertificate(), sslError); + URLProtectionSpace protectionSpace = new URLProtectionSpace(host, protocol, null, port, sslError.getCertificate(), sslError); ServerTrustChallenge challenge = new ServerTrustChallenge(protectionSpace); final InAppWebView webView = (InAppWebView) view; @@ -502,10 +500,9 @@ public class InAppWebViewClient extends WebViewClient { final String host = request.getHost(); final String protocol = uri.getScheme(); - final String realm = null; final int port = request.getPort(); - URLProtectionSpace protectionSpace = new URLProtectionSpace(host, protocol, realm, port, view.getCertificate(), null); + URLProtectionSpace protectionSpace = new URLProtectionSpace(host, protocol, null, port, view.getCertificate(), null); ClientCertChallenge challenge = new ClientCertChallenge(protectionSpace, request.getPrincipals(), request.getKeyTypes()); final InAppWebView webView = (InAppWebView) view; @@ -620,36 +617,48 @@ public class InAppWebViewClient extends WebViewClient { } } - @Override - public WebResourceResponse shouldInterceptRequest(WebView view, final String url) { + public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequestExt request) { final InAppWebView webView = (InAppWebView) view; if (webView.customSettings.useShouldInterceptRequest) { - return onShouldInterceptRequest(view, url); - } - - URI uri; - try { - uri = new URI(url); - } catch (URISyntaxException uriExpection) { - String[] urlSplitted = url.split(":"); - String scheme = urlSplitted[0]; - try { - URL tempUrl = new URL(url.replace(scheme, "https")); - uri = new URI(scheme, tempUrl.getUserInfo(), tempUrl.getHost(), tempUrl.getPort(), tempUrl.getPath(), tempUrl.getQuery(), tempUrl.getRef()); - } catch (Exception e) { - e.printStackTrace(); - return null; + WebResourceResponseExt response = null; + if (webView.channelDelegate != null) { + try { + response = webView.channelDelegate.shouldInterceptRequest(request); + } catch (InterruptedException e) { + e.printStackTrace(); + return null; + } } + + if (response != null) { + String contentType = response.getContentType(); + String contentEncoding = response.getContentEncoding(); + byte[] data = response.getData(); + Map responseHeaders = response.getHeaders(); + Integer statusCode = response.getStatusCode(); + String reasonPhrase = response.getReasonPhrase(); + + ByteArrayInputStream inputStream = (data != null) ? new ByteArrayInputStream(data) : null; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && statusCode != null && reasonPhrase != null) { + return new WebResourceResponse(contentType, contentEncoding, statusCode, reasonPhrase, responseHeaders, inputStream); + } else { + return new WebResourceResponse(contentType, contentEncoding, inputStream); + } + } + + return null; } - String scheme = uri.getScheme(); + final String url = request.getUrl().toString(); + String scheme = request.getUrl().getScheme(); if (webView.customSettings.resourceCustomSchemes != null && webView.customSettings.resourceCustomSchemes.contains(scheme)) { CustomSchemeResponse customSchemeResponse = null; if (webView.channelDelegate != null) { try { - customSchemeResponse = webView.channelDelegate.onLoadResourceCustomScheme(url); + customSchemeResponse = webView.channelDelegate.onLoadResourceWithCustomScheme(request); } catch (InterruptedException e) { e.printStackTrace(); return null; @@ -665,8 +674,8 @@ public class InAppWebViewClient extends WebViewClient { } if (response != null) return response; - return new WebResourceResponse(customSchemeResponse.getContentType(), - customSchemeResponse.getContentType(), + return new WebResourceResponse(customSchemeResponse.getContentType(), + customSchemeResponse.getContentType(), new ByteArrayInputStream(customSchemeResponse.getData())); } } @@ -682,62 +691,20 @@ public class InAppWebViewClient extends WebViewClient { return response; } + @Override + public WebResourceResponse shouldInterceptRequest(WebView view, final String url) { + WebResourceRequestExt requestExt = new WebResourceRequestExt( + Uri.parse(url), null, false, + false, true, "GET" + ); + return shouldInterceptRequest(view, requestExt); + } + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { - final InAppWebView webView = (InAppWebView) view; - - String url = request.getUrl().toString(); - - if (webView.customSettings.useShouldInterceptRequest) { - return onShouldInterceptRequest(view, request); - } - - return shouldInterceptRequest(view, url); - } - - public WebResourceResponse onShouldInterceptRequest(WebView view, Object request) { - final InAppWebView webView = (InAppWebView) view; - - WebResourceRequestExt requestExt; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && request instanceof WebResourceRequest) { - WebResourceRequest webResourceRequest = (WebResourceRequest) request; - requestExt = WebResourceRequestExt.fromWebResourceRequest(webResourceRequest); - } else { - requestExt = new WebResourceRequestExt( - Uri.parse((String) request), null, false, - false, true, "GET" - ); - } - - WebResourceResponseExt response = null; - if (webView.channelDelegate != null) { - try { - response = webView.channelDelegate.shouldInterceptRequest(requestExt); - } catch (InterruptedException e) { - e.printStackTrace(); - return null; - } - } - - if (response != null) { - String contentType = response.getContentType(); - String contentEncoding = response.getContentEncoding(); - byte[] data = response.getData(); - Map responseHeaders = response.getHeaders(); - Integer statusCode = response.getStatusCode(); - String reasonPhrase = response.getReasonPhrase(); - - ByteArrayInputStream inputStream = (data != null) ? new ByteArrayInputStream(data) : null; - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && statusCode != null && reasonPhrase != null) { - return new WebResourceResponse(contentType, contentEncoding, statusCode, reasonPhrase, responseHeaders, inputStream); - } else { - return new WebResourceResponse(contentType, contentEncoding, inputStream); - } - } - - return null; + WebResourceRequestExt requestExt = WebResourceRequestExt.fromWebResourceRequest(request); + return shouldInterceptRequest(view, requestExt); } @Override diff --git a/example/integration_test/in_app_webview/main.dart b/example/integration_test/in_app_webview/main.dart index 0ef7c7a6..0f136e75 100644 --- a/example/integration_test/in_app_webview/main.dart +++ b/example/integration_test/in_app_webview/main.dart @@ -42,7 +42,7 @@ import 'on_js_before_unload.dart'; import 'on_received_error.dart'; import 'on_received_http_error.dart'; import 'on_load_resource.dart'; -import 'on_load_resource_custom_scheme.dart'; +import 'on_load_resource_with_custom_scheme.dart'; import 'on_navigation_response.dart'; import 'on_page_commit_visible.dart'; import 'on_permission_request.dart'; @@ -110,7 +110,7 @@ void main() { onDownloadStartRequest(); javascriptDialogs(); onReceivedHttpError(); - onLoadResourceCustomScheme(); + onLoadResourceWithCustomScheme(); onLoadResource(); onUpdateVisitedHistory(); onProgressChanged(); diff --git a/example/integration_test/in_app_webview/on_load_resource_custom_scheme.dart b/example/integration_test/in_app_webview/on_load_resource_with_custom_scheme.dart similarity index 86% rename from example/integration_test/in_app_webview/on_load_resource_custom_scheme.dart rename to example/integration_test/in_app_webview/on_load_resource_with_custom_scheme.dart index b961105c..827f23c6 100644 --- a/example/integration_test/in_app_webview/on_load_resource_custom_scheme.dart +++ b/example/integration_test/in_app_webview/on_load_resource_with_custom_scheme.dart @@ -6,7 +6,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:flutter_test/flutter_test.dart'; -void onLoadResourceCustomScheme() { +void onLoadResourceWithCustomScheme() { final shouldSkip = kIsWeb ? true : ![ @@ -15,7 +15,7 @@ void onLoadResourceCustomScheme() { TargetPlatform.macOS, ].contains(defaultTargetPlatform); - testWidgets('onLoadResourceCustomScheme', (WidgetTester tester) async { + testWidgets('onLoadResourceWithCustomScheme', (WidgetTester tester) async { final Completer controllerCompleter = Completer(); final Completer imageLoaded = Completer(); @@ -38,10 +38,10 @@ void onLoadResourceCustomScheme() { imageLoaded.complete(); }); }, - onLoadResourceCustomScheme: (controller, url) async { - if (url.scheme == "my-special-custom-scheme") { + onLoadResourceWithCustomScheme: (controller, request) async { + if (request.url.scheme == "my-special-custom-scheme") { var bytes = await rootBundle.load("test_assets/" + - url + request.url .toString() .replaceFirst("my-special-custom-scheme://", "", 0)); var response = CustomSchemeResponse( diff --git a/ios/Classes/InAppWebView/CustomSchemeHandler.swift b/ios/Classes/InAppWebView/CustomSchemeHandler.swift index 2c1546b1..a1c3fdc7 100755 --- a/ios/Classes/InAppWebView/CustomSchemeHandler.swift +++ b/ios/Classes/InAppWebView/CustomSchemeHandler.swift @@ -16,27 +16,26 @@ public class CustomSchemeHandler : NSObject, WKURLSchemeHandler { public func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) { schemeHandlers[urlSchemeTask.hash] = urlSchemeTask let inAppWebView = webView as! InAppWebView - if let url = urlSchemeTask.request.url { - let callback = WebViewChannelDelegate.LoadResourceCustomSchemeCallback() - callback.nonNullSuccess = { (response: CustomSchemeResponse) in - if (self.schemeHandlers[urlSchemeTask.hash] != nil) { - let urlResponse = URLResponse(url: url, mimeType: response.contentType, expectedContentLength: -1, textEncodingName: response.contentEncoding) - urlSchemeTask.didReceive(urlResponse) - urlSchemeTask.didReceive(response.data) - urlSchemeTask.didFinish() - self.schemeHandlers.removeValue(forKey: urlSchemeTask.hash) - } - return false - } - callback.error = { (code: String, message: String?, details: Any?) in - print(code + ", " + (message ?? "")) - } - - if let channelDelegate = inAppWebView.channelDelegate { - channelDelegate.onLoadResourceCustomScheme(url: url, callback: callback) - } else { - callback.defaultBehaviour(nil) + let request = WebResourceRequest.init(fromURLRequest: urlSchemeTask.request) + let callback = WebViewChannelDelegate.LoadResourceWithCustomSchemeCallback() + callback.nonNullSuccess = { (response: CustomSchemeResponse) in + if (self.schemeHandlers[urlSchemeTask.hash] != nil) { + let urlResponse = URLResponse(url: request.url, mimeType: response.contentType, expectedContentLength: -1, textEncodingName: response.contentEncoding) + urlSchemeTask.didReceive(urlResponse) + urlSchemeTask.didReceive(response.data) + urlSchemeTask.didFinish() + self.schemeHandlers.removeValue(forKey: urlSchemeTask.hash) } + return false + } + callback.error = { (code: String, message: String?, details: Any?) in + print(code + ", " + (message ?? "")) + } + + if let channelDelegate = inAppWebView.channelDelegate { + channelDelegate.onLoadResourceWithCustomScheme(request: request, callback: callback) + } else { + callback.defaultBehaviour(nil) } } diff --git a/ios/Classes/InAppWebView/InAppWebView.swift b/ios/Classes/InAppWebView/InAppWebView.swift index b2e89aeb..d0ec35b6 100755 --- a/ios/Classes/InAppWebView/InAppWebView.swift +++ b/ios/Classes/InAppWebView/InAppWebView.swift @@ -1695,15 +1695,8 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) { if let response = navigationResponse.response as? HTTPURLResponse, response.statusCode >= 400 { - let request = WebResourceRequest(url: response.url ?? URL(string: "about:blank")!, - headers: response.allHeaderFields, - isForMainFrame: navigationResponse.isForMainFrame) - let errorResponse = WebResourceResponse(contentType: response.mimeType ?? "", - contentEncoding: response.textEncodingName ?? "", - data: nil, - headers: response.allHeaderFields, - statusCode: response.statusCode, - reasonPhrase: nil) + let request = WebResourceRequest.init(fromWKNavigationResponse: navigationResponse) + let errorResponse = WebResourceResponse.init(fromWKNavigationResponse: navigationResponse) channelDelegate?.onReceivedHttpError(request: request, errorResponse: errorResponse) } diff --git a/ios/Classes/InAppWebView/WebViewChannelDelegate.swift b/ios/Classes/InAppWebView/WebViewChannelDelegate.swift index e2975986..b1cb5fa3 100644 --- a/ios/Classes/InAppWebView/WebViewChannelDelegate.swift +++ b/ios/Classes/InAppWebView/WebViewChannelDelegate.swift @@ -947,7 +947,7 @@ public class WebViewChannelDelegate : ChannelDelegate { channel?.invokeMethod("onPageCommitVisible", arguments: arguments) } - public class LoadResourceCustomSchemeCallback : BaseCallbackResult { + public class LoadResourceWithCustomSchemeCallback : BaseCallbackResult { override init() { super.init() self.decodeResult = { (obj: Any?) in @@ -956,13 +956,13 @@ public class WebViewChannelDelegate : ChannelDelegate { } } - public func onLoadResourceCustomScheme(url: URL, callback: LoadResourceCustomSchemeCallback) { + public func onLoadResourceWithCustomScheme(request: WebResourceRequest, callback: LoadResourceWithCustomSchemeCallback) { guard let channel = channel else { callback.defaultBehaviour(nil) return } - let arguments: [String: Any?] = ["url": url.absoluteString] - channel.invokeMethod("onLoadResourceCustomScheme", arguments: arguments, callback: callback) + let arguments: [String: Any?] = ["request": request.toMap()] + channel.invokeMethod("onLoadResourceWithCustomScheme", arguments: arguments, callback: callback) } public class CallJsHandlerCallback : BaseCallbackResult { diff --git a/ios/Classes/Types/WebResourceRequest.swift b/ios/Classes/Types/WebResourceRequest.swift index 7bdb3df2..ad7635c4 100644 --- a/ios/Classes/Types/WebResourceRequest.swift +++ b/ios/Classes/Types/WebResourceRequest.swift @@ -6,6 +6,7 @@ // import Foundation +import WebKit public class WebResourceRequest: NSObject { var url: URL @@ -26,6 +27,19 @@ public class WebResourceRequest: NSObject { self.isForMainFrame = isForMainFrame } + public init(fromURLRequest: URLRequest) { + self.url = fromURLRequest.url ?? URL(string: "about:blank")! + self.headers = fromURLRequest.allHTTPHeaderFields + self.method = fromURLRequest.httpMethod ?? "GET" + } + + public init(fromWKNavigationResponse: WKNavigationResponse) { + let response = fromWKNavigationResponse.response as? HTTPURLResponse + self.url = response?.url ?? URL(string: "about:blank")! + self.headers = response?.allHeaderFields + self.isForMainFrame = fromWKNavigationResponse.isForMainFrame + } + public func toMap () -> [String:Any?] { return [ "url": url.absoluteString, diff --git a/ios/Classes/Types/WebResourceResponse.swift b/ios/Classes/Types/WebResourceResponse.swift index b7f1f55f..4fcf13e7 100644 --- a/ios/Classes/Types/WebResourceResponse.swift +++ b/ios/Classes/Types/WebResourceResponse.swift @@ -6,6 +6,7 @@ // import Foundation +import WebKit public class WebResourceResponse: NSObject { var contentType: String @@ -25,6 +26,14 @@ public class WebResourceResponse: NSObject { self.reasonPhrase = reasonPhrase } + public init(fromWKNavigationResponse: WKNavigationResponse) { + let response = fromWKNavigationResponse.response as? HTTPURLResponse + self.contentType = response?.mimeType ?? "" + self.contentEncoding = response?.textEncodingName ?? "" + self.headers = response?.allHeaderFields + self.statusCode = response?.statusCode + } + public func toMap () -> [String:Any?] { return [ "contentType": contentType, diff --git a/lib/src/in_app_browser/in_app_browser.dart b/lib/src/in_app_browser/in_app_browser.dart index 4c60483c..9da0c544 100755 --- a/lib/src/in_app_browser/in_app_browser.dart +++ b/lib/src/in_app_browser/in_app_browser.dart @@ -431,7 +431,9 @@ class InAppBrowser { ///- Android native WebView ([Official API - WebViewClient.shouldOverrideUrlLoading](https://developer.android.com/reference/android/webkit/WebViewClient#shouldOverrideUrlLoading(android.webkit.WebView,%20java.lang.String))) ///- iOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455641-webview)) Future? shouldOverrideUrlLoading( - NavigationAction navigationAction) {} + NavigationAction navigationAction) { + return null; + } ///Event fired when the [InAppBrowser] webview loads a resource. /// @@ -469,16 +471,22 @@ class InAppBrowser { ///- iOS void onDownloadStartRequest(DownloadStartRequest downloadStartRequest) {} - ///Event fired when the [InAppBrowser] webview finds the `custom-scheme` while loading a resource. Here you can handle the url request and return a [CustomSchemeResponse] to load a specific resource encoded to `base64`. - /// - ///[scheme] represents the scheme of the url. - /// - ///[url] represents the url of the request. + ///Use [onLoadResourceWithCustomScheme] instead. + @Deprecated('Use onLoadResourceWithCustomScheme instead') + Future? onLoadResourceCustomScheme(Uri url) { + return null; + } + + ///Event fired when the [InAppBrowser] webview finds the `custom-scheme` while loading a resource. + ///Here you can handle the url [request] and return a [CustomSchemeResponse] to load a specific resource encoded to `base64`. /// ///**Supported Platforms/Implementations**: ///- Android native WebView ///- iOS ([Official API - WKURLSchemeHandler](https://developer.apple.com/documentation/webkit/wkurlschemehandler)) - Future? onLoadResourceCustomScheme(Uri url) {} + Future? onLoadResourceWithCustomScheme( + WebResourceRequest request) { + return null; + } ///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. @@ -511,7 +519,9 @@ class InAppBrowser { ///**Supported Platforms/Implementations**: ///- Android native WebView ([Official API - WebChromeClient.onCreateWindow](https://developer.android.com/reference/android/webkit/WebChromeClient#onCreateWindow(android.webkit.WebView,%20boolean,%20boolean,%20android.os.Message))) ///- iOS ([Official API - WKUIDelegate.webView](https://developer.apple.com/documentation/webkit/wkuidelegate/1536907-webview)) - Future? onCreateWindow(CreateWindowAction createWindowAction) {} + Future? onCreateWindow(CreateWindowAction createWindowAction) { + return null; + } ///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. @@ -545,7 +555,9 @@ class InAppBrowser { ///**Supported Platforms/Implementations**: ///- Android native WebView ([Official API - WebChromeClient.onJsAlert](https://developer.android.com/reference/android/webkit/WebChromeClient#onJsAlert(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20android.webkit.JsResult))) ///- iOS ([Official API - WKUIDelegate.webView](https://developer.apple.com/documentation/webkit/wkuidelegate/1537406-webview)) - Future? onJsAlert(JsAlertRequest jsAlertRequest) {} + Future? onJsAlert(JsAlertRequest jsAlertRequest) { + return null; + } ///Event fired when javascript calls the `confirm()` method to display a confirm dialog. ///If [JsConfirmResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog. @@ -555,7 +567,9 @@ class InAppBrowser { ///**Supported Platforms/Implementations**: ///- Android native WebView ([Official API - WebChromeClient.onJsConfirm](https://developer.android.com/reference/android/webkit/WebChromeClient#onJsConfirm(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20android.webkit.JsResult))) ///- iOS ([Official API - WKUIDelegate.webView](https://developer.apple.com/documentation/webkit/wkuidelegate/1536489-webview)) - Future? onJsConfirm(JsConfirmRequest jsConfirmRequest) {} + Future? onJsConfirm(JsConfirmRequest jsConfirmRequest) { + return null; + } ///Event fired when javascript calls the `prompt()` method to display a prompt dialog. ///If [JsPromptResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog. @@ -565,7 +579,9 @@ class InAppBrowser { ///**Supported Platforms/Implementations**: ///- Android native WebView ([Official API - WebChromeClient.onJsPrompt](https://developer.android.com/reference/android/webkit/WebChromeClient#onJsPrompt(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20java.lang.String,%20android.webkit.JsPromptResult))) ///- iOS ([Official API - WKUIDelegate.webView](https://developer.apple.com/documentation/webkit/wkuidelegate/1538086-webview)) - Future? onJsPrompt(JsPromptRequest jsPromptRequest) {} + Future? onJsPrompt(JsPromptRequest jsPromptRequest) { + return null; + } ///Event fired when the WebView received an HTTP authentication request. The default behavior is to cancel the request. /// @@ -575,7 +591,9 @@ class InAppBrowser { ///- Android native WebView ([Official API - WebViewClient.onReceivedHttpAuthRequest](https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedHttpAuthRequest(android.webkit.WebView,%20android.webkit.HttpAuthHandler,%20java.lang.String,%20java.lang.String))) ///- iOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455638-webview)) Future? onReceivedHttpAuthRequest( - URLAuthenticationChallenge challenge) {} + URLAuthenticationChallenge challenge) { + return null; + } ///Event fired when the WebView need to perform server trust authentication (certificate validation). ///The host application must return either [ServerTrustAuthResponse] instance with [ServerTrustAuthResponseAction.CANCEL] or [ServerTrustAuthResponseAction.PROCEED]. @@ -586,7 +604,9 @@ class InAppBrowser { ///- Android native WebView ([Official API - WebViewClient.onReceivedSslError](https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedSslError(android.webkit.WebView,%20android.webkit.SslErrorHandler,%20android.net.http.SslError))) ///- iOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455638-webview)) Future? onReceivedServerTrustAuthRequest( - URLAuthenticationChallenge challenge) {} + URLAuthenticationChallenge challenge) { + return null; + } ///Notify the host application to handle an SSL client certificate request. ///Webview stores the response in memory (for the life of the application) if [ClientCertResponseAction.PROCEED] or [ClientCertResponseAction.CANCEL] @@ -599,7 +619,9 @@ class InAppBrowser { ///- Android native WebView ([Official API - WebViewClient.onReceivedClientCertRequest](https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedClientCertRequest(android.webkit.WebView,%20android.webkit.ClientCertRequest))) ///- iOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455638-webview)) Future? onReceivedClientCertRequest( - URLAuthenticationChallenge challenge) {} + URLAuthenticationChallenge challenge) { + return null; + } ///Event fired as find-on-page operations progress. ///The listener may be notified multiple times while the operation is underway, and the [numberOfMatches] value should not be considered final unless [isDoneCounting] is true. @@ -630,7 +652,9 @@ class InAppBrowser { ///**Supported Platforms/Implementations**: ///- Android native WebView ///- iOS - Future? shouldInterceptAjaxRequest(AjaxRequest ajaxRequest) {} + Future? shouldInterceptAjaxRequest(AjaxRequest ajaxRequest) { + return null; + } ///Event fired whenever the `readyState` attribute of an `XMLHttpRequest` changes. ///It gives the host application a chance to abort the request. @@ -646,7 +670,9 @@ class InAppBrowser { ///**Supported Platforms/Implementations**: ///- Android native WebView ///- iOS - Future? onAjaxReadyStateChange(AjaxRequest ajaxRequest) {} + Future? onAjaxReadyStateChange(AjaxRequest ajaxRequest) { + return null; + } ///Event fired as an `XMLHttpRequest` progress. ///It gives the host application a chance to abort the request. @@ -662,7 +688,9 @@ class InAppBrowser { ///**Supported Platforms/Implementations**: ///- Android native WebView ///- iOS - Future? onAjaxProgress(AjaxRequest ajaxRequest) {} + Future? onAjaxProgress(AjaxRequest ajaxRequest) { + return null; + } ///Event fired when a request is sent to a server through [Fetch API](https://developer.mozilla.org/it/docs/Web/API/Fetch_API). ///It gives the host application a chance to take control over the request before sending it. @@ -679,7 +707,9 @@ class InAppBrowser { ///- Android native WebView ///- iOS Future? shouldInterceptFetchRequest( - FetchRequest fetchRequest) {} + FetchRequest fetchRequest) { + return null; + } ///Event fired when the host application updates its visited links database. ///This event is also fired when the navigation state of the [InAppWebView] changes through the usage of @@ -777,7 +807,9 @@ class InAppBrowser { ///Use [onSafeBrowsingHit] instead. @Deprecated("Use onSafeBrowsingHit instead") Future? androidOnSafeBrowsingHit( - Uri url, SafeBrowsingThreat? threatType) {} + Uri url, SafeBrowsingThreat? threatType) { + return null; + } ///Event fired when the WebView notifies that a loading URL has been flagged by Safe Browsing. ///The default behavior is to show an interstitial to the user, with the reporting checkbox visible. @@ -791,12 +823,16 @@ class InAppBrowser { ///**Supported Platforms/Implementations**: ///- Android native WebView ([Official API - WebViewClient.onSafeBrowsingHit](https://developer.android.com/reference/android/webkit/WebViewClient#onSafeBrowsingHit(android.webkit.WebView,%20android.webkit.WebResourceRequest,%20int,%20android.webkit.SafeBrowsingResponse))) Future? onSafeBrowsingHit( - Uri url, SafeBrowsingThreat? threatType) {} + Uri url, SafeBrowsingThreat? threatType) { + return null; + } ///Use [onPermissionRequest] instead. @Deprecated("Use onPermissionRequest instead") Future? androidOnPermissionRequest( - String origin, List resources) {} + String origin, List resources) { + return null; + } ///Event fired when the WebView is requesting permission to access the specified resources and the permission currently isn't granted or denied. /// @@ -812,12 +848,16 @@ class InAppBrowser { ///- Android native WebView ([Official API - WebChromeClient.onPermissionRequest](https://developer.android.com/reference/android/webkit/WebChromeClient#onPermissionRequest(android.webkit.PermissionRequest))) ///- iOS Future? onPermissionRequest( - PermissionRequest permissionRequest) {} + PermissionRequest permissionRequest) { + return null; + } ///Use [onGeolocationPermissionsShowPrompt] instead. @Deprecated("Use onGeolocationPermissionsShowPrompt instead") Future? - androidOnGeolocationPermissionsShowPrompt(String origin) {} + androidOnGeolocationPermissionsShowPrompt(String origin) { + return null; + } ///Event that notifies the host application that web content from the specified origin is attempting to use the Geolocation API, but no permission state is currently set for that origin. ///Note that for applications targeting Android N and later SDKs (API level > `Build.VERSION_CODES.M`) this method is only called for requests originating from secure origins such as https. @@ -828,7 +868,9 @@ class InAppBrowser { ///**Supported Platforms/Implementations**: ///- Android native WebView ([Official API - WebChromeClient.onGeolocationPermissionsShowPrompt](https://developer.android.com/reference/android/webkit/WebChromeClient#onGeolocationPermissionsShowPrompt(java.lang.String,%20android.webkit.GeolocationPermissions.Callback))) Future? - onGeolocationPermissionsShowPrompt(String origin) {} + onGeolocationPermissionsShowPrompt(String origin) { + return null; + } ///Use [onGeolocationPermissionsHidePrompt] instead. @Deprecated("Use onGeolocationPermissionsHidePrompt instead") @@ -844,7 +886,9 @@ class InAppBrowser { ///Use [shouldInterceptRequest] instead. @Deprecated("Use shouldInterceptRequest instead") Future? androidShouldInterceptRequest( - WebResourceRequest request) {} + WebResourceRequest request) { + return null; + } ///Notify the host application of a resource request and allow the application to return the data. ///If the return value is `null`, the WebView will continue to load the resource as usual. @@ -863,12 +907,16 @@ class InAppBrowser { ///**Supported Platforms/Implementations**: ///- Android native WebView ([Official API - WebViewClient.shouldInterceptRequest](https://developer.android.com/reference/android/webkit/WebViewClient#shouldInterceptRequest(android.webkit.WebView,%20android.webkit.WebResourceRequest))) Future? shouldInterceptRequest( - WebResourceRequest request) {} + WebResourceRequest request) { + return null; + } ///Use [onRenderProcessUnresponsive] instead. @Deprecated("Use onRenderProcessUnresponsive instead") Future? androidOnRenderProcessUnresponsive( - Uri? url) {} + Uri? url) { + return null; + } ///Event called when the renderer currently associated with the WebView becomes unresponsive as a result of a long running blocking task such as the execution of JavaScript. /// @@ -889,12 +937,16 @@ class InAppBrowser { /// ///**Supported Platforms/Implementations**: ///- Android native WebView ([Official API - WebViewRenderProcessClient.onRenderProcessUnresponsive](https://developer.android.com/reference/android/webkit/WebViewRenderProcessClient#onRenderProcessUnresponsive(android.webkit.WebView,%20android.webkit.WebViewRenderProcess))) - Future? onRenderProcessUnresponsive(Uri? url) {} + Future? onRenderProcessUnresponsive(Uri? url) { + return null; + } ///Use [onRenderProcessResponsive] instead. @Deprecated("Use onRenderProcessResponsive instead") Future? androidOnRenderProcessResponsive( - Uri? url) {} + Uri? url) { + return null; + } ///Event called once when an unresponsive renderer currently associated with the WebView becomes responsive. /// @@ -908,7 +960,9 @@ class InAppBrowser { /// ///**Supported Platforms/Implementations**: ///- Android native WebView ([Official API - WebViewRenderProcessClient.onRenderProcessResponsive](https://developer.android.com/reference/android/webkit/WebViewRenderProcessClient#onRenderProcessResponsive(android.webkit.WebView,%20android.webkit.WebViewRenderProcess))) - Future? onRenderProcessResponsive(Uri? url) {} + Future? onRenderProcessResponsive(Uri? url) { + return null; + } ///Use [onRenderProcessGone] instead. @Deprecated("Use onRenderProcessGone instead") @@ -928,13 +982,17 @@ class InAppBrowser { ///Use [onFormResubmission] instead. @Deprecated('Use onFormResubmission instead') - Future? androidOnFormResubmission(Uri? url) {} + Future? androidOnFormResubmission(Uri? url) { + return null; + } ///As the host application if the browser should resend data as the requested page was a result of a POST. The default is to not resend the data. /// ///**Supported Platforms/Implementations**: ///- Android native WebView ([Official API - WebViewClient.onFormResubmission](https://developer.android.com/reference/android/webkit/WebViewClient#onFormResubmission(android.webkit.WebView,%20android.os.Message,%20android.os.Message))) - Future? onFormResubmission(Uri? url) {} + Future? onFormResubmission(Uri? url) { + return null; + } ///Use [onZoomScaleChanged] instead. @Deprecated('Use onZoomScaleChanged instead') @@ -969,7 +1027,9 @@ class InAppBrowser { ///Use [onJsBeforeUnload] instead. @Deprecated('Use onJsBeforeUnload instead') Future? androidOnJsBeforeUnload( - JsBeforeUnloadRequest jsBeforeUnloadRequest) {} + JsBeforeUnloadRequest jsBeforeUnloadRequest) { + return null; + } ///Event fired when the client should display a dialog to confirm navigation away from the current page. ///This is the result of the `onbeforeunload` javascript event. @@ -984,7 +1044,9 @@ class InAppBrowser { ///**Supported Platforms/Implementations**: ///- Android native WebView ([Official API - WebChromeClient.onJsBeforeUnload](https://developer.android.com/reference/android/webkit/WebChromeClient#onJsBeforeUnload(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20android.webkit.JsResult))) Future? onJsBeforeUnload( - JsBeforeUnloadRequest jsBeforeUnloadRequest) {} + JsBeforeUnloadRequest jsBeforeUnloadRequest) { + return null; + } ///Use [onReceivedLoginRequest] instead. @Deprecated('Use onReceivedLoginRequest instead') @@ -1021,7 +1083,9 @@ class InAppBrowser { ///Use [onNavigationResponse] instead. @Deprecated('Use onNavigationResponse instead') Future? iosOnNavigationResponse( - IOSWKNavigationResponse navigationResponse) {} + IOSWKNavigationResponse navigationResponse) { + return null; + } ///Called when a web view asks for permission to navigate to new content after the response to the navigation request is known. /// @@ -1032,12 +1096,16 @@ class InAppBrowser { ///**Supported Platforms/Implementations**: ///- iOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455643-webview)) Future? onNavigationResponse( - NavigationResponse navigationResponse) {} + NavigationResponse navigationResponse) { + return null; + } ///Use [shouldAllowDeprecatedTLS] instead. @Deprecated('Use shouldAllowDeprecatedTLS instead') Future? iosShouldAllowDeprecatedTLS( - URLAuthenticationChallenge challenge) {} + URLAuthenticationChallenge challenge) { + return null; + } ///Called when a web view asks whether to continue with a connection that uses a deprecated version of TLS (v1.0 and v1.1). /// @@ -1048,7 +1116,9 @@ class InAppBrowser { ///**Supported Platforms/Implementations**: ///- iOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/3601237-webview)) Future? shouldAllowDeprecatedTLS( - URLAuthenticationChallenge challenge) {} + URLAuthenticationChallenge challenge) { + return null; + } ///Event fired when a change in the camera capture state occurred. /// diff --git a/lib/src/in_app_webview/headless_in_app_webview.dart b/lib/src/in_app_webview/headless_in_app_webview.dart index a05bb759..9aac14a6 100644 --- a/lib/src/in_app_webview/headless_in_app_webview.dart +++ b/lib/src/in_app_webview/headless_in_app_webview.dart @@ -74,7 +74,8 @@ class HeadlessInAppWebView implements WebView { this.onScrollChanged, @Deprecated('Use onDownloadStartRequest instead') this.onDownloadStart, this.onDownloadStartRequest, - this.onLoadResourceCustomScheme, + @Deprecated('Use onLoadResourceWithCustomScheme instead') this.onLoadResourceCustomScheme, + this.onLoadResourceWithCustomScheme, this.onCreateWindow, this.onCloseWindow, this.onJsAlert, @@ -451,10 +452,16 @@ class HeadlessInAppWebView implements WebView { void Function(InAppWebViewController controller, LoadedResource resource)? onLoadResource; + ///Use [onLoadResourceWithCustomScheme] instead. + @Deprecated('Use onLoadResourceWithCustomScheme instead') @override - Future Function( + final Future Function( InAppWebViewController controller, Uri url)? onLoadResourceCustomScheme; + @override + final Future Function( + InAppWebViewController controller, WebResourceRequest request)? onLoadResourceWithCustomScheme; + @override void Function(InAppWebViewController controller, Uri? url)? onLoadStart; diff --git a/lib/src/in_app_webview/in_app_webview.dart b/lib/src/in_app_webview/in_app_webview.dart index 16254a09..9410736c 100755 --- a/lib/src/in_app_webview/in_app_webview.dart +++ b/lib/src/in_app_webview/in_app_webview.dart @@ -65,7 +65,8 @@ class InAppWebView extends StatefulWidget implements WebView { this.onScrollChanged, @Deprecated('Use onDownloadStartRequest instead') this.onDownloadStart, this.onDownloadStartRequest, - this.onLoadResourceCustomScheme, + @Deprecated('Use onLoadResourceWithCustomScheme instead') this.onLoadResourceCustomScheme, + this.onLoadResourceWithCustomScheme, this.onCreateWindow, this.onCloseWindow, this.onJsAlert, @@ -336,10 +337,16 @@ class InAppWebView extends StatefulWidget implements WebView { InAppWebViewController controller, LoadedResource resource)? onLoadResource; + ///Use [onLoadResourceWithCustomScheme] instead. + @Deprecated('Use onLoadResourceWithCustomScheme instead') @override final Future Function( InAppWebViewController controller, Uri url)? onLoadResourceCustomScheme; + @override + final Future Function( + InAppWebViewController controller, WebResourceRequest request)? onLoadResourceWithCustomScheme; + @override final void Function(InAppWebViewController controller, Uri? url)? onLoadStart; diff --git a/lib/src/in_app_webview/in_app_webview_controller.dart b/lib/src/in_app_webview/in_app_webview_controller.dart index baf426f0..beb29205 100644 --- a/lib/src/in_app_webview/in_app_webview_controller.dart +++ b/lib/src/in_app_webview/in_app_webview_controller.dart @@ -108,7 +108,8 @@ class InAppWebViewController { for (var regExp in WebView.debugLoggingSettings.excludeFilter) { if (regExp.hasMatch(method)) return; } - var maxLogMessageLength = WebView.debugLoggingSettings.maxLogMessageLength; + var maxLogMessageLength = + WebView.debugLoggingSettings.maxLogMessageLength; String viewId = (getViewId() ?? _inAppBrowser?.id).toString(); String message = (_inAppBrowser == null ? "WebView" : "InAppBrowser") + " ID " + @@ -125,7 +126,8 @@ class InAppWebViewController { } Future handleMethod(MethodCall call) async { - if (WebView.debugLoggingSettings.enabled && call.method != "onCallJsHandler") { + if (WebView.debugLoggingSettings.enabled && + call.method != "onCallJsHandler") { _debugLog(call.method, call.arguments); } @@ -293,18 +295,35 @@ class InAppWebViewController { } } break; - case "onLoadResourceCustomScheme": + case "onLoadResourceWithCustomScheme": if ((_webview != null && - _webview!.onLoadResourceCustomScheme != null) || + (_webview!.onLoadResourceWithCustomScheme != null || + // ignore: deprecated_member_use_from_same_package + _webview!.onLoadResourceCustomScheme != null)) || _inAppBrowser != null) { - String url = call.arguments["url"]; - Uri uri = Uri.parse(url); - if (_webview != null && _webview!.onLoadResourceCustomScheme != null) - return (await _webview!.onLoadResourceCustomScheme!(this, uri)) - ?.toMap(); - else - return (await _inAppBrowser!.onLoadResourceCustomScheme(uri)) + Map requestMap = + call.arguments["request"].cast(); + WebResourceRequest request = WebResourceRequest.fromMap(requestMap)!; + + if (_webview != null) { + if (_webview!.onLoadResourceWithCustomScheme != null) + return (await _webview!.onLoadResourceWithCustomScheme!( + this, request)) + ?.toMap(); + else { + return (await _webview! + // ignore: deprecated_member_use_from_same_package + .onLoadResourceCustomScheme!(this, request.url)) + ?.toMap(); + } + } else { + return ((await _inAppBrowser! + .onLoadResourceWithCustomScheme(request)) ?? + (await _inAppBrowser! + // ignore: deprecated_member_use_from_same_package + .onLoadResourceCustomScheme(request.url))) ?.toMap(); + } } break; case "onCreateWindow": diff --git a/lib/src/in_app_webview/webview.dart b/lib/src/in_app_webview/webview.dart index c009a118..cc4aefcb 100644 --- a/lib/src/in_app_webview/webview.dart +++ b/lib/src/in_app_webview/webview.dart @@ -172,15 +172,19 @@ abstract class WebView { final void Function(InAppWebViewController controller, DownloadStartRequest downloadStartRequest)? onDownloadStartRequest; - ///Event fired when the [WebView] finds the `custom-scheme` while loading a resource. Here you can handle the url request and return a [CustomSchemeResponse] to load a specific resource encoded to `base64`. - /// - ///[url] represents the url of the request. + ///Use [onLoadResourceWithCustomScheme] instead. + @Deprecated('Use onLoadResourceWithCustomScheme instead') + final Future Function( + InAppWebViewController controller, Uri url)? onLoadResourceCustomScheme; + + ///Event fired when the [WebView] finds the `custom-scheme` while loading a resource. + ///Here you can handle the url [request] and return a [CustomSchemeResponse] to load a specific resource encoded to `base64`. /// ///**Supported Platforms/Implementations**: ///- Android native WebView ///- iOS ([Official API - WKURLSchemeHandler](https://developer.apple.com/documentation/webkit/wkurlschemehandler)) final Future Function( - InAppWebViewController controller, Uri url)? onLoadResourceCustomScheme; + InAppWebViewController controller, WebResourceRequest request)? onLoadResourceWithCustomScheme; ///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. @@ -963,7 +967,8 @@ abstract class WebView { @Deprecated('Use onDownloadStartRequest instead') this.onDownloadStart, this.onDownloadStartRequest, - this.onLoadResourceCustomScheme, + @Deprecated('Use onLoadResourceWithCustomScheme instead') this.onLoadResourceCustomScheme, + this.onLoadResourceWithCustomScheme, this.onCreateWindow, this.onCloseWindow, this.onJsAlert,