diff --git a/CHANGELOG.md b/CHANGELOG.md index e2b6601d..6217dddf 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 6.0.0-beta.22 + +- Updated `window.flutter_inappwebview.callHandler` implementation: if there is an error/exception on Flutter/Dart side, the `callHandler` will reject the JavaScript promise with the error/exception message, so you can catch it also on JavaScript side +- Fixed Android Web Storage Manager `deleteAllData` and `deleteOrigin` methods implementation +- Fixed "Xiaomi store - Conflict of Privacy Permissions, android.permission.MY_READ_INSTALLED_PACKAGES" [#1462](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1462) +- Fixed "Flutter 3.0.5 compilation issue" [#1475](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1475) + ## 6.0.0-beta.21 - Fixed "Android plugin version 6 - UserScripts not executing on new tabs." [#1455](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1455) @@ -174,6 +181,10 @@ - Removed `URLProtectionSpace.iosIsProxy` property - `historyUrl` and `baseUrl` of `InAppWebViewInitialData` can be `null` +## 5.7.2+3 + +- Fixed "Xiaomi store - Conflict of Privacy Permissions, android.permission.MY_READ_INSTALLED_PACKAGES" [#1462](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1462) + ## 5.7.2+2 - Fixed "Unexpected addWebMessageListener behaviour" [#1422](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1422) diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/MyCookieManager.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/MyCookieManager.java index dde98e41..20ef995c 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/MyCookieManager.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/MyCookieManager.java @@ -30,14 +30,21 @@ public class MyCookieManager extends ChannelDelegateImpl { @Nullable public InAppWebViewFlutterPlugin plugin; - public MyCookieManager(final InAppWebViewFlutterPlugin plugin) { + public MyCookieManager(@NonNull final InAppWebViewFlutterPlugin plugin) { super(new MethodChannel(plugin.messenger, METHOD_CHANNEL_NAME)); this.plugin = plugin; - cookieManager = getCookieManager(); + } + + public static void init() { + if (cookieManager == null) { + cookieManager = getCookieManager(); + } } @Override public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { + init(); + switch (call.method) { case "setCookie": { diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/MyWebStorage.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/MyWebStorage.java index b9ff890a..ad3cc982 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/MyWebStorage.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/MyWebStorage.java @@ -25,20 +25,27 @@ public class MyWebStorage extends ChannelDelegateImpl { @Nullable public InAppWebViewFlutterPlugin plugin; - public MyWebStorage(final InAppWebViewFlutterPlugin plugin) { + public MyWebStorage(@NonNull final InAppWebViewFlutterPlugin plugin) { super(new MethodChannel(plugin.messenger, METHOD_CHANNEL_NAME)); this.plugin = plugin; - webStorageManager = WebStorage.getInstance(); + } + + public static void init() { + if (webStorageManager == null) { + webStorageManager = WebStorage.getInstance(); + } } @Override public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { + init(); + switch (call.method) { case "getOrigins": getOrigins(result); break; case "deleteAllData": - if (webStorageManager == null) { + if (webStorageManager != null) { webStorageManager.deleteAllData(); result.success(true); } else { @@ -47,7 +54,7 @@ public class MyWebStorage extends ChannelDelegateImpl { break; case "deleteOrigin": { - if (webStorageManager == null) { + if (webStorageManager != null) { String origin = (String) call.argument("origin"); webStorageManager.deleteOrigin(origin); result.success(true); diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/WebViewFeatureManager.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/WebViewFeatureManager.java index ac38dd94..17f57baf 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/WebViewFeatureManager.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/WebViewFeatureManager.java @@ -16,7 +16,7 @@ public class WebViewFeatureManager extends ChannelDelegateImpl { @Nullable public InAppWebViewFlutterPlugin plugin; - public WebViewFeatureManager(final InAppWebViewFlutterPlugin plugin) { + public WebViewFeatureManager(@NonNull final InAppWebViewFlutterPlugin plugin) { super(new MethodChannel(plugin.messenger, METHOD_CHANNEL_NAME)); this.plugin = plugin; } diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/credential_database/CredentialDatabaseHandler.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/credential_database/CredentialDatabaseHandler.java index bb532a9e..eb1df65d 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/credential_database/CredentialDatabaseHandler.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/credential_database/CredentialDatabaseHandler.java @@ -30,14 +30,23 @@ public class CredentialDatabaseHandler extends ChannelDelegateImpl { @Nullable public InAppWebViewFlutterPlugin plugin; - public CredentialDatabaseHandler(final InAppWebViewFlutterPlugin plugin) { + public CredentialDatabaseHandler(@NonNull final InAppWebViewFlutterPlugin plugin) { super(new MethodChannel(plugin.messenger, METHOD_CHANNEL_NAME)); this.plugin = plugin; - credentialDatabase = CredentialDatabase.getInstance(plugin.applicationContext); + } + + public static void init(@NonNull InAppWebViewFlutterPlugin plugin) { + if (credentialDatabase == null) { + credentialDatabase = CredentialDatabase.getInstance(plugin.applicationContext); + } } @Override public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { + if (plugin != null) { + init(plugin); + } + switch (call.method) { case "getAllAuthCredentials": { diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/plugin_scripts_js/JavaScriptBridgeJS.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/plugin_scripts_js/JavaScriptBridgeJS.java index 792e5b1d..cfdf656d 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/plugin_scripts_js/JavaScriptBridgeJS.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/plugin_scripts_js/JavaScriptBridgeJS.java @@ -220,7 +220,7 @@ public class JavaScriptBridgeJS { " var _callHandlerID = setTimeout(function(){});" + " window." + JAVASCRIPT_BRIDGE_NAME + "._callHandler(arguments[0], _callHandlerID, JSON.stringify(Array.prototype.slice.call(arguments, 1)));" + " return new Promise(function(resolve, reject) {" + - " window." + JAVASCRIPT_BRIDGE_NAME + "[_callHandlerID] = resolve;" + + " window." + JAVASCRIPT_BRIDGE_NAME + "[_callHandlerID] = {resolve: resolve, reject: reject};" + " });" + " };" + " }"+ @@ -230,7 +230,7 @@ public class JavaScriptBridgeJS { " var _callHandlerID = setTimeout(function(){});" + " window.top." + JAVASCRIPT_BRIDGE_NAME + "._callHandler(arguments[0], _callHandlerID, JSON.stringify(Array.prototype.slice.call(arguments, 1)));" + " return new Promise(function(resolve, reject) {" + - " window.top." + JAVASCRIPT_BRIDGE_NAME + "[_callHandlerID] = resolve;" + + " window.top." + JAVASCRIPT_BRIDGE_NAME + "[_callHandlerID] = {resolve: resolve, reject: reject};" + " });" + " };" + "}" + diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/proxy/ProxyManager.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/proxy/ProxyManager.java index f2b5b07f..6b3b4a00 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/proxy/ProxyManager.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/proxy/ProxyManager.java @@ -25,18 +25,22 @@ public class ProxyManager extends ChannelDelegateImpl { @Nullable public InAppWebViewFlutterPlugin plugin; - public ProxyManager(final InAppWebViewFlutterPlugin plugin) { + public ProxyManager(@NonNull final InAppWebViewFlutterPlugin plugin) { super(new MethodChannel(plugin.messenger, METHOD_CHANNEL_NAME)); this.plugin = plugin; - if (WebViewFeature.isFeatureSupported(WebViewFeature.PROXY_OVERRIDE)) { + } + + public static void init() { + if (proxyController == null && + WebViewFeature.isFeatureSupported(WebViewFeature.PROXY_OVERRIDE)) { proxyController = ProxyController.getInstance(); - } else { - proxyController = null; } } @Override public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { + init(); + switch (call.method) { case "setProxyOverride": if (proxyController != null) { diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/service_worker/ServiceWorkerChannelDelegate.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/service_worker/ServiceWorkerChannelDelegate.java index 7c6a1b04..c59ea010 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/service_worker/ServiceWorkerChannelDelegate.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/service_worker/ServiceWorkerChannelDelegate.java @@ -36,6 +36,7 @@ public class ServiceWorkerChannelDelegate extends ChannelDelegateImpl { @SuppressLint("RestrictedApi") @Override public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { + ServiceWorkerManager.init(); ServiceWorkerControllerCompat serviceWorkerController = ServiceWorkerManager.serviceWorkerController; ServiceWorkerWebSettingsCompat serviceWorkerWebSettings = (serviceWorkerController != null) ? serviceWorkerController.getServiceWorkerWebSettings() : null; diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/service_worker/ServiceWorkerManager.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/service_worker/ServiceWorkerManager.java index b188ab0e..74a52800 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/service_worker/ServiceWorkerManager.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/service_worker/ServiceWorkerManager.java @@ -33,14 +33,16 @@ public class ServiceWorkerManager implements Disposable { @Nullable public InAppWebViewFlutterPlugin plugin; - public ServiceWorkerManager(final InAppWebViewFlutterPlugin plugin) { + public ServiceWorkerManager(@NonNull final InAppWebViewFlutterPlugin plugin) { this.plugin = plugin; final MethodChannel channel = new MethodChannel(plugin.messenger, METHOD_CHANNEL_NAME); this.channelDelegate = new ServiceWorkerChannelDelegate(this, channel); - if (WebViewFeature.isFeatureSupported(WebViewFeature.SERVICE_WORKER_BASIC_USAGE)) { + } + + public static void init() { + if (serviceWorkerController == null && + WebViewFeature.isFeatureSupported(WebViewFeature.SERVICE_WORKER_BASIC_USAGE)) { serviceWorkerController = ServiceWorkerControllerCompat.getInstance(); - } else { - serviceWorkerController = null; } } diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/tracing/TracingControllerChannelDelegate.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/tracing/TracingControllerChannelDelegate.java index d5e136a2..92293875 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/tracing/TracingControllerChannelDelegate.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/tracing/TracingControllerChannelDelegate.java @@ -27,6 +27,7 @@ public class TracingControllerChannelDelegate extends ChannelDelegateImpl { @Override public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { + TracingControllerManager.init(); TracingController tracingController = TracingControllerManager.tracingController; switch (call.method) { diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/tracing/TracingControllerManager.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/tracing/TracingControllerManager.java index 77aa3f99..3f46efa3 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/tracing/TracingControllerManager.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/tracing/TracingControllerManager.java @@ -1,6 +1,7 @@ package com.pichillilorenzo.flutter_inappwebview.tracing; import androidx.annotation.Nullable; +import androidx.webkit.ProxyController; import androidx.webkit.TracingConfig; import androidx.webkit.TracingController; import androidx.webkit.WebViewFeature; @@ -25,10 +26,12 @@ public class TracingControllerManager implements Disposable { this.plugin = plugin; final MethodChannel channel = new MethodChannel(plugin.messenger, METHOD_CHANNEL_NAME); this.channelDelegate = new TracingControllerChannelDelegate(this, channel); - if (WebViewFeature.isFeatureSupported(WebViewFeature.TRACING_CONTROLLER_BASIC_USAGE)) { + } + + public static void init() { + if (tracingController == null && + WebViewFeature.isFeatureSupported(WebViewFeature.TRACING_CONTROLLER_BASIC_USAGE)) { tracingController = TracingController.getInstance(); - } else { - tracingController = null; } } diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/JavaScriptBridgeInterface.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/JavaScriptBridgeInterface.java index 1eb0cede..fd872fa1 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/JavaScriptBridgeInterface.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/JavaScriptBridgeInterface.java @@ -130,7 +130,7 @@ public class JavaScriptBridgeInterface { return; } String sourceCode = "if (window." + JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + "[" + _callHandlerID + "] != null) { " + - "window." + JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + "[" + _callHandlerID + "](" + json + "); " + + "window." + JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + "[" + _callHandlerID + "].resolve(" + json + "); " + "delete window." + JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + "[" + _callHandlerID + "]; " + "}"; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { @@ -143,7 +143,24 @@ public class JavaScriptBridgeInterface { @Override public void error(String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails) { - Log.e(LOG_TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + String message = errorCode + ((errorMessage != null) ? ", " + errorMessage : ""); + Log.e(LOG_TAG, message); + + if (inAppWebView == null) { + // The webview has already been disposed, ignore. + return; + } + + String sourceCode = "if (window." + JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + "[" + _callHandlerID + "] != null) { " + + "window." + JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + "[" + _callHandlerID + "].reject(new Error(" + JSONObject.quote(message) + ")); " + + "delete window." + JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + "[" + _callHandlerID + "]; " + + "}"; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + inAppWebView.evaluateJavascript(sourceCode, (ValueCallback) null); + } + else { + inAppWebView.loadUrl("javascript:" + sourceCode); + } } }); } diff --git a/example/integration_test/chrome_safari_browser/open_and_close.dart b/example/integration_test/chrome_safari_browser/open_and_close.dart index 5b5a4d9e..336a79ef 100644 --- a/example/integration_test/chrome_safari_browser/open_and_close.dart +++ b/example/integration_test/chrome_safari_browser/open_and_close.dart @@ -45,7 +45,7 @@ void openAndClose() { activityButton: ActivityButton( templateImage: UIImage(systemName: "sun.max"), extensionIdentifier: - "com.pichillilorenzo.flutter-inappwebview6-example.test"))); + "com.pichillilorenzo.flutter-inappwebview-example6.test"))); await chromeSafariBrowser.opened.future; expect(chromeSafariBrowser.isOpened(), true); expect(() async { diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 52e55bba..48d9b6a7 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -451,7 +451,7 @@ MARKETING_VERSION = 1.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutter-inappwebview6-example.test"; + PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutter-inappwebview-example6.test"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; @@ -484,7 +484,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; MARKETING_VERSION = 1.0; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutter-inappwebview6-example.test"; + PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutter-inappwebview-example6.test"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; @@ -627,7 +627,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutter-inappwebview6-example"; + PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutter-inappwebview-example6"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -659,7 +659,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutter-inappwebview6-example"; + PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutter-inappwebview-example6"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; diff --git a/ios/Classes/InAppWebView/InAppWebView.swift b/ios/Classes/InAppWebView/InAppWebView.swift index 1506aab5..d8733865 100755 --- a/ios/Classes/InAppWebView/InAppWebView.swift +++ b/ios/Classes/InAppWebView/InAppWebView.swift @@ -2738,13 +2738,21 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, self.evaluateJavaScript(""" if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) { - window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)](\(json)); + window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)].resolve(\(json)); delete window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)]; } """, completionHandler: nil) } callback.error = { (code: String, message: String?, details: Any?) in - print(code + ", " + (message ?? "")) + let errorMessage = code + (message != nil ? ", " + (message ?? "") : "") + print(errorMessage) + + self.evaluateJavaScript(""" +if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) { + window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)].reject(new Error('\(errorMessage.replacingOccurrences(of: "\'", with: "\\'"))')); + delete window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)]; +} +""", completionHandler: nil) } if let channelDelegate = webView.channelDelegate { diff --git a/ios/Classes/PluginScriptsJS/JavaScriptBridgeJS.swift b/ios/Classes/PluginScriptsJS/JavaScriptBridgeJS.swift index cddca764..1549c28b 100644 --- a/ios/Classes/PluginScriptsJS/JavaScriptBridgeJS.swift +++ b/ios/Classes/PluginScriptsJS/JavaScriptBridgeJS.swift @@ -26,7 +26,7 @@ window.\(JAVASCRIPT_BRIDGE_NAME).callHandler = function() { var _callHandlerID = setTimeout(function(){}); window.webkit.messageHandlers['callHandler'].postMessage( {'handlerName': arguments[0], '_callHandlerID': _callHandlerID, 'args': JSON.stringify(Array.prototype.slice.call(arguments, 1)), '_windowId': _windowId} ); return new Promise(function(resolve, reject) { - window.\(JAVASCRIPT_BRIDGE_NAME)[_callHandlerID] = resolve; + window.\(JAVASCRIPT_BRIDGE_NAME)[_callHandlerID] = {resolve: resolve, reject: reject}; }); }; \(WEB_MESSAGE_LISTENER_JS_SOURCE) diff --git a/lib/src/in_app_browser/in_app_browser.dart b/lib/src/in_app_browser/in_app_browser.dart index 3fd65997..30199275 100755 --- a/lib/src/in_app_browser/in_app_browser.dart +++ b/lib/src/in_app_browser/in_app_browser.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:collection'; import 'dart:typed_data'; +import 'dart:ui'; import 'package:flutter/services.dart'; 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 50703aab..12ff13a7 100644 --- a/lib/src/in_app_webview/in_app_webview_controller.dart +++ b/lib/src/in_app_webview/in_app_webview_controller.dart @@ -1378,9 +1378,10 @@ class InAppWebViewController { // convert result to json try { return jsonEncode(await javaScriptHandlersMap[handlerName]!(args)); - } catch (error) { - developer.log(error.toString(), name: this.runtimeType.toString()); - return null; + } catch (error, stacktrace) { + developer.log(error.toString() + '\n' + stacktrace.toString(), + name: 'JavaScript Handler "$handlerName"'); + throw Exception(error.toString().replaceFirst('Exception: ', '')); } } break; diff --git a/lib/src/in_app_webview/in_app_webview_settings.dart b/lib/src/in_app_webview/in_app_webview_settings.dart index a0c4eb30..b5bb9f74 100755 --- a/lib/src/in_app_webview/in_app_webview_settings.dart +++ b/lib/src/in_app_webview/in_app_webview_settings.dart @@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_inappwebview/src/types/user_preferred_content_mode.dart'; import 'package:flutter_inappwebview_internal_annotations/flutter_inappwebview_internal_annotations.dart'; +import 'dart:typed_data'; import '../android/webview_asset_loader.dart'; import '../types/action_mode_menu_item.dart'; diff --git a/macos/Classes/InAppWebView/InAppWebView.swift b/macos/Classes/InAppWebView/InAppWebView.swift index 5c8bf04f..4c0b8944 100755 --- a/macos/Classes/InAppWebView/InAppWebView.swift +++ b/macos/Classes/InAppWebView/InAppWebView.swift @@ -2102,13 +2102,21 @@ public class InAppWebView: WKWebView, WKUIDelegate, self.evaluateJavaScript(""" if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) { - window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)](\(json)); + window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)].resolve(\(json)); delete window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)]; } """, completionHandler: nil) } callback.error = { (code: String, message: String?, details: Any?) in - print(code + ", " + (message ?? "")) + let errorMessage = code + (message != nil ? ", " + (message ?? "") : "") + print(errorMessage) + + self.evaluateJavaScript(""" +if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) { + window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)].reject(new Error('\(errorMessage.replacingOccurrences(of: "\'", with: "\\'"))')); + delete window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)]; +} +""", completionHandler: nil) } if let channelDelegate = webView.channelDelegate { diff --git a/macos/Classes/PluginScriptsJS/JavaScriptBridgeJS.swift b/macos/Classes/PluginScriptsJS/JavaScriptBridgeJS.swift index cddca764..1549c28b 100644 --- a/macos/Classes/PluginScriptsJS/JavaScriptBridgeJS.swift +++ b/macos/Classes/PluginScriptsJS/JavaScriptBridgeJS.swift @@ -26,7 +26,7 @@ window.\(JAVASCRIPT_BRIDGE_NAME).callHandler = function() { var _callHandlerID = setTimeout(function(){}); window.webkit.messageHandlers['callHandler'].postMessage( {'handlerName': arguments[0], '_callHandlerID': _callHandlerID, 'args': JSON.stringify(Array.prototype.slice.call(arguments, 1)), '_windowId': _windowId} ); return new Promise(function(resolve, reject) { - window.\(JAVASCRIPT_BRIDGE_NAME)[_callHandlerID] = resolve; + window.\(JAVASCRIPT_BRIDGE_NAME)[_callHandlerID] = {resolve: resolve, reject: reject}; }); }; \(WEB_MESSAGE_LISTENER_JS_SOURCE) diff --git a/pubspec.yaml b/pubspec.yaml index c1deee90..36f66988 100755 --- a/pubspec.yaml +++ b/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.21 +version: 6.0.0-beta.22 homepage: https://inappwebview.dev/ repository: https://github.com/pichillilorenzo/flutter_inappwebview issue_tracker: https://github.com/pichillilorenzo/flutter_inappwebview/issues