From e60fe1740a276e4de7914a93a5007bf1536f49ce Mon Sep 17 00:00:00 2001 From: Lorenzo Pichilli Date: Thu, 7 Dec 2023 16:59:30 +0100 Subject: [PATCH] fix #1905, updated useShouldInterceptAjaxRequest automatic infer logic --- dev_packages/generators/pubspec.yaml | 4 +- flutter_inappwebview/CHANGELOG.md | 5 + flutter_inappwebview/pubspec.yaml | 6 +- flutter_inappwebview_android/CHANGELOG.md | 5 + .../InterceptAjaxRequestJS.java | 17 +++- .../webview/in_app_webview/InAppWebView.java | 14 +++ .../in_app_webview/InAppWebViewSettings.java | 5 + .../src/in_app_webview/in_app_webview.dart | 93 ++++++++++--------- flutter_inappwebview_android/pubspec.yaml | 4 +- flutter_inappwebview_ios/CHANGELOG.md | 5 + .../Classes/InAppWebView/InAppWebView.swift | 18 +++- .../InAppWebView/InAppWebViewSettings.swift | 1 + .../InterceptAjaxRequestJS.swift | 17 +++- .../ios/Classes/Types/PluginScript.swift | 19 ++++ .../Types/WKUserContentController.swift | 27 +++++- .../src/in_app_webview/in_app_webview.dart | 78 ++++++++-------- flutter_inappwebview_ios/pubspec.yaml | 4 +- flutter_inappwebview_macos/CHANGELOG.md | 5 + .../src/in_app_webview/in_app_webview.dart | 85 ++++++++--------- .../Classes/InAppWebView/InAppWebView.swift | 18 +++- .../InAppWebView/InAppWebViewSettings.swift | 1 + .../InterceptAjaxRequestJS.swift | 18 +++- .../macos/Classes/Types/PluginScript.swift | 19 ++++ .../Types/WKUserContentController.swift | 27 +++++- flutter_inappwebview_macos/pubspec.yaml | 4 +- .../CHANGELOG.md | 5 + .../in_app_webview_settings.dart | 18 +++- .../in_app_webview_settings.g.dart | 26 +++++- .../src/in_app_webview/platform_webview.dart | 3 + .../pubspec.yaml | 4 +- flutter_inappwebview_web/CHANGELOG.md | 4 + flutter_inappwebview_web/pubspec.yaml | 4 +- 32 files changed, 402 insertions(+), 161 deletions(-) diff --git a/dev_packages/generators/pubspec.yaml b/dev_packages/generators/pubspec.yaml index c470af0a..be0fb811 100755 --- a/dev_packages/generators/pubspec.yaml +++ b/dev_packages/generators/pubspec.yaml @@ -10,11 +10,11 @@ environment: dependencies: flutter: sdk: flutter - build: 2.3.1 + build: ^2.4.0 source_gen: ^1.3.1 flutter_inappwebview_internal_annotations: ^1.1.1 dev_dependencies: - build_runner: 2.3.3 + build_runner: ^2.4.0 build_test: ^2.1.7 test: ^1.24.2 \ No newline at end of file diff --git a/flutter_inappwebview/CHANGELOG.md b/flutter_inappwebview/CHANGELOG.md index 279fb9b3..f5853796 100755 --- a/flutter_inappwebview/CHANGELOG.md +++ b/flutter_inappwebview/CHANGELOG.md @@ -1,3 +1,8 @@ +## 6.0.0-beta.32 + +- Updated minimum platform interface and implementation versions +- Added `InAppWebViewSettings.interceptOnlyAsyncAjaxRequests` [#1905](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1905) + ## 6.0.0-beta.31 - Updated minimum platform interface and implementation versions diff --git a/flutter_inappwebview/pubspec.yaml b/flutter_inappwebview/pubspec.yaml index c91de9d1..d097ae26 100755 --- a/flutter_inappwebview/pubspec.yaml +++ b/flutter_inappwebview/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_inappwebview description: A Flutter plugin that allows you to add an inline webview, to use an headless webview, and to open an in-app browser window. -version: 6.0.0-beta.31 +version: 6.0.0-beta.32 homepage: https://inappwebview.dev/ repository: https://github.com/pichillilorenzo/flutter_inappwebview issue_tracker: https://github.com/pichillilorenzo/flutter_inappwebview/issues @@ -22,7 +22,7 @@ dependencies: flutter_inappwebview_android: ^1.0.5 flutter_inappwebview_ios: ^1.0.5 flutter_inappwebview_macos: ^1.0.3 - flutter_inappwebview_web: ^1.0.2 + flutter_inappwebview_web: ^1.0.3 dev_dependencies: flutter_test: @@ -30,7 +30,7 @@ dev_dependencies: flutter_driver: sdk: flutter flutter_lints: ^2.0.1 - build_runner: 2.3.3 + build_runner: ^2.4.0 generators: path: ../dev_packages/generators diff --git a/flutter_inappwebview_android/CHANGELOG.md b/flutter_inappwebview_android/CHANGELOG.md index 312ac5a1..941cf434 100644 --- a/flutter_inappwebview_android/CHANGELOG.md +++ b/flutter_inappwebview_android/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.0.8 + +- Implemented `InAppWebViewSettings.interceptOnlyAsyncAjaxRequests` +- Updated `useShouldInterceptAjaxRequest` automatic infer logic + ## 1.0.7 - Merged "Fixed error in InterceptAjaxRequestJS 'Failed to set responseType property'" [#1904](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1904) (thanks to [EArminjon](https://github.com/EArminjon)) diff --git a/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/plugin_scripts_js/InterceptAjaxRequestJS.java b/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/plugin_scripts_js/InterceptAjaxRequestJS.java index 4a892dc7..2ec2e017 100644 --- a/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/plugin_scripts_js/InterceptAjaxRequestJS.java +++ b/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/plugin_scripts_js/InterceptAjaxRequestJS.java @@ -7,6 +7,7 @@ public class InterceptAjaxRequestJS { public static final String INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT_GROUP_NAME = "IN_APP_WEBVIEW_INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT"; public static final String FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_AJAX_REQUEST_JS_SOURCE = JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + "._useShouldInterceptAjaxRequest"; + public static final String FLAG_VARIABLE_FOR_INTERCEPT_ONLY_ASYNC_AJAX_REQUESTS_JS_SOURCE = JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + "._interceptOnlyAsyncAjaxRequests"; public static final PluginScript INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT = new PluginScript( InterceptAjaxRequestJS.INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT_GROUP_NAME, InterceptAjaxRequestJS.INTERCEPT_AJAX_REQUEST_JS_SOURCE, @@ -16,6 +17,17 @@ public class InterceptAjaxRequestJS { null ); + public static PluginScript createInterceptOnlyAsyncAjaxRequestsPluginScript(boolean onlyAsync) { + return new PluginScript( + InterceptAjaxRequestJS.INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT_GROUP_NAME, + "window." + FLAG_VARIABLE_FOR_INTERCEPT_ONLY_ASYNC_AJAX_REQUESTS_JS_SOURCE + " = " + onlyAsync +";", + UserScriptInjectionTime.AT_DOCUMENT_START, + null, + true, + null + ); + } + public static final String INTERCEPT_AJAX_REQUEST_JS_SOURCE = "(function(ajax) {" + " var w = (window.top == null || window.top === window) ? window : window.top;" + " w." + FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_AJAX_REQUEST_JS_SOURCE + " = true;" + @@ -122,7 +134,8 @@ public class InterceptAjaxRequestJS { " ajax.prototype.send = function(data) {" + " var self = this;" + " var w = (window.top == null || window.top === window) ? window : window.top;" + - " if (w." + FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_AJAX_REQUEST_JS_SOURCE + " == null || w." + FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_AJAX_REQUEST_JS_SOURCE + " == true) {" + + " var canBeIntercepted = self._flutter_inappwebview_isAsync || w." + FLAG_VARIABLE_FOR_INTERCEPT_ONLY_ASYNC_AJAX_REQUESTS_JS_SOURCE + " === false;" + + " if (canBeIntercepted && (w." + FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_AJAX_REQUEST_JS_SOURCE + " == null || w." + FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_AJAX_REQUEST_JS_SOURCE + " == true)) {" + " if (!this._flutter_inappwebview_already_onreadystatechange_wrapped) {" + " this._flutter_inappwebview_already_onreadystatechange_wrapped = true;" + " var onreadystatechange = this.onreadystatechange;" + @@ -220,7 +233,7 @@ public class InterceptAjaxRequestJS { " data = new Uint8Array(result.data);" + " }" + " self.withCredentials = result.withCredentials;" + - " if (result.responseType != null && self.isAsync) {" + + " if (result.responseType != null && self._flutter_inappwebview_isAsync) {" + " self.responseType = result.responseType;" + " };" + " for (var header in result.headers) {" + diff --git a/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/in_app_webview/InAppWebView.java b/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/in_app_webview/InAppWebView.java index ed11145c..27f4a25f 100755 --- a/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/in_app_webview/InAppWebView.java +++ b/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/in_app_webview/InAppWebView.java @@ -174,6 +174,9 @@ final public class InAppWebView extends InputAwareWebView implements InAppWebVie @Nullable public WebViewAssetLoaderExt webViewAssetLoaderExt; + @Nullable + private PluginScript interceptOnlyAsyncAjaxRequestsPluginScript; + public InAppWebView(Context context) { super(context); } @@ -565,7 +568,9 @@ final public class InAppWebView extends InputAwareWebView implements InAppWebVie userContentController.addPluginScript(PrintJS.PRINT_JS_PLUGIN_SCRIPT); userContentController.addPluginScript(OnWindowBlurEventJS.ON_WINDOW_BLUR_EVENT_JS_PLUGIN_SCRIPT); userContentController.addPluginScript(OnWindowFocusEventJS.ON_WINDOW_FOCUS_EVENT_JS_PLUGIN_SCRIPT); + interceptOnlyAsyncAjaxRequestsPluginScript = InterceptAjaxRequestJS.createInterceptOnlyAsyncAjaxRequestsPluginScript(customSettings.interceptOnlyAsyncAjaxRequests); if (customSettings.useShouldInterceptAjaxRequest) { + userContentController.addPluginScript(interceptOnlyAsyncAjaxRequestsPluginScript); userContentController.addPluginScript(InterceptAjaxRequestJS.INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT); } if (customSettings.useShouldInterceptFetchRequest) { @@ -772,6 +777,14 @@ final public class InAppWebView extends InputAwareWebView implements InAppWebVie ); } + if (newSettingsMap.get("interceptOnlyAsyncAjaxRequests") != null && customSettings.interceptOnlyAsyncAjaxRequests != newCustomSettings.interceptOnlyAsyncAjaxRequests) { + enablePluginScriptAtRuntime( + InterceptAjaxRequestJS.FLAG_VARIABLE_FOR_INTERCEPT_ONLY_ASYNC_AJAX_REQUESTS_JS_SOURCE, + newCustomSettings.interceptOnlyAsyncAjaxRequests, + interceptOnlyAsyncAjaxRequestsPluginScript + ); + } + if (newSettingsMap.get("useShouldInterceptFetchRequest") != null && customSettings.useShouldInterceptFetchRequest != newCustomSettings.useShouldInterceptFetchRequest) { enablePluginScriptAtRuntime( InterceptFetchRequestJS.FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_FETCH_REQUEST_JS_SOURCE, @@ -2030,6 +2043,7 @@ final public class InAppWebView extends InputAwareWebView implements InAppWebVie destroy(); } }); + interceptOnlyAsyncAjaxRequestsPluginScript = null; userContentController.dispose(); if (findInteractionController != null) { findInteractionController.dispose(); diff --git a/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/in_app_webview/InAppWebViewSettings.java b/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/in_app_webview/InAppWebViewSettings.java index d1d08a9e..3c0feaef 100755 --- a/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/in_app_webview/InAppWebViewSettings.java +++ b/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/in_app_webview/InAppWebViewSettings.java @@ -44,6 +44,7 @@ public class InAppWebViewSettings implements ISettings { public List>> contentBlockers = new ArrayList<>(); public Integer preferredContentMode = PreferredContentModeOptionType.RECOMMENDED.toValue(); public Boolean useShouldInterceptAjaxRequest = false; + public Boolean interceptOnlyAsyncAjaxRequests = true; public Boolean useShouldInterceptFetchRequest = false; public Boolean incognito = false; public Boolean cacheEnabled = true; @@ -184,6 +185,9 @@ public class InAppWebViewSettings implements ISettings { case "useShouldInterceptAjaxRequest": useShouldInterceptAjaxRequest = (Boolean) value; break; + case "interceptOnlyAsyncAjaxRequests": + interceptOnlyAsyncAjaxRequests = (Boolean) value; + break; case "useShouldInterceptFetchRequest": useShouldInterceptFetchRequest = (Boolean) value; break; @@ -426,6 +430,7 @@ public class InAppWebViewSettings implements ISettings { settings.put("contentBlockers", contentBlockers); settings.put("preferredContentMode", preferredContentMode); settings.put("useShouldInterceptAjaxRequest", useShouldInterceptAjaxRequest); + settings.put("interceptOnlyAsyncAjaxRequests", interceptOnlyAsyncAjaxRequests); settings.put("useShouldInterceptFetchRequest", useShouldInterceptFetchRequest); settings.put("incognito", incognito); settings.put("cacheEnabled", cacheEnabled); diff --git a/flutter_inappwebview_android/lib/src/in_app_webview/in_app_webview.dart b/flutter_inappwebview_android/lib/src/in_app_webview/in_app_webview.dart index 8b790a0a..e96a92b7 100755 --- a/flutter_inappwebview_android/lib/src/in_app_webview/in_app_webview.dart +++ b/flutter_inappwebview_android/lib/src/in_app_webview/in_app_webview.dart @@ -281,43 +281,41 @@ class AndroidInAppWebViewWidget extends PlatformInAppWebViewWidget { AndroidInAppWebViewController? _controller; AndroidHeadlessInAppWebView? get _androidHeadlessInAppWebView => - _androidParams.headlessWebView as AndroidHeadlessInAppWebView?; + params.headlessWebView as AndroidHeadlessInAppWebView?; @override Widget build(BuildContext context) { - final initialSettings = - _androidParams.initialSettings ?? InAppWebViewSettings(); + final initialSettings = params.initialSettings ?? InAppWebViewSettings(); _inferInitialSettings(initialSettings); - Map settingsMap = (_androidParams.initialSettings != null - ? initialSettings.toMap() - : null) ?? - // ignore: deprecated_member_use_from_same_package - _androidParams.initialOptions?.toMap() ?? - initialSettings.toMap(); + Map settingsMap = + (params.initialSettings != null ? initialSettings.toMap() : null) ?? + // ignore: deprecated_member_use_from_same_package + params.initialOptions?.toMap() ?? + initialSettings.toMap(); Map pullToRefreshSettings = - _androidParams.pullToRefreshController?.params.settings.toMap() ?? + params.pullToRefreshController?.params.settings.toMap() ?? // ignore: deprecated_member_use_from_same_package - _androidParams.pullToRefreshController?.params.options.toMap() ?? + params.pullToRefreshController?.params.options.toMap() ?? PullToRefreshSettings(enabled: false).toMap(); - if ((_androidParams.headlessWebView?.isRunning() ?? false) && - _androidParams.keepAlive != null) { - final headlessId = _androidParams.headlessWebView?.id; + if ((params.headlessWebView?.isRunning() ?? false) && + params.keepAlive != null) { + final headlessId = params.headlessWebView?.id; if (headlessId != null) { // force keep alive id to match headless webview id - _androidParams.keepAlive?.id = headlessId; + params.keepAlive?.id = headlessId; } } - var useHybridComposition = (_androidParams.initialSettings != null + var useHybridComposition = (params.initialSettings != null ? initialSettings.useHybridComposition - : _androidParams.initialOptions?.android.useHybridComposition) ?? + : params.initialOptions?.android.useHybridComposition) ?? true; return PlatformViewLink( - key: _androidParams.key, + key: params.key, viewType: 'com.pichillilorenzo/flutter_inappwebview', surfaceFactory: ( BuildContext context, @@ -325,7 +323,7 @@ class AndroidInAppWebViewWidget extends PlatformInAppWebViewWidget { ) { return AndroidViewSurface( controller: controller as AndroidViewController, - gestureRecognizers: _androidParams.gestureRecognizers ?? + gestureRecognizers: params.gestureRecognizers ?? const >{}, hitTestBehavior: PlatformViewHitTestBehavior.opaque, ); @@ -335,26 +333,28 @@ class AndroidInAppWebViewWidget extends PlatformInAppWebViewWidget { hybridComposition: useHybridComposition, id: params.id, viewType: 'com.pichillilorenzo/flutter_inappwebview', - layoutDirection: _androidParams.layoutDirection ?? + layoutDirection: this.params.layoutDirection ?? Directionality.maybeOf(context) ?? TextDirection.rtl, creationParams: { - 'initialUrlRequest': _androidParams.initialUrlRequest?.toMap(), - 'initialFile': _androidParams.initialFile, - 'initialData': _androidParams.initialData?.toMap(), + 'initialUrlRequest': this.params.initialUrlRequest?.toMap(), + 'initialFile': this.params.initialFile, + 'initialData': this.params.initialData?.toMap(), 'initialSettings': settingsMap, - 'contextMenu': _androidParams.contextMenu?.toMap() ?? {}, - 'windowId': _androidParams.windowId, + 'contextMenu': this.params.contextMenu?.toMap() ?? {}, + 'windowId': this.params.windowId, 'headlessWebViewId': - _androidParams.headlessWebView?.isRunning() ?? false - ? _androidParams.headlessWebView?.id + this.params.headlessWebView?.isRunning() ?? false + ? this.params.headlessWebView?.id : null, - 'initialUserScripts': _androidParams.initialUserScripts + 'initialUserScripts': this + .params + .initialUserScripts ?.map((e) => e.toMap()) .toList() ?? [], 'pullToRefreshSettings': pullToRefreshSettings, - 'keepAliveId': _androidParams.keepAlive?.id + 'keepAliveId': this.params.keepAlive?.id }, ) ..addOnPlatformViewCreatedListener(params.onPlatformViewCreated) @@ -391,10 +391,10 @@ class AndroidInAppWebViewWidget extends PlatformInAppWebViewWidget { void _onPlatformViewCreated(int id) { dynamic viewId = id; - if (_androidParams.headlessWebView?.isRunning() ?? false) { - viewId = _androidParams.headlessWebView?.id; + if (params.headlessWebView?.isRunning() ?? false) { + viewId = params.headlessWebView?.id; } - viewId = _androidParams.keepAlive?.id ?? viewId ?? id; + viewId = params.keepAlive?.id ?? viewId ?? id; _androidHeadlessInAppWebView?.internalDispose(); _controller = AndroidInAppWebViewController( PlatformInAppWebViewControllerCreationParams( @@ -408,42 +408,43 @@ class AndroidInAppWebViewWidget extends PlatformInAppWebViewWidget { PlatformInAppWebViewController.debugLoggingSettings, method: "onWebViewCreated", args: []); - if (_androidParams.onWebViewCreated != null) { - _androidParams.onWebViewCreated!( + if (params.onWebViewCreated != null) { + params.onWebViewCreated!( params.controllerFromPlatform?.call(_controller!) ?? _controller!); } } void _inferInitialSettings(InAppWebViewSettings settings) { - if (_androidParams.shouldOverrideUrlLoading != null && + if (params.shouldOverrideUrlLoading != null && settings.useShouldOverrideUrlLoading == null) { settings.useShouldOverrideUrlLoading = true; } - if (_androidParams.onLoadResource != null && - settings.useOnLoadResource == null) { + if (params.onLoadResource != null && settings.useOnLoadResource == null) { settings.useOnLoadResource = true; } - if (_androidParams.onDownloadStartRequest != null && + if (params.onDownloadStartRequest != null && settings.useOnDownloadStart == null) { settings.useOnDownloadStart = true; } - if (_androidParams.shouldInterceptAjaxRequest != null && + if ((params.shouldInterceptAjaxRequest != null || + params.onAjaxProgress != null || + params.onAjaxReadyStateChange != null) && settings.useShouldInterceptAjaxRequest == null) { settings.useShouldInterceptAjaxRequest = true; } - if (_androidParams.shouldInterceptFetchRequest != null && + if (params.shouldInterceptFetchRequest != null && settings.useShouldInterceptFetchRequest == null) { settings.useShouldInterceptFetchRequest = true; } - if (_androidParams.shouldInterceptRequest != null && + if (params.shouldInterceptRequest != null && settings.useShouldInterceptRequest == null) { settings.useShouldInterceptRequest = true; } - if (_androidParams.onRenderProcessGone != null && + if (params.onRenderProcessGone != null && settings.useOnRenderProcessGone == null) { settings.useOnRenderProcessGone = true; } - if (_androidParams.onNavigationResponse != null && + if (params.onNavigationResponse != null && settings.useOnNavigationResponse == null) { settings.useOnNavigationResponse = true; } @@ -459,11 +460,11 @@ class AndroidInAppWebViewWidget extends PlatformInAppWebViewWidget { PlatformInAppWebViewController.debugLoggingSettings, method: "dispose", args: []); - final isKeepAlive = _androidParams.keepAlive != null; + final isKeepAlive = params.keepAlive != null; _controller?.dispose(isKeepAlive: isKeepAlive); _controller = null; - _androidParams.pullToRefreshController?.dispose(isKeepAlive: isKeepAlive); - _androidParams.findInteractionController?.dispose(isKeepAlive: isKeepAlive); + params.pullToRefreshController?.dispose(isKeepAlive: isKeepAlive); + params.findInteractionController?.dispose(isKeepAlive: isKeepAlive); } @override diff --git a/flutter_inappwebview_android/pubspec.yaml b/flutter_inappwebview_android/pubspec.yaml index bae65bdd..0e28a3cc 100644 --- a/flutter_inappwebview_android/pubspec.yaml +++ b/flutter_inappwebview_android/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_inappwebview_android description: Android implementation of the flutter_inappwebview plugin. -version: 1.0.7 +version: 1.0.8 homepage: https://inappwebview.dev/ repository: https://github.com/pichillilorenzo/flutter_inappwebview/tree/master/flutter_inappwebview_android issue_tracker: https://github.com/pichillilorenzo/flutter_inappwebview/issues @@ -18,7 +18,7 @@ environment: dependencies: flutter: sdk: flutter - flutter_inappwebview_platform_interface: ^1.0.5 + flutter_inappwebview_platform_interface: ^1.0.6 dev_dependencies: flutter_test: diff --git a/flutter_inappwebview_ios/CHANGELOG.md b/flutter_inappwebview_ios/CHANGELOG.md index b5882261..6a5fa537 100644 --- a/flutter_inappwebview_ios/CHANGELOG.md +++ b/flutter_inappwebview_ios/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.0.9 + +- Implemented `InAppWebViewSettings.interceptOnlyAsyncAjaxRequests` +- Updated `useShouldInterceptAjaxRequest` automatic infer logic + ## 1.0.8 - Fixed error in InterceptAjaxRequestJS 'Failed to set responseType property' diff --git a/flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebView.swift b/flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebView.swift index e3deed4b..a0b3d201 100755 --- a/flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebView.swift +++ b/flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebView.swift @@ -67,6 +67,8 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, var oldZoomScale = Float(1.0) + fileprivate var interceptOnlyAsyncAjaxRequestsPluginScript: PluginScript? + init(id: Any?, plugin: SwiftFlutterPlugin?, frame: CGRect, configuration: WKWebViewConfiguration, contextMenu: [String: Any]?, userScripts: [UserScript] = []) { super.init(frame: frame, configuration: configuration) @@ -562,7 +564,11 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, configuration.userContentController.addPluginScript(FIND_TEXT_HIGHLIGHT_JS_PLUGIN_SCRIPT) configuration.userContentController.addPluginScript(ORIGINAL_VIEWPORT_METATAG_CONTENT_JS_PLUGIN_SCRIPT) if let settings = settings { + interceptOnlyAsyncAjaxRequestsPluginScript = createInterceptOnlyAsyncAjaxRequestsPluginScript(onlyAsync: settings.interceptOnlyAsyncAjaxRequests) if settings.useShouldInterceptAjaxRequest { + if let interceptOnlyAsyncAjaxRequestsPluginScript = interceptOnlyAsyncAjaxRequestsPluginScript { + configuration.userContentController.addPluginScript(interceptOnlyAsyncAjaxRequestsPluginScript) + } configuration.userContentController.addPluginScript(INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT) } if settings.useShouldInterceptFetchRequest { @@ -1063,7 +1069,16 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, enable: newSettings.useShouldInterceptAjaxRequest, pluginScript: INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT) } else { - newSettings.useShouldInterceptFetchRequest = false + newSettings.useShouldInterceptAjaxRequest = false + } + } + + if newSettingsMap["interceptOnlyAsyncAjaxRequests"] != nil && settings?.interceptOnlyAsyncAjaxRequests != newSettings.interceptOnlyAsyncAjaxRequests { + if let applePayAPIEnabled = settings?.applePayAPIEnabled, !applePayAPIEnabled, + let interceptOnlyAsyncAjaxRequestsPluginScript = interceptOnlyAsyncAjaxRequestsPluginScript { + enablePluginScriptAtRuntime(flagVariable: FLAG_VARIABLE_FOR_INTERCEPT_ONLY_ASYNC_AJAX_REQUESTS_JS_SOURCE, + enable: newSettings.interceptOnlyAsyncAjaxRequests, + pluginScript: interceptOnlyAsyncAjaxRequestsPluginScript) } } @@ -3266,6 +3281,7 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) { webMessageListener.dispose() } webMessageListeners.removeAll() + interceptOnlyAsyncAjaxRequestsPluginScript = nil if windowId == nil { configuration.userContentController.removeAllPluginScriptMessageHandlers() configuration.userContentController.removeScriptMessageHandler(forName: "onCallAsyncJavaScriptResultBelowIOS14Received") diff --git a/flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebViewSettings.swift b/flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebViewSettings.swift index c09cd951..c668fc17 100755 --- a/flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebViewSettings.swift +++ b/flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebViewSettings.swift @@ -26,6 +26,7 @@ public class InAppWebViewSettings: ISettings { var contentBlockers: [[String: [String : Any]]] = [] var minimumFontSize = 0 var useShouldInterceptAjaxRequest = false + var interceptOnlyAsyncAjaxRequests = true var useShouldInterceptFetchRequest = false var incognito = false var cacheEnabled = true diff --git a/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/InterceptAjaxRequestJS.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/InterceptAjaxRequestJS.swift index be260499..28ebb58b 100644 --- a/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/InterceptAjaxRequestJS.swift +++ b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/InterceptAjaxRequestJS.swift @@ -10,6 +10,8 @@ import Foundation let INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT_GROUP_NAME = "IN_APP_WEBVIEW_INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT" let FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_AJAX_REQUEST_JS_SOURCE = "window.\(JAVASCRIPT_BRIDGE_NAME)._useShouldInterceptAjaxRequest" +let FLAG_VARIABLE_FOR_INTERCEPT_ONLY_ASYNC_AJAX_REQUESTS_JS_SOURCE = "window.\(JAVASCRIPT_BRIDGE_NAME)._interceptOnlyAsyncAjaxRequests"; + let INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT = PluginScript( groupName: INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT_GROUP_NAME, source: INTERCEPT_AJAX_REQUEST_JS_SOURCE, @@ -18,6 +20,16 @@ let INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT = PluginScript( requiredInAllContentWorlds: true, messageHandlerNames: []) +func createInterceptOnlyAsyncAjaxRequestsPluginScript(onlyAsync: Bool) -> PluginScript { + return PluginScript(groupName: INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT_GROUP_NAME, + source: "\(FLAG_VARIABLE_FOR_INTERCEPT_ONLY_ASYNC_AJAX_REQUESTS_JS_SOURCE) = \(onlyAsync);", + injectionTime: .atDocumentStart, + forMainFrameOnly: false, + requiredInAllContentWorlds: true, + messageHandlerNames: [] + ); +} + let INTERCEPT_AJAX_REQUEST_JS_SOURCE = """ \(FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_AJAX_REQUEST_JS_SOURCE) = true; (function(ajax) { @@ -122,7 +134,8 @@ let INTERCEPT_AJAX_REQUEST_JS_SOURCE = """ }; ajax.prototype.send = function(data) { var self = this; - if (\(FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_AJAX_REQUEST_JS_SOURCE) == null || \(FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_AJAX_REQUEST_JS_SOURCE) == true) { + var canBeIntercepted = self._flutter_inappwebview_isAsync || \(FLAG_VARIABLE_FOR_INTERCEPT_ONLY_ASYNC_AJAX_REQUESTS_JS_SOURCE) === false; + if (canBeIntercepted && (\(FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_AJAX_REQUEST_JS_SOURCE) == null || \(FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_AJAX_REQUEST_JS_SOURCE) == true)) { if (!this._flutter_inappwebview_already_onreadystatechange_wrapped) { this._flutter_inappwebview_already_onreadystatechange_wrapped = true; var onreadystatechange = this.onreadystatechange; @@ -219,7 +232,7 @@ let INTERCEPT_AJAX_REQUEST_JS_SOURCE = """ data = new Uint8Array(result.data); } self.withCredentials = result.withCredentials; - if (result.responseType != null && self.isAsync) { + if (result.responseType != null && self._flutter_inappwebview_isAsync) { self.responseType = result.responseType; }; if (result.headers != null) { diff --git a/flutter_inappwebview_ios/ios/Classes/Types/PluginScript.swift b/flutter_inappwebview_ios/ios/Classes/Types/PluginScript.swift index 97ca2834..913137e0 100644 --- a/flutter_inappwebview_ios/ios/Classes/Types/PluginScript.swift +++ b/flutter_inappwebview_ios/ios/Classes/Types/PluginScript.swift @@ -87,4 +87,23 @@ public class PluginScript : UserScript { messageHandlerNames: messageHandlerNames ?? self.messageHandlerNames ) } + + static func == (lhs: PluginScript, rhs: PluginScript) -> Bool { + if #available(iOS 14.0, *) { + return lhs.groupName == rhs.groupName && + lhs.source == rhs.source && + lhs.injectionTime == rhs.injectionTime && + lhs.isForMainFrameOnly == rhs.isForMainFrameOnly && + lhs.contentWorld == rhs.contentWorld && + lhs.requiredInAllContentWorlds == rhs.requiredInAllContentWorlds && + lhs.messageHandlerNames == rhs.messageHandlerNames + } else { + return lhs.groupName == rhs.groupName && + lhs.source == rhs.source && + lhs.injectionTime == rhs.injectionTime && + lhs.isForMainFrameOnly == rhs.isForMainFrameOnly && + lhs.requiredInAllContentWorlds == rhs.requiredInAllContentWorlds && + lhs.messageHandlerNames == rhs.messageHandlerNames + } + } } diff --git a/flutter_inappwebview_ios/ios/Classes/Types/WKUserContentController.swift b/flutter_inappwebview_ios/ios/Classes/Types/WKUserContentController.swift index eecba322..633f1e1b 100644 --- a/flutter_inappwebview_ios/ios/Classes/Types/WKUserContentController.swift +++ b/flutter_inappwebview_ios/ios/Classes/Types/WKUserContentController.swift @@ -91,7 +91,7 @@ extension WKUserContentController { public func sync(scriptMessageHandler: WKScriptMessageHandler) { let pluginScriptsList = pluginScripts.compactMap({ $0.value }).joined() for pluginScript in pluginScriptsList { - if !containsPluginScript(with: pluginScript.groupName!) { + if !containsPluginScript(pluginScript: pluginScript) { addUserScript(pluginScript) for messageHandlerName in pluginScript.messageHandlerNames { removeScriptMessageHandler(forName: messageHandlerName) @@ -100,8 +100,8 @@ extension WKUserContentController { } if #available(iOS 14.0, *), pluginScript.requiredInAllContentWorlds { for contentWorld in contentWorlds { - let pluginScriptWithContentWorld = pluginScript.copyAndSet(contentWorld: contentWorld) - if !containsPluginScript(with: pluginScriptWithContentWorld.groupName!, in: contentWorld) { + if !containsPluginScript(pluginScript: pluginScript, in: contentWorld) { + let pluginScriptWithContentWorld = pluginScript.copyAndSet(contentWorld: contentWorld) addUserScript(pluginScriptWithContentWorld) for messageHandlerName in pluginScriptWithContentWorld.messageHandlerNames { removeScriptMessageHandler(forName: messageHandlerName, contentWorld: contentWorld) @@ -314,6 +314,16 @@ extension WKUserContentController { removeUserScripts(scriptsToRemove: scriptsToRemove, shouldAddPreviousScripts: shouldAddPreviousScripts) } + public func containsPluginScript(pluginScript: PluginScript) -> Bool { + let userScripts = useCopyOfUserScripts() + for script in userScripts { + if let script = script as? PluginScript, script == pluginScript { + return true + } + } + return false + } + public func containsPluginScript(with groupName: String) -> Bool { let userScripts = useCopyOfUserScripts() for script in userScripts { @@ -324,6 +334,17 @@ extension WKUserContentController { return false } + @available(iOS 14.0, *) + public func containsPluginScript(pluginScript: PluginScript, in contentWorld: WKContentWorld) -> Bool { + let userScripts = useCopyOfUserScripts() + for script in userScripts { + if let script = script as? PluginScript, script == pluginScript, script.contentWorld == contentWorld { + return true + } + } + return false + } + @available(iOS 14.0, *) public func containsPluginScript(with groupName: String, in contentWorld: WKContentWorld) -> Bool { let userScripts = useCopyOfUserScripts() diff --git a/flutter_inappwebview_ios/lib/src/in_app_webview/in_app_webview.dart b/flutter_inappwebview_ios/lib/src/in_app_webview/in_app_webview.dart index 5c773779..235d4ed1 100755 --- a/flutter_inappwebview_ios/lib/src/in_app_webview/in_app_webview.dart +++ b/flutter_inappwebview_ios/lib/src/in_app_webview/in_app_webview.dart @@ -278,54 +278,53 @@ class IOSInAppWebViewWidget extends PlatformInAppWebViewWidget { IOSInAppWebViewController? _controller; IOSHeadlessInAppWebView? get _iosHeadlessInAppWebView => - _iosParams.headlessWebView as IOSHeadlessInAppWebView?; + params.headlessWebView as IOSHeadlessInAppWebView?; @override Widget build(BuildContext context) { - final initialSettings = - _iosParams.initialSettings ?? InAppWebViewSettings(); + final initialSettings = params.initialSettings ?? InAppWebViewSettings(); _inferInitialSettings(initialSettings); Map settingsMap = - (_iosParams.initialSettings != null ? initialSettings.toMap() : null) ?? + (params.initialSettings != null ? initialSettings.toMap() : null) ?? // ignore: deprecated_member_use_from_same_package - _iosParams.initialOptions?.toMap() ?? + params.initialOptions?.toMap() ?? initialSettings.toMap(); Map pullToRefreshSettings = - _iosParams.pullToRefreshController?.params.settings.toMap() ?? + params.pullToRefreshController?.params.settings.toMap() ?? // ignore: deprecated_member_use_from_same_package - _iosParams.pullToRefreshController?.params.options.toMap() ?? + params.pullToRefreshController?.params.options.toMap() ?? PullToRefreshSettings(enabled: false).toMap(); - if ((_iosParams.headlessWebView?.isRunning() ?? false) && - _iosParams.keepAlive != null) { - final headlessId = _iosParams.headlessWebView?.id; + if ((params.headlessWebView?.isRunning() ?? false) && + params.keepAlive != null) { + final headlessId = params.headlessWebView?.id; if (headlessId != null) { // force keep alive id to match headless webview id - _iosParams.keepAlive?.id = headlessId; + params.keepAlive?.id = headlessId; } } return UiKitView( viewType: 'com.pichillilorenzo/flutter_inappwebview', onPlatformViewCreated: _onPlatformViewCreated, - gestureRecognizers: _iosParams.gestureRecognizers, + gestureRecognizers: params.gestureRecognizers, creationParams: { - 'initialUrlRequest': _iosParams.initialUrlRequest?.toMap(), - 'initialFile': _iosParams.initialFile, - 'initialData': _iosParams.initialData?.toMap(), + 'initialUrlRequest': params.initialUrlRequest?.toMap(), + 'initialFile': params.initialFile, + 'initialData': params.initialData?.toMap(), 'initialSettings': settingsMap, - 'contextMenu': _iosParams.contextMenu?.toMap() ?? {}, - 'windowId': _iosParams.windowId, - 'headlessWebViewId': _iosParams.headlessWebView?.isRunning() ?? false - ? _iosParams.headlessWebView?.id + 'contextMenu': params.contextMenu?.toMap() ?? {}, + 'windowId': params.windowId, + 'headlessWebViewId': params.headlessWebView?.isRunning() ?? false + ? params.headlessWebView?.id : null, 'initialUserScripts': - _iosParams.initialUserScripts?.map((e) => e.toMap()).toList() ?? [], + params.initialUserScripts?.map((e) => e.toMap()).toList() ?? [], 'pullToRefreshSettings': pullToRefreshSettings, - 'keepAliveId': _iosParams.keepAlive?.id, - 'preventGestureDelay': _iosParams.preventGestureDelay + 'keepAliveId': params.keepAlive?.id, + 'preventGestureDelay': params.preventGestureDelay }, creationParamsCodec: const StandardMessageCodec(), ); @@ -333,10 +332,10 @@ class IOSInAppWebViewWidget extends PlatformInAppWebViewWidget { void _onPlatformViewCreated(int id) { dynamic viewId = id; - if (_iosParams.headlessWebView?.isRunning() ?? false) { - viewId = _iosParams.headlessWebView?.id; + if (params.headlessWebView?.isRunning() ?? false) { + viewId = params.headlessWebView?.id; } - viewId = _iosParams.keepAlive?.id ?? viewId ?? id; + viewId = params.keepAlive?.id ?? viewId ?? id; _iosHeadlessInAppWebView?.internalDispose(); _controller = IOSInAppWebViewController( PlatformInAppWebViewControllerCreationParams( @@ -350,42 +349,43 @@ class IOSInAppWebViewWidget extends PlatformInAppWebViewWidget { PlatformInAppWebViewController.debugLoggingSettings, method: "onWebViewCreated", args: []); - if (_iosParams.onWebViewCreated != null) { - _iosParams.onWebViewCreated!( + if (params.onWebViewCreated != null) { + params.onWebViewCreated!( params.controllerFromPlatform?.call(_controller!) ?? _controller!); } } void _inferInitialSettings(InAppWebViewSettings settings) { - if (_iosParams.shouldOverrideUrlLoading != null && + if (params.shouldOverrideUrlLoading != null && settings.useShouldOverrideUrlLoading == null) { settings.useShouldOverrideUrlLoading = true; } - if (_iosParams.onLoadResource != null && - settings.useOnLoadResource == null) { + if (params.onLoadResource != null && settings.useOnLoadResource == null) { settings.useOnLoadResource = true; } - if (_iosParams.onDownloadStartRequest != null && + if (params.onDownloadStartRequest != null && settings.useOnDownloadStart == null) { settings.useOnDownloadStart = true; } - if (_iosParams.shouldInterceptAjaxRequest != null && + if ((params.shouldInterceptAjaxRequest != null || + params.onAjaxProgress != null || + params.onAjaxReadyStateChange != null) && settings.useShouldInterceptAjaxRequest == null) { settings.useShouldInterceptAjaxRequest = true; } - if (_iosParams.shouldInterceptFetchRequest != null && + if (params.shouldInterceptFetchRequest != null && settings.useShouldInterceptFetchRequest == null) { settings.useShouldInterceptFetchRequest = true; } - if (_iosParams.shouldInterceptRequest != null && + if (params.shouldInterceptRequest != null && settings.useShouldInterceptRequest == null) { settings.useShouldInterceptRequest = true; } - if (_iosParams.onRenderProcessGone != null && + if (params.onRenderProcessGone != null && settings.useOnRenderProcessGone == null) { settings.useOnRenderProcessGone = true; } - if (_iosParams.onNavigationResponse != null && + if (params.onNavigationResponse != null && settings.useOnNavigationResponse == null) { settings.useOnNavigationResponse = true; } @@ -401,11 +401,11 @@ class IOSInAppWebViewWidget extends PlatformInAppWebViewWidget { PlatformInAppWebViewController.debugLoggingSettings, method: "dispose", args: []); - final isKeepAlive = _iosParams.keepAlive != null; + final isKeepAlive = params.keepAlive != null; _controller?.dispose(isKeepAlive: isKeepAlive); _controller = null; - _iosParams.pullToRefreshController?.dispose(isKeepAlive: isKeepAlive); - _iosParams.findInteractionController?.dispose(isKeepAlive: isKeepAlive); + params.pullToRefreshController?.dispose(isKeepAlive: isKeepAlive); + params.findInteractionController?.dispose(isKeepAlive: isKeepAlive); } @override diff --git a/flutter_inappwebview_ios/pubspec.yaml b/flutter_inappwebview_ios/pubspec.yaml index f58a92d0..b266ca03 100644 --- a/flutter_inappwebview_ios/pubspec.yaml +++ b/flutter_inappwebview_ios/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_inappwebview_ios description: iOS implementation of the flutter_inappwebview plugin. -version: 1.0.8 +version: 1.0.9 homepage: https://inappwebview.dev/ repository: https://github.com/pichillilorenzo/flutter_inappwebview/tree/master/flutter_inappwebview_ios issue_tracker: https://github.com/pichillilorenzo/flutter_inappwebview/issues @@ -18,7 +18,7 @@ environment: dependencies: flutter: sdk: flutter - flutter_inappwebview_platform_interface: ^1.0.5 + flutter_inappwebview_platform_interface: ^1.0.6 dev_dependencies: flutter_test: diff --git a/flutter_inappwebview_macos/CHANGELOG.md b/flutter_inappwebview_macos/CHANGELOG.md index 54e62ae3..7b05a820 100644 --- a/flutter_inappwebview_macos/CHANGELOG.md +++ b/flutter_inappwebview_macos/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.0.7 + +- Implemented `InAppWebViewSettings.interceptOnlyAsyncAjaxRequests` +- Updated `useShouldInterceptAjaxRequest` automatic infer logic + ## 1.0.6 - Fixed error in InterceptAjaxRequestJS 'Failed to set responseType property' diff --git a/flutter_inappwebview_macos/lib/src/in_app_webview/in_app_webview.dart b/flutter_inappwebview_macos/lib/src/in_app_webview/in_app_webview.dart index 43680d5f..90fb8fc3 100755 --- a/flutter_inappwebview_macos/lib/src/in_app_webview/in_app_webview.dart +++ b/flutter_inappwebview_macos/lib/src/in_app_webview/in_app_webview.dart @@ -272,56 +272,53 @@ class MacOSInAppWebViewWidget extends PlatformInAppWebViewWidget { MacOSInAppWebViewController? _controller; MacOSHeadlessInAppWebView? get _macosHeadlessInAppWebView => - _macosParams.headlessWebView as MacOSHeadlessInAppWebView?; + params.headlessWebView as MacOSHeadlessInAppWebView?; @override Widget build(BuildContext context) { - final initialSettings = - _macosParams.initialSettings ?? InAppWebViewSettings(); + final initialSettings = params.initialSettings ?? InAppWebViewSettings(); _inferInitialSettings(initialSettings); - Map settingsMap = (_macosParams.initialSettings != null - ? initialSettings.toMap() - : null) ?? - // ignore: deprecated_member_use_from_same_package - _macosParams.initialOptions?.toMap() ?? - initialSettings.toMap(); + Map settingsMap = + (params.initialSettings != null ? initialSettings.toMap() : null) ?? + // ignore: deprecated_member_use_from_same_package + params.initialOptions?.toMap() ?? + initialSettings.toMap(); Map pullToRefreshSettings = - _macosParams.pullToRefreshController?.params.settings.toMap() ?? + params.pullToRefreshController?.params.settings.toMap() ?? // ignore: deprecated_member_use_from_same_package - _macosParams.pullToRefreshController?.params.options.toMap() ?? + params.pullToRefreshController?.params.options.toMap() ?? PullToRefreshSettings(enabled: false).toMap(); - if ((_macosParams.headlessWebView?.isRunning() ?? false) && - _macosParams.keepAlive != null) { - final headlessId = _macosParams.headlessWebView?.id; + if ((params.headlessWebView?.isRunning() ?? false) && + params.keepAlive != null) { + final headlessId = params.headlessWebView?.id; if (headlessId != null) { // force keep alive id to match headless webview id - _macosParams.keepAlive?.id = headlessId; + params.keepAlive?.id = headlessId; } } return UiKitView( viewType: 'com.pichillilorenzo/flutter_inappwebview', onPlatformViewCreated: _onPlatformViewCreated, - gestureRecognizers: _macosParams.gestureRecognizers, + gestureRecognizers: params.gestureRecognizers, creationParams: { - 'initialUrlRequest': _macosParams.initialUrlRequest?.toMap(), - 'initialFile': _macosParams.initialFile, - 'initialData': _macosParams.initialData?.toMap(), + 'initialUrlRequest': params.initialUrlRequest?.toMap(), + 'initialFile': params.initialFile, + 'initialData': params.initialData?.toMap(), 'initialSettings': settingsMap, - 'contextMenu': _macosParams.contextMenu?.toMap() ?? {}, - 'windowId': _macosParams.windowId, - 'headlessWebViewId': _macosParams.headlessWebView?.isRunning() ?? false - ? _macosParams.headlessWebView?.id + 'contextMenu': params.contextMenu?.toMap() ?? {}, + 'windowId': params.windowId, + 'headlessWebViewId': params.headlessWebView?.isRunning() ?? false + ? params.headlessWebView?.id : null, 'initialUserScripts': - _macosParams.initialUserScripts?.map((e) => e.toMap()).toList() ?? - [], + params.initialUserScripts?.map((e) => e.toMap()).toList() ?? [], 'pullToRefreshSettings': pullToRefreshSettings, - 'keepAliveId': _macosParams.keepAlive?.id, - 'preventGestureDelay': _macosParams.preventGestureDelay + 'keepAliveId': params.keepAlive?.id, + 'preventGestureDelay': params.preventGestureDelay }, creationParamsCodec: const StandardMessageCodec(), ); @@ -329,10 +326,10 @@ class MacOSInAppWebViewWidget extends PlatformInAppWebViewWidget { void _onPlatformViewCreated(int id) { dynamic viewId = id; - if (_macosParams.headlessWebView?.isRunning() ?? false) { - viewId = _macosParams.headlessWebView?.id; + if (params.headlessWebView?.isRunning() ?? false) { + viewId = params.headlessWebView?.id; } - viewId = _macosParams.keepAlive?.id ?? viewId ?? id; + viewId = params.keepAlive?.id ?? viewId ?? id; _macosHeadlessInAppWebView?.internalDispose(); _controller = MacOSInAppWebViewController( PlatformInAppWebViewControllerCreationParams( @@ -345,42 +342,43 @@ class MacOSInAppWebViewWidget extends PlatformInAppWebViewWidget { PlatformInAppWebViewController.debugLoggingSettings, method: "onWebViewCreated", args: []); - if (_macosParams.onWebViewCreated != null) { - _macosParams.onWebViewCreated!( + if (params.onWebViewCreated != null) { + params.onWebViewCreated!( params.controllerFromPlatform?.call(_controller!) ?? _controller!); } } void _inferInitialSettings(InAppWebViewSettings settings) { - if (_macosParams.shouldOverrideUrlLoading != null && + if (params.shouldOverrideUrlLoading != null && settings.useShouldOverrideUrlLoading == null) { settings.useShouldOverrideUrlLoading = true; } - if (_macosParams.onLoadResource != null && - settings.useOnLoadResource == null) { + if (params.onLoadResource != null && settings.useOnLoadResource == null) { settings.useOnLoadResource = true; } - if (_macosParams.onDownloadStartRequest != null && + if (params.onDownloadStartRequest != null && settings.useOnDownloadStart == null) { settings.useOnDownloadStart = true; } - if (_macosParams.shouldInterceptAjaxRequest != null && + if ((params.shouldInterceptAjaxRequest != null || + params.onAjaxProgress != null || + params.onAjaxReadyStateChange != null) && settings.useShouldInterceptAjaxRequest == null) { settings.useShouldInterceptAjaxRequest = true; } - if (_macosParams.shouldInterceptFetchRequest != null && + if (params.shouldInterceptFetchRequest != null && settings.useShouldInterceptFetchRequest == null) { settings.useShouldInterceptFetchRequest = true; } - if (_macosParams.shouldInterceptRequest != null && + if (params.shouldInterceptRequest != null && settings.useShouldInterceptRequest == null) { settings.useShouldInterceptRequest = true; } - if (_macosParams.onRenderProcessGone != null && + if (params.onRenderProcessGone != null && settings.useOnRenderProcessGone == null) { settings.useOnRenderProcessGone = true; } - if (_macosParams.onNavigationResponse != null && + if (params.onNavigationResponse != null && settings.useOnNavigationResponse == null) { settings.useOnNavigationResponse = true; } @@ -396,11 +394,10 @@ class MacOSInAppWebViewWidget extends PlatformInAppWebViewWidget { PlatformInAppWebViewController.debugLoggingSettings, method: "dispose", args: []); - final isKeepAlive = _macosParams.keepAlive != null; + final isKeepAlive = params.keepAlive != null; _controller?.dispose(isKeepAlive: isKeepAlive); _controller = null; - _macosParams.pullToRefreshController?.dispose(isKeepAlive: isKeepAlive); - _macosParams.findInteractionController?.dispose(isKeepAlive: isKeepAlive); + params.findInteractionController?.dispose(isKeepAlive: isKeepAlive); } @override diff --git a/flutter_inappwebview_macos/macos/Classes/InAppWebView/InAppWebView.swift b/flutter_inappwebview_macos/macos/Classes/InAppWebView/InAppWebView.swift index 25ecf460..d68c0199 100755 --- a/flutter_inappwebview_macos/macos/Classes/InAppWebView/InAppWebView.swift +++ b/flutter_inappwebview_macos/macos/Classes/InAppWebView/InAppWebView.swift @@ -48,6 +48,8 @@ public class InAppWebView: WKWebView, WKUIDelegate, var currentOpenPanel: NSOpenPanel? + fileprivate var interceptOnlyAsyncAjaxRequestsPluginScript: PluginScript? + init(id: Any?, plugin: InAppWebViewFlutterPlugin?, frame: CGRect, configuration: WKWebViewConfiguration, userScripts: [UserScript] = []) { super.init(frame: frame, configuration: configuration) @@ -209,7 +211,11 @@ public class InAppWebView: WKWebView, WKUIDelegate, configuration.userContentController.addPluginScript(ORIGINAL_VIEWPORT_METATAG_CONTENT_JS_PLUGIN_SCRIPT) configuration.userContentController.addPluginScript(ON_SCROLL_CHANGED_EVENT_JS_PLUGIN_SCRIPT) if let settings = settings { + interceptOnlyAsyncAjaxRequestsPluginScript = createInterceptOnlyAsyncAjaxRequestsPluginScript(onlyAsync: settings.interceptOnlyAsyncAjaxRequests) if settings.useShouldInterceptAjaxRequest { + if let interceptOnlyAsyncAjaxRequestsPluginScript = interceptOnlyAsyncAjaxRequestsPluginScript { + configuration.userContentController.addPluginScript(interceptOnlyAsyncAjaxRequestsPluginScript) + } configuration.userContentController.addPluginScript(INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT) } if settings.useShouldInterceptFetchRequest { @@ -598,7 +604,16 @@ public class InAppWebView: WKWebView, WKUIDelegate, enable: newSettings.useShouldInterceptAjaxRequest, pluginScript: INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT) } else { - newSettings.useShouldInterceptFetchRequest = false + newSettings.useShouldInterceptAjaxRequest = false + } + } + + if newSettingsMap["interceptOnlyAsyncAjaxRequests"] != nil && settings?.interceptOnlyAsyncAjaxRequests != newSettings.interceptOnlyAsyncAjaxRequests { + if let applePayAPIEnabled = settings?.applePayAPIEnabled, !applePayAPIEnabled, + let interceptOnlyAsyncAjaxRequestsPluginScript = interceptOnlyAsyncAjaxRequestsPluginScript { + enablePluginScriptAtRuntime(flagVariable: FLAG_VARIABLE_FOR_INTERCEPT_ONLY_ASYNC_AJAX_REQUESTS_JS_SOURCE, + enable: newSettings.interceptOnlyAsyncAjaxRequests, + pluginScript: interceptOnlyAsyncAjaxRequestsPluginScript) } } @@ -2606,6 +2621,7 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) { webMessageListener.dispose() } webMessageListeners.removeAll() + interceptOnlyAsyncAjaxRequestsPluginScript = nil if windowId == nil { configuration.userContentController.removeAllPluginScriptMessageHandlers() configuration.userContentController.removeScriptMessageHandler(forName: "onCallAsyncJavaScriptResultBelowIOS14Received") diff --git a/flutter_inappwebview_macos/macos/Classes/InAppWebView/InAppWebViewSettings.swift b/flutter_inappwebview_macos/macos/Classes/InAppWebView/InAppWebViewSettings.swift index 4fe83db9..cb61cfee 100755 --- a/flutter_inappwebview_macos/macos/Classes/InAppWebView/InAppWebViewSettings.swift +++ b/flutter_inappwebview_macos/macos/Classes/InAppWebView/InAppWebViewSettings.swift @@ -24,6 +24,7 @@ public class InAppWebViewSettings: ISettings { var contentBlockers: [[String: [String : Any]]] = [] var minimumFontSize = 0 var useShouldInterceptAjaxRequest = false + var interceptOnlyAsyncAjaxRequests = true var useShouldInterceptFetchRequest = false var incognito = false var cacheEnabled = true diff --git a/flutter_inappwebview_macos/macos/Classes/PluginScriptsJS/InterceptAjaxRequestJS.swift b/flutter_inappwebview_macos/macos/Classes/PluginScriptsJS/InterceptAjaxRequestJS.swift index be260499..4a68e9b6 100644 --- a/flutter_inappwebview_macos/macos/Classes/PluginScriptsJS/InterceptAjaxRequestJS.swift +++ b/flutter_inappwebview_macos/macos/Classes/PluginScriptsJS/InterceptAjaxRequestJS.swift @@ -10,6 +10,9 @@ import Foundation let INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT_GROUP_NAME = "IN_APP_WEBVIEW_INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT" let FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_AJAX_REQUEST_JS_SOURCE = "window.\(JAVASCRIPT_BRIDGE_NAME)._useShouldInterceptAjaxRequest" + +let FLAG_VARIABLE_FOR_INTERCEPT_ONLY_ASYNC_AJAX_REQUESTS_JS_SOURCE = "window.\(JAVASCRIPT_BRIDGE_NAME)._interceptOnlyAsyncAjaxRequests"; + let INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT = PluginScript( groupName: INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT_GROUP_NAME, source: INTERCEPT_AJAX_REQUEST_JS_SOURCE, @@ -18,6 +21,16 @@ let INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT = PluginScript( requiredInAllContentWorlds: true, messageHandlerNames: []) +func createInterceptOnlyAsyncAjaxRequestsPluginScript(onlyAsync: Bool) -> PluginScript { + return PluginScript(groupName: INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT_GROUP_NAME, + source: "\(FLAG_VARIABLE_FOR_INTERCEPT_ONLY_ASYNC_AJAX_REQUESTS_JS_SOURCE) = \(onlyAsync);", + injectionTime: .atDocumentStart, + forMainFrameOnly: false, + requiredInAllContentWorlds: true, + messageHandlerNames: [] + ); +} + let INTERCEPT_AJAX_REQUEST_JS_SOURCE = """ \(FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_AJAX_REQUEST_JS_SOURCE) = true; (function(ajax) { @@ -122,7 +135,8 @@ let INTERCEPT_AJAX_REQUEST_JS_SOURCE = """ }; ajax.prototype.send = function(data) { var self = this; - if (\(FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_AJAX_REQUEST_JS_SOURCE) == null || \(FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_AJAX_REQUEST_JS_SOURCE) == true) { + var canBeIntercepted = self._flutter_inappwebview_isAsync || \(FLAG_VARIABLE_FOR_INTERCEPT_ONLY_ASYNC_AJAX_REQUESTS_JS_SOURCE) === false; + if (canBeIntercepted && (\(FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_AJAX_REQUEST_JS_SOURCE) == null || \(FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_AJAX_REQUEST_JS_SOURCE) == true)) { if (!this._flutter_inappwebview_already_onreadystatechange_wrapped) { this._flutter_inappwebview_already_onreadystatechange_wrapped = true; var onreadystatechange = this.onreadystatechange; @@ -219,7 +233,7 @@ let INTERCEPT_AJAX_REQUEST_JS_SOURCE = """ data = new Uint8Array(result.data); } self.withCredentials = result.withCredentials; - if (result.responseType != null && self.isAsync) { + if (result.responseType != null && self._flutter_inappwebview_isAsync) { self.responseType = result.responseType; }; if (result.headers != null) { diff --git a/flutter_inappwebview_macos/macos/Classes/Types/PluginScript.swift b/flutter_inappwebview_macos/macos/Classes/Types/PluginScript.swift index 503e440b..a9c9f37d 100644 --- a/flutter_inappwebview_macos/macos/Classes/Types/PluginScript.swift +++ b/flutter_inappwebview_macos/macos/Classes/Types/PluginScript.swift @@ -87,4 +87,23 @@ public class PluginScript : UserScript { messageHandlerNames: messageHandlerNames ?? self.messageHandlerNames ) } + + static func == (lhs: PluginScript, rhs: PluginScript) -> Bool { + if #available(macOS 11.0, *) { + return lhs.groupName == rhs.groupName && + lhs.source == rhs.source && + lhs.injectionTime == rhs.injectionTime && + lhs.isForMainFrameOnly == rhs.isForMainFrameOnly && + lhs.contentWorld == rhs.contentWorld && + lhs.requiredInAllContentWorlds == rhs.requiredInAllContentWorlds && + lhs.messageHandlerNames == rhs.messageHandlerNames + } else { + return lhs.groupName == rhs.groupName && + lhs.source == rhs.source && + lhs.injectionTime == rhs.injectionTime && + lhs.isForMainFrameOnly == rhs.isForMainFrameOnly && + lhs.requiredInAllContentWorlds == rhs.requiredInAllContentWorlds && + lhs.messageHandlerNames == rhs.messageHandlerNames + } + } } diff --git a/flutter_inappwebview_macos/macos/Classes/Types/WKUserContentController.swift b/flutter_inappwebview_macos/macos/Classes/Types/WKUserContentController.swift index 59f8f126..21d0b62c 100644 --- a/flutter_inappwebview_macos/macos/Classes/Types/WKUserContentController.swift +++ b/flutter_inappwebview_macos/macos/Classes/Types/WKUserContentController.swift @@ -91,7 +91,7 @@ extension WKUserContentController { public func sync(scriptMessageHandler: WKScriptMessageHandler) { let pluginScriptsList = pluginScripts.compactMap({ $0.value }).joined() for pluginScript in pluginScriptsList { - if !containsPluginScript(with: pluginScript.groupName!) { + if !containsPluginScript(pluginScript: pluginScript) { addUserScript(pluginScript) for messageHandlerName in pluginScript.messageHandlerNames { removeScriptMessageHandler(forName: messageHandlerName) @@ -100,8 +100,8 @@ extension WKUserContentController { } if #available(macOS 11.0, *), pluginScript.requiredInAllContentWorlds { for contentWorld in contentWorlds { - let pluginScriptWithContentWorld = pluginScript.copyAndSet(contentWorld: contentWorld) - if !containsPluginScript(with: pluginScriptWithContentWorld.groupName!, in: contentWorld) { + if !containsPluginScript(pluginScript: pluginScript, in: contentWorld) { + let pluginScriptWithContentWorld = pluginScript.copyAndSet(contentWorld: contentWorld) addUserScript(pluginScriptWithContentWorld) for messageHandlerName in pluginScriptWithContentWorld.messageHandlerNames { removeScriptMessageHandler(forName: messageHandlerName, contentWorld: contentWorld) @@ -313,6 +313,16 @@ extension WKUserContentController { } removeUserScripts(scriptsToRemove: scriptsToRemove, shouldAddPreviousScripts: shouldAddPreviousScripts) } + + public func containsPluginScript(pluginScript: PluginScript) -> Bool { + let userScripts = useCopyOfUserScripts() + for script in userScripts { + if let script = script as? PluginScript, script == pluginScript { + return true + } + } + return false + } public func containsPluginScript(with groupName: String) -> Bool { let userScripts = useCopyOfUserScripts() @@ -324,6 +334,17 @@ extension WKUserContentController { return false } + @available(macOS 11.0, *) + public func containsPluginScript(pluginScript: PluginScript, in contentWorld: WKContentWorld) -> Bool { + let userScripts = useCopyOfUserScripts() + for script in userScripts { + if let script = script as? PluginScript, script == pluginScript, script.contentWorld == contentWorld { + return true + } + } + return false + } + @available(macOS 11.0, *) public func containsPluginScript(with groupName: String, in contentWorld: WKContentWorld) -> Bool { let userScripts = useCopyOfUserScripts() diff --git a/flutter_inappwebview_macos/pubspec.yaml b/flutter_inappwebview_macos/pubspec.yaml index fab844bf..67647532 100644 --- a/flutter_inappwebview_macos/pubspec.yaml +++ b/flutter_inappwebview_macos/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_inappwebview_macos description: macOS implementation of the flutter_inappwebview plugin. -version: 1.0.6 +version: 1.0.7 homepage: https://inappwebview.dev/ repository: https://github.com/pichillilorenzo/flutter_inappwebview/tree/master/flutter_inappwebview_macos issue_tracker: https://github.com/pichillilorenzo/flutter_inappwebview/issues @@ -18,7 +18,7 @@ environment: dependencies: flutter: sdk: flutter - flutter_inappwebview_platform_interface: ^1.0.5 + flutter_inappwebview_platform_interface: ^1.0.6 dev_dependencies: flutter_test: diff --git a/flutter_inappwebview_platform_interface/CHANGELOG.md b/flutter_inappwebview_platform_interface/CHANGELOG.md index 2f6290ae..9484925b 100644 --- a/flutter_inappwebview_platform_interface/CHANGELOG.md +++ b/flutter_inappwebview_platform_interface/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.0.6 + +- Updated `InAppWebViewSettings.useShouldInterceptAjaxRequest` docs +- Added `InAppWebViewSettings.interceptOnlyAsyncAjaxRequests` [#1905](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1905) + ## 1.0.5 - Must call super `dispose` method for `PlatformInAppBrowser` and `PlatformChromeSafariBrowser` diff --git a/flutter_inappwebview_platform_interface/lib/src/in_app_webview/in_app_webview_settings.dart b/flutter_inappwebview_platform_interface/lib/src/in_app_webview/in_app_webview_settings.dart index 7599b599..8177772d 100755 --- a/flutter_inappwebview_platform_interface/lib/src/in_app_webview/in_app_webview_settings.dart +++ b/flutter_inappwebview_platform_interface/lib/src/in_app_webview/in_app_webview_settings.dart @@ -255,13 +255,28 @@ class InAppWebViewSettings_ { ///Set to `true` to be able to listen at the [PlatformWebViewCreationParams.shouldInterceptAjaxRequest] event. /// - ///If the [PlatformWebViewCreationParams.shouldInterceptAjaxRequest] event is implemented and this value is `null`, + ///Due to the async nature of [PlatformWebViewCreationParams.shouldInterceptAjaxRequest] event implementation, + ///it will intercept only async `XMLHttpRequest`s ([AjaxRequest.isAsync] with `true`). + ///To be able to intercept sync `XMLHttpRequest`s, use [InAppWebViewSettings.interceptOnlyAsyncAjaxRequests] to `false`. + /// + ///If the [PlatformWebViewCreationParams.shouldInterceptAjaxRequest] event or + ///any other Ajax event is implemented and this value is `null`, ///it will be automatically inferred as `true`, otherwise, the default value is `false`. ///This logic will not be applied for [PlatformInAppBrowser], where you must set the value manually. @SupportedPlatforms( platforms: [AndroidPlatform(), IOSPlatform(), MacOSPlatform()]) bool? useShouldInterceptAjaxRequest; + ///Set to `false` to be able to listen to also sync `XMLHttpRequest`s at the + ///[PlatformWebViewCreationParams.shouldInterceptAjaxRequest] event. + /// + ///**NOTE**: Using `false` will cause the `XMLHttpRequest.send()` method for sync + ///requests to not wait on the JavaScript code the response synchronously, + ///as if it was an async `XMLHttpRequest`. + @SupportedPlatforms( + platforms: [AndroidPlatform(), IOSPlatform(), MacOSPlatform()]) + bool? interceptOnlyAsyncAjaxRequests; + ///Set to `true` to be able to listen at the [PlatformWebViewCreationParams.shouldInterceptFetchRequest] event. /// ///If the [PlatformWebViewCreationParams.shouldInterceptFetchRequest] event is implemented and this value is `null`, @@ -1621,6 +1636,7 @@ as it can cause framerate drops on animations in Android 9 and lower (see [Hybri this.contentBlockers = const [], this.preferredContentMode = UserPreferredContentMode_.RECOMMENDED, this.useShouldInterceptAjaxRequest, + this.interceptOnlyAsyncAjaxRequests = true, this.useShouldInterceptFetchRequest, this.incognito = false, this.cacheEnabled = true, diff --git a/flutter_inappwebview_platform_interface/lib/src/in_app_webview/in_app_webview_settings.g.dart b/flutter_inappwebview_platform_interface/lib/src/in_app_webview/in_app_webview_settings.g.dart index d436b37c..d47bab86 100644 --- a/flutter_inappwebview_platform_interface/lib/src/in_app_webview/in_app_webview_settings.g.dart +++ b/flutter_inappwebview_platform_interface/lib/src/in_app_webview/in_app_webview_settings.g.dart @@ -589,6 +589,19 @@ class InAppWebViewSettings { ///- Android native WebView ([Official API - WebView.setInitialScale](https://developer.android.com/reference/android/webkit/WebView#setInitialScale(int))) int? initialScale; + ///Set to `false` to be able to listen to also sync `XMLHttpRequest`s at the + ///[PlatformWebViewCreationParams.shouldInterceptAjaxRequest] event. + /// + ///**NOTE**: Using `false` will cause the `XMLHttpRequest.send()` method for sync + ///requests to not wait on the JavaScript code the response synchronously, + ///as if it was an async `XMLHttpRequest`. + /// + ///**Officially Supported Platforms/Implementations**: + ///- Android native WebView + ///- iOS + ///- MacOS + bool? interceptOnlyAsyncAjaxRequests; + ///A Boolean value that determines whether scrolling is disabled in a particular direction. ///If this property is `false`, scrolling is permitted in both horizontal and vertical directions. ///If this property is `true` and the user begins dragging in one general direction (horizontally or vertically), @@ -1075,7 +1088,12 @@ class InAppWebViewSettings { ///Set to `true` to be able to listen at the [PlatformWebViewCreationParams.shouldInterceptAjaxRequest] event. /// - ///If the [PlatformWebViewCreationParams.shouldInterceptAjaxRequest] event is implemented and this value is `null`, + ///Due to the async nature of [PlatformWebViewCreationParams.shouldInterceptAjaxRequest] event implementation, + ///it will intercept only async `XMLHttpRequest`s ([AjaxRequest.isAsync] with `true`). + ///To be able to intercept sync `XMLHttpRequest`s, use [InAppWebViewSettings.interceptOnlyAsyncAjaxRequests] to `false`. + /// + ///If the [PlatformWebViewCreationParams.shouldInterceptAjaxRequest] event or + ///any other Ajax event is implemented and this value is `null`, ///it will be automatically inferred as `true`, otherwise, the default value is `false`. ///This logic will not be applied for [PlatformInAppBrowser], where you must set the value manually. /// @@ -1188,6 +1206,7 @@ class InAppWebViewSettings { this.contentBlockers = const [], this.preferredContentMode = UserPreferredContentMode.RECOMMENDED, this.useShouldInterceptAjaxRequest, + this.interceptOnlyAsyncAjaxRequests = true, this.useShouldInterceptFetchRequest, this.incognito = false, this.cacheEnabled = true, @@ -1477,6 +1496,8 @@ class InAppWebViewSettings { instance.ignoresViewportScaleLimits = map['ignoresViewportScaleLimits']; instance.incognito = map['incognito']; instance.initialScale = map['initialScale']; + instance.interceptOnlyAsyncAjaxRequests = + map['interceptOnlyAsyncAjaxRequests']; instance.isDirectionalLockEnabled = map['isDirectionalLockEnabled']; instance.isElementFullscreenEnabled = map['isElementFullscreenEnabled']; instance.isFindInteractionEnabled = map['isFindInteractionEnabled']; @@ -1616,6 +1637,7 @@ class InAppWebViewSettings { "ignoresViewportScaleLimits": ignoresViewportScaleLimits, "incognito": incognito, "initialScale": initialScale, + "interceptOnlyAsyncAjaxRequests": interceptOnlyAsyncAjaxRequests, "isDirectionalLockEnabled": isDirectionalLockEnabled, "isElementFullscreenEnabled": isElementFullscreenEnabled, "isFindInteractionEnabled": isFindInteractionEnabled, @@ -1703,6 +1725,6 @@ class InAppWebViewSettings { @override String toString() { - return 'InAppWebViewSettings{accessibilityIgnoresInvertColors: $accessibilityIgnoresInvertColors, algorithmicDarkeningAllowed: $algorithmicDarkeningAllowed, allowBackgroundAudioPlaying: $allowBackgroundAudioPlaying, allowContentAccess: $allowContentAccess, allowFileAccess: $allowFileAccess, allowFileAccessFromFileURLs: $allowFileAccessFromFileURLs, allowUniversalAccessFromFileURLs: $allowUniversalAccessFromFileURLs, allowingReadAccessTo: $allowingReadAccessTo, allowsAirPlayForMediaPlayback: $allowsAirPlayForMediaPlayback, allowsBackForwardNavigationGestures: $allowsBackForwardNavigationGestures, allowsInlineMediaPlayback: $allowsInlineMediaPlayback, allowsLinkPreview: $allowsLinkPreview, allowsPictureInPictureMediaPlayback: $allowsPictureInPictureMediaPlayback, alwaysBounceHorizontal: $alwaysBounceHorizontal, alwaysBounceVertical: $alwaysBounceVertical, appCachePath: $appCachePath, applePayAPIEnabled: $applePayAPIEnabled, applicationNameForUserAgent: $applicationNameForUserAgent, automaticallyAdjustsScrollIndicatorInsets: $automaticallyAdjustsScrollIndicatorInsets, blockNetworkImage: $blockNetworkImage, blockNetworkLoads: $blockNetworkLoads, builtInZoomControls: $builtInZoomControls, cacheEnabled: $cacheEnabled, cacheMode: $cacheMode, clearCache: $clearCache, clearSessionCache: $clearSessionCache, contentBlockers: $contentBlockers, contentInsetAdjustmentBehavior: $contentInsetAdjustmentBehavior, cursiveFontFamily: $cursiveFontFamily, dataDetectorTypes: $dataDetectorTypes, databaseEnabled: $databaseEnabled, decelerationRate: $decelerationRate, defaultFixedFontSize: $defaultFixedFontSize, defaultFontSize: $defaultFontSize, defaultTextEncodingName: $defaultTextEncodingName, defaultVideoPoster: $defaultVideoPoster, disableContextMenu: $disableContextMenu, disableDefaultErrorPage: $disableDefaultErrorPage, disableHorizontalScroll: $disableHorizontalScroll, disableInputAccessoryView: $disableInputAccessoryView, disableLongPressContextMenuOnLinks: $disableLongPressContextMenuOnLinks, disableVerticalScroll: $disableVerticalScroll, disabledActionModeMenuItems: $disabledActionModeMenuItems, disallowOverScroll: $disallowOverScroll, displayZoomControls: $displayZoomControls, domStorageEnabled: $domStorageEnabled, enableViewportScale: $enableViewportScale, enterpriseAuthenticationAppLinkPolicyEnabled: $enterpriseAuthenticationAppLinkPolicyEnabled, fantasyFontFamily: $fantasyFontFamily, fixedFontFamily: $fixedFontFamily, forceDark: $forceDark, forceDarkStrategy: $forceDarkStrategy, geolocationEnabled: $geolocationEnabled, hardwareAcceleration: $hardwareAcceleration, horizontalScrollBarEnabled: $horizontalScrollBarEnabled, horizontalScrollbarThumbColor: $horizontalScrollbarThumbColor, horizontalScrollbarTrackColor: $horizontalScrollbarTrackColor, iframeAllow: $iframeAllow, iframeAllowFullscreen: $iframeAllowFullscreen, iframeCsp: $iframeCsp, iframeName: $iframeName, iframeReferrerPolicy: $iframeReferrerPolicy, iframeSandbox: $iframeSandbox, ignoresViewportScaleLimits: $ignoresViewportScaleLimits, incognito: $incognito, initialScale: $initialScale, isDirectionalLockEnabled: $isDirectionalLockEnabled, isElementFullscreenEnabled: $isElementFullscreenEnabled, isFindInteractionEnabled: $isFindInteractionEnabled, isFraudulentWebsiteWarningEnabled: $isFraudulentWebsiteWarningEnabled, isInspectable: $isInspectable, isPagingEnabled: $isPagingEnabled, isSiteSpecificQuirksModeEnabled: $isSiteSpecificQuirksModeEnabled, isTextInteractionEnabled: $isTextInteractionEnabled, javaScriptCanOpenWindowsAutomatically: $javaScriptCanOpenWindowsAutomatically, javaScriptEnabled: $javaScriptEnabled, layoutAlgorithm: $layoutAlgorithm, limitsNavigationsToAppBoundDomains: $limitsNavigationsToAppBoundDomains, loadWithOverviewMode: $loadWithOverviewMode, loadsImagesAutomatically: $loadsImagesAutomatically, maximumViewportInset: $maximumViewportInset, maximumZoomScale: $maximumZoomScale, mediaPlaybackRequiresUserGesture: $mediaPlaybackRequiresUserGesture, mediaType: $mediaType, minimumFontSize: $minimumFontSize, minimumLogicalFontSize: $minimumLogicalFontSize, minimumViewportInset: $minimumViewportInset, minimumZoomScale: $minimumZoomScale, mixedContentMode: $mixedContentMode, needInitialFocus: $needInitialFocus, networkAvailable: $networkAvailable, offscreenPreRaster: $offscreenPreRaster, overScrollMode: $overScrollMode, pageZoom: $pageZoom, preferredContentMode: $preferredContentMode, regexToCancelSubFramesLoading: $regexToCancelSubFramesLoading, rendererPriorityPolicy: $rendererPriorityPolicy, requestedWithHeaderOriginAllowList: $requestedWithHeaderOriginAllowList, resourceCustomSchemes: $resourceCustomSchemes, safeBrowsingEnabled: $safeBrowsingEnabled, sansSerifFontFamily: $sansSerifFontFamily, saveFormData: $saveFormData, scrollBarDefaultDelayBeforeFade: $scrollBarDefaultDelayBeforeFade, scrollBarFadeDuration: $scrollBarFadeDuration, scrollBarStyle: $scrollBarStyle, scrollbarFadingEnabled: $scrollbarFadingEnabled, scrollsToTop: $scrollsToTop, selectionGranularity: $selectionGranularity, serifFontFamily: $serifFontFamily, sharedCookiesEnabled: $sharedCookiesEnabled, shouldPrintBackgrounds: $shouldPrintBackgrounds, standardFontFamily: $standardFontFamily, supportMultipleWindows: $supportMultipleWindows, supportZoom: $supportZoom, suppressesIncrementalRendering: $suppressesIncrementalRendering, textZoom: $textZoom, thirdPartyCookiesEnabled: $thirdPartyCookiesEnabled, transparentBackground: $transparentBackground, underPageBackgroundColor: $underPageBackgroundColor, upgradeKnownHostsToHTTPS: $upgradeKnownHostsToHTTPS, useHybridComposition: $useHybridComposition, useOnDownloadStart: $useOnDownloadStart, useOnLoadResource: $useOnLoadResource, useOnNavigationResponse: $useOnNavigationResponse, useOnRenderProcessGone: $useOnRenderProcessGone, useShouldInterceptAjaxRequest: $useShouldInterceptAjaxRequest, useShouldInterceptFetchRequest: $useShouldInterceptFetchRequest, useShouldInterceptRequest: $useShouldInterceptRequest, useShouldOverrideUrlLoading: $useShouldOverrideUrlLoading, useWideViewPort: $useWideViewPort, userAgent: $userAgent, verticalScrollBarEnabled: $verticalScrollBarEnabled, verticalScrollbarPosition: $verticalScrollbarPosition, verticalScrollbarThumbColor: $verticalScrollbarThumbColor, verticalScrollbarTrackColor: $verticalScrollbarTrackColor, webViewAssetLoader: $webViewAssetLoader}'; + return 'InAppWebViewSettings{accessibilityIgnoresInvertColors: $accessibilityIgnoresInvertColors, algorithmicDarkeningAllowed: $algorithmicDarkeningAllowed, allowBackgroundAudioPlaying: $allowBackgroundAudioPlaying, allowContentAccess: $allowContentAccess, allowFileAccess: $allowFileAccess, allowFileAccessFromFileURLs: $allowFileAccessFromFileURLs, allowUniversalAccessFromFileURLs: $allowUniversalAccessFromFileURLs, allowingReadAccessTo: $allowingReadAccessTo, allowsAirPlayForMediaPlayback: $allowsAirPlayForMediaPlayback, allowsBackForwardNavigationGestures: $allowsBackForwardNavigationGestures, allowsInlineMediaPlayback: $allowsInlineMediaPlayback, allowsLinkPreview: $allowsLinkPreview, allowsPictureInPictureMediaPlayback: $allowsPictureInPictureMediaPlayback, alwaysBounceHorizontal: $alwaysBounceHorizontal, alwaysBounceVertical: $alwaysBounceVertical, appCachePath: $appCachePath, applePayAPIEnabled: $applePayAPIEnabled, applicationNameForUserAgent: $applicationNameForUserAgent, automaticallyAdjustsScrollIndicatorInsets: $automaticallyAdjustsScrollIndicatorInsets, blockNetworkImage: $blockNetworkImage, blockNetworkLoads: $blockNetworkLoads, builtInZoomControls: $builtInZoomControls, cacheEnabled: $cacheEnabled, cacheMode: $cacheMode, clearCache: $clearCache, clearSessionCache: $clearSessionCache, contentBlockers: $contentBlockers, contentInsetAdjustmentBehavior: $contentInsetAdjustmentBehavior, cursiveFontFamily: $cursiveFontFamily, dataDetectorTypes: $dataDetectorTypes, databaseEnabled: $databaseEnabled, decelerationRate: $decelerationRate, defaultFixedFontSize: $defaultFixedFontSize, defaultFontSize: $defaultFontSize, defaultTextEncodingName: $defaultTextEncodingName, defaultVideoPoster: $defaultVideoPoster, disableContextMenu: $disableContextMenu, disableDefaultErrorPage: $disableDefaultErrorPage, disableHorizontalScroll: $disableHorizontalScroll, disableInputAccessoryView: $disableInputAccessoryView, disableLongPressContextMenuOnLinks: $disableLongPressContextMenuOnLinks, disableVerticalScroll: $disableVerticalScroll, disabledActionModeMenuItems: $disabledActionModeMenuItems, disallowOverScroll: $disallowOverScroll, displayZoomControls: $displayZoomControls, domStorageEnabled: $domStorageEnabled, enableViewportScale: $enableViewportScale, enterpriseAuthenticationAppLinkPolicyEnabled: $enterpriseAuthenticationAppLinkPolicyEnabled, fantasyFontFamily: $fantasyFontFamily, fixedFontFamily: $fixedFontFamily, forceDark: $forceDark, forceDarkStrategy: $forceDarkStrategy, geolocationEnabled: $geolocationEnabled, hardwareAcceleration: $hardwareAcceleration, horizontalScrollBarEnabled: $horizontalScrollBarEnabled, horizontalScrollbarThumbColor: $horizontalScrollbarThumbColor, horizontalScrollbarTrackColor: $horizontalScrollbarTrackColor, iframeAllow: $iframeAllow, iframeAllowFullscreen: $iframeAllowFullscreen, iframeCsp: $iframeCsp, iframeName: $iframeName, iframeReferrerPolicy: $iframeReferrerPolicy, iframeSandbox: $iframeSandbox, ignoresViewportScaleLimits: $ignoresViewportScaleLimits, incognito: $incognito, initialScale: $initialScale, interceptOnlyAsyncAjaxRequests: $interceptOnlyAsyncAjaxRequests, isDirectionalLockEnabled: $isDirectionalLockEnabled, isElementFullscreenEnabled: $isElementFullscreenEnabled, isFindInteractionEnabled: $isFindInteractionEnabled, isFraudulentWebsiteWarningEnabled: $isFraudulentWebsiteWarningEnabled, isInspectable: $isInspectable, isPagingEnabled: $isPagingEnabled, isSiteSpecificQuirksModeEnabled: $isSiteSpecificQuirksModeEnabled, isTextInteractionEnabled: $isTextInteractionEnabled, javaScriptCanOpenWindowsAutomatically: $javaScriptCanOpenWindowsAutomatically, javaScriptEnabled: $javaScriptEnabled, layoutAlgorithm: $layoutAlgorithm, limitsNavigationsToAppBoundDomains: $limitsNavigationsToAppBoundDomains, loadWithOverviewMode: $loadWithOverviewMode, loadsImagesAutomatically: $loadsImagesAutomatically, maximumViewportInset: $maximumViewportInset, maximumZoomScale: $maximumZoomScale, mediaPlaybackRequiresUserGesture: $mediaPlaybackRequiresUserGesture, mediaType: $mediaType, minimumFontSize: $minimumFontSize, minimumLogicalFontSize: $minimumLogicalFontSize, minimumViewportInset: $minimumViewportInset, minimumZoomScale: $minimumZoomScale, mixedContentMode: $mixedContentMode, needInitialFocus: $needInitialFocus, networkAvailable: $networkAvailable, offscreenPreRaster: $offscreenPreRaster, overScrollMode: $overScrollMode, pageZoom: $pageZoom, preferredContentMode: $preferredContentMode, regexToCancelSubFramesLoading: $regexToCancelSubFramesLoading, rendererPriorityPolicy: $rendererPriorityPolicy, requestedWithHeaderOriginAllowList: $requestedWithHeaderOriginAllowList, resourceCustomSchemes: $resourceCustomSchemes, safeBrowsingEnabled: $safeBrowsingEnabled, sansSerifFontFamily: $sansSerifFontFamily, saveFormData: $saveFormData, scrollBarDefaultDelayBeforeFade: $scrollBarDefaultDelayBeforeFade, scrollBarFadeDuration: $scrollBarFadeDuration, scrollBarStyle: $scrollBarStyle, scrollbarFadingEnabled: $scrollbarFadingEnabled, scrollsToTop: $scrollsToTop, selectionGranularity: $selectionGranularity, serifFontFamily: $serifFontFamily, sharedCookiesEnabled: $sharedCookiesEnabled, shouldPrintBackgrounds: $shouldPrintBackgrounds, standardFontFamily: $standardFontFamily, supportMultipleWindows: $supportMultipleWindows, supportZoom: $supportZoom, suppressesIncrementalRendering: $suppressesIncrementalRendering, textZoom: $textZoom, thirdPartyCookiesEnabled: $thirdPartyCookiesEnabled, transparentBackground: $transparentBackground, underPageBackgroundColor: $underPageBackgroundColor, upgradeKnownHostsToHTTPS: $upgradeKnownHostsToHTTPS, useHybridComposition: $useHybridComposition, useOnDownloadStart: $useOnDownloadStart, useOnLoadResource: $useOnLoadResource, useOnNavigationResponse: $useOnNavigationResponse, useOnRenderProcessGone: $useOnRenderProcessGone, useShouldInterceptAjaxRequest: $useShouldInterceptAjaxRequest, useShouldInterceptFetchRequest: $useShouldInterceptFetchRequest, useShouldInterceptRequest: $useShouldInterceptRequest, useShouldOverrideUrlLoading: $useShouldOverrideUrlLoading, useWideViewPort: $useWideViewPort, userAgent: $userAgent, verticalScrollBarEnabled: $verticalScrollBarEnabled, verticalScrollbarPosition: $verticalScrollbarPosition, verticalScrollbarThumbColor: $verticalScrollbarThumbColor, verticalScrollbarTrackColor: $verticalScrollbarTrackColor, webViewAssetLoader: $webViewAssetLoader}'; } } diff --git a/flutter_inappwebview_platform_interface/lib/src/in_app_webview/platform_webview.dart b/flutter_inappwebview_platform_interface/lib/src/in_app_webview/platform_webview.dart index 98c6133a..a4d4890d 100644 --- a/flutter_inappwebview_platform_interface/lib/src/in_app_webview/platform_webview.dart +++ b/flutter_inappwebview_platform_interface/lib/src/in_app_webview/platform_webview.dart @@ -403,6 +403,9 @@ class PlatformWebViewCreationParams { ///Event fired when an `XMLHttpRequest` is sent to a server. ///It gives the host application a chance to take control over the request before sending it. /// + ///Due to the async nature of this event implementation, it will intercept only async `XMLHttpRequest`s ([AjaxRequest.isAsync] with `true`). + ///To be able to intercept sync `XMLHttpRequest`s, use [InAppWebViewSettings.interceptOnlyAsyncAjaxRequests] to `false`. + /// ///[ajaxRequest] represents the `XMLHttpRequest`. /// ///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewSettings.useShouldInterceptAjaxRequest] setting to `true`. diff --git a/flutter_inappwebview_platform_interface/pubspec.yaml b/flutter_inappwebview_platform_interface/pubspec.yaml index 9a043901..ab199835 100644 --- a/flutter_inappwebview_platform_interface/pubspec.yaml +++ b/flutter_inappwebview_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_inappwebview_platform_interface description: A common platform interface for the flutter_inappwebview plugin. -version: 1.0.5 +version: 1.0.6 homepage: https://inappwebview.dev/ repository: https://github.com/pichillilorenzo/flutter_inappwebview/tree/master/flutter_inappwebview_platform_interface issue_tracker: https://github.com/pichillilorenzo/flutter_inappwebview/issues @@ -25,7 +25,7 @@ dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^2.0.0 - build_runner: ^2.2.1 + build_runner: ^2.4.0 generators: path: ../dev_packages/generators diff --git a/flutter_inappwebview_web/CHANGELOG.md b/flutter_inappwebview_web/CHANGELOG.md index 26105cdc..944174ca 100644 --- a/flutter_inappwebview_web/CHANGELOG.md +++ b/flutter_inappwebview_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.4 + +- Updated `flutter_inappwebview_platform_interface` version dependency to `1.0.6` + ## 1.0.3 - Fixed "Flutter 3.7.10 error Dart library 'dart:ui_web' is not available on this platform" [#1900](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1900) diff --git a/flutter_inappwebview_web/pubspec.yaml b/flutter_inappwebview_web/pubspec.yaml index b9de20d6..893cd69c 100644 --- a/flutter_inappwebview_web/pubspec.yaml +++ b/flutter_inappwebview_web/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_inappwebview_web description: Web implementation of the flutter_inappwebview plugin. -version: 1.0.3 +version: 1.0.4 homepage: https://inappwebview.dev/ repository: https://github.com/pichillilorenzo/flutter_inappwebview/tree/master/flutter_inappwebview_web issue_tracker: https://github.com/pichillilorenzo/flutter_inappwebview/issues @@ -21,7 +21,7 @@ dependencies: flutter_web_plugins: sdk: flutter js: ^0.6.4 - flutter_inappwebview_platform_interface: ^1.0.5 + flutter_inappwebview_platform_interface: ^1.0.6 dev_dependencies: flutter_test: