Added InAppWebView keep alive feature, Added hasJavaScriptHandler, hasUserScript, hasWebMessageListener InAppWebViewController methods, HeadlessInAppWebView.webViewController could be null, Removed throwIfAlreadyOpened, throwIfNotOpened InAppBrowser methods, Removed throwIfAlreadyOpened, throwIfNotOpened ChromeSafariBrowser methods
This commit is contained in:
parent
b6725128a8
commit
5a113f6e8a
|
@ -1,5 +1,10 @@
|
||||||
## 6.0.0-beta.24
|
## 6.0.0-beta.24
|
||||||
|
|
||||||
|
- Added InAppWebView keep alive feature
|
||||||
|
- Added `hasJavaScriptHandler`, `hasUserScript`, `hasWebMessageListener` InAppWebViewController methods
|
||||||
|
- `HeadlessInAppWebView.webViewController` could be `null`
|
||||||
|
- Removed `throwIfAlreadyOpened`, `throwIfNotOpened` InAppBrowser methods
|
||||||
|
- Removed `throwIfAlreadyOpened`, `throwIfNotOpened` ChromeSafariBrowser methods
|
||||||
- Merged "fix #1389 #1315 contextMenu ios 13" [#1575](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1575) (thanks to [heralight](https://github.com/heralight))
|
- Merged "fix #1389 #1315 contextMenu ios 13" [#1575](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1575) (thanks to [heralight](https://github.com/heralight))
|
||||||
- Merged "fix: remove ignored flutter_export_environment.sh" [#1593](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1593) (thanks to [Sunbreak](https://github.com/Sunbreak))
|
- Merged "fix: remove ignored flutter_export_environment.sh" [#1593](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1593) (thanks to [Sunbreak](https://github.com/Sunbreak))
|
||||||
- Merged "Fix AndroidX migration URL in README.md" [#1529](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1529) (thanks to [cslee](https://github.com/cslee))
|
- Merged "Fix AndroidX migration URL in README.md" [#1529](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1529) (thanks to [cslee](https://github.com/cslee))
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
package com.pichillilorenzo.flutter_inappwebview;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import com.pichillilorenzo.flutter_inappwebview.headless_in_app_webview.HeadlessInAppWebView;
|
|
||||||
import com.pichillilorenzo.flutter_inappwebview.headless_in_app_webview.HeadlessInAppWebViewManager;
|
|
||||||
import com.pichillilorenzo.flutter_inappwebview.webview.in_app_webview.FlutterWebView;
|
|
||||||
import com.pichillilorenzo.flutter_inappwebview.webview.PlatformWebView;
|
|
||||||
import com.pichillilorenzo.flutter_inappwebview.types.WebViewImplementation;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import io.flutter.plugin.common.StandardMessageCodec;
|
|
||||||
import io.flutter.plugin.platform.PlatformView;
|
|
||||||
import io.flutter.plugin.platform.PlatformViewFactory;
|
|
||||||
|
|
||||||
public class FlutterWebViewFactory extends PlatformViewFactory {
|
|
||||||
public static final String VIEW_TYPE_ID = "com.pichillilorenzo/flutter_inappwebview";
|
|
||||||
private final InAppWebViewFlutterPlugin plugin;
|
|
||||||
|
|
||||||
public FlutterWebViewFactory(final InAppWebViewFlutterPlugin plugin) {
|
|
||||||
super(StandardMessageCodec.INSTANCE);
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PlatformView create(Context context, int id, Object args) {
|
|
||||||
HashMap<String, Object> params = (HashMap<String, Object>) args;
|
|
||||||
PlatformWebView flutterWebView = null;
|
|
||||||
|
|
||||||
String headlessWebViewId = (String) params.get("headlessWebViewId");
|
|
||||||
if (headlessWebViewId != null) {
|
|
||||||
HeadlessInAppWebView headlessInAppWebView = HeadlessInAppWebViewManager.webViews.get(headlessWebViewId);
|
|
||||||
if (headlessInAppWebView != null) {
|
|
||||||
flutterWebView = headlessInAppWebView.disposeAndGetFlutterWebView();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flutterWebView == null) {
|
|
||||||
WebViewImplementation implementation = WebViewImplementation.fromValue((Integer) params.get("implementation"));
|
|
||||||
switch (implementation) {
|
|
||||||
case NATIVE:
|
|
||||||
default:
|
|
||||||
flutterWebView = new FlutterWebView(plugin, context, id, params);
|
|
||||||
}
|
|
||||||
flutterWebView.makeInitialLoad(params);
|
|
||||||
}
|
|
||||||
|
|
||||||
return flutterWebView;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -17,6 +17,8 @@ import com.pichillilorenzo.flutter_inappwebview.print_job.PrintJobManager;
|
||||||
import com.pichillilorenzo.flutter_inappwebview.proxy.ProxyManager;
|
import com.pichillilorenzo.flutter_inappwebview.proxy.ProxyManager;
|
||||||
import com.pichillilorenzo.flutter_inappwebview.service_worker.ServiceWorkerManager;
|
import com.pichillilorenzo.flutter_inappwebview.service_worker.ServiceWorkerManager;
|
||||||
import com.pichillilorenzo.flutter_inappwebview.tracing.TracingControllerManager;
|
import com.pichillilorenzo.flutter_inappwebview.tracing.TracingControllerManager;
|
||||||
|
import com.pichillilorenzo.flutter_inappwebview.webview.FlutterWebViewFactory;
|
||||||
|
import com.pichillilorenzo.flutter_inappwebview.webview.InAppWebViewManager;
|
||||||
|
|
||||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
|
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
|
||||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
|
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
|
||||||
|
@ -39,7 +41,7 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
|
||||||
@Nullable
|
@Nullable
|
||||||
public ChromeSafariBrowserManager chromeSafariBrowserManager;
|
public ChromeSafariBrowserManager chromeSafariBrowserManager;
|
||||||
@Nullable
|
@Nullable
|
||||||
public InAppWebViewStatic inAppWebViewStatic;
|
public InAppWebViewManager inAppWebViewManager;
|
||||||
@Nullable
|
@Nullable
|
||||||
public MyCookieManager myCookieManager;
|
public MyCookieManager myCookieManager;
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -56,11 +58,6 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
|
||||||
public PrintJobManager printJobManager;
|
public PrintJobManager printJobManager;
|
||||||
@Nullable
|
@Nullable
|
||||||
public TracingControllerManager tracingControllerManager;
|
public TracingControllerManager tracingControllerManager;
|
||||||
@Nullable
|
|
||||||
public static ValueCallback<Uri> filePathCallbackLegacy;
|
|
||||||
@Nullable
|
|
||||||
public static ValueCallback<Uri[]> filePathCallback;
|
|
||||||
|
|
||||||
public FlutterWebViewFactory flutterWebViewFactory;
|
public FlutterWebViewFactory flutterWebViewFactory;
|
||||||
public Context applicationContext;
|
public Context applicationContext;
|
||||||
public PluginRegistry.Registrar registrar;
|
public PluginRegistry.Registrar registrar;
|
||||||
|
@ -110,7 +107,7 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
|
||||||
FlutterWebViewFactory.VIEW_TYPE_ID, flutterWebViewFactory);
|
FlutterWebViewFactory.VIEW_TYPE_ID, flutterWebViewFactory);
|
||||||
|
|
||||||
platformUtil = new PlatformUtil(this);
|
platformUtil = new PlatformUtil(this);
|
||||||
inAppWebViewStatic = new InAppWebViewStatic(this);
|
inAppWebViewManager = new InAppWebViewManager(this);
|
||||||
myCookieManager = new MyCookieManager(this);
|
myCookieManager = new MyCookieManager(this);
|
||||||
myWebStorage = new MyWebStorage(this);
|
myWebStorage = new MyWebStorage(this);
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
@ -122,7 +119,7 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
|
||||||
webViewFeatureManager = new WebViewFeatureManager(this);
|
webViewFeatureManager = new WebViewFeatureManager(this);
|
||||||
proxyManager = new ProxyManager(this);
|
proxyManager = new ProxyManager(this);
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
printJobManager = new PrintJobManager();
|
printJobManager = new PrintJobManager(this);
|
||||||
}
|
}
|
||||||
tracingControllerManager = new TracingControllerManager(this);
|
tracingControllerManager = new TracingControllerManager(this);
|
||||||
}
|
}
|
||||||
|
@ -157,9 +154,9 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
|
||||||
credentialDatabaseHandler.dispose();
|
credentialDatabaseHandler.dispose();
|
||||||
credentialDatabaseHandler = null;
|
credentialDatabaseHandler = null;
|
||||||
}
|
}
|
||||||
if (inAppWebViewStatic != null) {
|
if (inAppWebViewManager != null) {
|
||||||
inAppWebViewStatic.dispose();
|
inAppWebViewManager.dispose();
|
||||||
inAppWebViewStatic = null;
|
inAppWebViewManager = null;
|
||||||
}
|
}
|
||||||
if (serviceWorkerManager != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
if (serviceWorkerManager != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
serviceWorkerManager.dispose();
|
serviceWorkerManager.dispose();
|
||||||
|
@ -181,8 +178,6 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
|
||||||
tracingControllerManager.dispose();
|
tracingControllerManager.dispose();
|
||||||
tracingControllerManager = null;
|
tracingControllerManager = null;
|
||||||
}
|
}
|
||||||
filePathCallbackLegacy = null;
|
|
||||||
filePathCallback = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -393,6 +393,5 @@ public class MyCookieManager extends ChannelDelegateImpl {
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
plugin = null;
|
plugin = null;
|
||||||
cookieManager = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,6 +134,5 @@ public class MyWebStorage extends ChannelDelegateImpl {
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
plugin = null;
|
plugin = null;
|
||||||
webStorageManager = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ public class ActionBroadcastReceiver extends BroadcastReceiver {
|
||||||
protected static final String LOG_TAG = "ActionBroadcastReceiver";
|
protected static final String LOG_TAG = "ActionBroadcastReceiver";
|
||||||
public static final String KEY_ACTION_ID = "com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ACTION_ID";
|
public static final String KEY_ACTION_ID = "com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ACTION_ID";
|
||||||
public static final String KEY_ACTION_VIEW_ID = "com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ACTION_VIEW_ID";
|
public static final String KEY_ACTION_VIEW_ID = "com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ACTION_VIEW_ID";
|
||||||
|
public static final String KEY_ACTION_MANAGER_ID = "com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ACTION_MANAGER_ID";
|
||||||
public static final String KEY_URL_TITLE = "android.intent.extra.SUBJECT";
|
public static final String KEY_URL_TITLE = "android.intent.extra.SUBJECT";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -21,17 +22,21 @@ public class ActionBroadcastReceiver extends BroadcastReceiver {
|
||||||
if (url != null) {
|
if (url != null) {
|
||||||
Bundle b = intent.getExtras();
|
Bundle b = intent.getExtras();
|
||||||
String viewId = b.getString(KEY_ACTION_VIEW_ID);
|
String viewId = b.getString(KEY_ACTION_VIEW_ID);
|
||||||
|
String managerId = b.getString(KEY_ACTION_MANAGER_ID);
|
||||||
|
|
||||||
|
if (managerId != null) {
|
||||||
|
ChromeSafariBrowserManager chromeSafariBrowserManager = ChromeSafariBrowserManager.shared.get(managerId);
|
||||||
|
if (chromeSafariBrowserManager != null) {
|
||||||
if (clickedId == -1) {
|
if (clickedId == -1) {
|
||||||
int id = b.getInt(KEY_ACTION_ID);
|
int id = b.getInt(KEY_ACTION_ID);
|
||||||
String title = b.getString(KEY_URL_TITLE);
|
String title = b.getString(KEY_URL_TITLE);
|
||||||
|
|
||||||
ChromeCustomTabsActivity browser = ChromeSafariBrowserManager.browsers.get(viewId);
|
ChromeCustomTabsActivity browser = chromeSafariBrowserManager.browsers.get(viewId);
|
||||||
if (browser != null && browser.channelDelegate != null) {
|
if (browser != null && browser.channelDelegate != null) {
|
||||||
browser.channelDelegate.onItemActionPerform(id, url, title);
|
browser.channelDelegate.onItemActionPerform(id, url, title);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ChromeCustomTabsActivity browser = ChromeSafariBrowserManager.browsers.get(viewId);
|
ChromeCustomTabsActivity browser = chromeSafariBrowserManager.browsers.get(viewId);
|
||||||
if (browser != null && browser.channelDelegate != null) {
|
if (browser != null && browser.channelDelegate != null) {
|
||||||
browser.channelDelegate.onSecondaryItemActionPerform(browser.getResources().getResourceName(clickedId), url);
|
browser.channelDelegate.onSecondaryItemActionPerform(browser.getResources().getResourceName(clickedId), url);
|
||||||
}
|
}
|
||||||
|
@ -39,3 +44,5 @@ public class ActionBroadcastReceiver extends BroadcastReceiver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ public class ChromeCustomTabsActivity extends Activity implements Disposable {
|
||||||
manager = ChromeSafariBrowserManager.shared.get(managerId);
|
manager = ChromeSafariBrowserManager.shared.get(managerId);
|
||||||
if (manager == null || manager.plugin == null || manager.plugin.messenger == null) return;
|
if (manager == null || manager.plugin == null || manager.plugin.messenger == null) return;
|
||||||
|
|
||||||
ChromeSafariBrowserManager.browsers.put(id, this);
|
manager.browsers.put(id, this);
|
||||||
|
|
||||||
MethodChannel channel = new MethodChannel(manager.plugin.messenger, METHOD_CHANNEL_NAME_PREFIX + id);
|
MethodChannel channel = new MethodChannel(manager.plugin.messenger, METHOD_CHANNEL_NAME_PREFIX + id);
|
||||||
channelDelegate = new ChromeCustomTabsChannelDelegate(this, channel);
|
channelDelegate = new ChromeCustomTabsChannelDelegate(this, channel);
|
||||||
|
@ -271,6 +271,7 @@ public class ChromeCustomTabsActivity extends Activity implements Disposable {
|
||||||
|
|
||||||
Bundle extras = new Bundle();
|
Bundle extras = new Bundle();
|
||||||
extras.putString(ActionBroadcastReceiver.KEY_ACTION_VIEW_ID, id);
|
extras.putString(ActionBroadcastReceiver.KEY_ACTION_VIEW_ID, id);
|
||||||
|
extras.putString(ActionBroadcastReceiver.KEY_ACTION_MANAGER_ID, manager != null ? manager.id : null);
|
||||||
broadcastIntent.putExtras(extras);
|
broadcastIntent.putExtras(extras);
|
||||||
|
|
||||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
|
@ -355,6 +356,7 @@ public class ChromeCustomTabsActivity extends Activity implements Disposable {
|
||||||
Bundle extras = new Bundle();
|
Bundle extras = new Bundle();
|
||||||
extras.putInt(ActionBroadcastReceiver.KEY_ACTION_ID, actionSourceId);
|
extras.putInt(ActionBroadcastReceiver.KEY_ACTION_ID, actionSourceId);
|
||||||
extras.putString(ActionBroadcastReceiver.KEY_ACTION_VIEW_ID, id);
|
extras.putString(ActionBroadcastReceiver.KEY_ACTION_VIEW_ID, id);
|
||||||
|
extras.putString(ActionBroadcastReceiver.KEY_ACTION_MANAGER_ID, manager != null ? manager.id : null);
|
||||||
actionIntent.putExtras(extras);
|
actionIntent.putExtras(extras);
|
||||||
|
|
||||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
|
@ -374,8 +376,10 @@ public class ChromeCustomTabsActivity extends Activity implements Disposable {
|
||||||
channelDelegate.dispose();
|
channelDelegate.dispose();
|
||||||
channelDelegate = null;
|
channelDelegate = null;
|
||||||
}
|
}
|
||||||
if (ChromeSafariBrowserManager.browsers.containsKey(id)) {
|
if (manager != null) {
|
||||||
ChromeSafariBrowserManager.browsers.put(id, null);
|
if (manager.browsers.containsKey(id)) {
|
||||||
|
manager.browsers.put(id, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
manager = null;
|
manager = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ public class ChromeSafariBrowserManager extends ChannelDelegateImpl {
|
||||||
public InAppWebViewFlutterPlugin plugin;
|
public InAppWebViewFlutterPlugin plugin;
|
||||||
public String id;
|
public String id;
|
||||||
public static final Map<String, ChromeSafariBrowserManager> shared = new HashMap<>();
|
public static final Map<String, ChromeSafariBrowserManager> shared = new HashMap<>();
|
||||||
public static final Map<String, ChromeCustomTabsActivity> browsers = new HashMap<>();
|
public final Map<String, ChromeCustomTabsActivity> browsers = new HashMap<>();
|
||||||
|
|
||||||
public ChromeSafariBrowserManager(final InAppWebViewFlutterPlugin plugin) {
|
public ChromeSafariBrowserManager(final InAppWebViewFlutterPlugin plugin) {
|
||||||
super(new MethodChannel(plugin.messenger, METHOD_CHANNEL_NAME));
|
super(new MethodChannel(plugin.messenger, METHOD_CHANNEL_NAME));
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.pichillilorenzo.flutter_inappwebview.headless_in_app_webview;
|
package com.pichillilorenzo.flutter_inappwebview.headless_in_app_webview;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
@ -130,10 +131,13 @@ public class HeadlessInAppWebView implements Disposable {
|
||||||
channelDelegate.dispose();
|
channelDelegate.dispose();
|
||||||
channelDelegate = null;
|
channelDelegate = null;
|
||||||
}
|
}
|
||||||
if (HeadlessInAppWebViewManager.webViews.containsKey(id)) {
|
if (plugin != null) {
|
||||||
HeadlessInAppWebViewManager.webViews.put(id, null);
|
HeadlessInAppWebViewManager headlessInAppWebViewManager = plugin.headlessInAppWebViewManager;
|
||||||
|
if (headlessInAppWebViewManager != null && headlessInAppWebViewManager.webViews.containsKey(id)) {
|
||||||
|
headlessInAppWebViewManager.webViews.put(id, null);
|
||||||
}
|
}
|
||||||
if (plugin != null && plugin.activity != null) {
|
Activity activity = plugin.activity;
|
||||||
|
if (activity != null) {
|
||||||
ViewGroup contentView = plugin.activity.findViewById(android.R.id.content);
|
ViewGroup contentView = plugin.activity.findViewById(android.R.id.content);
|
||||||
if (contentView != null) {
|
if (contentView != null) {
|
||||||
ViewGroup mainView = (ViewGroup) (contentView).getChildAt(0);
|
ViewGroup mainView = (ViewGroup) (contentView).getChildAt(0);
|
||||||
|
@ -145,6 +149,7 @@ public class HeadlessInAppWebView implements Disposable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (flutterWebView != null) {
|
if (flutterWebView != null) {
|
||||||
flutterWebView.dispose();
|
flutterWebView.dispose();
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class HeadlessInAppWebViewManager extends ChannelDelegateImpl {
|
||||||
protected static final String LOG_TAG = "HeadlessInAppWebViewManager";
|
protected static final String LOG_TAG = "HeadlessInAppWebViewManager";
|
||||||
public static final String METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_headless_inappwebview";
|
public static final String METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_headless_inappwebview";
|
||||||
|
|
||||||
public static final Map<String, HeadlessInAppWebView> webViews = new HashMap<>();
|
public final Map<String, HeadlessInAppWebView> webViews = new HashMap<>();
|
||||||
@Nullable
|
@Nullable
|
||||||
public InAppWebViewFlutterPlugin plugin;
|
public InAppWebViewFlutterPlugin plugin;
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ public class HeadlessInAppWebViewManager extends ChannelDelegateImpl {
|
||||||
}
|
}
|
||||||
FlutterWebView flutterWebView = new FlutterWebView(plugin, context, id, params);
|
FlutterWebView flutterWebView = new FlutterWebView(plugin, context, id, params);
|
||||||
HeadlessInAppWebView headlessInAppWebView = new HeadlessInAppWebView(plugin, id, flutterWebView);
|
HeadlessInAppWebView headlessInAppWebView = new HeadlessInAppWebView(plugin, id, flutterWebView);
|
||||||
HeadlessInAppWebViewManager.webViews.put(id, headlessInAppWebView);
|
webViews.put(id, headlessInAppWebView);
|
||||||
|
|
||||||
headlessInAppWebView.prepare(params);
|
headlessInAppWebView.prepare(params);
|
||||||
headlessInAppWebView.onWebViewCreated();
|
headlessInAppWebView.onWebViewCreated();
|
||||||
|
@ -93,5 +93,6 @@ public class HeadlessInAppWebViewManager extends ChannelDelegateImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
webViews.clear();
|
webViews.clear();
|
||||||
|
plugin = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,11 +141,13 @@ public class InAppBrowserActivity extends AppCompatActivity implements InAppBrow
|
||||||
prepareView();
|
prepareView();
|
||||||
|
|
||||||
if (windowId != -1) {
|
if (windowId != -1) {
|
||||||
Message resultMsg = InAppWebViewChromeClient.windowWebViewMessages.get(windowId);
|
if (webView.plugin != null && webView.plugin.inAppWebViewManager != null) {
|
||||||
|
Message resultMsg = webView.plugin.inAppWebViewManager.windowWebViewMessages.get(windowId);
|
||||||
if (resultMsg != null) {
|
if (resultMsg != null) {
|
||||||
((WebView.WebViewTransport) resultMsg.obj).setWebView(webView);
|
((WebView.WebViewTransport) resultMsg.obj).setWebView(webView);
|
||||||
resultMsg.sendToTarget();
|
resultMsg.sendToTarget();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
String initialFile = b.getString("initialFile");
|
String initialFile = b.getString("initialFile");
|
||||||
Map<String, Object> initialUrlRequest = (Map<String, Object>) b.getSerializable("initialUrlRequest");
|
Map<String, Object> initialUrlRequest = (Map<String, Object>) b.getSerializable("initialUrlRequest");
|
||||||
|
|
|
@ -21,6 +21,8 @@ public class PrintJobController implements Disposable {
|
||||||
@NonNull
|
@NonNull
|
||||||
public String id;
|
public String id;
|
||||||
@Nullable
|
@Nullable
|
||||||
|
public InAppWebViewFlutterPlugin plugin;
|
||||||
|
@Nullable
|
||||||
public PrintJobChannelDelegate channelDelegate;
|
public PrintJobChannelDelegate channelDelegate;
|
||||||
@Nullable
|
@Nullable
|
||||||
public android.print.PrintJob job;
|
public android.print.PrintJob job;
|
||||||
|
@ -30,6 +32,7 @@ public class PrintJobController implements Disposable {
|
||||||
public PrintJobController(@NonNull String id, @NonNull android.print.PrintJob job,
|
public PrintJobController(@NonNull String id, @NonNull android.print.PrintJob job,
|
||||||
@Nullable PrintJobSettings settings, @NonNull InAppWebViewFlutterPlugin plugin) {
|
@Nullable PrintJobSettings settings, @NonNull InAppWebViewFlutterPlugin plugin) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
this.plugin = plugin;
|
||||||
this.job = job;
|
this.job = job;
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
final MethodChannel channel = new MethodChannel(plugin.messenger, METHOD_CHANNEL_NAME_PREFIX + id);
|
final MethodChannel channel = new MethodChannel(plugin.messenger, METHOD_CHANNEL_NAME_PREFIX + id);
|
||||||
|
@ -61,12 +64,16 @@ public class PrintJobController implements Disposable {
|
||||||
channelDelegate.dispose();
|
channelDelegate.dispose();
|
||||||
channelDelegate = null;
|
channelDelegate = null;
|
||||||
}
|
}
|
||||||
if (PrintJobManager.jobs.containsKey(id)) {
|
if (plugin != null) {
|
||||||
PrintJobManager.jobs.put(id, null);
|
PrintJobManager printJobManager = plugin.printJobManager;
|
||||||
|
if (printJobManager != null && printJobManager.jobs.containsKey(id)) {
|
||||||
|
printJobManager.jobs.put(id, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (job != null) {
|
if (job != null) {
|
||||||
job = null;
|
job = null;
|
||||||
}
|
}
|
||||||
|
plugin = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -75,12 +82,16 @@ public class PrintJobController implements Disposable {
|
||||||
channelDelegate.dispose();
|
channelDelegate.dispose();
|
||||||
channelDelegate = null;
|
channelDelegate = null;
|
||||||
}
|
}
|
||||||
if (PrintJobManager.jobs.containsKey(id)) {
|
if (plugin != null) {
|
||||||
PrintJobManager.jobs.put(id, null);
|
PrintJobManager printJobManager = plugin.printJobManager;
|
||||||
|
if (printJobManager != null && printJobManager.jobs.containsKey(id)) {
|
||||||
|
printJobManager.jobs.put(id, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (job != null) {
|
if (job != null) {
|
||||||
job.cancel();
|
job.cancel();
|
||||||
job = null;
|
job = null;
|
||||||
}
|
}
|
||||||
|
plugin = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,11 @@ package com.pichillilorenzo.flutter_inappwebview.print_job;
|
||||||
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
|
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
|
||||||
import com.pichillilorenzo.flutter_inappwebview.types.Disposable;
|
import com.pichillilorenzo.flutter_inappwebview.types.Disposable;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -34,11 +37,13 @@ import java.util.Map;
|
||||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||||
public class PrintJobManager implements Disposable {
|
public class PrintJobManager implements Disposable {
|
||||||
protected static final String LOG_TAG = "PrintJobManager";
|
protected static final String LOG_TAG = "PrintJobManager";
|
||||||
|
@Nullable
|
||||||
|
public InAppWebViewFlutterPlugin plugin;
|
||||||
|
public final Map<String, PrintJobController> jobs = new HashMap<>();
|
||||||
|
|
||||||
public static final Map<String, PrintJobController> jobs = new HashMap<>();
|
public PrintJobManager(@NonNull final InAppWebViewFlutterPlugin plugin) {
|
||||||
|
|
||||||
public PrintJobManager() {
|
|
||||||
super();
|
super();
|
||||||
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
|
@ -49,5 +54,6 @@ public class PrintJobManager implements Disposable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jobs.clear();
|
jobs.clear();
|
||||||
|
plugin = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,21 +124,6 @@ public class ProxyManager extends ChannelDelegateImpl {
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
if (proxyController != null) {
|
|
||||||
// Clears the proxy settings
|
|
||||||
proxyController.clearProxyOverride(new Executor() {
|
|
||||||
@Override
|
|
||||||
public void execute(Runnable command) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}, new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
proxyController = null;
|
|
||||||
}
|
|
||||||
plugin = null;
|
plugin = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,10 +99,6 @@ public class ServiceWorkerManager implements Disposable {
|
||||||
channelDelegate.dispose();
|
channelDelegate.dispose();
|
||||||
channelDelegate = null;
|
channelDelegate = null;
|
||||||
}
|
}
|
||||||
if (serviceWorkerController != null) {
|
|
||||||
serviceWorkerController.setServiceWorkerClient(dummyServiceWorkerClientCompat());
|
|
||||||
serviceWorkerController = null;
|
|
||||||
}
|
|
||||||
plugin = null;
|
plugin = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,6 @@ public class TracingControllerManager implements Disposable {
|
||||||
channelDelegate.dispose();
|
channelDelegate.dispose();
|
||||||
channelDelegate = null;
|
channelDelegate = null;
|
||||||
}
|
}
|
||||||
tracingController = null;
|
|
||||||
plugin = null;
|
plugin = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
package com.pichillilorenzo.flutter_inappwebview.types;
|
|
||||||
|
|
||||||
public enum WebViewImplementation {
|
|
||||||
NATIVE(0);
|
|
||||||
|
|
||||||
private final int value;
|
|
||||||
|
|
||||||
private WebViewImplementation(int value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equalsValue(int otherValue) {
|
|
||||||
return value == otherValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static WebViewImplementation fromValue(int value) {
|
|
||||||
for( WebViewImplementation type : WebViewImplementation.values()) {
|
|
||||||
if(value == type.value)
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("No enum constant: " + value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int rawValue() {
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.valueOf(this.value);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
package com.pichillilorenzo.flutter_inappwebview.webview;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
|
||||||
|
import com.pichillilorenzo.flutter_inappwebview.headless_in_app_webview.HeadlessInAppWebView;
|
||||||
|
import com.pichillilorenzo.flutter_inappwebview.headless_in_app_webview.HeadlessInAppWebViewManager;
|
||||||
|
import com.pichillilorenzo.flutter_inappwebview.webview.in_app_webview.FlutterWebView;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import io.flutter.plugin.common.StandardMessageCodec;
|
||||||
|
import io.flutter.plugin.platform.PlatformView;
|
||||||
|
import io.flutter.plugin.platform.PlatformViewFactory;
|
||||||
|
|
||||||
|
public class FlutterWebViewFactory extends PlatformViewFactory {
|
||||||
|
public static final String VIEW_TYPE_ID = "com.pichillilorenzo/flutter_inappwebview";
|
||||||
|
private final InAppWebViewFlutterPlugin plugin;
|
||||||
|
|
||||||
|
public FlutterWebViewFactory(final InAppWebViewFlutterPlugin plugin) {
|
||||||
|
super(StandardMessageCodec.INSTANCE);
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PlatformView create(Context context, int id, Object args) {
|
||||||
|
HashMap<String, Object> params = (HashMap<String, Object>) args;
|
||||||
|
FlutterWebView flutterWebView = null;
|
||||||
|
Object viewId = id;
|
||||||
|
|
||||||
|
String keepAliveId = (String) params.get("keepAliveId");
|
||||||
|
String headlessWebViewId = (String) params.get("headlessWebViewId");
|
||||||
|
|
||||||
|
HeadlessInAppWebViewManager headlessInAppWebViewManager = plugin.headlessInAppWebViewManager;
|
||||||
|
if (headlessWebViewId != null && headlessInAppWebViewManager != null) {
|
||||||
|
HeadlessInAppWebView headlessInAppWebView = headlessInAppWebViewManager.webViews.get(headlessWebViewId);
|
||||||
|
if (headlessInAppWebView != null) {
|
||||||
|
flutterWebView = headlessInAppWebView.disposeAndGetFlutterWebView();
|
||||||
|
if (flutterWebView != null) {
|
||||||
|
flutterWebView.keepAliveId = keepAliveId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InAppWebViewManager inAppWebViewManager = plugin.inAppWebViewManager;
|
||||||
|
if (keepAliveId != null && flutterWebView == null && inAppWebViewManager != null) {
|
||||||
|
flutterWebView = inAppWebViewManager.keepAliveWebViews.get(keepAliveId);
|
||||||
|
if (flutterWebView != null) {
|
||||||
|
// be sure to remove the view from the previous parent.
|
||||||
|
View view = flutterWebView.getView();
|
||||||
|
if (view != null) {
|
||||||
|
ViewGroup parent = (ViewGroup) view.getParent();
|
||||||
|
if (parent != null) {
|
||||||
|
parent.removeView(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean shouldMakeInitialLoad = flutterWebView == null;
|
||||||
|
if (flutterWebView == null) {
|
||||||
|
if (keepAliveId != null) {
|
||||||
|
viewId = keepAliveId;
|
||||||
|
}
|
||||||
|
flutterWebView = new FlutterWebView(plugin, context, viewId, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keepAliveId != null && inAppWebViewManager != null) {
|
||||||
|
inAppWebViewManager.keepAliveWebViews.put(keepAliveId, flutterWebView);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldMakeInitialLoad) {
|
||||||
|
flutterWebView.makeInitialLoad(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
return flutterWebView;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
package com.pichillilorenzo.flutter_inappwebview;
|
package com.pichillilorenzo.flutter_inappwebview.webview;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
import android.webkit.ValueCallback;
|
import android.webkit.ValueCallback;
|
||||||
import android.webkit.WebSettings;
|
import android.webkit.WebSettings;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
|
@ -13,9 +16,12 @@ import androidx.annotation.Nullable;
|
||||||
import androidx.webkit.WebViewCompat;
|
import androidx.webkit.WebViewCompat;
|
||||||
import androidx.webkit.WebViewFeature;
|
import androidx.webkit.WebViewFeature;
|
||||||
|
|
||||||
|
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
|
||||||
|
import com.pichillilorenzo.flutter_inappwebview.headless_in_app_webview.HeadlessInAppWebView;
|
||||||
import com.pichillilorenzo.flutter_inappwebview.types.ChannelDelegateImpl;
|
import com.pichillilorenzo.flutter_inappwebview.types.ChannelDelegateImpl;
|
||||||
|
import com.pichillilorenzo.flutter_inappwebview.webview.in_app_webview.FlutterWebView;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -25,14 +31,19 @@ import java.util.Set;
|
||||||
import io.flutter.plugin.common.MethodCall;
|
import io.flutter.plugin.common.MethodCall;
|
||||||
import io.flutter.plugin.common.MethodChannel;
|
import io.flutter.plugin.common.MethodChannel;
|
||||||
|
|
||||||
public class InAppWebViewStatic extends ChannelDelegateImpl {
|
public class InAppWebViewManager extends ChannelDelegateImpl {
|
||||||
protected static final String LOG_TAG = "InAppWebViewStatic";
|
protected static final String LOG_TAG = "InAppWebViewManager";
|
||||||
public static final String METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappwebview_static";
|
public static final String METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappwebview_manager";
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public InAppWebViewFlutterPlugin plugin;
|
public InAppWebViewFlutterPlugin plugin;
|
||||||
|
|
||||||
public InAppWebViewStatic(final InAppWebViewFlutterPlugin plugin) {
|
public final Map<String, FlutterWebView> keepAliveWebViews = new HashMap<>();
|
||||||
|
|
||||||
|
public final Map<Integer, Message> windowWebViewMessages = new HashMap<>();
|
||||||
|
public int windowAutoincrementId = 0;
|
||||||
|
|
||||||
|
public InAppWebViewManager(final InAppWebViewFlutterPlugin plugin) {
|
||||||
super(new MethodChannel(plugin.messenger, METHOD_CHANNEL_NAME));
|
super(new MethodChannel(plugin.messenger, METHOD_CHANNEL_NAME));
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
@ -41,7 +52,11 @@ public class InAppWebViewStatic extends ChannelDelegateImpl {
|
||||||
public void onMethodCall(@NonNull MethodCall call, @NonNull final MethodChannel.Result result) {
|
public void onMethodCall(@NonNull MethodCall call, @NonNull final MethodChannel.Result result) {
|
||||||
switch (call.method) {
|
switch (call.method) {
|
||||||
case "getDefaultUserAgent":
|
case "getDefaultUserAgent":
|
||||||
|
if (plugin != null) {
|
||||||
result.success(WebSettings.getDefaultUserAgent(plugin.applicationContext));
|
result.success(WebSettings.getDefaultUserAgent(plugin.applicationContext));
|
||||||
|
} else {
|
||||||
|
result.success(null);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "clearClientCertPreferences":
|
case "clearClientCertPreferences":
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
@ -118,6 +133,13 @@ public class InAppWebViewStatic extends ChannelDelegateImpl {
|
||||||
result.success(false);
|
result.success(false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "disposeKeepAlive":
|
||||||
|
final String keepAliveId = (String) call.argument("keepAliveId");
|
||||||
|
if (keepAliveId != null) {
|
||||||
|
disposeKeepAlive(keepAliveId);
|
||||||
|
}
|
||||||
|
result.success(true);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
result.notImplemented();
|
result.notImplemented();
|
||||||
}
|
}
|
||||||
|
@ -133,9 +155,37 @@ public class InAppWebViewStatic extends ChannelDelegateImpl {
|
||||||
return webViewPackageInfoMap;
|
return webViewPackageInfoMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void disposeKeepAlive(@NonNull String keepAliveId) {
|
||||||
|
FlutterWebView flutterWebView = keepAliveWebViews.get(keepAliveId);
|
||||||
|
if (flutterWebView != null) {
|
||||||
|
flutterWebView.keepAliveId = null;
|
||||||
|
// be sure to remove the view from the previous parent.
|
||||||
|
View view = flutterWebView.getView();
|
||||||
|
if (view != null) {
|
||||||
|
ViewGroup parent = (ViewGroup) view.getParent();
|
||||||
|
if (parent != null) {
|
||||||
|
parent.removeView(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flutterWebView.dispose();
|
||||||
|
}
|
||||||
|
if (keepAliveWebViews.containsKey(keepAliveId)) {
|
||||||
|
keepAliveWebViews.put(keepAliveId, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
Collection<FlutterWebView> flutterWebViews = keepAliveWebViews.values();
|
||||||
|
for (FlutterWebView flutterWebView : flutterWebViews) {
|
||||||
|
String keepAliveId = flutterWebView.keepAliveId;
|
||||||
|
if (keepAliveId != null) {
|
||||||
|
disposeKeepAlive(flutterWebView.keepAliveId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keepAliveWebViews.clear();
|
||||||
|
windowWebViewMessages.clear();
|
||||||
plugin = null;
|
plugin = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -76,11 +76,13 @@ public class JavaScriptBridgeInterface {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void defaultBehaviour(@Nullable Boolean handledByClient) {
|
public void defaultBehaviour(@Nullable Boolean handledByClient) {
|
||||||
PrintJobController printJobController = PrintJobManager.jobs.get(printJobId);
|
if (inAppWebView != null && inAppWebView.plugin != null && inAppWebView.plugin.printJobManager != null) {
|
||||||
|
PrintJobController printJobController = inAppWebView.plugin.printJobManager.jobs.get(printJobId);
|
||||||
if (printJobController != null) {
|
if (printJobController != null) {
|
||||||
printJobController.disposeNoCancel();
|
printJobController.disposeNoCancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails) {
|
public void error(String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails) {
|
||||||
|
|
|
@ -42,6 +42,8 @@ public class FlutterWebView implements PlatformWebView {
|
||||||
public InAppWebView webView;
|
public InAppWebView webView;
|
||||||
@Nullable
|
@Nullable
|
||||||
public PullToRefreshLayout pullToRefreshLayout;
|
public PullToRefreshLayout pullToRefreshLayout;
|
||||||
|
@Nullable
|
||||||
|
public String keepAliveId;
|
||||||
|
|
||||||
public FlutterWebView(final InAppWebViewFlutterPlugin plugin, final Context context, Object id,
|
public FlutterWebView(final InAppWebViewFlutterPlugin plugin, final Context context, Object id,
|
||||||
HashMap<String, Object> params) {
|
HashMap<String, Object> params) {
|
||||||
|
@ -49,6 +51,8 @@ public class FlutterWebView implements PlatformWebView {
|
||||||
DisplayManager displayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
|
DisplayManager displayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
|
||||||
displayListenerProxy.onPreWebViewInitialization(displayManager);
|
displayListenerProxy.onPreWebViewInitialization(displayManager);
|
||||||
|
|
||||||
|
keepAliveId = (String) params.get("keepAliveId");
|
||||||
|
|
||||||
Map<String, Object> initialSettings = (Map<String, Object>) params.get("initialSettings");
|
Map<String, Object> initialSettings = (Map<String, Object>) params.get("initialSettings");
|
||||||
Map<String, Object> contextMenu = (Map<String, Object>) params.get("contextMenu");
|
Map<String, Object> contextMenu = (Map<String, Object>) params.get("contextMenu");
|
||||||
Integer windowId = (Integer) params.get("windowId");
|
Integer windowId = (Integer) params.get("windowId");
|
||||||
|
@ -101,7 +105,8 @@ public class FlutterWebView implements PlatformWebView {
|
||||||
final Map<String, String> initialData = (Map<String, String>) params.get("initialData");
|
final Map<String, String> initialData = (Map<String, String>) params.get("initialData");
|
||||||
|
|
||||||
if (windowId != null) {
|
if (windowId != null) {
|
||||||
Message resultMsg = InAppWebViewChromeClient.windowWebViewMessages.get(windowId);
|
if (webView.plugin != null && webView.plugin.inAppWebViewManager != null) {
|
||||||
|
Message resultMsg = webView.plugin.inAppWebViewManager.windowWebViewMessages.get(windowId);
|
||||||
if (resultMsg != null) {
|
if (resultMsg != null) {
|
||||||
((WebView.WebViewTransport) resultMsg.obj).setWebView(webView);
|
((WebView.WebViewTransport) resultMsg.obj).setWebView(webView);
|
||||||
resultMsg.sendToTarget();
|
resultMsg.sendToTarget();
|
||||||
|
@ -123,6 +128,7 @@ public class FlutterWebView implements PlatformWebView {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (initialFile != null) {
|
if (initialFile != null) {
|
||||||
try {
|
try {
|
||||||
|
@ -151,7 +157,7 @@ public class FlutterWebView implements PlatformWebView {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
if (webView != null) {
|
if (keepAliveId == null && webView != null) {
|
||||||
if (webView.channelDelegate != null) {
|
if (webView.channelDelegate != null) {
|
||||||
webView.channelDelegate.dispose();
|
webView.channelDelegate.dispose();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1439,10 +1439,10 @@ final public class InAppWebView extends InputAwareWebView implements InAppWebVie
|
||||||
// Create a printCurrentPage job with name and adapter instance
|
// Create a printCurrentPage job with name and adapter instance
|
||||||
android.print.PrintJob job = printManager.print(jobName, printAdapter, builder.build());
|
android.print.PrintJob job = printManager.print(jobName, printAdapter, builder.build());
|
||||||
|
|
||||||
if (settings != null && settings.handledByClient) {
|
if (settings != null && settings.handledByClient && plugin.printJobManager != null) {
|
||||||
String id = UUID.randomUUID().toString();
|
String id = UUID.randomUUID().toString();
|
||||||
PrintJobController printJobController = new PrintJobController(id, job, settings, plugin);
|
PrintJobController printJobController = new PrintJobController(id, job, settings, plugin);
|
||||||
PrintJobManager.jobs.put(printJobController.id, printJobController);
|
plugin.printJobManager.jobs.put(printJobController.id, printJobController);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2011,8 +2011,8 @@ final public class InAppWebView extends InputAwareWebView implements InAppWebVie
|
||||||
webViewAssetLoaderExt.dispose();
|
webViewAssetLoaderExt.dispose();
|
||||||
webViewAssetLoaderExt = null;
|
webViewAssetLoaderExt = null;
|
||||||
}
|
}
|
||||||
if (windowId != null) {
|
if (windowId != null && plugin != null && plugin.inAppWebViewManager != null) {
|
||||||
InAppWebViewChromeClient.windowWebViewMessages.remove(windowId);
|
plugin.inAppWebViewManager.windowWebViewMessages.remove(windowId);
|
||||||
}
|
}
|
||||||
mainLooperHandler.removeCallbacksAndMessages(null);
|
mainLooperHandler.removeCallbacksAndMessages(null);
|
||||||
mHandler.removeCallbacksAndMessages(null);
|
mHandler.removeCallbacksAndMessages(null);
|
||||||
|
|
|
@ -77,14 +77,10 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
||||||
|
|
||||||
protected static final String LOG_TAG = "IABWebChromeClient";
|
protected static final String LOG_TAG = "IABWebChromeClient";
|
||||||
private InAppBrowserDelegate inAppBrowserDelegate;
|
private InAppBrowserDelegate inAppBrowserDelegate;
|
||||||
public static Map<Integer, Message> windowWebViewMessages = new HashMap<>();
|
|
||||||
private static int windowAutoincrementId = 0;
|
|
||||||
|
|
||||||
private static final int PICKER = 1;
|
private static final int PICKER = 1;
|
||||||
private static final int PICKER_LEGACY = 3;
|
private static final int PICKER_LEGACY = 3;
|
||||||
final String DEFAULT_MIME_TYPES = "*/*";
|
final String DEFAULT_MIME_TYPES = "*/*";
|
||||||
private static Uri videoOutputFileUri;
|
|
||||||
private static Uri imageOutputFileUri;
|
|
||||||
|
|
||||||
protected static final FrameLayout.LayoutParams FULLSCREEN_LAYOUT_PARAMS = new FrameLayout.LayoutParams(
|
protected static final FrameLayout.LayoutParams FULLSCREEN_LAYOUT_PARAMS = new FrameLayout.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER);
|
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER);
|
||||||
|
@ -115,6 +111,15 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
||||||
@Nullable
|
@Nullable
|
||||||
public InAppWebView inAppWebView;
|
public InAppWebView inAppWebView;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private ValueCallback<Uri> filePathCallbackLegacy;
|
||||||
|
@Nullable
|
||||||
|
private ValueCallback<Uri[]> filePathCallback;
|
||||||
|
@Nullable
|
||||||
|
private Uri videoOutputFileUri;
|
||||||
|
@Nullable
|
||||||
|
private Uri imageOutputFileUri;
|
||||||
|
|
||||||
public InAppWebViewChromeClient(@NonNull final InAppWebViewFlutterPlugin plugin,
|
public InAppWebViewChromeClient(@NonNull final InAppWebViewFlutterPlugin plugin,
|
||||||
@NonNull InAppWebView inAppWebView, InAppBrowserDelegate inAppBrowserDelegate) {
|
@NonNull InAppWebView inAppWebView, InAppBrowserDelegate inAppBrowserDelegate) {
|
||||||
super();
|
super();
|
||||||
|
@ -610,8 +615,11 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, final Message resultMsg) {
|
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, final Message resultMsg) {
|
||||||
windowAutoincrementId++;
|
int windowId = 0;
|
||||||
final int windowId = windowAutoincrementId;
|
if (plugin != null && plugin.inAppWebViewManager != null) {
|
||||||
|
plugin.inAppWebViewManager.windowAutoincrementId++;
|
||||||
|
windowId = plugin.inAppWebViewManager.windowAutoincrementId;
|
||||||
|
}
|
||||||
|
|
||||||
WebView.HitTestResult result = view.getHitTestResult();
|
WebView.HitTestResult result = view.getHitTestResult();
|
||||||
String url = result.getExtra();
|
String url = result.getExtra();
|
||||||
|
@ -639,9 +647,12 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
||||||
isDialog
|
isDialog
|
||||||
);
|
);
|
||||||
|
|
||||||
windowWebViewMessages.put(windowId, resultMsg);
|
if (plugin != null && plugin.inAppWebViewManager != null) {
|
||||||
|
plugin.inAppWebViewManager.windowWebViewMessages.put(windowId, resultMsg);
|
||||||
|
}
|
||||||
|
|
||||||
if (inAppWebView != null && inAppWebView.channelDelegate != null) {
|
if (inAppWebView != null && inAppWebView.channelDelegate != null) {
|
||||||
|
int finalWindowId = windowId;
|
||||||
inAppWebView.channelDelegate.onCreateWindow(createWindowAction, new WebViewChannelDelegate.CreateWindowCallback() {
|
inAppWebView.channelDelegate.onCreateWindow(createWindowAction, new WebViewChannelDelegate.CreateWindowCallback() {
|
||||||
@Override
|
@Override
|
||||||
public boolean nonNullSuccess(@NonNull Boolean handledByClient) {
|
public boolean nonNullSuccess(@NonNull Boolean handledByClient) {
|
||||||
|
@ -650,7 +661,9 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void defaultBehaviour(@Nullable Boolean handledByClient) {
|
public void defaultBehaviour(@Nullable Boolean handledByClient) {
|
||||||
InAppWebViewChromeClient.windowWebViewMessages.remove(windowId);
|
if (plugin != null && plugin.inAppWebViewManager != null) {
|
||||||
|
plugin.inAppWebViewManager.windowWebViewMessages.remove(finalWindowId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -824,7 +837,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
|
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
if (InAppWebViewFlutterPlugin.filePathCallback == null && InAppWebViewFlutterPlugin.filePathCallbackLegacy == null) {
|
if (filePathCallback == null && filePathCallbackLegacy == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -838,8 +851,8 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
||||||
results = getSelectedFiles(data, resultCode);
|
results = getSelectedFiles(data, resultCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (InAppWebViewFlutterPlugin.filePathCallback != null) {
|
if (filePathCallback != null) {
|
||||||
InAppWebViewFlutterPlugin.filePathCallback.onReceiveValue(results);
|
filePathCallback.onReceiveValue(results);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -848,13 +861,14 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
||||||
if (resultCode == RESULT_OK) {
|
if (resultCode == RESULT_OK) {
|
||||||
result = data != null ? data.getData() : getCapturedMediaFile();
|
result = data != null ? data.getData() : getCapturedMediaFile();
|
||||||
}
|
}
|
||||||
|
if (filePathCallbackLegacy != null) {
|
||||||
InAppWebViewFlutterPlugin.filePathCallbackLegacy.onReceiveValue(result);
|
filePathCallbackLegacy.onReceiveValue(result);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
InAppWebViewFlutterPlugin.filePathCallback = null;
|
filePathCallback = null;
|
||||||
InAppWebViewFlutterPlugin.filePathCallbackLegacy = null;
|
filePathCallbackLegacy = null;
|
||||||
imageOutputFileUri = null;
|
imageOutputFileUri = null;
|
||||||
videoOutputFileUri = null;
|
videoOutputFileUri = null;
|
||||||
|
|
||||||
|
@ -921,7 +935,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startPickerIntent(ValueCallback<Uri> filePathCallback, String acceptType, @Nullable String capture) {
|
public void startPickerIntent(ValueCallback<Uri> filePathCallback, String acceptType, @Nullable String capture) {
|
||||||
InAppWebViewFlutterPlugin.filePathCallbackLegacy = filePathCallback;
|
filePathCallbackLegacy = filePathCallback;
|
||||||
|
|
||||||
boolean images = acceptsImages(acceptType);
|
boolean images = acceptsImages(acceptType);
|
||||||
boolean video = acceptsVideo(acceptType);
|
boolean video = acceptsVideo(acceptType);
|
||||||
|
@ -965,7 +979,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
||||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||||
public boolean startPickerIntent(final ValueCallback<Uri[]> callback, final String[] acceptTypes,
|
public boolean startPickerIntent(final ValueCallback<Uri[]> callback, final String[] acceptTypes,
|
||||||
final boolean allowMultiple, final boolean captureEnabled) {
|
final boolean allowMultiple, final boolean captureEnabled) {
|
||||||
InAppWebViewFlutterPlugin.filePathCallback = callback;
|
filePathCallback = callback;
|
||||||
|
|
||||||
boolean images = acceptsImages(acceptTypes);
|
boolean images = acceptsImages(acceptTypes);
|
||||||
boolean video = acceptsVideo(acceptTypes);
|
boolean video = acceptsVideo(acceptTypes);
|
||||||
|
@ -1289,7 +1303,11 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
||||||
inAppBrowserDelegate.getActivityResultListeners().clear();
|
inAppBrowserDelegate.getActivityResultListeners().clear();
|
||||||
inAppBrowserDelegate = null;
|
inAppBrowserDelegate = null;
|
||||||
}
|
}
|
||||||
plugin = null;
|
filePathCallbackLegacy = null;
|
||||||
|
filePathCallback = null;
|
||||||
|
videoOutputFileUri = null;
|
||||||
|
imageOutputFileUri = null;
|
||||||
inAppWebView = null;
|
inAppWebView = null;
|
||||||
|
plugin = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ void customMenuItem() {
|
||||||
expect(chromeSafariBrowser.isOpened(), true);
|
expect(chromeSafariBrowser.isOpened(), true);
|
||||||
expect(() async {
|
expect(() async {
|
||||||
await chromeSafariBrowser.open(url: TEST_CROSS_PLATFORM_URL_1);
|
await chromeSafariBrowser.open(url: TEST_CROSS_PLATFORM_URL_1);
|
||||||
}, throwsA(isInstanceOf<ChromeSafariBrowserAlreadyOpenedException>()));
|
}, throwsException);
|
||||||
|
|
||||||
await expectLater(chromeSafariBrowser.firstPageLoaded.future, completes);
|
await expectLater(chromeSafariBrowser.firstPageLoaded.future, completes);
|
||||||
await chromeSafariBrowser.close();
|
await chromeSafariBrowser.close();
|
||||||
|
|
|
@ -26,7 +26,7 @@ void customTabs() {
|
||||||
expect(chromeSafariBrowser.isOpened(), true);
|
expect(chromeSafariBrowser.isOpened(), true);
|
||||||
expect(() async {
|
expect(() async {
|
||||||
await chromeSafariBrowser.open(url: TEST_CROSS_PLATFORM_URL_1);
|
await chromeSafariBrowser.open(url: TEST_CROSS_PLATFORM_URL_1);
|
||||||
}, throwsA(isInstanceOf<ChromeSafariBrowserAlreadyOpenedException>()));
|
}, throwsException);
|
||||||
|
|
||||||
await expectLater(chromeSafariBrowser.firstPageLoaded.future, completes);
|
await expectLater(chromeSafariBrowser.firstPageLoaded.future, completes);
|
||||||
await chromeSafariBrowser.close();
|
await chromeSafariBrowser.close();
|
||||||
|
@ -45,7 +45,7 @@ void customTabs() {
|
||||||
expect(chromeSafariBrowser.isOpened(), true);
|
expect(chromeSafariBrowser.isOpened(), true);
|
||||||
expect(() async {
|
expect(() async {
|
||||||
await chromeSafariBrowser.open(url: TEST_CROSS_PLATFORM_URL_1);
|
await chromeSafariBrowser.open(url: TEST_CROSS_PLATFORM_URL_1);
|
||||||
}, throwsA(isInstanceOf<ChromeSafariBrowserAlreadyOpenedException>()));
|
}, throwsException);
|
||||||
|
|
||||||
await expectLater(chromeSafariBrowser.firstPageLoaded.future, completes);
|
await expectLater(chromeSafariBrowser.firstPageLoaded.future, completes);
|
||||||
await chromeSafariBrowser.close();
|
await chromeSafariBrowser.close();
|
||||||
|
@ -71,7 +71,7 @@ void customTabs() {
|
||||||
expect(chromeSafariBrowser.isOpened(), true);
|
expect(chromeSafariBrowser.isOpened(), true);
|
||||||
expect(() async {
|
expect(() async {
|
||||||
await chromeSafariBrowser.open(url: TEST_CROSS_PLATFORM_URL_1);
|
await chromeSafariBrowser.open(url: TEST_CROSS_PLATFORM_URL_1);
|
||||||
}, throwsA(isInstanceOf<ChromeSafariBrowserAlreadyOpenedException>()));
|
}, throwsException);
|
||||||
|
|
||||||
await expectLater(chromeSafariBrowser.firstPageLoaded.future, completes);
|
await expectLater(chromeSafariBrowser.firstPageLoaded.future, completes);
|
||||||
await chromeSafariBrowser.updateActionButton(
|
await chromeSafariBrowser.updateActionButton(
|
||||||
|
|
|
@ -50,7 +50,7 @@ void openAndClose() {
|
||||||
expect(chromeSafariBrowser.isOpened(), true);
|
expect(chromeSafariBrowser.isOpened(), true);
|
||||||
expect(() async {
|
expect(() async {
|
||||||
await chromeSafariBrowser.open(url: TEST_CROSS_PLATFORM_URL_1);
|
await chromeSafariBrowser.open(url: TEST_CROSS_PLATFORM_URL_1);
|
||||||
}, throwsA(isInstanceOf<ChromeSafariBrowserAlreadyOpenedException>()));
|
}, throwsException);
|
||||||
|
|
||||||
await expectLater(chromeSafariBrowser.firstPageLoaded.future, completes);
|
await expectLater(chromeSafariBrowser.firstPageLoaded.future, completes);
|
||||||
await chromeSafariBrowser.close();
|
await chromeSafariBrowser.close();
|
||||||
|
|
|
@ -22,7 +22,7 @@ void sfSafariViewController() {
|
||||||
expect(chromeSafariBrowser.isOpened(), true);
|
expect(chromeSafariBrowser.isOpened(), true);
|
||||||
expect(() async {
|
expect(() async {
|
||||||
await chromeSafariBrowser.open(url: TEST_CROSS_PLATFORM_URL_1);
|
await chromeSafariBrowser.open(url: TEST_CROSS_PLATFORM_URL_1);
|
||||||
}, throwsA(isInstanceOf<ChromeSafariBrowserAlreadyOpenedException>()));
|
}, throwsException);
|
||||||
|
|
||||||
expect(await chromeSafariBrowser.firstPageLoaded.future, true);
|
expect(await chromeSafariBrowser.firstPageLoaded.future, true);
|
||||||
await chromeSafariBrowser.close();
|
await chromeSafariBrowser.close();
|
||||||
|
|
|
@ -24,7 +24,7 @@ void trustedWebActivity() {
|
||||||
expect(chromeSafariBrowser.isOpened(), true);
|
expect(chromeSafariBrowser.isOpened(), true);
|
||||||
expect(() async {
|
expect(() async {
|
||||||
await chromeSafariBrowser.open(url: TEST_CROSS_PLATFORM_URL_1);
|
await chromeSafariBrowser.open(url: TEST_CROSS_PLATFORM_URL_1);
|
||||||
}, throwsA(isInstanceOf<ChromeSafariBrowserAlreadyOpenedException>()));
|
}, throwsException);
|
||||||
|
|
||||||
await expectLater(chromeSafariBrowser.firstPageLoaded.future, completes);
|
await expectLater(chromeSafariBrowser.firstPageLoaded.future, completes);
|
||||||
await chromeSafariBrowser.close();
|
await chromeSafariBrowser.close();
|
||||||
|
@ -44,7 +44,7 @@ void trustedWebActivity() {
|
||||||
expect(chromeSafariBrowser.isOpened(), true);
|
expect(chromeSafariBrowser.isOpened(), true);
|
||||||
expect(() async {
|
expect(() async {
|
||||||
await chromeSafariBrowser.open(url: TEST_CROSS_PLATFORM_URL_1);
|
await chromeSafariBrowser.open(url: TEST_CROSS_PLATFORM_URL_1);
|
||||||
}, throwsA(isInstanceOf<ChromeSafariBrowserAlreadyOpenedException>()));
|
}, throwsException);
|
||||||
|
|
||||||
await expectLater(chromeSafariBrowser.firstPageLoaded.future, completes);
|
await expectLater(chromeSafariBrowser.firstPageLoaded.future, completes);
|
||||||
await chromeSafariBrowser.close();
|
await chromeSafariBrowser.close();
|
||||||
|
|
|
@ -19,7 +19,7 @@ void openDataAndClose() {
|
||||||
expect(inAppBrowser.isOpened(), false);
|
expect(inAppBrowser.isOpened(), false);
|
||||||
expect(() async {
|
expect(() async {
|
||||||
await inAppBrowser.show();
|
await inAppBrowser.show();
|
||||||
}, throwsA(isInstanceOf<InAppBrowserNotOpenedException>()));
|
}, throwsException);
|
||||||
|
|
||||||
await inAppBrowser.openData(
|
await inAppBrowser.openData(
|
||||||
data: """
|
data: """
|
||||||
|
@ -46,7 +46,7 @@ void openDataAndClose() {
|
||||||
expect(() async {
|
expect(() async {
|
||||||
await inAppBrowser.openUrlRequest(
|
await inAppBrowser.openUrlRequest(
|
||||||
urlRequest: URLRequest(url: TEST_URL_1));
|
urlRequest: URLRequest(url: TEST_URL_1));
|
||||||
}, throwsA(isInstanceOf<InAppBrowserAlreadyOpenedException>()));
|
}, throwsException);
|
||||||
|
|
||||||
await inAppBrowser.firstPageLoaded.future;
|
await inAppBrowser.firstPageLoaded.future;
|
||||||
var controller = inAppBrowser.webViewController;
|
var controller = inAppBrowser.webViewController;
|
||||||
|
|
|
@ -19,7 +19,7 @@ void openFileAndClose() {
|
||||||
expect(inAppBrowser.isOpened(), false);
|
expect(inAppBrowser.isOpened(), false);
|
||||||
expect(() async {
|
expect(() async {
|
||||||
await inAppBrowser.show();
|
await inAppBrowser.show();
|
||||||
}, throwsA(isInstanceOf<InAppBrowserNotOpenedException>()));
|
}, throwsException);
|
||||||
|
|
||||||
await inAppBrowser.openFile(
|
await inAppBrowser.openFile(
|
||||||
assetFilePath: "test_assets/in_app_webview_initial_file_test.html");
|
assetFilePath: "test_assets/in_app_webview_initial_file_test.html");
|
||||||
|
@ -28,7 +28,7 @@ void openFileAndClose() {
|
||||||
expect(() async {
|
expect(() async {
|
||||||
await inAppBrowser.openUrlRequest(
|
await inAppBrowser.openUrlRequest(
|
||||||
urlRequest: URLRequest(url: TEST_URL_1));
|
urlRequest: URLRequest(url: TEST_URL_1));
|
||||||
}, throwsA(isInstanceOf<InAppBrowserAlreadyOpenedException>()));
|
}, throwsException);
|
||||||
|
|
||||||
await inAppBrowser.firstPageLoaded.future;
|
await inAppBrowser.firstPageLoaded.future;
|
||||||
var controller = inAppBrowser.webViewController;
|
var controller = inAppBrowser.webViewController;
|
||||||
|
|
|
@ -19,7 +19,7 @@ void openUrlAndClose() {
|
||||||
expect(inAppBrowser.isOpened(), false);
|
expect(inAppBrowser.isOpened(), false);
|
||||||
expect(() async {
|
expect(() async {
|
||||||
await inAppBrowser.show();
|
await inAppBrowser.show();
|
||||||
}, throwsA(isInstanceOf<InAppBrowserNotOpenedException>()));
|
}, throwsException);
|
||||||
|
|
||||||
await inAppBrowser.openUrlRequest(urlRequest: URLRequest(url: TEST_URL_1));
|
await inAppBrowser.openUrlRequest(urlRequest: URLRequest(url: TEST_URL_1));
|
||||||
await inAppBrowser.browserCreated.future;
|
await inAppBrowser.browserCreated.future;
|
||||||
|
@ -27,7 +27,7 @@ void openUrlAndClose() {
|
||||||
expect(() async {
|
expect(() async {
|
||||||
await inAppBrowser.openUrlRequest(
|
await inAppBrowser.openUrlRequest(
|
||||||
urlRequest: URLRequest(url: TEST_CROSS_PLATFORM_URL_1));
|
urlRequest: URLRequest(url: TEST_CROSS_PLATFORM_URL_1));
|
||||||
}, throwsA(isInstanceOf<InAppBrowserAlreadyOpenedException>()));
|
}, throwsException);
|
||||||
|
|
||||||
await inAppBrowser.firstPageLoaded.future;
|
await inAppBrowser.firstPageLoaded.future;
|
||||||
var controller = inAppBrowser.webViewController;
|
var controller = inAppBrowser.webViewController;
|
||||||
|
|
|
@ -86,7 +86,7 @@ class _HeadlessInAppWebViewExampleScreenState
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (headlessWebView?.isRunning() ?? false) {
|
if (headlessWebView?.isRunning() ?? false) {
|
||||||
await headlessWebView?.webViewController.evaluateJavascript(
|
await headlessWebView?.webViewController?.evaluateJavascript(
|
||||||
source: """console.log('Here is the message!');""");
|
source: """console.log('Here is the message!');""");
|
||||||
} else {
|
} else {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||||
|
|
|
@ -126,7 +126,6 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
|
||||||
pullToRefreshController: pullToRefreshController,
|
pullToRefreshController: pullToRefreshController,
|
||||||
onWebViewCreated: (controller) async {
|
onWebViewCreated: (controller) async {
|
||||||
webViewController = controller;
|
webViewController = controller;
|
||||||
print(await controller.getUrl());
|
|
||||||
},
|
},
|
||||||
onLoadStart: (controller, url) async {
|
onLoadStart: (controller, url) async {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import Flutter
|
||||||
public class FindInteractionController : NSObject, Disposable {
|
public class FindInteractionController : NSObject, Disposable {
|
||||||
|
|
||||||
static var METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_find_interaction_";
|
static var METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_find_interaction_";
|
||||||
|
var plugin: SwiftFlutterPlugin?
|
||||||
var webView: InAppWebView?
|
var webView: InAppWebView?
|
||||||
var channelDelegate: FindInteractionChannelDelegate?
|
var channelDelegate: FindInteractionChannelDelegate?
|
||||||
var settings: FindInteractionSettings?
|
var settings: FindInteractionSettings?
|
||||||
|
@ -48,14 +49,17 @@ public class FindInteractionController : NSObject, Disposable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(registrar: FlutterPluginRegistrar, id: Any, webView: InAppWebView, settings: FindInteractionSettings?) {
|
public init(plugin: SwiftFlutterPlugin, id: Any, webView: InAppWebView, settings: FindInteractionSettings?) {
|
||||||
super.init()
|
super.init()
|
||||||
|
self.plugin = plugin
|
||||||
self.webView = webView
|
self.webView = webView
|
||||||
self.settings = settings
|
self.settings = settings
|
||||||
|
if let registrar = plugin.registrar {
|
||||||
let channel = FlutterMethodChannel(name: FindInteractionController.METHOD_CHANNEL_NAME_PREFIX + String(describing: id),
|
let channel = FlutterMethodChannel(name: FindInteractionController.METHOD_CHANNEL_NAME_PREFIX + String(describing: id),
|
||||||
binaryMessenger: registrar.messenger())
|
binaryMessenger: registrar.messenger())
|
||||||
self.channelDelegate = FindInteractionChannelDelegate(findInteractionController: self, channel: channel)
|
self.channelDelegate = FindInteractionChannelDelegate(findInteractionController: self, channel: channel)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func prepare() {
|
public func prepare() {
|
||||||
// if let settings = settings {
|
// if let settings = settings {
|
||||||
|
@ -148,6 +152,7 @@ public class FindInteractionController : NSObject, Disposable {
|
||||||
channelDelegate = nil
|
channelDelegate = nil
|
||||||
webView = nil
|
webView = nil
|
||||||
activeFindSession = nil
|
activeFindSession = nil
|
||||||
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
|
|
@ -79,7 +79,7 @@ public class HeadlessInAppWebView : Disposable {
|
||||||
public func dispose() {
|
public func dispose() {
|
||||||
channelDelegate?.dispose()
|
channelDelegate?.dispose()
|
||||||
channelDelegate = nil
|
channelDelegate = nil
|
||||||
HeadlessInAppWebViewManager.webViews[id] = nil
|
plugin?.headlessInAppWebViewManager?.webViews[id] = nil
|
||||||
flutterWebView = nil
|
flutterWebView = nil
|
||||||
plugin = nil
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ import AVFoundation
|
||||||
public class HeadlessInAppWebViewManager: ChannelDelegate {
|
public class HeadlessInAppWebViewManager: ChannelDelegate {
|
||||||
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_headless_inappwebview"
|
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_headless_inappwebview"
|
||||||
var plugin: SwiftFlutterPlugin?
|
var plugin: SwiftFlutterPlugin?
|
||||||
static var webViews: [String: HeadlessInAppWebView?] = [:]
|
var webViews: [String: HeadlessInAppWebView?] = [:]
|
||||||
|
|
||||||
init(plugin: SwiftFlutterPlugin) {
|
init(plugin: SwiftFlutterPlugin) {
|
||||||
super.init(channel: FlutterMethodChannel(name: HeadlessInAppWebViewManager.METHOD_CHANNEL_NAME, binaryMessenger: plugin.registrar!.messenger()))
|
super.init(channel: FlutterMethodChannel(name: HeadlessInAppWebViewManager.METHOD_CHANNEL_NAME, binaryMessenger: plugin.registrar!.messenger()))
|
||||||
|
@ -40,15 +40,15 @@ public class HeadlessInAppWebViewManager: ChannelDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
public func run(id: String, params: [String: Any?]) {
|
public func run(id: String, params: [String: Any?]) {
|
||||||
guard let plugin = plugin, let registrar = plugin.registrar else {
|
guard let plugin = plugin else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let flutterWebView = FlutterWebViewController(registrar: registrar,
|
let flutterWebView = FlutterWebViewController(plugin: plugin,
|
||||||
withFrame: CGRect.zero,
|
withFrame: CGRect.zero,
|
||||||
viewIdentifier: id,
|
viewIdentifier: id,
|
||||||
params: params as NSDictionary)
|
params: params as NSDictionary)
|
||||||
let headlessInAppWebView = HeadlessInAppWebView(plugin: plugin, id: id, flutterWebView: flutterWebView)
|
let headlessInAppWebView = HeadlessInAppWebView(plugin: plugin, id: id, flutterWebView: flutterWebView)
|
||||||
HeadlessInAppWebViewManager.webViews[id] = headlessInAppWebView
|
webViews[id] = headlessInAppWebView
|
||||||
|
|
||||||
headlessInAppWebView.prepare(params: params as NSDictionary)
|
headlessInAppWebView.prepare(params: params as NSDictionary)
|
||||||
headlessInAppWebView.onWebViewCreated()
|
headlessInAppWebView.onWebViewCreated()
|
||||||
|
@ -57,11 +57,11 @@ public class HeadlessInAppWebViewManager: ChannelDelegate {
|
||||||
|
|
||||||
public override func dispose() {
|
public override func dispose() {
|
||||||
super.dispose()
|
super.dispose()
|
||||||
let headlessWebViews = HeadlessInAppWebViewManager.webViews.values
|
let headlessWebViews = webViews.values
|
||||||
headlessWebViews.forEach { (headlessWebView: HeadlessInAppWebView?) in
|
headlessWebViews.forEach { (headlessWebView: HeadlessInAppWebView?) in
|
||||||
headlessWebView?.dispose()
|
headlessWebView?.dispose()
|
||||||
}
|
}
|
||||||
HeadlessInAppWebViewManager.webViews.removeAll()
|
webViews.removeAll()
|
||||||
plugin = nil
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class InAppBrowserWebViewController: UIViewController, InAppBrowserDelega
|
||||||
var isHidden = false
|
var isHidden = false
|
||||||
|
|
||||||
public override func loadView() {
|
public override func loadView() {
|
||||||
guard let registrar = plugin?.registrar else {
|
guard let plugin = plugin, let registrar = plugin.registrar else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,13 +55,13 @@ public class InAppBrowserWebViewController: UIViewController, InAppBrowserDelega
|
||||||
}
|
}
|
||||||
|
|
||||||
let preWebviewConfiguration = InAppWebView.preWKWebViewConfiguration(settings: webViewSettings)
|
let preWebviewConfiguration = InAppWebView.preWKWebViewConfiguration(settings: webViewSettings)
|
||||||
if let wId = windowId, let webViewTransport = InAppWebView.windowWebViews[wId] {
|
if let wId = windowId, let webViewTransport = plugin.inAppWebViewManager?.windowWebViews[wId] {
|
||||||
webView = webViewTransport.webView
|
webView = webViewTransport.webView
|
||||||
webView!.contextMenu = contextMenu
|
webView!.contextMenu = contextMenu
|
||||||
webView!.initialUserScripts = userScripts
|
webView!.initialUserScripts = userScripts
|
||||||
} else {
|
} else {
|
||||||
webView = InAppWebView(id: nil,
|
webView = InAppWebView(id: nil,
|
||||||
registrar: nil,
|
plugin: nil,
|
||||||
frame: .zero,
|
frame: .zero,
|
||||||
configuration: preWebviewConfiguration,
|
configuration: preWebviewConfiguration,
|
||||||
contextMenu: contextMenu,
|
contextMenu: contextMenu,
|
||||||
|
@ -74,17 +74,18 @@ public class InAppBrowserWebViewController: UIViewController, InAppBrowserDelega
|
||||||
|
|
||||||
webView.inAppBrowserDelegate = self
|
webView.inAppBrowserDelegate = self
|
||||||
webView.id = id
|
webView.id = id
|
||||||
|
webView.plugin = plugin
|
||||||
webView.channelDelegate = WebViewChannelDelegate(webView: webView, channel: channel)
|
webView.channelDelegate = WebViewChannelDelegate(webView: webView, channel: channel)
|
||||||
|
|
||||||
let pullToRefreshSettings = PullToRefreshSettings()
|
let pullToRefreshSettings = PullToRefreshSettings()
|
||||||
let _ = pullToRefreshSettings.parse(settings: pullToRefreshInitialSettings)
|
let _ = pullToRefreshSettings.parse(settings: pullToRefreshInitialSettings)
|
||||||
let pullToRefreshControl = PullToRefreshControl(registrar: registrar, id: id, settings: pullToRefreshSettings)
|
let pullToRefreshControl = PullToRefreshControl(plugin: plugin, id: id, settings: pullToRefreshSettings)
|
||||||
webView.pullToRefreshControl = pullToRefreshControl
|
webView.pullToRefreshControl = pullToRefreshControl
|
||||||
pullToRefreshControl.delegate = webView
|
pullToRefreshControl.delegate = webView
|
||||||
pullToRefreshControl.prepare()
|
pullToRefreshControl.prepare()
|
||||||
|
|
||||||
let findInteractionController = FindInteractionController(
|
let findInteractionController = FindInteractionController(
|
||||||
registrar: registrar,
|
plugin: plugin,
|
||||||
id: id, webView: webView, settings: nil)
|
id: id, webView: webView, settings: nil)
|
||||||
webView.findInteractionController = findInteractionController
|
webView.findInteractionController = findInteractionController
|
||||||
findInteractionController.prepare()
|
findInteractionController.prepare()
|
||||||
|
@ -132,7 +133,7 @@ public class InAppBrowserWebViewController: UIViewController, InAppBrowserDelega
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let wId = windowId, let webViewTransport = InAppWebView.windowWebViews[wId] {
|
if let wId = windowId, let webViewTransport = plugin?.inAppWebViewManager?.windowWebViews[wId] {
|
||||||
webView?.load(webViewTransport.request)
|
webView?.load(webViewTransport.request)
|
||||||
channelDelegate?.onBrowserCreated()
|
channelDelegate?.onBrowserCreated()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -11,13 +11,16 @@ import WebKit
|
||||||
public class FlutterWebViewController: NSObject, FlutterPlatformView, Disposable {
|
public class FlutterWebViewController: NSObject, FlutterPlatformView, Disposable {
|
||||||
|
|
||||||
var myView: UIView?
|
var myView: UIView?
|
||||||
|
var keepAliveId: String?
|
||||||
|
|
||||||
init(registrar: FlutterPluginRegistrar, withFrame frame: CGRect, viewIdentifier viewId: Any, params: NSDictionary) {
|
init(plugin: SwiftFlutterPlugin, withFrame frame: CGRect, viewIdentifier viewId: Any, params: NSDictionary) {
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
myView = UIView(frame: frame)
|
myView = UIView(frame: frame)
|
||||||
myView!.clipsToBounds = true
|
myView!.clipsToBounds = true
|
||||||
|
|
||||||
|
keepAliveId = params["keepAliveId"] as? String
|
||||||
|
|
||||||
let initialSettings = params["initialSettings"] as! [String: Any?]
|
let initialSettings = params["initialSettings"] as! [String: Any?]
|
||||||
let contextMenu = params["contextMenu"] as? [String: Any]
|
let contextMenu = params["contextMenu"] as? [String: Any]
|
||||||
let windowId = params["windowId"] as? Int64
|
let windowId = params["windowId"] as? Int64
|
||||||
|
@ -37,18 +40,21 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView, Disposable
|
||||||
|
|
||||||
var webView: InAppWebView?
|
var webView: InAppWebView?
|
||||||
|
|
||||||
if let wId = windowId, let webViewTransport = InAppWebView.windowWebViews[wId] {
|
if let wId = windowId, let webViewTransport = plugin.inAppWebViewManager?.windowWebViews[wId] {
|
||||||
webView = webViewTransport.webView
|
webView = webViewTransport.webView
|
||||||
webView!.id = viewId
|
webView!.id = viewId
|
||||||
|
webView!.plugin = plugin
|
||||||
|
if let registrar = plugin.registrar {
|
||||||
let channel = FlutterMethodChannel(name: InAppWebView.METHOD_CHANNEL_NAME_PREFIX + String(describing: viewId),
|
let channel = FlutterMethodChannel(name: InAppWebView.METHOD_CHANNEL_NAME_PREFIX + String(describing: viewId),
|
||||||
binaryMessenger: registrar.messenger())
|
binaryMessenger: registrar.messenger())
|
||||||
webView!.channelDelegate = WebViewChannelDelegate(webView: webView!, channel: channel)
|
webView!.channelDelegate = WebViewChannelDelegate(webView: webView!, channel: channel)
|
||||||
|
}
|
||||||
webView!.frame = myView!.bounds
|
webView!.frame = myView!.bounds
|
||||||
webView!.contextMenu = contextMenu
|
webView!.contextMenu = contextMenu
|
||||||
webView!.initialUserScripts = userScripts
|
webView!.initialUserScripts = userScripts
|
||||||
} else {
|
} else {
|
||||||
webView = InAppWebView(id: viewId,
|
webView = InAppWebView(id: viewId,
|
||||||
registrar: registrar,
|
plugin: plugin,
|
||||||
frame: myView!.bounds,
|
frame: myView!.bounds,
|
||||||
configuration: preWebviewConfiguration,
|
configuration: preWebviewConfiguration,
|
||||||
contextMenu: contextMenu,
|
contextMenu: contextMenu,
|
||||||
|
@ -57,13 +63,13 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView, Disposable
|
||||||
|
|
||||||
let pullToRefreshSettings = PullToRefreshSettings()
|
let pullToRefreshSettings = PullToRefreshSettings()
|
||||||
let _ = pullToRefreshSettings.parse(settings: pullToRefreshInitialSettings)
|
let _ = pullToRefreshSettings.parse(settings: pullToRefreshInitialSettings)
|
||||||
let pullToRefreshControl = PullToRefreshControl(registrar: registrar, id: viewId, settings: pullToRefreshSettings)
|
let pullToRefreshControl = PullToRefreshControl(plugin: plugin, id: viewId, settings: pullToRefreshSettings)
|
||||||
webView!.pullToRefreshControl = pullToRefreshControl
|
webView!.pullToRefreshControl = pullToRefreshControl
|
||||||
pullToRefreshControl.delegate = webView!
|
pullToRefreshControl.delegate = webView!
|
||||||
pullToRefreshControl.prepare()
|
pullToRefreshControl.prepare()
|
||||||
|
|
||||||
let findInteractionController = FindInteractionController(
|
let findInteractionController = FindInteractionController(
|
||||||
registrar: registrar,
|
plugin: plugin,
|
||||||
id: viewId, webView: webView!, settings: nil)
|
id: viewId, webView: webView!, settings: nil)
|
||||||
webView!.findInteractionController = findInteractionController
|
webView!.findInteractionController = findInteractionController
|
||||||
findInteractionController.prepare()
|
findInteractionController.prepare()
|
||||||
|
@ -132,7 +138,7 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView, Disposable
|
||||||
}
|
}
|
||||||
load(initialUrlRequest: initialUrlRequest, initialFile: initialFile, initialData: initialData)
|
load(initialUrlRequest: initialUrlRequest, initialFile: initialFile, initialData: initialData)
|
||||||
}
|
}
|
||||||
else if let wId = windowId, let webViewTransport = InAppWebView.windowWebViews[wId] {
|
else if let wId = windowId, let webViewTransport = webView.plugin?.inAppWebViewManager?.windowWebViews[wId] {
|
||||||
webView.load(webViewTransport.request)
|
webView.load(webViewTransport.request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,11 +186,13 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView, Disposable
|
||||||
}
|
}
|
||||||
|
|
||||||
public func dispose() {
|
public func dispose() {
|
||||||
|
if keepAliveId == nil {
|
||||||
if let webView = webView() {
|
if let webView = webView() {
|
||||||
webView.dispose()
|
webView.dispose()
|
||||||
}
|
}
|
||||||
myView = nil
|
myView = nil
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
debugPrint("FlutterWebViewController - dealloc")
|
debugPrint("FlutterWebViewController - dealloc")
|
||||||
|
|
|
@ -10,11 +10,11 @@ import Foundation
|
||||||
|
|
||||||
public class FlutterWebViewFactory: NSObject, FlutterPlatformViewFactory {
|
public class FlutterWebViewFactory: NSObject, FlutterPlatformViewFactory {
|
||||||
static let VIEW_TYPE_ID = "com.pichillilorenzo/flutter_inappwebview"
|
static let VIEW_TYPE_ID = "com.pichillilorenzo/flutter_inappwebview"
|
||||||
private var registrar: FlutterPluginRegistrar?
|
private var plugin: SwiftFlutterPlugin
|
||||||
|
|
||||||
init(registrar: FlutterPluginRegistrar?) {
|
init(plugin: SwiftFlutterPlugin) {
|
||||||
|
self.plugin = plugin
|
||||||
super.init()
|
super.init()
|
||||||
self.registrar = registrar
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
|
public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
|
||||||
|
@ -23,18 +23,48 @@ public class FlutterWebViewFactory: NSObject, FlutterPlatformViewFactory {
|
||||||
|
|
||||||
public func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView {
|
public func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView {
|
||||||
let arguments = args as? NSDictionary
|
let arguments = args as? NSDictionary
|
||||||
|
var flutterWebView: FlutterWebViewController?
|
||||||
|
var id: Any = viewId
|
||||||
|
|
||||||
if let headlessWebViewId = arguments?["headlessWebViewId"] as? String,
|
let keepAliveId = arguments?["keepAliveId"] as? String
|
||||||
let headlessWebView = HeadlessInAppWebViewManager.webViews[headlessWebViewId],
|
let headlessWebViewId = arguments?["headlessWebViewId"] as? String
|
||||||
|
|
||||||
|
if let headlessWebViewId = headlessWebViewId,
|
||||||
|
let headlessWebView = plugin.headlessInAppWebViewManager?.webViews[headlessWebViewId],
|
||||||
let platformView = headlessWebView?.disposeAndGetFlutterWebView(withFrame: frame) {
|
let platformView = headlessWebView?.disposeAndGetFlutterWebView(withFrame: frame) {
|
||||||
return platformView
|
flutterWebView = platformView
|
||||||
|
flutterWebView?.keepAliveId = keepAliveId
|
||||||
}
|
}
|
||||||
|
|
||||||
let webviewController = FlutterWebViewController(registrar: registrar!,
|
if let keepAliveId = keepAliveId,
|
||||||
|
flutterWebView == nil,
|
||||||
|
let keepAliveWebView = plugin.inAppWebViewManager?.keepAliveWebViews[keepAliveId] {
|
||||||
|
flutterWebView = keepAliveWebView
|
||||||
|
if let view = flutterWebView?.view() {
|
||||||
|
// remove from parent
|
||||||
|
view.removeFromSuperview()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let shouldMakeInitialLoad = flutterWebView == nil
|
||||||
|
if flutterWebView == nil {
|
||||||
|
if let keepAliveId = keepAliveId {
|
||||||
|
id = keepAliveId
|
||||||
|
}
|
||||||
|
flutterWebView = FlutterWebViewController(plugin: plugin,
|
||||||
withFrame: frame,
|
withFrame: frame,
|
||||||
viewIdentifier: viewId,
|
viewIdentifier: id,
|
||||||
params: arguments!)
|
params: arguments!)
|
||||||
webviewController.makeInitialLoad(params: arguments!)
|
}
|
||||||
return webviewController
|
|
||||||
|
if let keepAliveId = keepAliveId {
|
||||||
|
plugin.inAppWebViewManager?.keepAliveWebViews[keepAliveId] = flutterWebView!
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldMakeInitialLoad {
|
||||||
|
flutterWebView?.makeInitialLoad(params: arguments!)
|
||||||
|
}
|
||||||
|
|
||||||
|
return flutterWebView!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
|
||||||
static var METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_"
|
static var METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_"
|
||||||
|
|
||||||
var id: Any? // viewId
|
var id: Any? // viewId
|
||||||
var registrar: FlutterPluginRegistrar?
|
var plugin: SwiftFlutterPlugin?
|
||||||
var windowId: Int64?
|
var windowId: Int64?
|
||||||
var windowCreated = false
|
var windowCreated = false
|
||||||
var inAppBrowserDelegate: InAppBrowserDelegate?
|
var inAppBrowserDelegate: InAppBrowserDelegate?
|
||||||
|
@ -61,19 +61,16 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
|
||||||
|
|
||||||
var customIMPs: [IMP] = []
|
var customIMPs: [IMP] = []
|
||||||
|
|
||||||
static var windowWebViews: [Int64:WebViewTransport] = [:]
|
|
||||||
static var windowAutoincrementId: Int64 = 0;
|
|
||||||
|
|
||||||
var callAsyncJavaScriptBelowIOS14Results: [String:((Any?) -> Void)] = [:]
|
var callAsyncJavaScriptBelowIOS14Results: [String:((Any?) -> Void)] = [:]
|
||||||
|
|
||||||
var oldZoomScale = Float(1.0)
|
var oldZoomScale = Float(1.0)
|
||||||
|
|
||||||
init(id: Any?, registrar: FlutterPluginRegistrar?, frame: CGRect, configuration: WKWebViewConfiguration,
|
init(id: Any?, plugin: SwiftFlutterPlugin?, frame: CGRect, configuration: WKWebViewConfiguration,
|
||||||
contextMenu: [String: Any]?, userScripts: [UserScript] = []) {
|
contextMenu: [String: Any]?, userScripts: [UserScript] = []) {
|
||||||
super.init(frame: frame, configuration: configuration)
|
super.init(frame: frame, configuration: configuration)
|
||||||
self.id = id
|
self.id = id
|
||||||
self.registrar = registrar
|
self.plugin = plugin
|
||||||
if let id = id, let registrar = registrar {
|
if let id = id, let registrar = plugin?.registrar {
|
||||||
let channel = FlutterMethodChannel(name: InAppWebView.METHOD_CHANNEL_NAME_PREFIX + String(describing: id),
|
let channel = FlutterMethodChannel(name: InAppWebView.METHOD_CHANNEL_NAME_PREFIX + String(describing: id),
|
||||||
binaryMessenger: registrar.messenger())
|
binaryMessenger: registrar.messenger())
|
||||||
self.channelDelegate = WebViewChannelDelegate(webView: self, channel: channel)
|
self.channelDelegate = WebViewChannelDelegate(webView: self, channel: channel)
|
||||||
|
@ -940,8 +937,8 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
|
||||||
}
|
}
|
||||||
|
|
||||||
public func loadFile(assetFilePath: String) throws {
|
public func loadFile(assetFilePath: String) throws {
|
||||||
if let registrar = registrar {
|
if let plugin = plugin {
|
||||||
let assetURL = try Util.getUrlAsset(registrar: registrar, assetFilePath: assetFilePath)
|
let assetURL = try Util.getUrlAsset(plugin: plugin, assetFilePath: assetFilePath)
|
||||||
let urlRequest = URLRequest(url: assetURL)
|
let urlRequest = URLRequest(url: assetURL)
|
||||||
loadUrl(urlRequest: urlRequest, allowingReadAccessTo: nil)
|
loadUrl(urlRequest: urlRequest, allowingReadAccessTo: nil)
|
||||||
}
|
}
|
||||||
|
@ -2090,8 +2087,8 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
|
||||||
|
|
||||||
var path: String = certificatePath
|
var path: String = certificatePath
|
||||||
do {
|
do {
|
||||||
if let registrar = self.registrar {
|
if let plugin = self.plugin {
|
||||||
path = try Util.getAbsPathAsset(registrar: registrar, assetFilePath: certificatePath)
|
path = try Util.getAbsPathAsset(plugin: plugin, assetFilePath: certificatePath)
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
|
@ -2464,10 +2461,14 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
|
||||||
createWebViewWith configuration: WKWebViewConfiguration,
|
createWebViewWith configuration: WKWebViewConfiguration,
|
||||||
for navigationAction: WKNavigationAction,
|
for navigationAction: WKNavigationAction,
|
||||||
windowFeatures: WKWindowFeatures) -> WKWebView? {
|
windowFeatures: WKWindowFeatures) -> WKWebView? {
|
||||||
InAppWebView.windowAutoincrementId += 1
|
var windowId: Int64 = 0
|
||||||
let windowId = InAppWebView.windowAutoincrementId
|
let inAppWebViewManager = plugin?.inAppWebViewManager
|
||||||
|
if let inAppWebViewManager = inAppWebViewManager {
|
||||||
|
inAppWebViewManager.windowAutoincrementId += 1
|
||||||
|
windowId = inAppWebViewManager.windowAutoincrementId
|
||||||
|
}
|
||||||
|
|
||||||
let windowWebView = InAppWebView(id: nil, registrar: nil, frame: CGRect.zero, configuration: configuration, contextMenu: nil)
|
let windowWebView = InAppWebView(id: nil, plugin: nil, frame: CGRect.zero, configuration: configuration, contextMenu: nil)
|
||||||
windowWebView.windowId = windowId
|
windowWebView.windowId = windowId
|
||||||
|
|
||||||
let webViewTransport = WebViewTransport(
|
let webViewTransport = WebViewTransport(
|
||||||
|
@ -2475,7 +2476,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
|
||||||
request: navigationAction.request
|
request: navigationAction.request
|
||||||
)
|
)
|
||||||
|
|
||||||
InAppWebView.windowWebViews[windowId] = webViewTransport
|
inAppWebViewManager?.windowWebViews[windowId] = webViewTransport
|
||||||
windowWebView.stopLoading()
|
windowWebView.stopLoading()
|
||||||
|
|
||||||
let createWindowAction = CreateWindowAction(navigationAction: navigationAction, windowId: windowId, windowFeatures: windowFeatures, isDialog: nil)
|
let createWindowAction = CreateWindowAction(navigationAction: navigationAction, windowId: windowId, windowFeatures: windowFeatures, isDialog: nil)
|
||||||
|
@ -2485,8 +2486,8 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
|
||||||
return !handledByClient
|
return !handledByClient
|
||||||
}
|
}
|
||||||
callback.defaultBehaviour = { (handledByClient: Bool?) in
|
callback.defaultBehaviour = { (handledByClient: Bool?) in
|
||||||
if InAppWebView.windowWebViews[windowId] != nil {
|
if inAppWebViewManager?.windowWebViews[windowId] != nil {
|
||||||
InAppWebView.windowWebViews.removeValue(forKey: windowId)
|
inAppWebViewManager?.windowWebViews.removeValue(forKey: windowId)
|
||||||
}
|
}
|
||||||
self.loadUrl(urlRequest: navigationAction.request, allowingReadAccessTo: nil)
|
self.loadUrl(urlRequest: navigationAction.request, allowingReadAccessTo: nil)
|
||||||
}
|
}
|
||||||
|
@ -2752,7 +2753,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
|
||||||
|
|
||||||
let _windowId = body["_windowId"] as? Int64
|
let _windowId = body["_windowId"] as? Int64
|
||||||
var webView = self
|
var webView = self
|
||||||
if let wId = _windowId, let webViewTransport = InAppWebView.windowWebViews[wId] {
|
if let wId = _windowId, let webViewTransport = plugin?.inAppWebViewManager?.windowWebViews[wId] {
|
||||||
webView = webViewTransport.webView
|
webView = webViewTransport.webView
|
||||||
}
|
}
|
||||||
webView.channelDelegate?.onConsoleMessage(message: consoleMessage, messageLevel: messageLevel)
|
webView.channelDelegate?.onConsoleMessage(message: consoleMessage, messageLevel: messageLevel)
|
||||||
|
@ -2769,7 +2770,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
|
||||||
return !handledByClient
|
return !handledByClient
|
||||||
}
|
}
|
||||||
callback.defaultBehaviour = { (handledByClient: Bool?) in
|
callback.defaultBehaviour = { (handledByClient: Bool?) in
|
||||||
if let printJob = PrintJobManager.jobs[printJobId] {
|
if let printJob = self.plugin?.printJobManager?.jobs[printJobId] {
|
||||||
printJob?.disposeNoDismiss()
|
printJob?.disposeNoDismiss()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2787,7 +2788,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
|
||||||
|
|
||||||
let _windowId = body["_windowId"] as? Int64
|
let _windowId = body["_windowId"] as? Int64
|
||||||
var webView = self
|
var webView = self
|
||||||
if let wId = _windowId, let webViewTransport = InAppWebView.windowWebViews[wId] {
|
if let wId = _windowId, let webViewTransport = plugin?.inAppWebViewManager?.windowWebViews[wId] {
|
||||||
webView = webViewTransport.webView
|
webView = webViewTransport.webView
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2829,7 +2830,7 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
|
||||||
|
|
||||||
let _windowId = body["_windowId"] as? Int64
|
let _windowId = body["_windowId"] as? Int64
|
||||||
var webView = self
|
var webView = self
|
||||||
if let wId = _windowId, let webViewTransport = InAppWebView.windowWebViews[wId] {
|
if let wId = _windowId, let webViewTransport = plugin?.inAppWebViewManager?.windowWebViews[wId] {
|
||||||
webView = webViewTransport.webView
|
webView = webViewTransport.webView
|
||||||
}
|
}
|
||||||
webView.findInteractionController?.channelDelegate?.onFindResultReceived(activeMatchOrdinal: activeMatchOrdinal, numberOfMatches: numberOfMatches, isDoneCounting: isDoneCounting)
|
webView.findInteractionController?.channelDelegate?.onFindResultReceived(activeMatchOrdinal: activeMatchOrdinal, numberOfMatches: numberOfMatches, isDoneCounting: isDoneCounting)
|
||||||
|
@ -2979,9 +2980,9 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let animated = settings?.animated ?? true
|
let animated = settings?.animated ?? true
|
||||||
if let id = printJobId, let registrar = registrar {
|
if let id = printJobId, let plugin = plugin {
|
||||||
let printJob = PrintJobController(registrar: registrar, id: id, job: printController, settings: settings)
|
let printJob = PrintJobController(plugin: plugin, id: id, job: printController, settings: settings)
|
||||||
PrintJobManager.jobs[id] = printJob
|
plugin.printJobManager?.jobs[id] = printJob
|
||||||
printJob.present(animated: animated, completionHandler: completionHandler)
|
printJob.present(animated: animated, completionHandler: completionHandler)
|
||||||
} else {
|
} else {
|
||||||
printController.present(animated: animated, completionHandler: completionHandler)
|
printController.present(animated: animated, completionHandler: completionHandler)
|
||||||
|
@ -3123,12 +3124,12 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public func createWebMessageChannel(completionHandler: ((WebMessageChannel?) -> Void)? = nil) -> WebMessageChannel? {
|
public func createWebMessageChannel(completionHandler: ((WebMessageChannel?) -> Void)? = nil) -> WebMessageChannel? {
|
||||||
guard let registrar = registrar else {
|
guard let plugin = plugin else {
|
||||||
completionHandler?(nil)
|
completionHandler?(nil)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
let id = NSUUID().uuidString
|
let id = NSUUID().uuidString
|
||||||
let webMessageChannel = WebMessageChannel(registrar: registrar, id: id)
|
let webMessageChannel = WebMessageChannel(plugin: plugin, id: id)
|
||||||
webMessageChannel.initJsInstance(webView: self, completionHandler: completionHandler)
|
webMessageChannel.initJsInstance(webView: self, completionHandler: completionHandler)
|
||||||
webMessageChannels[id] = webMessageChannel
|
webMessageChannels[id] = webMessageChannel
|
||||||
|
|
||||||
|
@ -3216,8 +3217,8 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
|
||||||
if #available(iOS 11.0, *) {
|
if #available(iOS 11.0, *) {
|
||||||
configuration.userContentController.removeAllContentRuleLists()
|
configuration.userContentController.removeAllContentRuleLists()
|
||||||
}
|
}
|
||||||
} else if let wId = windowId, InAppWebView.windowWebViews[wId] != nil {
|
} else if let wId = windowId, plugin?.inAppWebViewManager?.windowWebViews[wId] != nil {
|
||||||
InAppWebView.windowWebViews.removeValue(forKey: wId)
|
plugin?.inAppWebViewManager?.windowWebViews.removeValue(forKey: wId)
|
||||||
}
|
}
|
||||||
configuration.userContentController.dispose(windowId: windowId)
|
configuration.userContentController.dispose(windowId: windowId)
|
||||||
NotificationCenter.default.removeObserver(self)
|
NotificationCenter.default.removeObserver(self)
|
||||||
|
@ -3245,7 +3246,7 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
|
||||||
SharedLastTouchPointTimestamp.removeValue(forKey: self)
|
SharedLastTouchPointTimestamp.removeValue(forKey: self)
|
||||||
callAsyncJavaScriptBelowIOS14Results.removeAll()
|
callAsyncJavaScriptBelowIOS14Results.removeAll()
|
||||||
super.removeFromSuperview()
|
super.removeFromSuperview()
|
||||||
registrar = nil
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
// InAppWebViewStatic.swift
|
// InAppWebViewManager.swift
|
||||||
// flutter_inappwebview
|
// flutter_inappwebview
|
||||||
//
|
//
|
||||||
// Created by Lorenzo Pichilli on 08/12/2019.
|
// Created by Lorenzo Pichilli on 08/12/2019.
|
||||||
|
@ -8,14 +8,18 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import WebKit
|
import WebKit
|
||||||
|
|
||||||
public class InAppWebViewStatic: ChannelDelegate {
|
public class InAppWebViewManager: ChannelDelegate {
|
||||||
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappwebview_static"
|
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappwebview_manager"
|
||||||
var plugin: SwiftFlutterPlugin?
|
var plugin: SwiftFlutterPlugin?
|
||||||
var webViewForUserAgent: WKWebView?
|
var webViewForUserAgent: WKWebView?
|
||||||
var defaultUserAgent: String?
|
var defaultUserAgent: String?
|
||||||
|
|
||||||
|
var keepAliveWebViews: [String:FlutterWebViewController?] = [:]
|
||||||
|
var windowWebViews: [Int64:WebViewTransport] = [:]
|
||||||
|
var windowAutoincrementId: Int64 = 0
|
||||||
|
|
||||||
init(plugin: SwiftFlutterPlugin) {
|
init(plugin: SwiftFlutterPlugin) {
|
||||||
super.init(channel: FlutterMethodChannel(name: InAppWebViewStatic.METHOD_CHANNEL_NAME, binaryMessenger: plugin.registrar!.messenger()))
|
super.init(channel: FlutterMethodChannel(name: InAppWebViewManager.METHOD_CHANNEL_NAME, binaryMessenger: plugin.registrar!.messenger()))
|
||||||
self.plugin = plugin
|
self.plugin = plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +40,11 @@ public class InAppWebViewStatic: ChannelDelegate {
|
||||||
result(false)
|
result(false)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
case "disposeKeepAlive":
|
||||||
|
let keepAliveId = arguments!["keepAliveId"] as! String
|
||||||
|
disposeKeepAlive(keepAliveId: keepAliveId)
|
||||||
|
result(true)
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
result(FlutterMethodNotImplemented)
|
result(FlutterMethodNotImplemented)
|
||||||
break
|
break
|
||||||
|
@ -67,11 +76,27 @@ public class InAppWebViewStatic: ChannelDelegate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func disposeKeepAlive(keepAliveId: String) {
|
||||||
|
if let flutterWebView = keepAliveWebViews[keepAliveId] as? FlutterWebViewController {
|
||||||
|
flutterWebView.keepAliveId = nil
|
||||||
|
flutterWebView.dispose()
|
||||||
|
keepAliveWebViews[keepAliveId] = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override func dispose() {
|
public override func dispose() {
|
||||||
super.dispose()
|
super.dispose()
|
||||||
plugin = nil
|
let keepAliveWebViewValues = keepAliveWebViews.values
|
||||||
|
keepAliveWebViewValues.forEach {(keepAliveWebView: FlutterWebViewController?) in
|
||||||
|
if let keepAliveId = keepAliveWebView?.keepAliveId {
|
||||||
|
disposeKeepAlive(keepAliveId: keepAliveId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keepAliveWebViews.removeAll()
|
||||||
|
windowWebViews.removeAll()
|
||||||
webViewForUserAgent = nil
|
webViewForUserAgent = nil
|
||||||
defaultUserAgent = nil
|
defaultUserAgent = nil
|
||||||
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
|
@ -10,18 +10,20 @@ import Foundation
|
||||||
public class WebMessageChannel : FlutterMethodCallDelegate {
|
public class WebMessageChannel : FlutterMethodCallDelegate {
|
||||||
static var METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_web_message_channel_"
|
static var METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_web_message_channel_"
|
||||||
var id: String
|
var id: String
|
||||||
|
var plugin: SwiftFlutterPlugin?
|
||||||
var channelDelegate: WebMessageChannelChannelDelegate?
|
var channelDelegate: WebMessageChannelChannelDelegate?
|
||||||
weak var webView: InAppWebView?
|
weak var webView: InAppWebView?
|
||||||
var ports: [WebMessagePort] = []
|
var ports: [WebMessagePort] = []
|
||||||
var registrar: FlutterPluginRegistrar?
|
|
||||||
|
|
||||||
public init(registrar: FlutterPluginRegistrar, id: String) {
|
public init(plugin: SwiftFlutterPlugin, id: String) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.registrar = registrar
|
self.plugin = plugin
|
||||||
super.init()
|
super.init()
|
||||||
|
if let registrar = plugin.registrar {
|
||||||
let channel = FlutterMethodChannel(name: WebMessageChannel.METHOD_CHANNEL_NAME_PREFIX + id,
|
let channel = FlutterMethodChannel(name: WebMessageChannel.METHOD_CHANNEL_NAME_PREFIX + id,
|
||||||
binaryMessenger: registrar.messenger())
|
binaryMessenger: registrar.messenger())
|
||||||
self.channelDelegate = WebMessageChannelChannelDelegate(webMessageChannel: self, channel: channel)
|
self.channelDelegate = WebMessageChannelChannelDelegate(webMessageChannel: self, channel: channel)
|
||||||
|
}
|
||||||
self.ports = [
|
self.ports = [
|
||||||
WebMessagePort(name: "port1", webMessageChannel: self),
|
WebMessagePort(name: "port1", webMessageChannel: self),
|
||||||
WebMessagePort(name: "port2", webMessageChannel: self)
|
WebMessagePort(name: "port2", webMessageChannel: self)
|
||||||
|
@ -67,7 +69,7 @@ public class WebMessageChannel : FlutterMethodCallDelegate {
|
||||||
})();
|
})();
|
||||||
""")
|
""")
|
||||||
webView = nil
|
webView = nil
|
||||||
registrar = nil
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
|
|
@ -15,18 +15,20 @@ public class WebMessageListener : FlutterMethodCallDelegate {
|
||||||
var allowedOriginRules: Set<String>
|
var allowedOriginRules: Set<String>
|
||||||
var channelDelegate: WebMessageListenerChannelDelegate?
|
var channelDelegate: WebMessageListenerChannelDelegate?
|
||||||
weak var webView: InAppWebView?
|
weak var webView: InAppWebView?
|
||||||
var registrar: FlutterPluginRegistrar?
|
var plugin: SwiftFlutterPlugin?
|
||||||
|
|
||||||
public init(registrar: FlutterPluginRegistrar, id: String, jsObjectName: String, allowedOriginRules: Set<String>) {
|
public init(plugin: SwiftFlutterPlugin, id: String, jsObjectName: String, allowedOriginRules: Set<String>) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.registrar = registrar
|
self.plugin = plugin
|
||||||
self.jsObjectName = jsObjectName
|
self.jsObjectName = jsObjectName
|
||||||
self.allowedOriginRules = allowedOriginRules
|
self.allowedOriginRules = allowedOriginRules
|
||||||
super.init()
|
super.init()
|
||||||
|
if let registrar = plugin.registrar {
|
||||||
let channel = FlutterMethodChannel(name: WebMessageListener.METHOD_CHANNEL_NAME_PREFIX + self.id + "_" + self.jsObjectName,
|
let channel = FlutterMethodChannel(name: WebMessageListener.METHOD_CHANNEL_NAME_PREFIX + self.id + "_" + self.jsObjectName,
|
||||||
binaryMessenger: registrar.messenger())
|
binaryMessenger: registrar.messenger())
|
||||||
self.channelDelegate = WebMessageListenerChannelDelegate(webMessageListener: self, channel: channel)
|
self.channelDelegate = WebMessageListenerChannelDelegate(webMessageListener: self, channel: channel)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func assertOriginRulesValid() throws {
|
public func assertOriginRulesValid() throws {
|
||||||
for (index, originRule) in allowedOriginRules.enumerated() {
|
for (index, originRule) in allowedOriginRules.enumerated() {
|
||||||
|
@ -116,12 +118,12 @@ public class WebMessageListener : FlutterMethodCallDelegate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func fromMap(registrar: FlutterPluginRegistrar, map: [String:Any?]?) -> WebMessageListener? {
|
public static func fromMap(plugin: SwiftFlutterPlugin, map: [String:Any?]?) -> WebMessageListener? {
|
||||||
guard let map = map else {
|
guard let map = map else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return WebMessageListener(
|
return WebMessageListener(
|
||||||
registrar: registrar,
|
plugin: plugin,
|
||||||
id: map["id"] as! String,
|
id: map["id"] as! String,
|
||||||
jsObjectName: map["jsObjectName"] as! String,
|
jsObjectName: map["jsObjectName"] as! String,
|
||||||
allowedOriginRules: Set(map["allowedOriginRules"] as! [String])
|
allowedOriginRules: Set(map["allowedOriginRules"] as! [String])
|
||||||
|
@ -180,7 +182,7 @@ public class WebMessageListener : FlutterMethodCallDelegate {
|
||||||
channelDelegate?.dispose()
|
channelDelegate?.dispose()
|
||||||
channelDelegate = nil
|
channelDelegate = nil
|
||||||
webView = nil
|
webView = nil
|
||||||
registrar = nil
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
|
|
@ -536,9 +536,9 @@ public class WebViewChannelDelegate : ChannelDelegate {
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case .addWebMessageListener:
|
case .addWebMessageListener:
|
||||||
if let webView = webView, let registrar = webView.registrar {
|
if let webView = webView, let plugin = webView.plugin {
|
||||||
let webMessageListenerMap = arguments!["webMessageListener"] as! [String: Any?]
|
let webMessageListenerMap = arguments!["webMessageListener"] as! [String: Any?]
|
||||||
let webMessageListener = WebMessageListener.fromMap(registrar: registrar, map: webMessageListenerMap)!
|
let webMessageListener = WebMessageListener.fromMap(plugin: plugin, map: webMessageListenerMap)!
|
||||||
do {
|
do {
|
||||||
try webView.addWebMessageListener(webMessageListener: webMessageListener)
|
try webView.addWebMessageListener(webMessageListener: webMessageListener)
|
||||||
result(false)
|
result(false)
|
||||||
|
|
|
@ -18,7 +18,7 @@ public enum PrintJobState: Int {
|
||||||
public class PrintJobController : NSObject, Disposable, UIPrintInteractionControllerDelegate {
|
public class PrintJobController : NSObject, Disposable, UIPrintInteractionControllerDelegate {
|
||||||
static let METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_printjobcontroller_"
|
static let METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_printjobcontroller_"
|
||||||
var id: String
|
var id: String
|
||||||
var registrar: FlutterPluginRegistrar?
|
var plugin: SwiftFlutterPlugin?
|
||||||
var job: UIPrintInteractionController?
|
var job: UIPrintInteractionController?
|
||||||
var settings: PrintJobSettings?
|
var settings: PrintJobSettings?
|
||||||
var printFormatter: UIPrintFormatter?
|
var printFormatter: UIPrintFormatter?
|
||||||
|
@ -27,19 +27,21 @@ public class PrintJobController : NSObject, Disposable, UIPrintInteractionContro
|
||||||
var state = PrintJobState.created
|
var state = PrintJobState.created
|
||||||
var creationTime = Int64(Date().timeIntervalSince1970 * 1000)
|
var creationTime = Int64(Date().timeIntervalSince1970 * 1000)
|
||||||
|
|
||||||
public init(registrar: FlutterPluginRegistrar, id: String, job: UIPrintInteractionController? = nil, settings: PrintJobSettings? = nil) {
|
public init(plugin: SwiftFlutterPlugin, id: String, job: UIPrintInteractionController? = nil, settings: PrintJobSettings? = nil) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.registrar = registrar
|
self.plugin = plugin
|
||||||
super.init()
|
super.init()
|
||||||
self.job = job
|
self.job = job
|
||||||
self.settings = settings
|
self.settings = settings
|
||||||
self.printFormatter = job?.printFormatter
|
self.printFormatter = job?.printFormatter
|
||||||
self.printPageRenderer = job?.printPageRenderer
|
self.printPageRenderer = job?.printPageRenderer
|
||||||
self.job?.delegate = self
|
self.job?.delegate = self
|
||||||
|
if let registrar = plugin.registrar {
|
||||||
let channel = FlutterMethodChannel(name: PrintJobController.METHOD_CHANNEL_NAME_PREFIX + id,
|
let channel = FlutterMethodChannel(name: PrintJobController.METHOD_CHANNEL_NAME_PREFIX + id,
|
||||||
binaryMessenger: registrar.messenger())
|
binaryMessenger: registrar.messenger())
|
||||||
self.channelDelegate = PrintJobChannelDelegate(printJobController: self, channel: channel)
|
self.channelDelegate = PrintJobChannelDelegate(printJobController: self, channel: channel)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func printInteractionControllerWillStartJob(_ printInteractionController: UIPrintInteractionController) {
|
public func printInteractionControllerWillStartJob(_ printInteractionController: UIPrintInteractionController) {
|
||||||
state = .started
|
state = .started
|
||||||
|
@ -82,7 +84,8 @@ public class PrintJobController : NSObject, Disposable, UIPrintInteractionContro
|
||||||
printPageRenderer = nil
|
printPageRenderer = nil
|
||||||
job?.delegate = nil
|
job?.delegate = nil
|
||||||
job = nil
|
job = nil
|
||||||
PrintJobManager.jobs[id] = nil
|
plugin?.printJobManager?.jobs[id] = nil
|
||||||
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
public func dispose() {
|
public func dispose() {
|
||||||
|
@ -93,7 +96,7 @@ public class PrintJobController : NSObject, Disposable, UIPrintInteractionContro
|
||||||
job?.delegate = nil
|
job?.delegate = nil
|
||||||
job?.dismiss(animated: false)
|
job?.dismiss(animated: false)
|
||||||
job = nil
|
job = nil
|
||||||
PrintJobManager.jobs[id] = nil
|
plugin?.printJobManager?.jobs[id] = nil
|
||||||
registrar = nil
|
plugin = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,18 +8,21 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public class PrintJobManager: NSObject, Disposable {
|
public class PrintJobManager: NSObject, Disposable {
|
||||||
static var jobs: [String: PrintJobController?] = [:]
|
var plugin: SwiftFlutterPlugin?
|
||||||
|
var jobs: [String: PrintJobController?] = [:]
|
||||||
|
|
||||||
public override init() {
|
public init(plugin: SwiftFlutterPlugin?) {
|
||||||
super.init()
|
super.init()
|
||||||
|
self.plugin = plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
public func dispose() {
|
public func dispose() {
|
||||||
let jobs = PrintJobManager.jobs.values
|
let jobValues = jobs.values
|
||||||
jobs.forEach { (job: PrintJobController?) in
|
jobValues.forEach { (job: PrintJobController?) in
|
||||||
job?.dispose()
|
job?.dispose()
|
||||||
}
|
}
|
||||||
PrintJobManager.jobs.removeAll()
|
jobs.removeAll()
|
||||||
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
|
|
@ -10,18 +10,22 @@ import Flutter
|
||||||
|
|
||||||
public class PullToRefreshControl : UIRefreshControl, Disposable {
|
public class PullToRefreshControl : UIRefreshControl, Disposable {
|
||||||
static var METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_pull_to_refresh_";
|
static var METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_pull_to_refresh_";
|
||||||
|
var plugin: SwiftFlutterPlugin?
|
||||||
var channelDelegate: PullToRefreshChannelDelegate?
|
var channelDelegate: PullToRefreshChannelDelegate?
|
||||||
var settings: PullToRefreshSettings?
|
var settings: PullToRefreshSettings?
|
||||||
var shouldCallOnRefresh = false
|
var shouldCallOnRefresh = false
|
||||||
var delegate: PullToRefreshDelegate?
|
var delegate: PullToRefreshDelegate?
|
||||||
|
|
||||||
public init(registrar: FlutterPluginRegistrar, id: Any, settings: PullToRefreshSettings?) {
|
public init(plugin: SwiftFlutterPlugin, id: Any, settings: PullToRefreshSettings?) {
|
||||||
super.init()
|
super.init()
|
||||||
|
self.plugin = plugin
|
||||||
self.settings = settings
|
self.settings = settings
|
||||||
|
if let registrar = plugin.registrar {
|
||||||
let channel = FlutterMethodChannel(name: PullToRefreshControl.METHOD_CHANNEL_NAME_PREFIX + String(describing: id),
|
let channel = FlutterMethodChannel(name: PullToRefreshControl.METHOD_CHANNEL_NAME_PREFIX + String(describing: id),
|
||||||
binaryMessenger: registrar.messenger())
|
binaryMessenger: registrar.messenger())
|
||||||
self.channelDelegate = PullToRefreshChannelDelegate(pullToRefreshControl: self, channel: channel)
|
self.channelDelegate = PullToRefreshChannelDelegate(pullToRefreshControl: self, channel: channel)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
super.init(coder: coder)
|
super.init(coder: coder)
|
||||||
|
@ -59,6 +63,7 @@ public class PullToRefreshControl : UIRefreshControl, Disposable {
|
||||||
channelDelegate = nil
|
channelDelegate = nil
|
||||||
removeTarget(self, action: #selector(updateShouldCallOnRefresh), for: .valueChanged)
|
removeTarget(self, action: #selector(updateShouldCallOnRefresh), for: .valueChanged)
|
||||||
delegate = nil
|
delegate = nil
|
||||||
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
|
|
@ -15,9 +15,8 @@ import SafariServices
|
||||||
public class ChromeSafariBrowserManager: ChannelDelegate {
|
public class ChromeSafariBrowserManager: ChannelDelegate {
|
||||||
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_chromesafaribrowser"
|
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_chromesafaribrowser"
|
||||||
var plugin: SwiftFlutterPlugin?
|
var plugin: SwiftFlutterPlugin?
|
||||||
static var browsers: [String: SafariViewController?] = [:]
|
var browsers: [String: SafariViewController?] = [:]
|
||||||
@available(iOS 15.0, *)
|
var prewarmingTokens: [String: Any?] = [:]
|
||||||
static var prewarmingTokens: [String: SFSafariViewController.PrewarmingToken?] = [:]
|
|
||||||
|
|
||||||
init(plugin: SwiftFlutterPlugin) {
|
init(plugin: SwiftFlutterPlugin) {
|
||||||
super.init(channel: FlutterMethodChannel(name: ChromeSafariBrowserManager.METHOD_CHANNEL_NAME, binaryMessenger: plugin.registrar!.messenger()))
|
super.init(channel: FlutterMethodChannel(name: ChromeSafariBrowserManager.METHOD_CHANNEL_NAME, binaryMessenger: plugin.registrar!.messenger()))
|
||||||
|
@ -61,7 +60,7 @@ public class ChromeSafariBrowserManager: ChannelDelegate {
|
||||||
}
|
}
|
||||||
let prewarmingToken = SFSafariViewController.prewarmConnections(to: URLs)
|
let prewarmingToken = SFSafariViewController.prewarmConnections(to: URLs)
|
||||||
let prewarmingTokenId = NSUUID().uuidString
|
let prewarmingTokenId = NSUUID().uuidString
|
||||||
ChromeSafariBrowserManager.prewarmingTokens[prewarmingTokenId] = prewarmingToken
|
prewarmingTokens[prewarmingTokenId] = prewarmingToken
|
||||||
result([
|
result([
|
||||||
"id": prewarmingTokenId
|
"id": prewarmingTokenId
|
||||||
])
|
])
|
||||||
|
@ -72,9 +71,9 @@ public class ChromeSafariBrowserManager: ChannelDelegate {
|
||||||
if #available(iOS 15.0, *) {
|
if #available(iOS 15.0, *) {
|
||||||
let prewarmingToken = arguments!["prewarmingToken"] as! [String:Any?]
|
let prewarmingToken = arguments!["prewarmingToken"] as! [String:Any?]
|
||||||
if let prewarmingTokenId = prewarmingToken["id"] as? String,
|
if let prewarmingTokenId = prewarmingToken["id"] as? String,
|
||||||
let prewarmingToken = ChromeSafariBrowserManager.prewarmingTokens[prewarmingTokenId] {
|
let prewarmingToken = prewarmingTokens[prewarmingTokenId] as? SFSafariViewController.PrewarmingToken? {
|
||||||
prewarmingToken?.invalidate()
|
prewarmingToken?.invalidate()
|
||||||
ChromeSafariBrowserManager.prewarmingTokens[prewarmingTokenId] = nil
|
prewarmingTokens[prewarmingTokenId] = nil
|
||||||
}
|
}
|
||||||
result(true)
|
result(true)
|
||||||
} else {
|
} else {
|
||||||
|
@ -115,7 +114,7 @@ public class ChromeSafariBrowserManager: ChannelDelegate {
|
||||||
result(true)
|
result(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
ChromeSafariBrowserManager.browsers[id] = safari
|
browsers[id] = safari
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -125,17 +124,20 @@ public class ChromeSafariBrowserManager: ChannelDelegate {
|
||||||
|
|
||||||
public override func dispose() {
|
public override func dispose() {
|
||||||
super.dispose()
|
super.dispose()
|
||||||
let browsers = ChromeSafariBrowserManager.browsers.values
|
let browserValues = browsers.values
|
||||||
browsers.forEach { (browser: SafariViewController?) in
|
browserValues.forEach { (browser: SafariViewController?) in
|
||||||
browser?.close(result: nil)
|
browser?.close(result: nil)
|
||||||
browser?.dispose()
|
browser?.dispose()
|
||||||
}
|
}
|
||||||
ChromeSafariBrowserManager.browsers.removeAll()
|
browsers.removeAll()
|
||||||
if #available(iOS 15.0, *) {
|
if #available(iOS 15.0, *) {
|
||||||
ChromeSafariBrowserManager.prewarmingTokens.values.forEach { (prewarmingToken: SFSafariViewController.PrewarmingToken?) in
|
let prewarmingTokensValues = prewarmingTokens.values
|
||||||
|
prewarmingTokensValues.forEach { (prewarmingToken: Any?) in
|
||||||
|
if let prewarmingToken = prewarmingToken as? SFSafariViewController.PrewarmingToken? {
|
||||||
prewarmingToken?.invalidate()
|
prewarmingToken?.invalidate()
|
||||||
}
|
}
|
||||||
ChromeSafariBrowserManager.prewarmingTokens.removeAll()
|
}
|
||||||
|
prewarmingTokens.removeAll()
|
||||||
}
|
}
|
||||||
plugin = nil
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class CustomUIActivity : UIActivity {
|
class CustomUIActivity : UIActivity {
|
||||||
|
var plugin: SwiftFlutterPlugin
|
||||||
var viewId: String
|
var viewId: String
|
||||||
var id: Int64
|
var id: Int64
|
||||||
var url: URL
|
var url: URL
|
||||||
|
@ -16,7 +17,8 @@ class CustomUIActivity : UIActivity {
|
||||||
var label: String?
|
var label: String?
|
||||||
var image: UIImage?
|
var image: UIImage?
|
||||||
|
|
||||||
init(viewId: String, id: Int64, url: URL, title: String?, label: String?, type: UIActivity.ActivityType?, image: UIImage?) {
|
init(plugin: SwiftFlutterPlugin, viewId: String, id: Int64, url: URL, title: String?, label: String?, type: UIActivity.ActivityType?, image: UIImage?) {
|
||||||
|
self.plugin = plugin
|
||||||
self.viewId = viewId
|
self.viewId = viewId
|
||||||
self.id = id
|
self.id = id
|
||||||
self.url = url
|
self.url = url
|
||||||
|
@ -47,7 +49,7 @@ class CustomUIActivity : UIActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
override func perform() {
|
override func perform() {
|
||||||
let browser = ChromeSafariBrowserManager.browsers[viewId]
|
let browser = plugin.chromeSafariBrowserManager?.browsers[viewId]
|
||||||
browser??.channelDelegate?.onItemActionPerform(id: id, url: url, title: title)
|
browser??.channelDelegate?.onItemActionPerform(id: id, url: url, title: title)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,9 +105,14 @@ public class SafariViewController: SFSafariViewController, SFSafariViewControlle
|
||||||
}
|
}
|
||||||
|
|
||||||
public func safariViewController(_ controller: SFSafariViewController, activityItemsFor URL: URL, title: String?) -> [UIActivity] {
|
public func safariViewController(_ controller: SFSafariViewController, activityItemsFor URL: URL, title: String?) -> [UIActivity] {
|
||||||
|
guard let plugin = plugin else {
|
||||||
|
return []
|
||||||
|
}
|
||||||
var uiActivities: [UIActivity] = []
|
var uiActivities: [UIActivity] = []
|
||||||
menuItemList.forEach { (menuItem) in
|
menuItemList.forEach { (menuItem) in
|
||||||
let activity = CustomUIActivity(viewId: id, id: menuItem["id"] as! Int64, url: URL, title: title, label: menuItem["label"] as? String, type: nil, image: .fromMap(map: menuItem["image"] as? [String:Any?]))
|
let activity = CustomUIActivity(plugin: plugin, viewId: id, id: menuItem["id"] as! Int64, url: URL,
|
||||||
|
title: title, label: menuItem["label"] as? String, type: nil,
|
||||||
|
image: .fromMap(map: menuItem["image"] as? [String:Any?]))
|
||||||
uiActivities.append(activity)
|
uiActivities.append(activity)
|
||||||
}
|
}
|
||||||
return uiActivities
|
return uiActivities
|
||||||
|
@ -125,7 +130,7 @@ public class SafariViewController: SFSafariViewController, SFSafariViewControlle
|
||||||
channelDelegate?.dispose()
|
channelDelegate?.dispose()
|
||||||
channelDelegate = nil
|
channelDelegate = nil
|
||||||
delegate = nil
|
delegate = nil
|
||||||
ChromeSafariBrowserManager.browsers[id] = nil
|
plugin?.chromeSafariBrowserManager?.browsers[id] = nil
|
||||||
plugin = nil
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
||||||
|
|
||||||
var registrar: FlutterPluginRegistrar?
|
var registrar: FlutterPluginRegistrar?
|
||||||
var platformUtil: PlatformUtil?
|
var platformUtil: PlatformUtil?
|
||||||
var inAppWebViewStatic: InAppWebViewStatic?
|
var inAppWebViewManager: InAppWebViewManager?
|
||||||
var myCookieManager: Any?
|
var myCookieManager: Any?
|
||||||
var myWebStorageManager: Any?
|
var myWebStorageManager: Any?
|
||||||
var credentialDatabase: CredentialDatabase?
|
var credentialDatabase: CredentialDatabase?
|
||||||
|
@ -43,13 +43,13 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
self.registrar = registrar
|
self.registrar = registrar
|
||||||
registrar.register(FlutterWebViewFactory(registrar: registrar) as FlutterPlatformViewFactory, withId: FlutterWebViewFactory.VIEW_TYPE_ID)
|
registrar.register(FlutterWebViewFactory(plugin: self) as FlutterPlatformViewFactory, withId: FlutterWebViewFactory.VIEW_TYPE_ID)
|
||||||
|
|
||||||
platformUtil = PlatformUtil(plugin: self)
|
platformUtil = PlatformUtil(plugin: self)
|
||||||
inAppBrowserManager = InAppBrowserManager(plugin: self)
|
inAppBrowserManager = InAppBrowserManager(plugin: self)
|
||||||
headlessInAppWebViewManager = HeadlessInAppWebViewManager(plugin: self)
|
headlessInAppWebViewManager = HeadlessInAppWebViewManager(plugin: self)
|
||||||
chromeSafariBrowserManager = ChromeSafariBrowserManager(plugin: self)
|
chromeSafariBrowserManager = ChromeSafariBrowserManager(plugin: self)
|
||||||
inAppWebViewStatic = InAppWebViewStatic(plugin: self)
|
inAppWebViewManager = InAppWebViewManager(plugin: self)
|
||||||
credentialDatabase = CredentialDatabase(plugin: self)
|
credentialDatabase = CredentialDatabase(plugin: self)
|
||||||
if #available(iOS 11.0, *) {
|
if #available(iOS 11.0, *) {
|
||||||
myCookieManager = MyCookieManager(plugin: self)
|
myCookieManager = MyCookieManager(plugin: self)
|
||||||
|
@ -58,7 +58,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
||||||
myWebStorageManager = MyWebStorageManager(plugin: self)
|
myWebStorageManager = MyWebStorageManager(plugin: self)
|
||||||
}
|
}
|
||||||
webAuthenticationSessionManager = WebAuthenticationSessionManager(plugin: self)
|
webAuthenticationSessionManager = WebAuthenticationSessionManager(plugin: self)
|
||||||
printJobManager = PrintJobManager()
|
printJobManager = PrintJobManager(plugin: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||||
|
@ -74,8 +74,8 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
||||||
headlessInAppWebViewManager = nil
|
headlessInAppWebViewManager = nil
|
||||||
chromeSafariBrowserManager?.dispose()
|
chromeSafariBrowserManager?.dispose()
|
||||||
chromeSafariBrowserManager = nil
|
chromeSafariBrowserManager = nil
|
||||||
inAppWebViewStatic?.dispose()
|
inAppWebViewManager?.dispose()
|
||||||
inAppWebViewStatic = nil
|
inAppWebViewManager = nil
|
||||||
credentialDatabase?.dispose()
|
credentialDatabase?.dispose()
|
||||||
credentialDatabase = nil
|
credentialDatabase = nil
|
||||||
if #available(iOS 11.0, *) {
|
if #available(iOS 11.0, *) {
|
||||||
|
|
|
@ -11,17 +11,17 @@ import WebKit
|
||||||
var SharedLastTouchPointTimestamp: [InAppWebView: Int64] = [:]
|
var SharedLastTouchPointTimestamp: [InAppWebView: Int64] = [:]
|
||||||
|
|
||||||
public class Util {
|
public class Util {
|
||||||
public static func getUrlAsset(registrar: FlutterPluginRegistrar, assetFilePath: String) throws -> URL {
|
public static func getUrlAsset(plugin: SwiftFlutterPlugin, assetFilePath: String) throws -> URL {
|
||||||
let key = registrar.lookupKey(forAsset: assetFilePath)
|
guard let key = plugin.registrar?.lookupKey(forAsset: assetFilePath),
|
||||||
guard let assetURL = Bundle.main.url(forResource: key, withExtension: nil) else {
|
let assetURL = Bundle.main.url(forResource: key, withExtension: nil) else {
|
||||||
throw NSError(domain: assetFilePath + " asset file cannot be found!", code: 0)
|
throw NSError(domain: assetFilePath + " asset file cannot be found!", code: 0)
|
||||||
}
|
}
|
||||||
return assetURL
|
return assetURL
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func getAbsPathAsset(registrar: FlutterPluginRegistrar, assetFilePath: String) throws -> String {
|
public static func getAbsPathAsset(plugin: SwiftFlutterPlugin, assetFilePath: String) throws -> String {
|
||||||
let key = registrar.lookupKey(forAsset: assetFilePath)
|
guard let key = plugin.registrar?.lookupKey(forAsset: assetFilePath),
|
||||||
guard let assetAbsPath = Bundle.main.path(forResource: key, ofType: nil) else {
|
let assetAbsPath = Bundle.main.path(forResource: key, ofType: nil) else {
|
||||||
throw NSError(domain: assetFilePath + " asset file cannot be found!", code: 0)
|
throw NSError(domain: assetFilePath + " asset file cannot be found!", code: 0)
|
||||||
}
|
}
|
||||||
return assetAbsPath
|
return assetAbsPath
|
||||||
|
|
|
@ -98,7 +98,7 @@ public class WebAuthenticationSession : NSObject, ASWebAuthenticationPresentatio
|
||||||
channelDelegate?.dispose()
|
channelDelegate?.dispose()
|
||||||
channelDelegate = nil
|
channelDelegate = nil
|
||||||
session = nil
|
session = nil
|
||||||
WebAuthenticationSessionManager.sessions[id] = nil
|
plugin?.webAuthenticationSessionManager?.sessions[id] = nil
|
||||||
plugin = nil
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ import SafariServices
|
||||||
public class WebAuthenticationSessionManager: ChannelDelegate {
|
public class WebAuthenticationSessionManager: ChannelDelegate {
|
||||||
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_webauthenticationsession"
|
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_webauthenticationsession"
|
||||||
var plugin: SwiftFlutterPlugin?
|
var plugin: SwiftFlutterPlugin?
|
||||||
static var sessions: [String: WebAuthenticationSession?] = [:]
|
var sessions: [String: WebAuthenticationSession?] = [:]
|
||||||
|
|
||||||
init(plugin: SwiftFlutterPlugin) {
|
init(plugin: SwiftFlutterPlugin) {
|
||||||
super.init(channel: FlutterMethodChannel(name: WebAuthenticationSessionManager.METHOD_CHANNEL_NAME, binaryMessenger: plugin.registrar!.messenger()))
|
super.init(channel: FlutterMethodChannel(name: WebAuthenticationSessionManager.METHOD_CHANNEL_NAME, binaryMessenger: plugin.registrar!.messenger()))
|
||||||
|
@ -53,7 +53,7 @@ public class WebAuthenticationSessionManager: ChannelDelegate {
|
||||||
let _ = initialSettings.parse(settings: settings)
|
let _ = initialSettings.parse(settings: settings)
|
||||||
let session = WebAuthenticationSession(plugin: plugin, id: id, url: sessionUrl, callbackURLScheme: callbackURLScheme, settings: initialSettings)
|
let session = WebAuthenticationSession(plugin: plugin, id: id, url: sessionUrl, callbackURLScheme: callbackURLScheme, settings: initialSettings)
|
||||||
session.prepare()
|
session.prepare()
|
||||||
WebAuthenticationSessionManager.sessions[id] = session
|
sessions[id] = session
|
||||||
result(true)
|
result(true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -63,12 +63,12 @@ public class WebAuthenticationSessionManager: ChannelDelegate {
|
||||||
|
|
||||||
public override func dispose() {
|
public override func dispose() {
|
||||||
super.dispose()
|
super.dispose()
|
||||||
let sessions = WebAuthenticationSessionManager.sessions.values
|
let sessionValues = sessions.values
|
||||||
sessions.forEach { (session: WebAuthenticationSession?) in
|
sessionValues.forEach { (session: WebAuthenticationSession?) in
|
||||||
session?.cancel()
|
session?.cancel()
|
||||||
session?.dispose()
|
session?.dispose()
|
||||||
}
|
}
|
||||||
WebAuthenticationSessionManager.sessions.removeAll()
|
sessions.removeAll()
|
||||||
plugin = nil
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
export 'service_worker_controller.dart';
|
export 'service_worker_controller.dart';
|
||||||
export 'webview_feature.dart' show WebViewFeature, AndroidWebViewFeature;
|
export 'webview_feature.dart' show WebViewFeature, AndroidWebViewFeature;
|
||||||
export 'proxy_controller.dart';
|
export 'proxy_controller.dart' show ProxyController, ProxySettings;
|
||||||
export 'webview_asset_loader.dart'
|
export 'webview_asset_loader.dart'
|
||||||
show
|
show
|
||||||
WebViewAssetLoader,
|
WebViewAssetLoader,
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_inappwebview_internal_annotations/flutter_inappwebview_internal_annotations.dart';
|
||||||
|
import '../types/proxy_rule.dart';
|
||||||
import 'webview_feature.dart';
|
import 'webview_feature.dart';
|
||||||
import '../in_app_webview/webview.dart';
|
import '../in_app_webview/webview.dart';
|
||||||
import '../types/main.dart';
|
import '../types/main.dart';
|
||||||
|
|
||||||
|
part 'proxy_controller.g.dart';
|
||||||
|
|
||||||
///Manages setting and clearing a process-specific override for the Android system-wide proxy settings that govern network requests made by [WebView].
|
///Manages setting and clearing a process-specific override for the Android system-wide proxy settings that govern network requests made by [WebView].
|
||||||
///
|
///
|
||||||
///[WebView] may make network requests in order to fetch content that is not otherwise read from the file system or provided directly by application code.
|
///[WebView] may make network requests in order to fetch content that is not otherwise read from the file system or provided directly by application code.
|
||||||
|
@ -78,7 +82,8 @@ class ProxyController {
|
||||||
///
|
///
|
||||||
///**Supported Platforms/Implementations**:
|
///**Supported Platforms/Implementations**:
|
||||||
///- Android native WebView ([Official API - ProxyConfig](https://developer.android.com/reference/androidx/webkit/ProxyConfig))
|
///- Android native WebView ([Official API - ProxyConfig](https://developer.android.com/reference/androidx/webkit/ProxyConfig))
|
||||||
class ProxySettings {
|
@ExchangeableObject(copyMethod: true)
|
||||||
|
class ProxySettings_ {
|
||||||
///List of bypass rules.
|
///List of bypass rules.
|
||||||
///
|
///
|
||||||
///A bypass rule describes URLs that should skip proxy override settings and make a direct connection instead. These can be URLs or IP addresses. Wildcards are accepted.
|
///A bypass rule describes URLs that should skip proxy override settings and make a direct connection instead. These can be URLs or IP addresses. Wildcards are accepted.
|
||||||
|
@ -99,7 +104,7 @@ class ProxySettings {
|
||||||
///Port number is optional and defaults to `80` for `HTTP`, `443` for `HTTPS` and `1080` for `SOCKS`.
|
///Port number is optional and defaults to `80` for `HTTP`, `443` for `HTTPS` and `1080` for `SOCKS`.
|
||||||
///
|
///
|
||||||
///The correct syntax for hosts is defined by [RFC 3986](https://tools.ietf.org/html/rfc3986#section-3.2.2).
|
///The correct syntax for hosts is defined by [RFC 3986](https://tools.ietf.org/html/rfc3986#section-3.2.2).
|
||||||
List<ProxyRule> proxyRules;
|
List<ProxyRule_> proxyRules;
|
||||||
|
|
||||||
///Hostnames without a period in them (and that are not IP literals) will skip proxy settings and be connected to directly instead. Examples: `"abc"`, `"local"`, `"some-domain"`.
|
///Hostnames without a period in them (and that are not IP literals) will skip proxy settings and be connected to directly instead. Examples: `"abc"`, `"local"`, `"some-domain"`.
|
||||||
///
|
///
|
||||||
|
@ -128,7 +133,7 @@ class ProxySettings {
|
||||||
///**NOTE**: available only if [WebViewFeature.PROXY_OVERRIDE_REVERSE_BYPASS] feature is supported.
|
///**NOTE**: available only if [WebViewFeature.PROXY_OVERRIDE_REVERSE_BYPASS] feature is supported.
|
||||||
bool reverseBypassEnabled;
|
bool reverseBypassEnabled;
|
||||||
|
|
||||||
ProxySettings(
|
ProxySettings_(
|
||||||
{this.bypassRules = const [],
|
{this.bypassRules = const [],
|
||||||
this.directs = const [],
|
this.directs = const [],
|
||||||
this.proxyRules = const [],
|
this.proxyRules = const [],
|
||||||
|
@ -136,40 +141,40 @@ class ProxySettings {
|
||||||
this.removeImplicitRules,
|
this.removeImplicitRules,
|
||||||
this.reverseBypassEnabled = false});
|
this.reverseBypassEnabled = false});
|
||||||
|
|
||||||
Map<String, dynamic> toMap() {
|
// Map<String, dynamic> toMap() {
|
||||||
return {
|
// return {
|
||||||
"bypassRules": bypassRules,
|
// "bypassRules": bypassRules,
|
||||||
"directs": directs,
|
// "directs": directs,
|
||||||
"proxyRules": proxyRules.map((e) => e.toMap()).toList(),
|
// "proxyRules": proxyRules.map((e) => e.toMap()).toList(),
|
||||||
"bypassSimpleHostnames": bypassSimpleHostnames,
|
// "bypassSimpleHostnames": bypassSimpleHostnames,
|
||||||
"removeImplicitRules": removeImplicitRules,
|
// "removeImplicitRules": removeImplicitRules,
|
||||||
"reverseBypassEnabled": reverseBypassEnabled
|
// "reverseBypassEnabled": reverseBypassEnabled
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
static ProxySettings fromMap(Map<String, dynamic> map) {
|
// static ProxySettings fromMap(Map<String, dynamic> map) {
|
||||||
var settings = ProxySettings();
|
// var settings = ProxySettings();
|
||||||
settings.bypassRules = map["bypassRules"];
|
// settings.bypassRules = map["bypassRules"];
|
||||||
settings.directs = map["directs"];
|
// settings.directs = map["directs"];
|
||||||
settings.proxyRules = (map["proxyRules"].cast<Map<String, dynamic>>()
|
// settings.proxyRules = (map["proxyRules"].cast<Map<String, dynamic>>()
|
||||||
as List<Map<String, dynamic>>)
|
// as List<Map<String, dynamic>>)
|
||||||
.map((e) => ProxyRule.fromMap(e)) as List<ProxyRule>;
|
// .map((e) => ProxyRule.fromMap(e)) as List<ProxyRule>;
|
||||||
settings.bypassSimpleHostnames = map["bypassSimpleHostnames"];
|
// settings.bypassSimpleHostnames = map["bypassSimpleHostnames"];
|
||||||
settings.removeImplicitRules = map["removeImplicitRules"];
|
// settings.removeImplicitRules = map["removeImplicitRules"];
|
||||||
settings.reverseBypassEnabled = map["reverseBypassEnabled"];
|
// settings.reverseBypassEnabled = map["reverseBypassEnabled"];
|
||||||
return settings;
|
// return settings;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
Map<String, dynamic> toJson() {
|
// Map<String, dynamic> toJson() {
|
||||||
return this.toMap();
|
// return this.toMap();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@override
|
// @override
|
||||||
String toString() {
|
// String toString() {
|
||||||
return toMap().toString();
|
// return 'ProxySettings{bypassRules: $bypassRules, directs: $directs, proxyRules: $proxyRules, bypassSimpleHostnames: $bypassSimpleHostnames, removeImplicitRules: $removeImplicitRules, reverseBypassEnabled: $reverseBypassEnabled}';
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
ProxySettings copy() {
|
// ProxySettings copy() {
|
||||||
return ProxySettings.fromMap(this.toMap());
|
// return ProxySettings.fromMap(this.toMap());
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'proxy_controller.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// ExchangeableObjectGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
///Class that represents the settings used to configure the [ProxyController].
|
||||||
|
///
|
||||||
|
///**Supported Platforms/Implementations**:
|
||||||
|
///- Android native WebView ([Official API - ProxyConfig](https://developer.android.com/reference/androidx/webkit/ProxyConfig))
|
||||||
|
class ProxySettings {
|
||||||
|
///List of bypass rules.
|
||||||
|
///
|
||||||
|
///A bypass rule describes URLs that should skip proxy override settings and make a direct connection instead. These can be URLs or IP addresses. Wildcards are accepted.
|
||||||
|
///For instance, the rule "*example.com" would mean that requests to "http://example.com" and "www.example.com" would not be directed to any proxy,
|
||||||
|
///instead, would be made directly to the origin specified by the URL.
|
||||||
|
List<String> bypassRules;
|
||||||
|
|
||||||
|
///Hostnames without a period in them (and that are not IP literals) will skip proxy settings and be connected to directly instead. Examples: `"abc"`, `"local"`, `"some-domain"`.
|
||||||
|
///
|
||||||
|
///Hostnames with a trailing dot are not considered simple by this definition.
|
||||||
|
bool? bypassSimpleHostnames;
|
||||||
|
|
||||||
|
///List of scheme filters.
|
||||||
|
///
|
||||||
|
///URLs that match these scheme filters are connected to directly instead of using a proxy server.
|
||||||
|
List<String> directs;
|
||||||
|
|
||||||
|
///List of proxy rules to be used for all URLs. This method can be called multiple times to add multiple rules. Additional rules have decreasing precedence.
|
||||||
|
///
|
||||||
|
///Proxy is a string in the format `[scheme://]host[:port]`.
|
||||||
|
///Scheme is optional, if present must be `HTTP`, `HTTPS` or [SOCKS](https://tools.ietf.org/html/rfc1928) and defaults to `HTTP`.
|
||||||
|
///Host is one of an IPv6 literal with brackets, an IPv4 literal or one or more labels separated by a period.
|
||||||
|
///Port number is optional and defaults to `80` for `HTTP`, `443` for `HTTPS` and `1080` for `SOCKS`.
|
||||||
|
///
|
||||||
|
///The correct syntax for hosts is defined by [RFC 3986](https://tools.ietf.org/html/rfc3986#section-3.2.2).
|
||||||
|
List<ProxyRule> proxyRules;
|
||||||
|
|
||||||
|
///By default, certain hostnames implicitly bypass the proxy if they are link-local IPs, or localhost addresses.
|
||||||
|
///For instance hostnames matching any of (non-exhaustive list):
|
||||||
|
///- localhost
|
||||||
|
///- *.localhost
|
||||||
|
///- [::1]
|
||||||
|
///- 127.0.0.1/8
|
||||||
|
///- 169.254/16
|
||||||
|
///- [FE80::]/10
|
||||||
|
///Set this to `true` to override the default behavior and force localhost and link-local URLs to be sent through the proxy.
|
||||||
|
bool? removeImplicitRules;
|
||||||
|
|
||||||
|
///Reverse the bypass list.
|
||||||
|
///
|
||||||
|
///The default value is `false`, in which case all URLs will use proxy settings except the ones in the bypass list, which will be connected to directly instead.
|
||||||
|
///
|
||||||
|
///If set to `true`, then only URLs in the bypass list will use these proxy settings, and all other URLs will be connected to directly.
|
||||||
|
///
|
||||||
|
///Use [bypassRules] to add bypass rules.
|
||||||
|
///
|
||||||
|
///**NOTE**: available only if [WebViewFeature.PROXY_OVERRIDE_REVERSE_BYPASS] feature is supported.
|
||||||
|
bool reverseBypassEnabled;
|
||||||
|
ProxySettings(
|
||||||
|
{this.bypassRules = const [],
|
||||||
|
this.bypassSimpleHostnames,
|
||||||
|
this.directs = const [],
|
||||||
|
this.proxyRules = const [],
|
||||||
|
this.removeImplicitRules,
|
||||||
|
this.reverseBypassEnabled = false});
|
||||||
|
|
||||||
|
///Gets a possible [ProxySettings] instance from a [Map] value.
|
||||||
|
static ProxySettings? fromMap(Map<String, dynamic>? map) {
|
||||||
|
if (map == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final instance = ProxySettings(
|
||||||
|
bypassSimpleHostnames: map['bypassSimpleHostnames'],
|
||||||
|
removeImplicitRules: map['removeImplicitRules'],
|
||||||
|
);
|
||||||
|
instance.bypassRules =
|
||||||
|
List<String>.from(map['bypassRules']!.cast<String>());
|
||||||
|
instance.directs = List<String>.from(map['directs']!.cast<String>());
|
||||||
|
instance.proxyRules = List<ProxyRule>.from(map['proxyRules']
|
||||||
|
.map((e) => ProxyRule.fromMap(e?.cast<String, dynamic>())!));
|
||||||
|
instance.reverseBypassEnabled = map['reverseBypassEnabled'];
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
///Converts instance to a map.
|
||||||
|
Map<String, dynamic> toMap() {
|
||||||
|
return {
|
||||||
|
"bypassRules": bypassRules,
|
||||||
|
"bypassSimpleHostnames": bypassSimpleHostnames,
|
||||||
|
"directs": directs,
|
||||||
|
"proxyRules": proxyRules.map((e) => e.toMap()).toList(),
|
||||||
|
"removeImplicitRules": removeImplicitRules,
|
||||||
|
"reverseBypassEnabled": reverseBypassEnabled,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
///Converts instance to a map.
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return toMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
///Returns a copy of ProxySettings.
|
||||||
|
ProxySettings copy() {
|
||||||
|
return ProxySettings.fromMap(toMap()) ?? ProxySettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ProxySettings{bypassRules: $bypassRules, bypassSimpleHostnames: $bypassSimpleHostnames, directs: $directs, proxyRules: $proxyRules, removeImplicitRules: $removeImplicitRules, reverseBypassEnabled: $reverseBypassEnabled}';
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,30 +15,6 @@ import '../debug_logging_settings.dart';
|
||||||
import '../web_uri.dart';
|
import '../web_uri.dart';
|
||||||
import 'chrome_safari_browser_settings.dart';
|
import 'chrome_safari_browser_settings.dart';
|
||||||
|
|
||||||
class ChromeSafariBrowserAlreadyOpenedException implements Exception {
|
|
||||||
final dynamic message;
|
|
||||||
|
|
||||||
ChromeSafariBrowserAlreadyOpenedException([this.message]);
|
|
||||||
|
|
||||||
String toString() {
|
|
||||||
Object? message = this.message;
|
|
||||||
if (message == null) return "ChromeSafariBrowserAlreadyOpenedException";
|
|
||||||
return "ChromeSafariBrowserAlreadyOpenedException: $message";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ChromeSafariBrowserNotOpenedException implements Exception {
|
|
||||||
final dynamic message;
|
|
||||||
|
|
||||||
ChromeSafariBrowserNotOpenedException([this.message]);
|
|
||||||
|
|
||||||
String toString() {
|
|
||||||
Object? message = this.message;
|
|
||||||
if (message == null) return "ChromeSafariBrowserNotOpenedException";
|
|
||||||
return "ChromeSafariBrowserNotOpenedException: $message";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///This class uses native [Chrome Custom Tabs](https://developer.android.com/reference/android/support/customtabs/package-summary) on Android
|
///This class uses native [Chrome Custom Tabs](https://developer.android.com/reference/android/support/customtabs/package-summary) on Android
|
||||||
///and [SFSafariViewController](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller) on iOS.
|
///and [SFSafariViewController](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller) on iOS.
|
||||||
///
|
///
|
||||||
|
@ -60,7 +36,7 @@ class ChromeSafariBrowser {
|
||||||
Map<int, ChromeSafariBrowserMenuItem> _menuItems = new HashMap();
|
Map<int, ChromeSafariBrowserMenuItem> _menuItems = new HashMap();
|
||||||
ChromeSafariBrowserSecondaryToolbar? _secondaryToolbar;
|
ChromeSafariBrowserSecondaryToolbar? _secondaryToolbar;
|
||||||
bool _isOpened = false;
|
bool _isOpened = false;
|
||||||
late MethodChannel _channel;
|
MethodChannel? _channel;
|
||||||
static const MethodChannel _sharedChannel =
|
static const MethodChannel _sharedChannel =
|
||||||
const MethodChannel('com.pichillilorenzo/flutter_chromesafaribrowser');
|
const MethodChannel('com.pichillilorenzo/flutter_chromesafaribrowser');
|
||||||
|
|
||||||
|
@ -68,7 +44,7 @@ class ChromeSafariBrowser {
|
||||||
id = IdGenerator.generate();
|
id = IdGenerator.generate();
|
||||||
this._channel =
|
this._channel =
|
||||||
MethodChannel('com.pichillilorenzo/flutter_chromesafaribrowser_$id');
|
MethodChannel('com.pichillilorenzo/flutter_chromesafaribrowser_$id');
|
||||||
this._channel.setMethodCallHandler((call) async {
|
this._channel?.setMethodCallHandler((call) async {
|
||||||
try {
|
try {
|
||||||
return await _handleMethod(call);
|
return await _handleMethod(call);
|
||||||
} on Error catch (e) {
|
} on Error catch (e) {
|
||||||
|
@ -79,6 +55,19 @@ class ChromeSafariBrowser {
|
||||||
_isOpened = false;
|
_isOpened = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_init() {
|
||||||
|
this._channel =
|
||||||
|
MethodChannel('com.pichillilorenzo/flutter_chromesafaribrowser_$id');
|
||||||
|
this._channel?.setMethodCallHandler((call) async {
|
||||||
|
try {
|
||||||
|
return await _handleMethod(call);
|
||||||
|
} on Error catch (e) {
|
||||||
|
print(e);
|
||||||
|
print(e.stackTrace);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
_debugLog(String method, dynamic args) {
|
_debugLog(String method, dynamic args) {
|
||||||
debugLog(
|
debugLog(
|
||||||
className: this.runtimeType.toString(),
|
className: this.runtimeType.toString(),
|
||||||
|
@ -125,8 +114,9 @@ class ChromeSafariBrowser {
|
||||||
onWillOpenInBrowser();
|
onWillOpenInBrowser();
|
||||||
break;
|
break;
|
||||||
case "onClosed":
|
case "onClosed":
|
||||||
|
_isOpened = false;
|
||||||
|
_dispose();
|
||||||
onClosed();
|
onClosed();
|
||||||
this._isOpened = false;
|
|
||||||
break;
|
break;
|
||||||
case "onItemActionPerform":
|
case "onItemActionPerform":
|
||||||
String url = call.arguments["url"];
|
String url = call.arguments["url"];
|
||||||
|
@ -208,6 +198,9 @@ class ChromeSafariBrowser {
|
||||||
// ignore: deprecated_member_use_from_same_package
|
// ignore: deprecated_member_use_from_same_package
|
||||||
ChromeSafariBrowserClassOptions? options,
|
ChromeSafariBrowserClassOptions? options,
|
||||||
ChromeSafariBrowserSettings? settings}) async {
|
ChromeSafariBrowserSettings? settings}) async {
|
||||||
|
assert(!_isOpened, 'The browser is already opened.');
|
||||||
|
_isOpened = true;
|
||||||
|
|
||||||
if (Util.isIOS) {
|
if (Util.isIOS) {
|
||||||
assert(url != null, 'The specified URL must not be null on iOS.');
|
assert(url != null, 'The specified URL must not be null on iOS.');
|
||||||
assert(['http', 'https'].contains(url!.scheme),
|
assert(['http', 'https'].contains(url!.scheme),
|
||||||
|
@ -216,9 +209,8 @@ class ChromeSafariBrowser {
|
||||||
if (url != null) {
|
if (url != null) {
|
||||||
assert(url.toString().isNotEmpty, 'The specified URL must not be empty.');
|
assert(url.toString().isNotEmpty, 'The specified URL must not be empty.');
|
||||||
}
|
}
|
||||||
this.throwIsAlreadyOpened(message: url != null ? 'Cannot open $url!' : '');
|
|
||||||
|
|
||||||
this._isOpened = true;
|
_init();
|
||||||
|
|
||||||
List<Map<String, dynamic>> menuItemList = [];
|
List<Map<String, dynamic>> menuItemList = [];
|
||||||
_menuItems.forEach((key, value) {
|
_menuItems.forEach((key, value) {
|
||||||
|
@ -269,7 +261,7 @@ class ChromeSafariBrowser {
|
||||||
args.putIfAbsent('otherLikelyURLs',
|
args.putIfAbsent('otherLikelyURLs',
|
||||||
() => otherLikelyURLs?.map((e) => e.toString()).toList());
|
() => otherLikelyURLs?.map((e) => e.toString()).toList());
|
||||||
args.putIfAbsent('referrer', () => referrer?.toString());
|
args.putIfAbsent('referrer', () => referrer?.toString());
|
||||||
await _channel.invokeMethod("launchUrl", args);
|
await _channel?.invokeMethod("launchUrl", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Tells the browser of a likely future navigation to a URL.
|
///Tells the browser of a likely future navigation to a URL.
|
||||||
|
@ -290,7 +282,7 @@ class ChromeSafariBrowser {
|
||||||
args.putIfAbsent('url', () => url?.toString());
|
args.putIfAbsent('url', () => url?.toString());
|
||||||
args.putIfAbsent('otherLikelyURLs',
|
args.putIfAbsent('otherLikelyURLs',
|
||||||
() => otherLikelyURLs?.map((e) => e.toString()).toList());
|
() => otherLikelyURLs?.map((e) => e.toString()).toList());
|
||||||
return await _channel.invokeMethod("mayLaunchUrl", args);
|
return await _channel?.invokeMethod("mayLaunchUrl", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Requests to validate a relationship between the application and an origin.
|
///Requests to validate a relationship between the application and an origin.
|
||||||
|
@ -315,7 +307,7 @@ class ChromeSafariBrowser {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('relation', () => relation.toNativeValue());
|
args.putIfAbsent('relation', () => relation.toNativeValue());
|
||||||
args.putIfAbsent('origin', () => origin.toString());
|
args.putIfAbsent('origin', () => origin.toString());
|
||||||
return await _channel.invokeMethod("validateRelationship", args);
|
return await _channel?.invokeMethod("validateRelationship", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Closes the [ChromeSafariBrowser] instance.
|
///Closes the [ChromeSafariBrowser] instance.
|
||||||
|
@ -325,7 +317,7 @@ class ChromeSafariBrowser {
|
||||||
///- iOS
|
///- iOS
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod("close", args);
|
await _channel?.invokeMethod("close", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Set a custom action button.
|
///Set a custom action button.
|
||||||
|
@ -349,7 +341,7 @@ class ChromeSafariBrowser {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('icon', () => icon);
|
args.putIfAbsent('icon', () => icon);
|
||||||
args.putIfAbsent('description', () => description);
|
args.putIfAbsent('description', () => description);
|
||||||
await _channel.invokeMethod("updateActionButton", args);
|
await _channel?.invokeMethod("updateActionButton", args);
|
||||||
_actionButton?.icon = icon;
|
_actionButton?.icon = icon;
|
||||||
_actionButton?.description = description;
|
_actionButton?.description = description;
|
||||||
}
|
}
|
||||||
|
@ -375,7 +367,7 @@ class ChromeSafariBrowser {
|
||||||
ChromeSafariBrowserSecondaryToolbar secondaryToolbar) async {
|
ChromeSafariBrowserSecondaryToolbar secondaryToolbar) async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('secondaryToolbar', () => secondaryToolbar.toMap());
|
args.putIfAbsent('secondaryToolbar', () => secondaryToolbar.toMap());
|
||||||
await _channel.invokeMethod("updateSecondaryToolbar", args);
|
await _channel?.invokeMethod("updateSecondaryToolbar", args);
|
||||||
this._secondaryToolbar = secondaryToolbar;
|
this._secondaryToolbar = secondaryToolbar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -546,23 +538,13 @@ class ChromeSafariBrowser {
|
||||||
///- Android
|
///- Android
|
||||||
///- iOS
|
///- iOS
|
||||||
bool isOpened() {
|
bool isOpened() {
|
||||||
return this._isOpened;
|
return _isOpened;
|
||||||
}
|
}
|
||||||
|
|
||||||
void throwIsAlreadyOpened({String message = ''}) {
|
///Disposes the channel.
|
||||||
if (this.isOpened()) {
|
void _dispose() {
|
||||||
throw ChromeSafariBrowserAlreadyOpenedException([
|
_channel?.setMethodCallHandler(null);
|
||||||
'Error: ${(message.isEmpty) ? '' : message + ' '}The browser is already opened.'
|
_channel = null;
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void throwIsNotOpened({String message = ''}) {
|
|
||||||
if (!this.isOpened()) {
|
|
||||||
throw ChromeSafariBrowserNotOpenedException([
|
|
||||||
'Error: ${(message.isEmpty) ? '' : message + ' '}The browser is not opened.'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -275,7 +275,7 @@ class CookieManager {
|
||||||
await pageLoaded.future;
|
await pageLoaded.future;
|
||||||
|
|
||||||
List<String> documentCookies = (await headlessWebView.webViewController
|
List<String> documentCookies = (await headlessWebView.webViewController
|
||||||
.evaluateJavascript(source: 'document.cookie') as String)
|
!.evaluateJavascript(source: 'document.cookie') as String)
|
||||||
.split(';')
|
.split(';')
|
||||||
.map((documentCookie) => documentCookie.trim())
|
.map((documentCookie) => documentCookie.trim())
|
||||||
.toList();
|
.toList();
|
||||||
|
|
|
@ -37,20 +37,6 @@ class FindInteractionController {
|
||||||
|
|
||||||
FindInteractionController({this.onFindResultReceived}) {}
|
FindInteractionController({this.onFindResultReceived}) {}
|
||||||
|
|
||||||
void initMethodChannel(dynamic id) {
|
|
||||||
this._channel = MethodChannel(
|
|
||||||
'com.pichillilorenzo/flutter_inappwebview_find_interaction_$id');
|
|
||||||
|
|
||||||
this._channel?.setMethodCallHandler((call) async {
|
|
||||||
try {
|
|
||||||
return await _handleMethod(call);
|
|
||||||
} on Error catch (e) {
|
|
||||||
print(e);
|
|
||||||
print(e.stackTrace);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_debugLog(String method, dynamic args) {
|
_debugLog(String method, dynamic args) {
|
||||||
debugLog(
|
debugLog(
|
||||||
className: this.runtimeType.toString(),
|
className: this.runtimeType.toString(),
|
||||||
|
@ -217,4 +203,29 @@ class FindInteractionController {
|
||||||
?.cast<String, dynamic>();
|
?.cast<String, dynamic>();
|
||||||
return FindSession.fromMap(result);
|
return FindSession.fromMap(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///Disposes the controller.
|
||||||
|
void dispose({bool isKeepAlive = false}) {
|
||||||
|
if (!isKeepAlive) {
|
||||||
|
_channel?.setMethodCallHandler(null);
|
||||||
|
}
|
||||||
|
_channel = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension InternalFindInteractionController on FindInteractionController {
|
||||||
|
void init(dynamic id) {
|
||||||
|
this._channel = MethodChannel(
|
||||||
|
'com.pichillilorenzo/flutter_inappwebview_find_interaction_$id');
|
||||||
|
|
||||||
|
this._channel?.setMethodCallHandler((call) async {
|
||||||
|
if (_channel == null) return null;
|
||||||
|
try {
|
||||||
|
return await _handleMethod(call);
|
||||||
|
} on Error catch (e) {
|
||||||
|
print(e);
|
||||||
|
print(e.stackTrace);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1 +1 @@
|
||||||
export 'find_interaction_controller.dart';
|
export 'find_interaction_controller.dart' show FindInteractionController;
|
||||||
|
|
|
@ -18,30 +18,7 @@ import '../print_job/main.dart';
|
||||||
import '../web_uri.dart';
|
import '../web_uri.dart';
|
||||||
import 'in_app_browser_settings.dart';
|
import 'in_app_browser_settings.dart';
|
||||||
import '../debug_logging_settings.dart';
|
import '../debug_logging_settings.dart';
|
||||||
|
import '../pull_to_refresh/pull_to_refresh_controller.dart';
|
||||||
class InAppBrowserAlreadyOpenedException implements Exception {
|
|
||||||
final dynamic message;
|
|
||||||
|
|
||||||
InAppBrowserAlreadyOpenedException([this.message]);
|
|
||||||
|
|
||||||
String toString() {
|
|
||||||
Object? message = this.message;
|
|
||||||
if (message == null) return "InAppBrowserAlreadyOpenedException";
|
|
||||||
return "InAppBrowserAlreadyOpenedException: $message";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class InAppBrowserNotOpenedException implements Exception {
|
|
||||||
final dynamic message;
|
|
||||||
|
|
||||||
InAppBrowserNotOpenedException([this.message]);
|
|
||||||
|
|
||||||
String toString() {
|
|
||||||
Object? message = this.message;
|
|
||||||
if (message == null) return "InAppBrowserNotOpenedException";
|
|
||||||
return "InAppBrowserNotOpenedException: $message";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///This class uses the native WebView of the platform.
|
///This class uses the native WebView of the platform.
|
||||||
///The [webViewController] field can be used to access the [InAppWebViewController] API.
|
///The [webViewController] field can be used to access the [InAppWebViewController] API.
|
||||||
|
@ -70,11 +47,11 @@ class InAppBrowser {
|
||||||
final UnmodifiableListView<UserScript>? initialUserScripts;
|
final UnmodifiableListView<UserScript>? initialUserScripts;
|
||||||
|
|
||||||
bool _isOpened = false;
|
bool _isOpened = false;
|
||||||
late MethodChannel _channel;
|
MethodChannel? _channel;
|
||||||
static const MethodChannel _sharedChannel =
|
static const MethodChannel _sharedChannel =
|
||||||
const MethodChannel('com.pichillilorenzo/flutter_inappbrowser');
|
const MethodChannel('com.pichillilorenzo/flutter_inappbrowser');
|
||||||
|
|
||||||
late final InAppWebViewController _webViewController;
|
InAppWebViewController? _webViewController;
|
||||||
|
|
||||||
///WebView Controller that can be used to access the [InAppWebViewController] API.
|
///WebView Controller that can be used to access the [InAppWebViewController] API.
|
||||||
///When [onExit] is fired, this will be `null` and cannot be used anymore.
|
///When [onExit] is fired, this will be `null` and cannot be used anymore.
|
||||||
|
@ -85,18 +62,16 @@ class InAppBrowser {
|
||||||
///The window id of a [CreateWindowAction.windowId].
|
///The window id of a [CreateWindowAction.windowId].
|
||||||
final int? windowId;
|
final int? windowId;
|
||||||
|
|
||||||
///Represents the WebView native implementation to be used.
|
|
||||||
///The default value is [WebViewImplementation.NATIVE].
|
|
||||||
final WebViewImplementation implementation;
|
|
||||||
|
|
||||||
InAppBrowser(
|
InAppBrowser(
|
||||||
{this.windowId,
|
{this.windowId,
|
||||||
this.initialUserScripts,
|
this.initialUserScripts}) {
|
||||||
this.implementation = WebViewImplementation.NATIVE}) {
|
|
||||||
id = IdGenerator.generate();
|
id = IdGenerator.generate();
|
||||||
|
}
|
||||||
|
|
||||||
|
_init() {
|
||||||
this._channel =
|
this._channel =
|
||||||
MethodChannel('com.pichillilorenzo/flutter_inappbrowser_$id');
|
MethodChannel('com.pichillilorenzo/flutter_inappbrowser_$id');
|
||||||
this._channel.setMethodCallHandler((call) async {
|
this._channel?.setMethodCallHandler((call) async {
|
||||||
try {
|
try {
|
||||||
return await _handleMethod(call);
|
return await _handleMethod(call);
|
||||||
} on Error catch (e) {
|
} on Error catch (e) {
|
||||||
|
@ -104,9 +79,10 @@ class InAppBrowser {
|
||||||
print(e.stackTrace);
|
print(e.stackTrace);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
_isOpened = false;
|
|
||||||
_webViewController = new InAppWebViewController.fromInAppBrowser(
|
_webViewController = new InAppWebViewController.fromInAppBrowser(
|
||||||
this._channel, this, this.initialUserScripts);
|
this._channel!, this, this.initialUserScripts);
|
||||||
|
pullToRefreshController?.init(id);
|
||||||
|
findInteractionController?.init(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
_debugLog(String method, dynamic args) {
|
_debugLog(String method, dynamic args) {
|
||||||
|
@ -122,18 +98,16 @@ class InAppBrowser {
|
||||||
switch (call.method) {
|
switch (call.method) {
|
||||||
case "onBrowserCreated":
|
case "onBrowserCreated":
|
||||||
_debugLog(call.method, call.arguments);
|
_debugLog(call.method, call.arguments);
|
||||||
this._isOpened = true;
|
|
||||||
this.pullToRefreshController?.initMethodChannel(id);
|
|
||||||
this.findInteractionController?.initMethodChannel(id);
|
|
||||||
onBrowserCreated();
|
onBrowserCreated();
|
||||||
break;
|
break;
|
||||||
case "onExit":
|
case "onExit":
|
||||||
_debugLog(call.method, call.arguments);
|
_debugLog(call.method, call.arguments);
|
||||||
this._isOpened = false;
|
_isOpened = false;
|
||||||
|
_dispose();
|
||||||
onExit();
|
onExit();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return _webViewController.handleMethod(call);
|
return _webViewController?.handleMethod(call);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,8 +128,10 @@ class InAppBrowser {
|
||||||
// ignore: deprecated_member_use_from_same_package
|
// ignore: deprecated_member_use_from_same_package
|
||||||
@Deprecated('Use settings instead') InAppBrowserClassOptions? options,
|
@Deprecated('Use settings instead') InAppBrowserClassOptions? options,
|
||||||
InAppBrowserClassSettings? settings}) async {
|
InAppBrowserClassSettings? settings}) async {
|
||||||
this.throwIfAlreadyOpened(message: 'Cannot open $urlRequest!');
|
assert(!_isOpened, 'The browser is already opened.');
|
||||||
|
_isOpened = true;
|
||||||
assert(urlRequest.url != null && urlRequest.url.toString().isNotEmpty);
|
assert(urlRequest.url != null && urlRequest.url.toString().isNotEmpty);
|
||||||
|
_init();
|
||||||
|
|
||||||
var initialSettings = settings?.toMap() ??
|
var initialSettings = settings?.toMap() ??
|
||||||
options?.toMap() ??
|
options?.toMap() ??
|
||||||
|
@ -173,7 +149,6 @@ class InAppBrowser {
|
||||||
args.putIfAbsent('settings', () => initialSettings);
|
args.putIfAbsent('settings', () => initialSettings);
|
||||||
args.putIfAbsent('contextMenu', () => contextMenu?.toMap() ?? {});
|
args.putIfAbsent('contextMenu', () => contextMenu?.toMap() ?? {});
|
||||||
args.putIfAbsent('windowId', () => windowId);
|
args.putIfAbsent('windowId', () => windowId);
|
||||||
args.putIfAbsent('implementation', () => implementation.toNativeValue());
|
|
||||||
args.putIfAbsent('initialUserScripts',
|
args.putIfAbsent('initialUserScripts',
|
||||||
() => initialUserScripts?.map((e) => e.toMap()).toList() ?? []);
|
() => initialUserScripts?.map((e) => e.toMap()).toList() ?? []);
|
||||||
args.putIfAbsent('pullToRefreshSettings', () => pullToRefreshSettings);
|
args.putIfAbsent('pullToRefreshSettings', () => pullToRefreshSettings);
|
||||||
|
@ -227,8 +202,10 @@ class InAppBrowser {
|
||||||
// ignore: deprecated_member_use_from_same_package
|
// ignore: deprecated_member_use_from_same_package
|
||||||
@Deprecated('Use settings instead') InAppBrowserClassOptions? options,
|
@Deprecated('Use settings instead') InAppBrowserClassOptions? options,
|
||||||
InAppBrowserClassSettings? settings}) async {
|
InAppBrowserClassSettings? settings}) async {
|
||||||
this.throwIfAlreadyOpened(message: 'Cannot open $assetFilePath!');
|
assert(!_isOpened, 'The browser is already opened.');
|
||||||
|
_isOpened = true;
|
||||||
assert(assetFilePath.isNotEmpty);
|
assert(assetFilePath.isNotEmpty);
|
||||||
|
_init();
|
||||||
|
|
||||||
var initialSettings = settings?.toMap() ??
|
var initialSettings = settings?.toMap() ??
|
||||||
options?.toMap() ??
|
options?.toMap() ??
|
||||||
|
@ -246,7 +223,6 @@ class InAppBrowser {
|
||||||
args.putIfAbsent('settings', () => initialSettings);
|
args.putIfAbsent('settings', () => initialSettings);
|
||||||
args.putIfAbsent('contextMenu', () => contextMenu?.toMap() ?? {});
|
args.putIfAbsent('contextMenu', () => contextMenu?.toMap() ?? {});
|
||||||
args.putIfAbsent('windowId', () => windowId);
|
args.putIfAbsent('windowId', () => windowId);
|
||||||
args.putIfAbsent('implementation', () => implementation.toNativeValue());
|
|
||||||
args.putIfAbsent('initialUserScripts',
|
args.putIfAbsent('initialUserScripts',
|
||||||
() => initialUserScripts?.map((e) => e.toMap()).toList() ?? []);
|
() => initialUserScripts?.map((e) => e.toMap()).toList() ?? []);
|
||||||
args.putIfAbsent('pullToRefreshSettings', () => pullToRefreshSettings);
|
args.putIfAbsent('pullToRefreshSettings', () => pullToRefreshSettings);
|
||||||
|
@ -279,7 +255,9 @@ class InAppBrowser {
|
||||||
// ignore: deprecated_member_use_from_same_package
|
// ignore: deprecated_member_use_from_same_package
|
||||||
@Deprecated('Use settings instead') InAppBrowserClassOptions? options,
|
@Deprecated('Use settings instead') InAppBrowserClassOptions? options,
|
||||||
InAppBrowserClassSettings? settings}) async {
|
InAppBrowserClassSettings? settings}) async {
|
||||||
this.throwIfAlreadyOpened(message: 'Cannot open data!');
|
assert(!_isOpened, 'The browser is already opened.');
|
||||||
|
_isOpened = true;
|
||||||
|
_init();
|
||||||
|
|
||||||
var initialSettings = settings?.toMap() ??
|
var initialSettings = settings?.toMap() ??
|
||||||
options?.toMap() ??
|
options?.toMap() ??
|
||||||
|
@ -302,7 +280,6 @@ class InAppBrowser {
|
||||||
() => (historyUrl ?? androidHistoryUrl)?.toString() ?? "about:blank");
|
() => (historyUrl ?? androidHistoryUrl)?.toString() ?? "about:blank");
|
||||||
args.putIfAbsent('contextMenu', () => contextMenu?.toMap() ?? {});
|
args.putIfAbsent('contextMenu', () => contextMenu?.toMap() ?? {});
|
||||||
args.putIfAbsent('windowId', () => windowId);
|
args.putIfAbsent('windowId', () => windowId);
|
||||||
args.putIfAbsent('implementation', () => implementation.toNativeValue());
|
|
||||||
args.putIfAbsent('initialUserScripts',
|
args.putIfAbsent('initialUserScripts',
|
||||||
() => initialUserScripts?.map((e) => e.toMap()).toList() ?? []);
|
() => initialUserScripts?.map((e) => e.toMap()).toList() ?? []);
|
||||||
args.putIfAbsent('pullToRefreshSettings', () => pullToRefreshSettings);
|
args.putIfAbsent('pullToRefreshSettings', () => pullToRefreshSettings);
|
||||||
|
@ -317,6 +294,7 @@ class InAppBrowser {
|
||||||
///- MacOS
|
///- MacOS
|
||||||
static Future<void> openWithSystemBrowser({required WebUri url}) async {
|
static Future<void> openWithSystemBrowser({required WebUri url}) async {
|
||||||
assert(url.toString().isNotEmpty);
|
assert(url.toString().isNotEmpty);
|
||||||
|
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('url', () => url.toString());
|
args.putIfAbsent('url', () => url.toString());
|
||||||
return await _sharedChannel.invokeMethod('openWithSystemBrowser', args);
|
return await _sharedChannel.invokeMethod('openWithSystemBrowser', args);
|
||||||
|
@ -329,9 +307,10 @@ class InAppBrowser {
|
||||||
///- iOS
|
///- iOS
|
||||||
///- MacOS
|
///- MacOS
|
||||||
Future<void> show() async {
|
Future<void> show() async {
|
||||||
this.throwIfNotOpened();
|
assert(_isOpened, 'The browser is not opened.');
|
||||||
|
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('show', args);
|
await _channel?.invokeMethod('show', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Hides the [InAppBrowser] window. Calling this has no effect if the [InAppBrowser] was already hidden.
|
///Hides the [InAppBrowser] window. Calling this has no effect if the [InAppBrowser] was already hidden.
|
||||||
|
@ -341,9 +320,10 @@ class InAppBrowser {
|
||||||
///- iOS
|
///- iOS
|
||||||
///- MacOS
|
///- MacOS
|
||||||
Future<void> hide() async {
|
Future<void> hide() async {
|
||||||
this.throwIfNotOpened();
|
assert(_isOpened, 'The browser is not opened.');
|
||||||
|
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('hide', args);
|
await _channel?.invokeMethod('hide', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Closes the [InAppBrowser] window.
|
///Closes the [InAppBrowser] window.
|
||||||
|
@ -353,9 +333,10 @@ class InAppBrowser {
|
||||||
///- iOS
|
///- iOS
|
||||||
///- MacOS
|
///- MacOS
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
this.throwIfNotOpened();
|
assert(_isOpened, 'The browser is not opened.');
|
||||||
|
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('close', args);
|
await _channel?.invokeMethod('close', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Check if the Web View of the [InAppBrowser] instance is hidden.
|
///Check if the Web View of the [InAppBrowser] instance is hidden.
|
||||||
|
@ -365,29 +346,30 @@ class InAppBrowser {
|
||||||
///- iOS
|
///- iOS
|
||||||
///- MacOS
|
///- MacOS
|
||||||
Future<bool> isHidden() async {
|
Future<bool> isHidden() async {
|
||||||
this.throwIfNotOpened();
|
assert(_isOpened, 'The browser is not opened.');
|
||||||
|
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('isHidden', args);
|
return await _channel?.invokeMethod('isHidden', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [setSettings] instead.
|
///Use [setSettings] instead.
|
||||||
@Deprecated('Use setSettings instead')
|
@Deprecated('Use setSettings instead')
|
||||||
Future<void> setOptions({required InAppBrowserClassOptions options}) async {
|
Future<void> setOptions({required InAppBrowserClassOptions options}) async {
|
||||||
this.throwIfNotOpened();
|
assert(_isOpened, 'The browser is not opened.');
|
||||||
|
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('settings', () => options.toMap());
|
args.putIfAbsent('settings', () => options.toMap());
|
||||||
await _channel.invokeMethod('setSettings', args);
|
await _channel?.invokeMethod('setSettings', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [getSettings] instead.
|
///Use [getSettings] instead.
|
||||||
@Deprecated('Use getSettings instead')
|
@Deprecated('Use getSettings instead')
|
||||||
Future<InAppBrowserClassOptions?> getOptions() async {
|
Future<InAppBrowserClassOptions?> getOptions() async {
|
||||||
this.throwIfNotOpened();
|
assert(_isOpened, 'The browser is not opened.');
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
|
|
||||||
Map<dynamic, dynamic>? options =
|
Map<dynamic, dynamic>? options =
|
||||||
await _channel.invokeMethod('getSettings', args);
|
await _channel?.invokeMethod('getSettings', args);
|
||||||
if (options != null) {
|
if (options != null) {
|
||||||
options = options.cast<String, dynamic>();
|
options = options.cast<String, dynamic>();
|
||||||
return InAppBrowserClassOptions.fromMap(options as Map<String, dynamic>);
|
return InAppBrowserClassOptions.fromMap(options as Map<String, dynamic>);
|
||||||
|
@ -404,11 +386,11 @@ class InAppBrowser {
|
||||||
///- MacOS
|
///- MacOS
|
||||||
Future<void> setSettings(
|
Future<void> setSettings(
|
||||||
{required InAppBrowserClassSettings settings}) async {
|
{required InAppBrowserClassSettings settings}) async {
|
||||||
this.throwIfNotOpened();
|
assert(_isOpened, 'The browser is not opened.');
|
||||||
|
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('settings', () => settings.toMap());
|
args.putIfAbsent('settings', () => settings.toMap());
|
||||||
await _channel.invokeMethod('setSettings', args);
|
await _channel?.invokeMethod('setSettings', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Gets the current [InAppBrowser] settings. Returns `null` if it wasn't able to get them.
|
///Gets the current [InAppBrowser] settings. Returns `null` if it wasn't able to get them.
|
||||||
|
@ -418,11 +400,12 @@ class InAppBrowser {
|
||||||
///- iOS
|
///- iOS
|
||||||
///- MacOS
|
///- MacOS
|
||||||
Future<InAppBrowserClassSettings?> getSettings() async {
|
Future<InAppBrowserClassSettings?> getSettings() async {
|
||||||
this.throwIfNotOpened();
|
assert(_isOpened, 'The browser is not opened.');
|
||||||
|
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
|
|
||||||
Map<dynamic, dynamic>? settings =
|
Map<dynamic, dynamic>? settings =
|
||||||
await _channel.invokeMethod('getSettings', args);
|
await _channel?.invokeMethod('getSettings', args);
|
||||||
if (settings != null) {
|
if (settings != null) {
|
||||||
settings = settings.cast<String, dynamic>();
|
settings = settings.cast<String, dynamic>();
|
||||||
return InAppBrowserClassSettings.fromMap(
|
return InAppBrowserClassSettings.fromMap(
|
||||||
|
@ -1321,19 +1304,15 @@ class InAppBrowser {
|
||||||
///- iOS
|
///- iOS
|
||||||
void onContentSizeChanged(Size oldContentSize, Size newContentSize) {}
|
void onContentSizeChanged(Size oldContentSize, Size newContentSize) {}
|
||||||
|
|
||||||
void throwIfAlreadyOpened({String message = ''}) {
|
///Disposes the channel and controllers.
|
||||||
if (this.isOpened()) {
|
void _dispose() {
|
||||||
throw InAppBrowserAlreadyOpenedException([
|
_channel?.setMethodCallHandler(null);
|
||||||
'Error: ${(message.isEmpty) ? '' : message + ' '}The browser is already opened.'
|
_channel = null;
|
||||||
]);
|
_webViewController?.dispose();
|
||||||
}
|
_webViewController = null;
|
||||||
}
|
pullToRefreshController?.dispose();
|
||||||
|
pullToRefreshController = null;
|
||||||
void throwIfNotOpened({String message = ''}) {
|
findInteractionController?.dispose();
|
||||||
if (!this.isOpened()) {
|
findInteractionController = null;
|
||||||
throw InAppBrowserNotOpenedException([
|
|
||||||
'Error: ${(message.isEmpty) ? '' : message + ' '}The browser is not opened.'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
const IN_APP_WEBVIEW_STATIC_CHANNEL =
|
const IN_APP_WEBVIEW_STATIC_CHANNEL =
|
||||||
const MethodChannel('com.pichillilorenzo/flutter_inappwebview_static');
|
const MethodChannel('com.pichillilorenzo/flutter_inappwebview_manager');
|
||||||
|
|
|
@ -8,7 +8,7 @@ import '../in_app_webview_controller.dart';
|
||||||
///Use [InAppWebViewController] instead.
|
///Use [InAppWebViewController] instead.
|
||||||
@Deprecated("Use InAppWebViewController instead")
|
@Deprecated("Use InAppWebViewController instead")
|
||||||
class AndroidInAppWebViewController {
|
class AndroidInAppWebViewController {
|
||||||
late MethodChannel _channel;
|
MethodChannel? _channel;
|
||||||
|
|
||||||
AndroidInAppWebViewController({required MethodChannel channel}) {
|
AndroidInAppWebViewController({required MethodChannel channel}) {
|
||||||
this._channel = channel;
|
this._channel = channel;
|
||||||
|
@ -18,28 +18,28 @@ class AndroidInAppWebViewController {
|
||||||
@Deprecated("Use InAppWebViewController.startSafeBrowsing instead")
|
@Deprecated("Use InAppWebViewController.startSafeBrowsing instead")
|
||||||
Future<bool> startSafeBrowsing() async {
|
Future<bool> startSafeBrowsing() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('startSafeBrowsing', args);
|
return await _channel?.invokeMethod('startSafeBrowsing', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [InAppWebViewController.clearSslPreferences] instead.
|
///Use [InAppWebViewController.clearSslPreferences] instead.
|
||||||
@Deprecated("Use InAppWebViewController.clearSslPreferences instead")
|
@Deprecated("Use InAppWebViewController.clearSslPreferences instead")
|
||||||
Future<void> clearSslPreferences() async {
|
Future<void> clearSslPreferences() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('clearSslPreferences', args);
|
await _channel?.invokeMethod('clearSslPreferences', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [InAppWebViewController.pause] instead.
|
///Use [InAppWebViewController.pause] instead.
|
||||||
@Deprecated("Use InAppWebViewController.pause instead")
|
@Deprecated("Use InAppWebViewController.pause instead")
|
||||||
Future<void> pause() async {
|
Future<void> pause() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('pause', args);
|
await _channel?.invokeMethod('pause', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [InAppWebViewController.resume] instead.
|
///Use [InAppWebViewController.resume] instead.
|
||||||
@Deprecated("Use InAppWebViewController.resume instead")
|
@Deprecated("Use InAppWebViewController.resume instead")
|
||||||
Future<void> resume() async {
|
Future<void> resume() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('resume', args);
|
await _channel?.invokeMethod('resume', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [InAppWebViewController.pageDown] instead.
|
///Use [InAppWebViewController.pageDown] instead.
|
||||||
|
@ -47,7 +47,7 @@ class AndroidInAppWebViewController {
|
||||||
Future<bool> pageDown({required bool bottom}) async {
|
Future<bool> pageDown({required bool bottom}) async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent("bottom", () => bottom);
|
args.putIfAbsent("bottom", () => bottom);
|
||||||
return await _channel.invokeMethod('pageDown', args);
|
return await _channel?.invokeMethod('pageDown', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [InAppWebViewController.pageUp] instead.
|
///Use [InAppWebViewController.pageUp] instead.
|
||||||
|
@ -55,28 +55,28 @@ class AndroidInAppWebViewController {
|
||||||
Future<bool> pageUp({required bool top}) async {
|
Future<bool> pageUp({required bool top}) async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent("top", () => top);
|
args.putIfAbsent("top", () => top);
|
||||||
return await _channel.invokeMethod('pageUp', args);
|
return await _channel?.invokeMethod('pageUp', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [InAppWebViewController.zoomIn] instead.
|
///Use [InAppWebViewController.zoomIn] instead.
|
||||||
@Deprecated("Use InAppWebViewController.zoomIn instead")
|
@Deprecated("Use InAppWebViewController.zoomIn instead")
|
||||||
Future<bool> zoomIn() async {
|
Future<bool> zoomIn() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('zoomIn', args);
|
return await _channel?.invokeMethod('zoomIn', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [InAppWebViewController.zoomOut] instead.
|
///Use [InAppWebViewController.zoomOut] instead.
|
||||||
@Deprecated("Use InAppWebViewController.zoomOut instead")
|
@Deprecated("Use InAppWebViewController.zoomOut instead")
|
||||||
Future<bool> zoomOut() async {
|
Future<bool> zoomOut() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('zoomOut', args);
|
return await _channel?.invokeMethod('zoomOut', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [InAppWebViewController.clearHistory] instead.
|
///Use [InAppWebViewController.clearHistory] instead.
|
||||||
@Deprecated("Use InAppWebViewController.clearHistory instead")
|
@Deprecated("Use InAppWebViewController.clearHistory instead")
|
||||||
Future<void> clearHistory() async {
|
Future<void> clearHistory() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('clearHistory', args);
|
return await _channel?.invokeMethod('clearHistory', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [InAppWebViewController.clearClientCertPreferences] instead.
|
///Use [InAppWebViewController.clearClientCertPreferences] instead.
|
||||||
|
@ -120,7 +120,11 @@ class AndroidInAppWebViewController {
|
||||||
@Deprecated('Use InAppWebViewController.getOriginalUrl instead')
|
@Deprecated('Use InAppWebViewController.getOriginalUrl instead')
|
||||||
Future<Uri?> getOriginalUrl() async {
|
Future<Uri?> getOriginalUrl() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
String? url = await _channel.invokeMethod('getOriginalUrl', args);
|
String? url = await _channel?.invokeMethod('getOriginalUrl', args);
|
||||||
return url != null ? Uri.tryParse(url) : null;
|
return url != null ? Uri.tryParse(url) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dispose() {
|
||||||
|
_channel = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,8 @@ import '../in_app_webview_controller.dart';
|
||||||
///Use [InAppWebViewController] instead.
|
///Use [InAppWebViewController] instead.
|
||||||
@Deprecated("Use InAppWebViewController instead")
|
@Deprecated("Use InAppWebViewController instead")
|
||||||
class IOSInAppWebViewController {
|
class IOSInAppWebViewController {
|
||||||
late MethodChannel _channel;
|
MethodChannel? _channel;
|
||||||
|
|
||||||
IOSInAppWebViewController({required MethodChannel channel}) {
|
IOSInAppWebViewController({required MethodChannel channel}) {
|
||||||
this._channel = channel;
|
this._channel = channel;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +19,7 @@ class IOSInAppWebViewController {
|
||||||
@Deprecated("Use InAppWebViewController.reloadFromOrigin instead")
|
@Deprecated("Use InAppWebViewController.reloadFromOrigin instead")
|
||||||
Future<void> reloadFromOrigin() async {
|
Future<void> reloadFromOrigin() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('reloadFromOrigin', args);
|
await _channel?.invokeMethod('reloadFromOrigin', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [InAppWebViewController.createPdf] instead.
|
///Use [InAppWebViewController.createPdf] instead.
|
||||||
|
@ -31,21 +32,21 @@ class IOSInAppWebViewController {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('pdfConfiguration',
|
args.putIfAbsent('pdfConfiguration',
|
||||||
() => pdfConfiguration?.toMap() ?? iosWKPdfConfiguration?.toMap());
|
() => pdfConfiguration?.toMap() ?? iosWKPdfConfiguration?.toMap());
|
||||||
return await _channel.invokeMethod('createPdf', args);
|
return await _channel?.invokeMethod('createPdf', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [InAppWebViewController.createWebArchiveData] instead.
|
///Use [InAppWebViewController.createWebArchiveData] instead.
|
||||||
@Deprecated("Use InAppWebViewController.createWebArchiveData instead")
|
@Deprecated("Use InAppWebViewController.createWebArchiveData instead")
|
||||||
Future<Uint8List?> createWebArchiveData() async {
|
Future<Uint8List?> createWebArchiveData() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('createWebArchiveData', args);
|
return await _channel?.invokeMethod('createWebArchiveData', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [InAppWebViewController.hasOnlySecureContent] instead.
|
///Use [InAppWebViewController.hasOnlySecureContent] instead.
|
||||||
@Deprecated("Use InAppWebViewController.hasOnlySecureContent instead")
|
@Deprecated("Use InAppWebViewController.hasOnlySecureContent instead")
|
||||||
Future<bool> hasOnlySecureContent() async {
|
Future<bool> hasOnlySecureContent() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('hasOnlySecureContent', args);
|
return await _channel?.invokeMethod('hasOnlySecureContent', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [InAppWebViewController.handlesURLScheme] instead.
|
///Use [InAppWebViewController.handlesURLScheme] instead.
|
||||||
|
@ -53,4 +54,8 @@ class IOSInAppWebViewController {
|
||||||
static Future<bool> handlesURLScheme(String urlScheme) async {
|
static Future<bool> handlesURLScheme(String urlScheme) async {
|
||||||
return await InAppWebViewController.handlesURLScheme(urlScheme);
|
return await InAppWebViewController.handlesURLScheme(urlScheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dispose() {
|
||||||
|
_channel = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'dart:typed_data';
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_inappwebview/src/util.dart';
|
import '../util.dart';
|
||||||
|
|
||||||
import '../context_menu.dart';
|
import '../context_menu.dart';
|
||||||
import '../find_interaction/find_interaction_controller.dart';
|
import '../find_interaction/find_interaction_controller.dart';
|
||||||
|
@ -38,10 +38,12 @@ class HeadlessInAppWebView implements WebView, Disposable {
|
||||||
|
|
||||||
static const MethodChannel _sharedChannel =
|
static const MethodChannel _sharedChannel =
|
||||||
const MethodChannel('com.pichillilorenzo/flutter_headless_inappwebview');
|
const MethodChannel('com.pichillilorenzo/flutter_headless_inappwebview');
|
||||||
late MethodChannel _channel;
|
MethodChannel? _channel;
|
||||||
|
|
||||||
|
InAppWebViewController? _webViewController;
|
||||||
|
|
||||||
///WebView Controller that can be used to access the [InAppWebViewController] API.
|
///WebView Controller that can be used to access the [InAppWebViewController] API.
|
||||||
late final InAppWebViewController webViewController;
|
InAppWebViewController? get webViewController => _webViewController;
|
||||||
|
|
||||||
///{@macro flutter_inappwebview.WebView.windowId}
|
///{@macro flutter_inappwebview.WebView.windowId}
|
||||||
final int? windowId;
|
final int? windowId;
|
||||||
|
@ -74,7 +76,6 @@ class HeadlessInAppWebView implements WebView, Disposable {
|
||||||
this.initialUserScripts,
|
this.initialUserScripts,
|
||||||
this.pullToRefreshController,
|
this.pullToRefreshController,
|
||||||
this.findInteractionController,
|
this.findInteractionController,
|
||||||
this.implementation = WebViewImplementation.NATIVE,
|
|
||||||
this.onWebViewCreated,
|
this.onWebViewCreated,
|
||||||
this.onLoadStart,
|
this.onLoadStart,
|
||||||
this.onLoadStop,
|
this.onLoadStop,
|
||||||
|
@ -180,10 +181,15 @@ class HeadlessInAppWebView implements WebView, Disposable {
|
||||||
this.onMicrophoneCaptureStateChanged,
|
this.onMicrophoneCaptureStateChanged,
|
||||||
this.onContentSizeChanged}) {
|
this.onContentSizeChanged}) {
|
||||||
id = IdGenerator.generate();
|
id = IdGenerator.generate();
|
||||||
webViewController = new InAppWebViewController(id, this);
|
}
|
||||||
|
|
||||||
|
_init() {
|
||||||
|
_webViewController = InAppWebViewController(id, this);
|
||||||
|
pullToRefreshController?.init(id);
|
||||||
|
findInteractionController?.init(id);
|
||||||
this._channel =
|
this._channel =
|
||||||
MethodChannel('com.pichillilorenzo/flutter_headless_inappwebview_$id');
|
MethodChannel('com.pichillilorenzo/flutter_headless_inappwebview_$id');
|
||||||
this._channel.setMethodCallHandler((call) async {
|
this._channel?.setMethodCallHandler((call) async {
|
||||||
try {
|
try {
|
||||||
return await handleMethod(call);
|
return await handleMethod(call);
|
||||||
} on Error catch (e) {
|
} on Error catch (e) {
|
||||||
|
@ -196,10 +202,8 @@ class HeadlessInAppWebView implements WebView, Disposable {
|
||||||
Future<dynamic> handleMethod(MethodCall call) async {
|
Future<dynamic> handleMethod(MethodCall call) async {
|
||||||
switch (call.method) {
|
switch (call.method) {
|
||||||
case "onWebViewCreated":
|
case "onWebViewCreated":
|
||||||
pullToRefreshController?.initMethodChannel(id);
|
if (onWebViewCreated != null && _webViewController != null) {
|
||||||
findInteractionController?.initMethodChannel(id);
|
onWebViewCreated!(_webViewController!);
|
||||||
if (onWebViewCreated != null) {
|
|
||||||
onWebViewCreated!(webViewController);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -222,6 +226,7 @@ class HeadlessInAppWebView implements WebView, Disposable {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_started = true;
|
_started = true;
|
||||||
|
_init();
|
||||||
|
|
||||||
final initialSettings = this.initialSettings ?? InAppWebViewSettings();
|
final initialSettings = this.initialSettings ?? InAppWebViewSettings();
|
||||||
_inferInitialSettings(initialSettings);
|
_inferInitialSettings(initialSettings);
|
||||||
|
@ -249,7 +254,6 @@ class HeadlessInAppWebView implements WebView, Disposable {
|
||||||
'initialSettings': settingsMap,
|
'initialSettings': settingsMap,
|
||||||
'contextMenu': this.contextMenu?.toMap() ?? {},
|
'contextMenu': this.contextMenu?.toMap() ?? {},
|
||||||
'windowId': this.windowId,
|
'windowId': this.windowId,
|
||||||
'implementation': this.implementation.toNativeValue(),
|
|
||||||
'initialUserScripts':
|
'initialUserScripts':
|
||||||
this.initialUserScripts?.map((e) => e.toMap()).toList() ?? [],
|
this.initialUserScripts?.map((e) => e.toMap()).toList() ?? [],
|
||||||
'pullToRefreshSettings': pullToRefreshSettings,
|
'pullToRefreshSettings': pullToRefreshSettings,
|
||||||
|
@ -306,9 +310,15 @@ class HeadlessInAppWebView implements WebView, Disposable {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('dispose', args);
|
await _channel?.invokeMethod('dispose', args);
|
||||||
|
_channel?.setMethodCallHandler(null);
|
||||||
|
_channel = null;
|
||||||
_started = false;
|
_started = false;
|
||||||
_running = false;
|
_running = false;
|
||||||
|
_webViewController?.dispose();
|
||||||
|
_webViewController = null;
|
||||||
|
pullToRefreshController?.dispose();
|
||||||
|
findInteractionController?.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
///Indicates if the headless WebView is running or not.
|
///Indicates if the headless WebView is running or not.
|
||||||
|
@ -343,7 +353,7 @@ class HeadlessInAppWebView implements WebView, Disposable {
|
||||||
|
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('size', () => size.toMap());
|
args.putIfAbsent('size', () => size.toMap());
|
||||||
await _channel.invokeMethod('setSize', args);
|
await _channel?.invokeMethod('setSize', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Gets the current size in pixels of the WebView.
|
///Gets the current size in pixels of the WebView.
|
||||||
|
@ -362,7 +372,7 @@ class HeadlessInAppWebView implements WebView, Disposable {
|
||||||
|
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
Map<String, dynamic> sizeMap =
|
Map<String, dynamic> sizeMap =
|
||||||
(await _channel.invokeMethod('getSize', args))?.cast<String, dynamic>();
|
(await _channel?.invokeMethod('getSize', args))?.cast<String, dynamic>();
|
||||||
return MapSize.fromMap(sizeMap);
|
return MapSize.fromMap(sizeMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,10 +413,6 @@ class HeadlessInAppWebView implements WebView, Disposable {
|
||||||
@override
|
@override
|
||||||
final FindInteractionController? findInteractionController;
|
final FindInteractionController? findInteractionController;
|
||||||
|
|
||||||
///{@macro flutter_inappwebview.WebView.implementation}
|
|
||||||
@override
|
|
||||||
final WebViewImplementation implementation;
|
|
||||||
|
|
||||||
///Use [onGeolocationPermissionsHidePrompt] instead.
|
///Use [onGeolocationPermissionsHidePrompt] instead.
|
||||||
@override
|
@override
|
||||||
@Deprecated('Use onGeolocationPermissionsHidePrompt instead')
|
@Deprecated('Use onGeolocationPermissionsHidePrompt instead')
|
||||||
|
|
|
@ -8,8 +8,8 @@ import 'package:flutter/rendering.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter_inappwebview/src/in_app_webview/headless_in_app_webview.dart';
|
import 'headless_in_app_webview.dart';
|
||||||
import 'package:flutter_inappwebview/src/util.dart';
|
import '../util.dart';
|
||||||
|
|
||||||
import '../find_interaction/find_interaction_controller.dart';
|
import '../find_interaction/find_interaction_controller.dart';
|
||||||
import '../web/web_platform_manager.dart';
|
import '../web/web_platform_manager.dart';
|
||||||
|
@ -23,6 +23,8 @@ import 'webview.dart';
|
||||||
import 'in_app_webview_controller.dart';
|
import 'in_app_webview_controller.dart';
|
||||||
import 'in_app_webview_settings.dart';
|
import 'in_app_webview_settings.dart';
|
||||||
import '../pull_to_refresh/main.dart';
|
import '../pull_to_refresh/main.dart';
|
||||||
|
import '../pull_to_refresh/pull_to_refresh_controller.dart';
|
||||||
|
import 'in_app_webview_keep_alive.dart';
|
||||||
|
|
||||||
///{@template flutter_inappwebview.InAppWebView}
|
///{@template flutter_inappwebview.InAppWebView}
|
||||||
///Flutter Widget for adding an **inline native WebView** integrated in the flutter widget tree.
|
///Flutter Widget for adding an **inline native WebView** integrated in the flutter widget tree.
|
||||||
|
@ -46,7 +48,7 @@ class InAppWebView extends StatefulWidget implements WebView {
|
||||||
@override
|
@override
|
||||||
final int? windowId;
|
final int? windowId;
|
||||||
|
|
||||||
///The [HeadlessInAppWebView] to use to initialize this widget
|
///The [HeadlessInAppWebView] to use to initialize this widget.
|
||||||
///
|
///
|
||||||
///**Supported Platforms/Implementations**:
|
///**Supported Platforms/Implementations**:
|
||||||
///- Android native WebView
|
///- Android native WebView
|
||||||
|
@ -54,33 +56,46 @@ class InAppWebView extends StatefulWidget implements WebView {
|
||||||
///- Web
|
///- Web
|
||||||
final HeadlessInAppWebView? headlessWebView;
|
final HeadlessInAppWebView? headlessWebView;
|
||||||
|
|
||||||
|
///Used to keep alive this WebView.
|
||||||
|
///Remember to dispose the [InAppWebViewKeepAlive] instance
|
||||||
|
///using [InAppWebViewController.disposeKeepAlive].
|
||||||
|
///
|
||||||
|
///**Supported Platforms/Implementations**:
|
||||||
|
///- Android native WebView
|
||||||
|
///- iOS
|
||||||
|
final InAppWebViewKeepAlive? keepAlive;
|
||||||
|
|
||||||
///{@macro flutter_inappwebview.InAppWebView}
|
///{@macro flutter_inappwebview.InAppWebView}
|
||||||
const InAppWebView({
|
const InAppWebView({
|
||||||
Key? key,
|
Key? key,
|
||||||
this.windowId,
|
this.windowId,
|
||||||
|
this.keepAlive,
|
||||||
this.initialUrlRequest,
|
this.initialUrlRequest,
|
||||||
this.initialFile,
|
this.initialFile,
|
||||||
this.initialData,
|
this.initialData,
|
||||||
@Deprecated('Use initialSettings instead') this.initialOptions,
|
@Deprecated('Use initialSettings instead')
|
||||||
|
this.initialOptions,
|
||||||
this.initialSettings,
|
this.initialSettings,
|
||||||
this.initialUserScripts,
|
this.initialUserScripts,
|
||||||
this.pullToRefreshController,
|
this.pullToRefreshController,
|
||||||
this.findInteractionController,
|
this.findInteractionController,
|
||||||
this.implementation = WebViewImplementation.NATIVE,
|
|
||||||
this.contextMenu,
|
this.contextMenu,
|
||||||
this.onWebViewCreated,
|
this.onWebViewCreated,
|
||||||
this.onLoadStart,
|
this.onLoadStart,
|
||||||
this.onLoadStop,
|
this.onLoadStop,
|
||||||
@Deprecated("Use onReceivedError instead") this.onLoadError,
|
@Deprecated("Use onReceivedError instead")
|
||||||
|
this.onLoadError,
|
||||||
this.onReceivedError,
|
this.onReceivedError,
|
||||||
@Deprecated("Use onReceivedHttpError instead") this.onLoadHttpError,
|
@Deprecated("Use onReceivedHttpError instead")
|
||||||
|
this.onLoadHttpError,
|
||||||
this.onReceivedHttpError,
|
this.onReceivedHttpError,
|
||||||
this.onConsoleMessage,
|
this.onConsoleMessage,
|
||||||
this.onProgressChanged,
|
this.onProgressChanged,
|
||||||
this.shouldOverrideUrlLoading,
|
this.shouldOverrideUrlLoading,
|
||||||
this.onLoadResource,
|
this.onLoadResource,
|
||||||
this.onScrollChanged,
|
this.onScrollChanged,
|
||||||
@Deprecated('Use onDownloadStartRequest instead') this.onDownloadStart,
|
@Deprecated('Use onDownloadStartRequest instead')
|
||||||
|
this.onDownloadStart,
|
||||||
this.onDownloadStartRequest,
|
this.onDownloadStartRequest,
|
||||||
@Deprecated('Use onLoadResourceWithCustomScheme instead')
|
@Deprecated('Use onLoadResourceWithCustomScheme instead')
|
||||||
this.onLoadResourceCustomScheme,
|
this.onLoadResourceCustomScheme,
|
||||||
|
@ -100,7 +115,8 @@ class InAppWebView extends StatefulWidget implements WebView {
|
||||||
this.onAjaxProgress,
|
this.onAjaxProgress,
|
||||||
this.shouldInterceptFetchRequest,
|
this.shouldInterceptFetchRequest,
|
||||||
this.onUpdateVisitedHistory,
|
this.onUpdateVisitedHistory,
|
||||||
@Deprecated("Use onPrintRequest instead") this.onPrint,
|
@Deprecated("Use onPrintRequest instead")
|
||||||
|
this.onPrint,
|
||||||
this.onPrintRequest,
|
this.onPrintRequest,
|
||||||
this.onLongPressHitTestResult,
|
this.onLongPressHitTestResult,
|
||||||
this.onEnterFullscreen,
|
this.onEnterFullscreen,
|
||||||
|
@ -111,7 +127,8 @@ class InAppWebView extends StatefulWidget implements WebView {
|
||||||
this.onWindowBlur,
|
this.onWindowBlur,
|
||||||
this.onOverScrolled,
|
this.onOverScrolled,
|
||||||
this.onZoomScaleChanged,
|
this.onZoomScaleChanged,
|
||||||
@Deprecated('Use onSafeBrowsingHit instead') this.androidOnSafeBrowsingHit,
|
@Deprecated('Use onSafeBrowsingHit instead')
|
||||||
|
this.androidOnSafeBrowsingHit,
|
||||||
this.onSafeBrowsingHit,
|
this.onSafeBrowsingHit,
|
||||||
@Deprecated('Use onPermissionRequest instead')
|
@Deprecated('Use onPermissionRequest instead')
|
||||||
this.androidOnPermissionRequest,
|
this.androidOnPermissionRequest,
|
||||||
|
@ -137,13 +154,16 @@ class InAppWebView extends StatefulWidget implements WebView {
|
||||||
@Deprecated('Use onFormResubmission instead')
|
@Deprecated('Use onFormResubmission instead')
|
||||||
this.androidOnFormResubmission,
|
this.androidOnFormResubmission,
|
||||||
this.onFormResubmission,
|
this.onFormResubmission,
|
||||||
@Deprecated('Use onZoomScaleChanged instead') this.androidOnScaleChanged,
|
@Deprecated('Use onZoomScaleChanged instead')
|
||||||
@Deprecated('Use onReceivedIcon instead') this.androidOnReceivedIcon,
|
this.androidOnScaleChanged,
|
||||||
|
@Deprecated('Use onReceivedIcon instead')
|
||||||
|
this.androidOnReceivedIcon,
|
||||||
this.onReceivedIcon,
|
this.onReceivedIcon,
|
||||||
@Deprecated('Use onReceivedTouchIconUrl instead')
|
@Deprecated('Use onReceivedTouchIconUrl instead')
|
||||||
this.androidOnReceivedTouchIconUrl,
|
this.androidOnReceivedTouchIconUrl,
|
||||||
this.onReceivedTouchIconUrl,
|
this.onReceivedTouchIconUrl,
|
||||||
@Deprecated('Use onJsBeforeUnload instead') this.androidOnJsBeforeUnload,
|
@Deprecated('Use onJsBeforeUnload instead')
|
||||||
|
this.androidOnJsBeforeUnload,
|
||||||
this.onJsBeforeUnload,
|
this.onJsBeforeUnload,
|
||||||
@Deprecated('Use onReceivedLoginRequest instead')
|
@Deprecated('Use onReceivedLoginRequest instead')
|
||||||
this.androidOnReceivedLoginRequest,
|
this.androidOnReceivedLoginRequest,
|
||||||
|
@ -222,10 +242,6 @@ class InAppWebView extends StatefulWidget implements WebView {
|
||||||
@override
|
@override
|
||||||
final URLRequest? initialUrlRequest;
|
final URLRequest? initialUrlRequest;
|
||||||
|
|
||||||
///{@macro flutter_inappwebview.WebView.implementation}
|
|
||||||
@override
|
|
||||||
final WebViewImplementation implementation;
|
|
||||||
|
|
||||||
///{@macro flutter_inappwebview.WebView.initialUserScripts}
|
///{@macro flutter_inappwebview.WebView.initialUserScripts}
|
||||||
@override
|
@override
|
||||||
final UnmodifiableListView<UserScript>? initialUserScripts;
|
final UnmodifiableListView<UserScript>? initialUserScripts;
|
||||||
|
@ -704,6 +720,15 @@ class _InAppWebViewState extends State<InAppWebView> {
|
||||||
widget.pullToRefreshController?.options.toMap() ??
|
widget.pullToRefreshController?.options.toMap() ??
|
||||||
PullToRefreshSettings(enabled: false).toMap();
|
PullToRefreshSettings(enabled: false).toMap();
|
||||||
|
|
||||||
|
if ((widget.headlessWebView?.isRunning() ?? false) &&
|
||||||
|
widget.keepAlive != null) {
|
||||||
|
final headlessId = widget.headlessWebView?.id;
|
||||||
|
if (headlessId != null) {
|
||||||
|
// force keep alive id to match headless webview id
|
||||||
|
widget.keepAlive?.id = headlessId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Util.isWeb) {
|
if (Util.isWeb) {
|
||||||
return HtmlElementView(
|
return HtmlElementView(
|
||||||
viewType: 'com.pichillilorenzo/flutter_inappwebview',
|
viewType: 'com.pichillilorenzo/flutter_inappwebview',
|
||||||
|
@ -727,9 +752,7 @@ class _InAppWebViewState extends State<InAppWebView> {
|
||||||
} else if (Util.isAndroid) {
|
} else if (Util.isAndroid) {
|
||||||
var useHybridComposition = (widget.initialSettings != null
|
var useHybridComposition = (widget.initialSettings != null
|
||||||
? initialSettings.useHybridComposition
|
? initialSettings.useHybridComposition
|
||||||
:
|
: widget.initialOptions?.android.useHybridComposition) ??
|
||||||
// ignore: deprecated_member_use_from_same_package
|
|
||||||
widget.initialOptions?.android.useHybridComposition) ??
|
|
||||||
true;
|
true;
|
||||||
|
|
||||||
return PlatformViewLink(
|
return PlatformViewLink(
|
||||||
|
@ -762,11 +785,11 @@ class _InAppWebViewState extends State<InAppWebView> {
|
||||||
'headlessWebViewId': widget.headlessWebView?.isRunning() ?? false
|
'headlessWebViewId': widget.headlessWebView?.isRunning() ?? false
|
||||||
? widget.headlessWebView?.id
|
? widget.headlessWebView?.id
|
||||||
: null,
|
: null,
|
||||||
'implementation': widget.implementation.toNativeValue(),
|
|
||||||
'initialUserScripts':
|
'initialUserScripts':
|
||||||
widget.initialUserScripts?.map((e) => e.toMap()).toList() ??
|
widget.initialUserScripts?.map((e) => e.toMap()).toList() ??
|
||||||
[],
|
[],
|
||||||
'pullToRefreshSettings': pullToRefreshSettings
|
'pullToRefreshSettings': pullToRefreshSettings,
|
||||||
|
'keepAliveId': widget.keepAlive?.id
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
|
..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
|
||||||
|
@ -790,10 +813,10 @@ class _InAppWebViewState extends State<InAppWebView> {
|
||||||
'headlessWebViewId': widget.headlessWebView?.isRunning() ?? false
|
'headlessWebViewId': widget.headlessWebView?.isRunning() ?? false
|
||||||
? widget.headlessWebView?.id
|
? widget.headlessWebView?.id
|
||||||
: null,
|
: null,
|
||||||
'implementation': widget.implementation.toNativeValue(),
|
|
||||||
'initialUserScripts':
|
'initialUserScripts':
|
||||||
widget.initialUserScripts?.map((e) => e.toMap()).toList() ?? [],
|
widget.initialUserScripts?.map((e) => e.toMap()).toList() ?? [],
|
||||||
'pullToRefreshSettings': pullToRefreshSettings
|
'pullToRefreshSettings': pullToRefreshSettings,
|
||||||
|
'keepAliveId': widget.keepAlive?.id
|
||||||
},
|
},
|
||||||
creationParamsCodec: const StandardMessageCodec(),
|
creationParamsCodec: const StandardMessageCodec(),
|
||||||
);
|
);
|
||||||
|
@ -810,13 +833,24 @@ class _InAppWebViewState extends State<InAppWebView> {
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
dynamic viewId = _controller?.getViewId();
|
dynamic viewId = _controller?.getViewId();
|
||||||
|
debugLog(
|
||||||
|
className: "InAppWebView",
|
||||||
|
name: "WebView",
|
||||||
|
id: viewId?.toString(),
|
||||||
|
debugLoggingSettings: WebView.debugLoggingSettings,
|
||||||
|
method: "dispose",
|
||||||
|
args: []);
|
||||||
if (viewId != null &&
|
if (viewId != null &&
|
||||||
kIsWeb &&
|
kIsWeb &&
|
||||||
WebPlatformManager.webViews.containsKey(viewId)) {
|
WebPlatformManager.webViews.containsKey(viewId)) {
|
||||||
WebPlatformManager.webViews.remove(viewId);
|
WebPlatformManager.webViews.remove(viewId);
|
||||||
}
|
}
|
||||||
super.dispose();
|
final isKeepAlive = widget.keepAlive != null;
|
||||||
|
_controller?.dispose(isKeepAlive: isKeepAlive);
|
||||||
_controller = null;
|
_controller = null;
|
||||||
|
widget.pullToRefreshController?.dispose(isKeepAlive: isKeepAlive);
|
||||||
|
widget.findInteractionController?.dispose(isKeepAlive: isKeepAlive);
|
||||||
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
AndroidViewController _createAndroidViewController({
|
AndroidViewController _createAndroidViewController({
|
||||||
|
@ -845,14 +879,17 @@ class _InAppWebViewState extends State<InAppWebView> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onPlatformViewCreated(int id) {
|
void _onPlatformViewCreated(int id) {
|
||||||
final viewId = (!kIsWeb && (widget.headlessWebView?.isRunning() ?? false))
|
dynamic viewId = id;
|
||||||
? widget.headlessWebView?.id
|
if (!kIsWeb) {
|
||||||
: id;
|
if (widget.headlessWebView?.isRunning() ?? false) {
|
||||||
|
viewId = widget.headlessWebView?.id;
|
||||||
|
}
|
||||||
|
viewId = widget.keepAlive?.id ?? viewId ?? id;
|
||||||
|
}
|
||||||
widget.headlessWebView?.internalDispose();
|
widget.headlessWebView?.internalDispose();
|
||||||
_controller = InAppWebViewController(viewId, widget);
|
_controller = InAppWebViewController(viewId, widget);
|
||||||
widget.pullToRefreshController?.initMethodChannel(viewId);
|
widget.pullToRefreshController?.init(viewId);
|
||||||
widget.findInteractionController?.initMethodChannel(viewId);
|
widget.findInteractionController?.init(viewId);
|
||||||
if (widget.onWebViewCreated != null) {
|
|
||||||
debugLog(
|
debugLog(
|
||||||
className: "InAppWebView",
|
className: "InAppWebView",
|
||||||
name: "WebView",
|
name: "WebView",
|
||||||
|
@ -860,6 +897,7 @@ class _InAppWebViewState extends State<InAppWebView> {
|
||||||
debugLoggingSettings: WebView.debugLoggingSettings,
|
debugLoggingSettings: WebView.debugLoggingSettings,
|
||||||
method: "onWebViewCreated",
|
method: "onWebViewCreated",
|
||||||
args: []);
|
args: []);
|
||||||
|
if (widget.onWebViewCreated != null) {
|
||||||
widget.onWebViewCreated!(_controller!);
|
widget.onWebViewCreated!(_controller!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import 'in_app_webview.dart';
|
||||||
import 'in_app_webview_settings.dart';
|
import 'in_app_webview_settings.dart';
|
||||||
import 'webview.dart';
|
import 'webview.dart';
|
||||||
import '_static_channel.dart';
|
import '_static_channel.dart';
|
||||||
|
import 'in_app_webview_keep_alive.dart';
|
||||||
|
|
||||||
import '../print_job/main.dart';
|
import '../print_job/main.dart';
|
||||||
import '../find_interaction/main.dart';
|
import '../find_interaction/main.dart';
|
||||||
|
@ -52,17 +53,23 @@ final _JAVASCRIPT_HANDLER_FORBIDDEN_NAMES = UnmodifiableListView<String>([
|
||||||
///callback. Instead, if you are using an [InAppBrowser] instance, you can get it through the [InAppBrowser.webViewController] attribute.
|
///callback. Instead, if you are using an [InAppBrowser] instance, you can get it through the [InAppBrowser.webViewController] attribute.
|
||||||
class InAppWebViewController {
|
class InAppWebViewController {
|
||||||
WebView? _webview;
|
WebView? _webview;
|
||||||
late MethodChannel _channel;
|
MethodChannel? _channel;
|
||||||
static MethodChannel _staticChannel = IN_APP_WEBVIEW_STATIC_CHANNEL;
|
static final MethodChannel _staticChannel = IN_APP_WEBVIEW_STATIC_CHANNEL;
|
||||||
Map<String, JavaScriptHandlerCallback> javaScriptHandlersMap =
|
|
||||||
|
// properties to be saved and restored for keep alive feature
|
||||||
|
Map<String, JavaScriptHandlerCallback> _javaScriptHandlersMap =
|
||||||
HashMap<String, JavaScriptHandlerCallback>();
|
HashMap<String, JavaScriptHandlerCallback>();
|
||||||
final Map<UserScriptInjectionTime, List<UserScript>> _userScripts = {
|
Map<UserScriptInjectionTime, List<UserScript>> _userScripts = {
|
||||||
UserScriptInjectionTime.AT_DOCUMENT_START: <UserScript>[],
|
UserScriptInjectionTime.AT_DOCUMENT_START: <UserScript>[],
|
||||||
UserScriptInjectionTime.AT_DOCUMENT_END: <UserScript>[]
|
UserScriptInjectionTime.AT_DOCUMENT_END: <UserScript>[]
|
||||||
};
|
};
|
||||||
Set<String> _webMessageListenerObjNames = Set();
|
Set<String> _webMessageListenerObjNames = Set();
|
||||||
Map<String, ScriptHtmlTagAttributes> _injectedScriptsFromURL = {};
|
Map<String, ScriptHtmlTagAttributes> _injectedScriptsFromURL = {};
|
||||||
|
|
||||||
|
// static map that contains the properties to be saved and restored for keep alive feature
|
||||||
|
static final Map<InAppWebViewKeepAlive, InAppWebViewControllerKeepAliveProps?>
|
||||||
|
_keepAliveMap = {};
|
||||||
|
|
||||||
dynamic _id;
|
dynamic _id;
|
||||||
|
|
||||||
InAppBrowser? _inAppBrowser;
|
InAppBrowser? _inAppBrowser;
|
||||||
|
@ -82,7 +89,8 @@ class InAppWebViewController {
|
||||||
this._id = id;
|
this._id = id;
|
||||||
this._channel =
|
this._channel =
|
||||||
MethodChannel('com.pichillilorenzo/flutter_inappwebview_$id');
|
MethodChannel('com.pichillilorenzo/flutter_inappwebview_$id');
|
||||||
this._channel.setMethodCallHandler((call) async {
|
this._channel?.setMethodCallHandler((call) async {
|
||||||
|
if (_channel == null) return null;
|
||||||
try {
|
try {
|
||||||
return await handleMethod(call);
|
return await handleMethod(call);
|
||||||
} on Error catch (e) {
|
} on Error catch (e) {
|
||||||
|
@ -136,12 +144,31 @@ class InAppWebViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _init() {
|
void _init() {
|
||||||
// ignore: deprecated_member_use_from_same_package
|
android = AndroidInAppWebViewController(channel: _channel!);
|
||||||
this.android = AndroidInAppWebViewController(channel: _channel);
|
ios = IOSInAppWebViewController(channel: _channel!);
|
||||||
// ignore: deprecated_member_use_from_same_package
|
webStorage = WebStorage(
|
||||||
this.ios = IOSInAppWebViewController(channel: _channel);
|
|
||||||
this.webStorage = WebStorage(
|
|
||||||
localStorage: LocalStorage(this), sessionStorage: SessionStorage(this));
|
localStorage: LocalStorage(this), sessionStorage: SessionStorage(this));
|
||||||
|
|
||||||
|
if (_webview is InAppWebView) {
|
||||||
|
final keepAlive = (_webview as InAppWebView).keepAlive;
|
||||||
|
if (keepAlive != null) {
|
||||||
|
InAppWebViewControllerKeepAliveProps? props = _keepAliveMap[keepAlive];
|
||||||
|
if (props == null) {
|
||||||
|
// save controller properties to restore it later
|
||||||
|
_keepAliveMap[keepAlive] = InAppWebViewControllerKeepAliveProps(
|
||||||
|
injectedScriptsFromURL: _injectedScriptsFromURL,
|
||||||
|
javaScriptHandlersMap: _javaScriptHandlersMap,
|
||||||
|
userScripts: _userScripts,
|
||||||
|
webMessageListenerObjNames: _webMessageListenerObjNames);
|
||||||
|
} else {
|
||||||
|
// restore controller properties
|
||||||
|
_injectedScriptsFromURL = props.injectedScriptsFromURL;
|
||||||
|
_javaScriptHandlersMap = props.javaScriptHandlersMap;
|
||||||
|
_userScripts = props.userScripts;
|
||||||
|
_webMessageListenerObjNames = props.webMessageListenerObjNames;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_debugLog(String method, dynamic args) {
|
_debugLog(String method, dynamic args) {
|
||||||
|
@ -1374,10 +1401,10 @@ class InAppWebViewController {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (javaScriptHandlersMap.containsKey(handlerName)) {
|
if (_javaScriptHandlersMap.containsKey(handlerName)) {
|
||||||
// convert result to json
|
// convert result to json
|
||||||
try {
|
try {
|
||||||
return jsonEncode(await javaScriptHandlersMap[handlerName]!(args));
|
return jsonEncode(await _javaScriptHandlersMap[handlerName]!(args));
|
||||||
} catch (error, stacktrace) {
|
} catch (error, stacktrace) {
|
||||||
developer.log(error.toString() + '\n' + stacktrace.toString(),
|
developer.log(error.toString() + '\n' + stacktrace.toString(),
|
||||||
name: 'JavaScript Handler "$handlerName"');
|
name: 'JavaScript Handler "$handlerName"');
|
||||||
|
@ -1404,7 +1431,7 @@ class InAppWebViewController {
|
||||||
///- Web
|
///- Web
|
||||||
Future<WebUri?> getUrl() async {
|
Future<WebUri?> getUrl() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
String? url = await _channel.invokeMethod('getUrl', args);
|
String? url = await _channel?.invokeMethod('getUrl', args);
|
||||||
return url != null ? WebUri(url) : null;
|
return url != null ? WebUri(url) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1419,7 +1446,7 @@ class InAppWebViewController {
|
||||||
///- Web
|
///- Web
|
||||||
Future<String?> getTitle() async {
|
Future<String?> getTitle() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('getTitle', args);
|
return await _channel?.invokeMethod('getTitle', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Gets the progress for the current page. The progress value is between 0 and 100.
|
///Gets the progress for the current page. The progress value is between 0 and 100.
|
||||||
|
@ -1430,7 +1457,7 @@ class InAppWebViewController {
|
||||||
///- MacOS ([Official API - WKWebView.estimatedProgress](https://developer.apple.com/documentation/webkit/wkwebview/1415007-estimatedprogress))
|
///- MacOS ([Official API - WKWebView.estimatedProgress](https://developer.apple.com/documentation/webkit/wkwebview/1415007-estimatedprogress))
|
||||||
Future<int?> getProgress() async {
|
Future<int?> getProgress() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('getProgress', args);
|
return await _channel?.invokeMethod('getProgress', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Gets the content html of the page. It first tries to get the content through javascript.
|
///Gets the content html of the page. It first tries to get the content through javascript.
|
||||||
|
@ -1693,7 +1720,7 @@ class InAppWebViewController {
|
||||||
() =>
|
() =>
|
||||||
allowingReadAccessTo?.toString() ??
|
allowingReadAccessTo?.toString() ??
|
||||||
iosAllowingReadAccessTo?.toString());
|
iosAllowingReadAccessTo?.toString());
|
||||||
await _channel.invokeMethod('loadUrl', args);
|
await _channel?.invokeMethod('loadUrl', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Loads the given [url] with [postData] (x-www-form-urlencoded) using `POST` method into this WebView.
|
///Loads the given [url] with [postData] (x-www-form-urlencoded) using `POST` method into this WebView.
|
||||||
|
@ -1717,7 +1744,7 @@ class InAppWebViewController {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('url', () => url.toString());
|
args.putIfAbsent('url', () => url.toString());
|
||||||
args.putIfAbsent('postData', () => postData);
|
args.putIfAbsent('postData', () => postData);
|
||||||
await _channel.invokeMethod('postUrl', args);
|
await _channel?.invokeMethod('postUrl', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Loads the given [data] into this WebView, using [baseUrl] as the base URL for the content.
|
///Loads the given [data] into this WebView, using [baseUrl] as the base URL for the content.
|
||||||
|
@ -1771,7 +1798,7 @@ class InAppWebViewController {
|
||||||
() =>
|
() =>
|
||||||
allowingReadAccessTo?.toString() ??
|
allowingReadAccessTo?.toString() ??
|
||||||
iosAllowingReadAccessTo?.toString());
|
iosAllowingReadAccessTo?.toString());
|
||||||
await _channel.invokeMethod('loadData', args);
|
await _channel?.invokeMethod('loadData', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Loads the given [assetFilePath].
|
///Loads the given [assetFilePath].
|
||||||
|
@ -1813,7 +1840,7 @@ class InAppWebViewController {
|
||||||
assert(assetFilePath.isNotEmpty);
|
assert(assetFilePath.isNotEmpty);
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('assetFilePath', () => assetFilePath);
|
args.putIfAbsent('assetFilePath', () => assetFilePath);
|
||||||
await _channel.invokeMethod('loadFile', args);
|
await _channel?.invokeMethod('loadFile', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Reloads the WebView.
|
///Reloads the WebView.
|
||||||
|
@ -1827,7 +1854,7 @@ class InAppWebViewController {
|
||||||
///- Web ([Official API - Location.reload](https://developer.mozilla.org/en-US/docs/Web/API/Location/reload))
|
///- Web ([Official API - Location.reload](https://developer.mozilla.org/en-US/docs/Web/API/Location/reload))
|
||||||
Future<void> reload() async {
|
Future<void> reload() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('reload', args);
|
await _channel?.invokeMethod('reload', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Goes back in the history of the WebView.
|
///Goes back in the history of the WebView.
|
||||||
|
@ -1841,7 +1868,7 @@ class InAppWebViewController {
|
||||||
///- Web ([Official API - History.back](https://developer.mozilla.org/en-US/docs/Web/API/History/back))
|
///- Web ([Official API - History.back](https://developer.mozilla.org/en-US/docs/Web/API/History/back))
|
||||||
Future<void> goBack() async {
|
Future<void> goBack() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('goBack', args);
|
await _channel?.invokeMethod('goBack', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Returns a boolean value indicating whether the WebView can move backward.
|
///Returns a boolean value indicating whether the WebView can move backward.
|
||||||
|
@ -1852,7 +1879,7 @@ class InAppWebViewController {
|
||||||
///- MacOS ([Official API - WKWebView.canGoBack](https://developer.apple.com/documentation/webkit/wkwebview/1414966-cangoback))
|
///- MacOS ([Official API - WKWebView.canGoBack](https://developer.apple.com/documentation/webkit/wkwebview/1414966-cangoback))
|
||||||
Future<bool> canGoBack() async {
|
Future<bool> canGoBack() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('canGoBack', args);
|
return await _channel?.invokeMethod('canGoBack', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Goes forward in the history of the WebView.
|
///Goes forward in the history of the WebView.
|
||||||
|
@ -1866,7 +1893,7 @@ class InAppWebViewController {
|
||||||
///- Web ([Official API - History.forward](https://developer.mozilla.org/en-US/docs/Web/API/History/forward))
|
///- Web ([Official API - History.forward](https://developer.mozilla.org/en-US/docs/Web/API/History/forward))
|
||||||
Future<void> goForward() async {
|
Future<void> goForward() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('goForward', args);
|
await _channel?.invokeMethod('goForward', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Returns a boolean value indicating whether the WebView can move forward.
|
///Returns a boolean value indicating whether the WebView can move forward.
|
||||||
|
@ -1877,7 +1904,7 @@ class InAppWebViewController {
|
||||||
///- MacOS ([Official API - WKWebView.canGoForward](https://developer.apple.com/documentation/webkit/wkwebview/1414962-cangoforward))
|
///- MacOS ([Official API - WKWebView.canGoForward](https://developer.apple.com/documentation/webkit/wkwebview/1414962-cangoforward))
|
||||||
Future<bool> canGoForward() async {
|
Future<bool> canGoForward() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('canGoForward', args);
|
return await _channel?.invokeMethod('canGoForward', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Goes to the history item that is the number of steps away from the current item. Steps is negative if backward and positive if forward.
|
///Goes to the history item that is the number of steps away from the current item. Steps is negative if backward and positive if forward.
|
||||||
|
@ -1892,7 +1919,7 @@ class InAppWebViewController {
|
||||||
Future<void> goBackOrForward({required int steps}) async {
|
Future<void> goBackOrForward({required int steps}) async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('steps', () => steps);
|
args.putIfAbsent('steps', () => steps);
|
||||||
await _channel.invokeMethod('goBackOrForward', args);
|
await _channel?.invokeMethod('goBackOrForward', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Returns a boolean value indicating whether the WebView can go back or forward the given number of steps. Steps is negative if backward and positive if forward.
|
///Returns a boolean value indicating whether the WebView can go back or forward the given number of steps. Steps is negative if backward and positive if forward.
|
||||||
|
@ -1904,7 +1931,7 @@ class InAppWebViewController {
|
||||||
Future<bool> canGoBackOrForward({required int steps}) async {
|
Future<bool> canGoBackOrForward({required int steps}) async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('steps', () => steps);
|
args.putIfAbsent('steps', () => steps);
|
||||||
return await _channel.invokeMethod('canGoBackOrForward', args);
|
return await _channel?.invokeMethod('canGoBackOrForward', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Navigates to a [WebHistoryItem] from the back-forward [WebHistory.list] and sets it as the current item.
|
///Navigates to a [WebHistoryItem] from the back-forward [WebHistory.list] and sets it as the current item.
|
||||||
|
@ -1932,7 +1959,7 @@ class InAppWebViewController {
|
||||||
///- Web
|
///- Web
|
||||||
Future<bool> isLoading() async {
|
Future<bool> isLoading() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('isLoading', args);
|
return await _channel?.invokeMethod('isLoading', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Stops the WebView from loading.
|
///Stops the WebView from loading.
|
||||||
|
@ -1946,7 +1973,7 @@ class InAppWebViewController {
|
||||||
///- Web ([Official API - Window.stop](https://developer.mozilla.org/en-US/docs/Web/API/Window/stop))
|
///- Web ([Official API - Window.stop](https://developer.mozilla.org/en-US/docs/Web/API/Window/stop))
|
||||||
Future<void> stopLoading() async {
|
Future<void> stopLoading() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('stopLoading', args);
|
await _channel?.invokeMethod('stopLoading', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Evaluates JavaScript [source] code into the WebView and returns the result of the evaluation.
|
///Evaluates JavaScript [source] code into the WebView and returns the result of the evaluation.
|
||||||
|
@ -1976,7 +2003,7 @@ class InAppWebViewController {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('source', () => source);
|
args.putIfAbsent('source', () => source);
|
||||||
args.putIfAbsent('contentWorld', () => contentWorld?.toMap());
|
args.putIfAbsent('contentWorld', () => contentWorld?.toMap());
|
||||||
var data = await _channel.invokeMethod('evaluateJavascript', args);
|
var data = await _channel?.invokeMethod('evaluateJavascript', args);
|
||||||
if (data != null && (Util.isAndroid || Util.isWeb)) {
|
if (data != null && (Util.isAndroid || Util.isWeb)) {
|
||||||
try {
|
try {
|
||||||
// try to json decode the data coming from JavaScript
|
// try to json decode the data coming from JavaScript
|
||||||
|
@ -2015,7 +2042,7 @@ class InAppWebViewController {
|
||||||
args.putIfAbsent('urlFile', () => urlFile.toString());
|
args.putIfAbsent('urlFile', () => urlFile.toString());
|
||||||
args.putIfAbsent(
|
args.putIfAbsent(
|
||||||
'scriptHtmlTagAttributes', () => scriptHtmlTagAttributes?.toMap());
|
'scriptHtmlTagAttributes', () => scriptHtmlTagAttributes?.toMap());
|
||||||
await _channel.invokeMethod('injectJavascriptFileFromUrl', args);
|
await _channel?.invokeMethod('injectJavascriptFileFromUrl', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Evaluates the content of a JavaScript file into the WebView from the flutter assets directory.
|
///Evaluates the content of a JavaScript file into the WebView from the flutter assets directory.
|
||||||
|
@ -2055,7 +2082,7 @@ class InAppWebViewController {
|
||||||
Future<void> injectCSSCode({required String source}) async {
|
Future<void> injectCSSCode({required String source}) async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('source', () => source);
|
args.putIfAbsent('source', () => source);
|
||||||
await _channel.invokeMethod('injectCSSCode', args);
|
await _channel?.invokeMethod('injectCSSCode', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Injects an external CSS file into the WebView from a defined url.
|
///Injects an external CSS file into the WebView from a defined url.
|
||||||
|
@ -2082,7 +2109,7 @@ class InAppWebViewController {
|
||||||
args.putIfAbsent('urlFile', () => urlFile.toString());
|
args.putIfAbsent('urlFile', () => urlFile.toString());
|
||||||
args.putIfAbsent(
|
args.putIfAbsent(
|
||||||
'cssLinkHtmlTagAttributes', () => cssLinkHtmlTagAttributes?.toMap());
|
'cssLinkHtmlTagAttributes', () => cssLinkHtmlTagAttributes?.toMap());
|
||||||
await _channel.invokeMethod('injectCSSFileFromUrl', args);
|
await _channel?.invokeMethod('injectCSSFileFromUrl', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Injects a CSS file into the WebView from the flutter assets directory.
|
///Injects a CSS file into the WebView from the flutter assets directory.
|
||||||
|
@ -2164,7 +2191,7 @@ class InAppWebViewController {
|
||||||
required JavaScriptHandlerCallback callback}) {
|
required JavaScriptHandlerCallback callback}) {
|
||||||
assert(!_JAVASCRIPT_HANDLER_FORBIDDEN_NAMES.contains(handlerName),
|
assert(!_JAVASCRIPT_HANDLER_FORBIDDEN_NAMES.contains(handlerName),
|
||||||
'"$handlerName" is a forbidden name!');
|
'"$handlerName" is a forbidden name!');
|
||||||
this.javaScriptHandlersMap[handlerName] = (callback);
|
this._javaScriptHandlersMap[handlerName] = (callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Removes a JavaScript message handler previously added with the [addJavaScriptHandler] associated to [handlerName] key.
|
///Removes a JavaScript message handler previously added with the [addJavaScriptHandler] associated to [handlerName] key.
|
||||||
|
@ -2177,7 +2204,17 @@ class InAppWebViewController {
|
||||||
///- MacOS
|
///- MacOS
|
||||||
JavaScriptHandlerCallback? removeJavaScriptHandler(
|
JavaScriptHandlerCallback? removeJavaScriptHandler(
|
||||||
{required String handlerName}) {
|
{required String handlerName}) {
|
||||||
return this.javaScriptHandlersMap.remove(handlerName);
|
return this._javaScriptHandlersMap.remove(handlerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
///Returns `true` if a JavaScript handler with [handlerName] already exists, otherwise `false`.
|
||||||
|
///
|
||||||
|
///**Supported Platforms/Implementations**:
|
||||||
|
///- Android native WebView
|
||||||
|
///- iOS
|
||||||
|
///- MacOS
|
||||||
|
bool hasJavaScriptHandler({required String handlerName}) {
|
||||||
|
return this._javaScriptHandlersMap.containsKey(handlerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Takes a screenshot of the WebView's visible viewport and returns a [Uint8List]. Returns `null` if it wasn't be able to take it.
|
///Takes a screenshot of the WebView's visible viewport and returns a [Uint8List]. Returns `null` if it wasn't be able to take it.
|
||||||
|
@ -2197,7 +2234,7 @@ class InAppWebViewController {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent(
|
args.putIfAbsent(
|
||||||
'screenshotConfiguration', () => screenshotConfiguration?.toMap());
|
'screenshotConfiguration', () => screenshotConfiguration?.toMap());
|
||||||
return await _channel.invokeMethod('takeScreenshot', args);
|
return await _channel?.invokeMethod('takeScreenshot', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [setSettings] instead.
|
///Use [setSettings] instead.
|
||||||
|
@ -2233,7 +2270,7 @@ class InAppWebViewController {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
|
|
||||||
args.putIfAbsent('settings', () => settings.toMap());
|
args.putIfAbsent('settings', () => settings.toMap());
|
||||||
await _channel.invokeMethod('setSettings', args);
|
await _channel?.invokeMethod('setSettings', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Gets the current WebView settings. Returns `null` if it wasn't able to get them.
|
///Gets the current WebView settings. Returns `null` if it wasn't able to get them.
|
||||||
|
@ -2247,7 +2284,7 @@ class InAppWebViewController {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
|
|
||||||
Map<dynamic, dynamic>? settings =
|
Map<dynamic, dynamic>? settings =
|
||||||
await _channel.invokeMethod('getSettings', args);
|
await _channel?.invokeMethod('getSettings', args);
|
||||||
if (settings != null) {
|
if (settings != null) {
|
||||||
settings = settings.cast<String, dynamic>();
|
settings = settings.cast<String, dynamic>();
|
||||||
return InAppWebViewSettings.fromMap(settings as Map<String, dynamic>);
|
return InAppWebViewSettings.fromMap(settings as Map<String, dynamic>);
|
||||||
|
@ -2268,7 +2305,7 @@ class InAppWebViewController {
|
||||||
Future<WebHistory?> getCopyBackForwardList() async {
|
Future<WebHistory?> getCopyBackForwardList() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
Map<String, dynamic>? result =
|
Map<String, dynamic>? result =
|
||||||
(await _channel.invokeMethod('getCopyBackForwardList', args))
|
(await _channel?.invokeMethod('getCopyBackForwardList', args))
|
||||||
?.cast<String, dynamic>();
|
?.cast<String, dynamic>();
|
||||||
return WebHistory.fromMap(result);
|
return WebHistory.fromMap(result);
|
||||||
}
|
}
|
||||||
|
@ -2281,7 +2318,7 @@ class InAppWebViewController {
|
||||||
///- MacOS
|
///- MacOS
|
||||||
Future<void> clearCache() async {
|
Future<void> clearCache() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('clearCache', args);
|
await _channel?.invokeMethod('clearCache', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [FindInteractionController.findAll] instead.
|
///Use [FindInteractionController.findAll] instead.
|
||||||
|
@ -2289,7 +2326,7 @@ class InAppWebViewController {
|
||||||
Future<void> findAllAsync({required String find}) async {
|
Future<void> findAllAsync({required String find}) async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('find', () => find);
|
args.putIfAbsent('find', () => find);
|
||||||
await _channel.invokeMethod('findAll', args);
|
await _channel?.invokeMethod('findAll', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [FindInteractionController.findNext] instead.
|
///Use [FindInteractionController.findNext] instead.
|
||||||
|
@ -2297,14 +2334,14 @@ class InAppWebViewController {
|
||||||
Future<void> findNext({required bool forward}) async {
|
Future<void> findNext({required bool forward}) async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('forward', () => forward);
|
args.putIfAbsent('forward', () => forward);
|
||||||
await _channel.invokeMethod('findNext', args);
|
await _channel?.invokeMethod('findNext', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [FindInteractionController.clearMatches] instead.
|
///Use [FindInteractionController.clearMatches] instead.
|
||||||
@Deprecated("Use FindInteractionController.clearMatches instead")
|
@Deprecated("Use FindInteractionController.clearMatches instead")
|
||||||
Future<void> clearMatches() async {
|
Future<void> clearMatches() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('clearMatches', args);
|
await _channel?.invokeMethod('clearMatches', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [tRexRunnerHtml] instead.
|
///Use [tRexRunnerHtml] instead.
|
||||||
|
@ -2342,7 +2379,7 @@ class InAppWebViewController {
|
||||||
args.putIfAbsent('x', () => x);
|
args.putIfAbsent('x', () => x);
|
||||||
args.putIfAbsent('y', () => y);
|
args.putIfAbsent('y', () => y);
|
||||||
args.putIfAbsent('animated', () => animated);
|
args.putIfAbsent('animated', () => animated);
|
||||||
await _channel.invokeMethod('scrollTo', args);
|
await _channel?.invokeMethod('scrollTo', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Moves the scrolled position of the WebView.
|
///Moves the scrolled position of the WebView.
|
||||||
|
@ -2368,7 +2405,7 @@ class InAppWebViewController {
|
||||||
args.putIfAbsent('x', () => x);
|
args.putIfAbsent('x', () => x);
|
||||||
args.putIfAbsent('y', () => y);
|
args.putIfAbsent('y', () => y);
|
||||||
args.putIfAbsent('animated', () => animated);
|
args.putIfAbsent('animated', () => animated);
|
||||||
await _channel.invokeMethod('scrollBy', args);
|
await _channel?.invokeMethod('scrollBy', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///On Android native WebView, it pauses all layout, parsing, and JavaScript timers for all WebViews.
|
///On Android native WebView, it pauses all layout, parsing, and JavaScript timers for all WebViews.
|
||||||
|
@ -2384,7 +2421,7 @@ class InAppWebViewController {
|
||||||
///- MacOS
|
///- MacOS
|
||||||
Future<void> pauseTimers() async {
|
Future<void> pauseTimers() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('pauseTimers', args);
|
await _channel?.invokeMethod('pauseTimers', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///On Android, it resumes all layout, parsing, and JavaScript timers for all WebViews. This will resume dispatching all timers.
|
///On Android, it resumes all layout, parsing, and JavaScript timers for all WebViews. This will resume dispatching all timers.
|
||||||
|
@ -2399,7 +2436,7 @@ class InAppWebViewController {
|
||||||
///- MacOS
|
///- MacOS
|
||||||
Future<void> resumeTimers() async {
|
Future<void> resumeTimers() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('resumeTimers', args);
|
await _channel?.invokeMethod('resumeTimers', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Prints the current page.
|
///Prints the current page.
|
||||||
|
@ -2422,7 +2459,7 @@ class InAppWebViewController {
|
||||||
{PrintJobSettings? settings}) async {
|
{PrintJobSettings? settings}) async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent("settings", () => settings?.toMap());
|
args.putIfAbsent("settings", () => settings?.toMap());
|
||||||
String? jobId = await _channel.invokeMethod('printCurrentPage', args);
|
String? jobId = await _channel?.invokeMethod('printCurrentPage', args);
|
||||||
if (jobId != null) {
|
if (jobId != null) {
|
||||||
return PrintJobController(id: jobId);
|
return PrintJobController(id: jobId);
|
||||||
}
|
}
|
||||||
|
@ -2442,7 +2479,7 @@ class InAppWebViewController {
|
||||||
///- Web ([Official API - Document.documentElement.scrollHeight](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight))
|
///- Web ([Official API - Document.documentElement.scrollHeight](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight))
|
||||||
Future<int?> getContentHeight() async {
|
Future<int?> getContentHeight() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
var height = await _channel.invokeMethod('getContentHeight', args);
|
var height = await _channel?.invokeMethod('getContentHeight', args);
|
||||||
if (height == null || height == 0) {
|
if (height == null || height == 0) {
|
||||||
// try to use javascript
|
// try to use javascript
|
||||||
var scrollHeight = await evaluateJavascript(
|
var scrollHeight = await evaluateJavascript(
|
||||||
|
@ -2469,7 +2506,7 @@ class InAppWebViewController {
|
||||||
///- Web ([Official API - Document.documentElement.scrollWidth](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollWidth))
|
///- Web ([Official API - Document.documentElement.scrollWidth](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollWidth))
|
||||||
Future<int?> getContentWidth() async {
|
Future<int?> getContentWidth() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
var height = await _channel.invokeMethod('getContentWidth', args);
|
var height = await _channel?.invokeMethod('getContentWidth', args);
|
||||||
if (height == null || height == 0) {
|
if (height == null || height == 0) {
|
||||||
// try to use javascript
|
// try to use javascript
|
||||||
var scrollHeight = await evaluateJavascript(
|
var scrollHeight = await evaluateJavascript(
|
||||||
|
@ -2503,7 +2540,7 @@ class InAppWebViewController {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('zoomFactor', () => zoomFactor);
|
args.putIfAbsent('zoomFactor', () => zoomFactor);
|
||||||
args.putIfAbsent('animated', () => iosAnimated ?? animated);
|
args.putIfAbsent('animated', () => iosAnimated ?? animated);
|
||||||
return await _channel.invokeMethod('zoomBy', args);
|
return await _channel?.invokeMethod('zoomBy', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Gets the URL that was originally requested for the current page.
|
///Gets the URL that was originally requested for the current page.
|
||||||
|
@ -2519,7 +2556,7 @@ class InAppWebViewController {
|
||||||
///- Web
|
///- Web
|
||||||
Future<WebUri?> getOriginalUrl() async {
|
Future<WebUri?> getOriginalUrl() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
String? url = await _channel.invokeMethod('getOriginalUrl', args);
|
String? url = await _channel?.invokeMethod('getOriginalUrl', args);
|
||||||
return url != null ? WebUri(url) : null;
|
return url != null ? WebUri(url) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2530,7 +2567,7 @@ class InAppWebViewController {
|
||||||
///- iOS ([Official API - UIScrollView.zoomScale](https://developer.apple.com/documentation/uikit/uiscrollview/1619419-zoomscale))
|
///- iOS ([Official API - UIScrollView.zoomScale](https://developer.apple.com/documentation/uikit/uiscrollview/1619419-zoomscale))
|
||||||
Future<double?> getZoomScale() async {
|
Future<double?> getZoomScale() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('getZoomScale', args);
|
return await _channel?.invokeMethod('getZoomScale', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Use [getZoomScale] instead.
|
///Use [getZoomScale] instead.
|
||||||
|
@ -2554,7 +2591,7 @@ class InAppWebViewController {
|
||||||
///- Web
|
///- Web
|
||||||
Future<String?> getSelectedText() async {
|
Future<String?> getSelectedText() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('getSelectedText', args);
|
return await _channel?.invokeMethod('getSelectedText', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Gets the hit result for hitting an HTML elements.
|
///Gets the hit result for hitting an HTML elements.
|
||||||
|
@ -2567,7 +2604,7 @@ class InAppWebViewController {
|
||||||
Future<InAppWebViewHitTestResult?> getHitTestResult() async {
|
Future<InAppWebViewHitTestResult?> getHitTestResult() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
Map<dynamic, dynamic>? hitTestResultMap =
|
Map<dynamic, dynamic>? hitTestResultMap =
|
||||||
await _channel.invokeMethod('getHitTestResult', args);
|
await _channel?.invokeMethod('getHitTestResult', args);
|
||||||
|
|
||||||
if (hitTestResultMap == null) {
|
if (hitTestResultMap == null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -2589,7 +2626,7 @@ class InAppWebViewController {
|
||||||
///- iOS ([Official API - UIResponder.resignFirstResponder](https://developer.apple.com/documentation/uikit/uiresponder/1621097-resignfirstresponder))
|
///- iOS ([Official API - UIResponder.resignFirstResponder](https://developer.apple.com/documentation/uikit/uiresponder/1621097-resignfirstresponder))
|
||||||
Future<void> clearFocus() async {
|
Future<void> clearFocus() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('clearFocus', args);
|
return await _channel?.invokeMethod('clearFocus', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Sets or updates the WebView context menu to be used next time it will appear.
|
///Sets or updates the WebView context menu to be used next time it will appear.
|
||||||
|
@ -2600,7 +2637,7 @@ class InAppWebViewController {
|
||||||
Future<void> setContextMenu(ContextMenu? contextMenu) async {
|
Future<void> setContextMenu(ContextMenu? contextMenu) async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent("contextMenu", () => contextMenu?.toMap());
|
args.putIfAbsent("contextMenu", () => contextMenu?.toMap());
|
||||||
await _channel.invokeMethod('setContextMenu', args);
|
await _channel?.invokeMethod('setContextMenu', args);
|
||||||
_inAppBrowser?.contextMenu = contextMenu;
|
_inAppBrowser?.contextMenu = contextMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2614,7 +2651,7 @@ class InAppWebViewController {
|
||||||
Future<RequestFocusNodeHrefResult?> requestFocusNodeHref() async {
|
Future<RequestFocusNodeHrefResult?> requestFocusNodeHref() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
Map<dynamic, dynamic>? result =
|
Map<dynamic, dynamic>? result =
|
||||||
await _channel.invokeMethod('requestFocusNodeHref', args);
|
await _channel?.invokeMethod('requestFocusNodeHref', args);
|
||||||
return result != null
|
return result != null
|
||||||
? RequestFocusNodeHrefResult(
|
? RequestFocusNodeHrefResult(
|
||||||
url: result['url'] != null ? WebUri(result['url']) : null,
|
url: result['url'] != null ? WebUri(result['url']) : null,
|
||||||
|
@ -2634,7 +2671,7 @@ class InAppWebViewController {
|
||||||
Future<RequestImageRefResult?> requestImageRef() async {
|
Future<RequestImageRefResult?> requestImageRef() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
Map<dynamic, dynamic>? result =
|
Map<dynamic, dynamic>? result =
|
||||||
await _channel.invokeMethod('requestImageRef', args);
|
await _channel?.invokeMethod('requestImageRef', args);
|
||||||
return result != null
|
return result != null
|
||||||
? RequestImageRefResult(
|
? RequestImageRefResult(
|
||||||
url: result['url'] != null ? WebUri(result['url']) : null,
|
url: result['url'] != null ? WebUri(result['url']) : null,
|
||||||
|
@ -2730,7 +2767,7 @@ class InAppWebViewController {
|
||||||
try {
|
try {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
themeColor = UtilColor.fromStringRepresentation(
|
themeColor = UtilColor.fromStringRepresentation(
|
||||||
await _channel.invokeMethod('getMetaThemeColor', args));
|
await _channel?.invokeMethod('getMetaThemeColor', args));
|
||||||
return themeColor;
|
return themeColor;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// not implemented
|
// not implemented
|
||||||
|
@ -2773,7 +2810,7 @@ class InAppWebViewController {
|
||||||
///- Web ([Official API - Window.scrollX](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollX))
|
///- Web ([Official API - Window.scrollX](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollX))
|
||||||
Future<int?> getScrollX() async {
|
Future<int?> getScrollX() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('getScrollX', args);
|
return await _channel?.invokeMethod('getScrollX', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Returns the scrolled top position of the current WebView.
|
///Returns the scrolled top position of the current WebView.
|
||||||
|
@ -2789,7 +2826,7 @@ class InAppWebViewController {
|
||||||
///- Web ([Official API - Window.scrollY](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY))
|
///- Web ([Official API - Window.scrollY](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY))
|
||||||
Future<int?> getScrollY() async {
|
Future<int?> getScrollY() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('getScrollY', args);
|
return await _channel?.invokeMethod('getScrollY', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Gets the SSL certificate for the main top-level page or null if there is no certificate (the site is not secure).
|
///Gets the SSL certificate for the main top-level page or null if there is no certificate (the site is not secure).
|
||||||
|
@ -2801,7 +2838,7 @@ class InAppWebViewController {
|
||||||
Future<SslCertificate?> getCertificate() async {
|
Future<SslCertificate?> getCertificate() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
Map<String, dynamic>? sslCertificateMap =
|
Map<String, dynamic>? sslCertificateMap =
|
||||||
(await _channel.invokeMethod('getCertificate', args))
|
(await _channel?.invokeMethod('getCertificate', args))
|
||||||
?.cast<String, dynamic>();
|
?.cast<String, dynamic>();
|
||||||
return SslCertificate.fromMap(sslCertificateMap);
|
return SslCertificate.fromMap(sslCertificateMap);
|
||||||
}
|
}
|
||||||
|
@ -2824,7 +2861,7 @@ class InAppWebViewController {
|
||||||
if (!(_userScripts[userScript.injectionTime]?.contains(userScript) ??
|
if (!(_userScripts[userScript.injectionTime]?.contains(userScript) ??
|
||||||
false)) {
|
false)) {
|
||||||
_userScripts[userScript.injectionTime]?.add(userScript);
|
_userScripts[userScript.injectionTime]?.add(userScript);
|
||||||
await _channel.invokeMethod('addUserScript', args);
|
await _channel?.invokeMethod('addUserScript', args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2870,7 +2907,7 @@ class InAppWebViewController {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('userScript', () => userScript.toMap());
|
args.putIfAbsent('userScript', () => userScript.toMap());
|
||||||
args.putIfAbsent('index', () => index);
|
args.putIfAbsent('index', () => index);
|
||||||
await _channel.invokeMethod('removeUserScript', args);
|
await _channel?.invokeMethod('removeUserScript', args);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2907,7 +2944,7 @@ class InAppWebViewController {
|
||||||
|
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('groupName', () => groupName);
|
args.putIfAbsent('groupName', () => groupName);
|
||||||
await _channel.invokeMethod('removeUserScriptsByGroupName', args);
|
await _channel?.invokeMethod('removeUserScriptsByGroupName', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Removes the [userScripts] from the webpage’s content.
|
///Removes the [userScripts] from the webpage’s content.
|
||||||
|
@ -2947,7 +2984,18 @@ class InAppWebViewController {
|
||||||
_userScripts[UserScriptInjectionTime.AT_DOCUMENT_END]?.clear();
|
_userScripts[UserScriptInjectionTime.AT_DOCUMENT_END]?.clear();
|
||||||
|
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('removeAllUserScripts', args);
|
await _channel?.invokeMethod('removeAllUserScripts', args);
|
||||||
|
}
|
||||||
|
|
||||||
|
///Returns `true` if the [userScript] has been already added, otherwise `false`.
|
||||||
|
///
|
||||||
|
///**Supported Platforms/Implementations**:
|
||||||
|
///- Android native WebView
|
||||||
|
///- iOS
|
||||||
|
///- MacOS
|
||||||
|
bool hasUserScript({required UserScript userScript}) {
|
||||||
|
return _userScripts[userScript.injectionTime]?.contains(userScript) ??
|
||||||
|
false;
|
||||||
}
|
}
|
||||||
|
|
||||||
///Executes the specified string as an asynchronous JavaScript function.
|
///Executes the specified string as an asynchronous JavaScript function.
|
||||||
|
@ -2991,7 +3039,7 @@ class InAppWebViewController {
|
||||||
args.putIfAbsent('functionBody', () => functionBody);
|
args.putIfAbsent('functionBody', () => functionBody);
|
||||||
args.putIfAbsent('arguments', () => arguments);
|
args.putIfAbsent('arguments', () => arguments);
|
||||||
args.putIfAbsent('contentWorld', () => contentWorld?.toMap());
|
args.putIfAbsent('contentWorld', () => contentWorld?.toMap());
|
||||||
var data = await _channel.invokeMethod('callAsyncJavaScript', args);
|
var data = await _channel?.invokeMethod('callAsyncJavaScript', args);
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -3034,7 +3082,7 @@ class InAppWebViewController {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent("filePath", () => filePath);
|
args.putIfAbsent("filePath", () => filePath);
|
||||||
args.putIfAbsent("autoname", () => autoname);
|
args.putIfAbsent("autoname", () => autoname);
|
||||||
return await _channel.invokeMethod('saveWebArchive', args);
|
return await _channel?.invokeMethod('saveWebArchive', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Indicates whether the webpage context is capable of using features that require [secure contexts](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts).
|
///Indicates whether the webpage context is capable of using features that require [secure contexts](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts).
|
||||||
|
@ -3051,7 +3099,7 @@ class InAppWebViewController {
|
||||||
///- Web ([Official API - Window.isSecureContext](https://developer.mozilla.org/en-US/docs/Web/API/Window/isSecureContext))
|
///- Web ([Official API - Window.isSecureContext](https://developer.mozilla.org/en-US/docs/Web/API/Window/isSecureContext))
|
||||||
Future<bool> isSecureContext() async {
|
Future<bool> isSecureContext() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('isSecureContext', args);
|
return await _channel?.invokeMethod('isSecureContext', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Creates a message channel to communicate with JavaScript and returns the message channel with ports that represent the endpoints of this message channel.
|
///Creates a message channel to communicate with JavaScript and returns the message channel with ports that represent the endpoints of this message channel.
|
||||||
|
@ -3074,7 +3122,7 @@ class InAppWebViewController {
|
||||||
Future<WebMessageChannel?> createWebMessageChannel() async {
|
Future<WebMessageChannel?> createWebMessageChannel() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
Map<String, dynamic>? result =
|
Map<String, dynamic>? result =
|
||||||
(await _channel.invokeMethod('createWebMessageChannel', args))
|
(await _channel?.invokeMethod('createWebMessageChannel', args))
|
||||||
?.cast<String, dynamic>();
|
?.cast<String, dynamic>();
|
||||||
return WebMessageChannel.fromMap(result);
|
return WebMessageChannel.fromMap(result);
|
||||||
}
|
}
|
||||||
|
@ -3102,7 +3150,7 @@ class InAppWebViewController {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('message', () => message.toMap());
|
args.putIfAbsent('message', () => message.toMap());
|
||||||
args.putIfAbsent('targetOrigin', () => targetOrigin.toString());
|
args.putIfAbsent('targetOrigin', () => targetOrigin.toString());
|
||||||
await _channel.invokeMethod('postWebMessage', args);
|
await _channel?.invokeMethod('postWebMessage', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Adds a [WebMessageListener] to the WebView and injects a JavaScript object into each frame that the [WebMessageListener] will listen on.
|
///Adds a [WebMessageListener] to the WebView and injects a JavaScript object into each frame that the [WebMessageListener] will listen on.
|
||||||
|
@ -3278,7 +3326,18 @@ class InAppWebViewController {
|
||||||
|
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('webMessageListener', () => webMessageListener.toMap());
|
args.putIfAbsent('webMessageListener', () => webMessageListener.toMap());
|
||||||
await _channel.invokeMethod('addWebMessageListener', args);
|
await _channel?.invokeMethod('addWebMessageListener', args);
|
||||||
|
}
|
||||||
|
|
||||||
|
///Returns `true` if the [webMessageListener] has been already added, otherwise `false`.
|
||||||
|
///
|
||||||
|
///**Supported Platforms/Implementations**:
|
||||||
|
///- Android native WebView
|
||||||
|
///- iOS
|
||||||
|
///- MacOS
|
||||||
|
bool hasWebMessageListener(WebMessageListener webMessageListener) {
|
||||||
|
return _webMessageListenerObjNames
|
||||||
|
.contains(webMessageListener.jsObjectName);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Returns `true` if the webpage can scroll vertically, otherwise `false`.
|
///Returns `true` if the webpage can scroll vertically, otherwise `false`.
|
||||||
|
@ -3294,7 +3353,7 @@ class InAppWebViewController {
|
||||||
///- Web
|
///- Web
|
||||||
Future<bool> canScrollVertically() async {
|
Future<bool> canScrollVertically() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('canScrollVertically', args);
|
return await _channel?.invokeMethod('canScrollVertically', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Returns `true` if the webpage can scroll horizontally, otherwise `false`.
|
///Returns `true` if the webpage can scroll horizontally, otherwise `false`.
|
||||||
|
@ -3310,7 +3369,7 @@ class InAppWebViewController {
|
||||||
///- Web
|
///- Web
|
||||||
Future<bool> canScrollHorizontally() async {
|
Future<bool> canScrollHorizontally() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('canScrollHorizontally', args);
|
return await _channel?.invokeMethod('canScrollHorizontally', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Starts Safe Browsing initialization.
|
///Starts Safe Browsing initialization.
|
||||||
|
@ -3327,7 +3386,7 @@ class InAppWebViewController {
|
||||||
///- Android native WebView ([Official API - WebView.startSafeBrowsing](https://developer.android.com/reference/android/webkit/WebView#startSafeBrowsing(android.content.Context,%20android.webkit.ValueCallback%3Cjava.lang.Boolean%3E)))
|
///- Android native WebView ([Official API - WebView.startSafeBrowsing](https://developer.android.com/reference/android/webkit/WebView#startSafeBrowsing(android.content.Context,%20android.webkit.ValueCallback%3Cjava.lang.Boolean%3E)))
|
||||||
Future<bool> startSafeBrowsing() async {
|
Future<bool> startSafeBrowsing() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('startSafeBrowsing', args);
|
return await _channel?.invokeMethod('startSafeBrowsing', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Clears the SSL preferences table stored in response to proceeding with SSL certificate errors.
|
///Clears the SSL preferences table stored in response to proceeding with SSL certificate errors.
|
||||||
|
@ -3336,7 +3395,7 @@ class InAppWebViewController {
|
||||||
///- Android native WebView ([Official API - WebView.clearSslPreferences](https://developer.android.com/reference/android/webkit/WebView#clearSslPreferences()))
|
///- Android native WebView ([Official API - WebView.clearSslPreferences](https://developer.android.com/reference/android/webkit/WebView#clearSslPreferences()))
|
||||||
Future<void> clearSslPreferences() async {
|
Future<void> clearSslPreferences() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('clearSslPreferences', args);
|
await _channel?.invokeMethod('clearSslPreferences', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Does a best-effort attempt to pause any processing that can be paused safely, such as animations and geolocation. Note that this call does not pause JavaScript.
|
///Does a best-effort attempt to pause any processing that can be paused safely, such as animations and geolocation. Note that this call does not pause JavaScript.
|
||||||
|
@ -3346,7 +3405,7 @@ class InAppWebViewController {
|
||||||
///- Android native WebView ([Official API - WebView.onPause](https://developer.android.com/reference/android/webkit/WebView#onPause()))
|
///- Android native WebView ([Official API - WebView.onPause](https://developer.android.com/reference/android/webkit/WebView#onPause()))
|
||||||
Future<void> pause() async {
|
Future<void> pause() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('pause', args);
|
await _channel?.invokeMethod('pause', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Resumes a WebView after a previous call to [pause].
|
///Resumes a WebView after a previous call to [pause].
|
||||||
|
@ -3355,7 +3414,7 @@ class InAppWebViewController {
|
||||||
///- Android native WebView ([Official API - WebView.onResume](https://developer.android.com/reference/android/webkit/WebView#onResume()))
|
///- Android native WebView ([Official API - WebView.onResume](https://developer.android.com/reference/android/webkit/WebView#onResume()))
|
||||||
Future<void> resume() async {
|
Future<void> resume() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('resume', args);
|
await _channel?.invokeMethod('resume', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Scrolls the contents of this WebView down by half the page size.
|
///Scrolls the contents of this WebView down by half the page size.
|
||||||
|
@ -3368,7 +3427,7 @@ class InAppWebViewController {
|
||||||
Future<bool> pageDown({required bool bottom}) async {
|
Future<bool> pageDown({required bool bottom}) async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent("bottom", () => bottom);
|
args.putIfAbsent("bottom", () => bottom);
|
||||||
return await _channel.invokeMethod('pageDown', args);
|
return await _channel?.invokeMethod('pageDown', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Scrolls the contents of this WebView up by half the view size.
|
///Scrolls the contents of this WebView up by half the view size.
|
||||||
|
@ -3381,7 +3440,7 @@ class InAppWebViewController {
|
||||||
Future<bool> pageUp({required bool top}) async {
|
Future<bool> pageUp({required bool top}) async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent("top", () => top);
|
args.putIfAbsent("top", () => top);
|
||||||
return await _channel.invokeMethod('pageUp', args);
|
return await _channel?.invokeMethod('pageUp', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Performs zoom in in this WebView.
|
///Performs zoom in in this WebView.
|
||||||
|
@ -3391,7 +3450,7 @@ class InAppWebViewController {
|
||||||
///- Android native WebView ([Official API - WebView.zoomIn](https://developer.android.com/reference/android/webkit/WebView#zoomIn()))
|
///- Android native WebView ([Official API - WebView.zoomIn](https://developer.android.com/reference/android/webkit/WebView#zoomIn()))
|
||||||
Future<bool> zoomIn() async {
|
Future<bool> zoomIn() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('zoomIn', args);
|
return await _channel?.invokeMethod('zoomIn', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Performs zoom out in this WebView.
|
///Performs zoom out in this WebView.
|
||||||
|
@ -3401,7 +3460,7 @@ class InAppWebViewController {
|
||||||
///- Android native WebView ([Official API - WebView.zoomOut](https://developer.android.com/reference/android/webkit/WebView#zoomOut()))
|
///- Android native WebView ([Official API - WebView.zoomOut](https://developer.android.com/reference/android/webkit/WebView#zoomOut()))
|
||||||
Future<bool> zoomOut() async {
|
Future<bool> zoomOut() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('zoomOut', args);
|
return await _channel?.invokeMethod('zoomOut', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Clears the internal back/forward list.
|
///Clears the internal back/forward list.
|
||||||
|
@ -3410,7 +3469,7 @@ class InAppWebViewController {
|
||||||
///- Android native WebView ([Official API - WebView.clearHistory](https://developer.android.com/reference/android/webkit/WebView#clearHistory()))
|
///- Android native WebView ([Official API - WebView.clearHistory](https://developer.android.com/reference/android/webkit/WebView#clearHistory()))
|
||||||
Future<void> clearHistory() async {
|
Future<void> clearHistory() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('clearHistory', args);
|
return await _channel?.invokeMethod('clearHistory', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Reloads the current page, performing end-to-end revalidation using cache-validating conditionals if possible.
|
///Reloads the current page, performing end-to-end revalidation using cache-validating conditionals if possible.
|
||||||
|
@ -3420,7 +3479,7 @@ class InAppWebViewController {
|
||||||
///- MacOS ([Official API - WKWebView.reloadFromOrigin](https://developer.apple.com/documentation/webkit/wkwebview/1414956-reloadfromorigin))
|
///- MacOS ([Official API - WKWebView.reloadFromOrigin](https://developer.apple.com/documentation/webkit/wkwebview/1414956-reloadfromorigin))
|
||||||
Future<void> reloadFromOrigin() async {
|
Future<void> reloadFromOrigin() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('reloadFromOrigin', args);
|
await _channel?.invokeMethod('reloadFromOrigin', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Generates PDF data from the web view’s contents asynchronously.
|
///Generates PDF data from the web view’s contents asynchronously.
|
||||||
|
@ -3443,7 +3502,7 @@ class InAppWebViewController {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('pdfConfiguration',
|
args.putIfAbsent('pdfConfiguration',
|
||||||
() => pdfConfiguration?.toMap() ?? iosWKPdfConfiguration?.toMap());
|
() => pdfConfiguration?.toMap() ?? iosWKPdfConfiguration?.toMap());
|
||||||
return await _channel.invokeMethod('createPdf', args);
|
return await _channel?.invokeMethod('createPdf', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Creates a web archive of the web view’s current contents asynchronously.
|
///Creates a web archive of the web view’s current contents asynchronously.
|
||||||
|
@ -3458,7 +3517,7 @@ class InAppWebViewController {
|
||||||
///- MacOS ([Official API - WKWebView.createWebArchiveData](https://developer.apple.com/documentation/webkit/wkwebview/3650491-createwebarchivedata))
|
///- MacOS ([Official API - WKWebView.createWebArchiveData](https://developer.apple.com/documentation/webkit/wkwebview/3650491-createwebarchivedata))
|
||||||
Future<Uint8List?> createWebArchiveData() async {
|
Future<Uint8List?> createWebArchiveData() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('createWebArchiveData', args);
|
return await _channel?.invokeMethod('createWebArchiveData', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///A Boolean value indicating whether all resources on the page have been loaded over securely encrypted connections.
|
///A Boolean value indicating whether all resources on the page have been loaded over securely encrypted connections.
|
||||||
|
@ -3468,7 +3527,7 @@ class InAppWebViewController {
|
||||||
///- MacOS ([Official API - WKWebView.hasOnlySecureContent](https://developer.apple.com/documentation/webkit/wkwebview/1415002-hasonlysecurecontent))
|
///- MacOS ([Official API - WKWebView.hasOnlySecureContent](https://developer.apple.com/documentation/webkit/wkwebview/1415002-hasonlysecurecontent))
|
||||||
Future<bool> hasOnlySecureContent() async {
|
Future<bool> hasOnlySecureContent() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('hasOnlySecureContent', args);
|
return await _channel?.invokeMethod('hasOnlySecureContent', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Pauses playback of all media in the web view.
|
///Pauses playback of all media in the web view.
|
||||||
|
@ -3482,7 +3541,7 @@ class InAppWebViewController {
|
||||||
///- MacOS ([Official API - WKWebView.pauseAllMediaPlayback](https://developer.apple.com/documentation/webkit/wkwebview/3752240-pauseallmediaplayback)).
|
///- MacOS ([Official API - WKWebView.pauseAllMediaPlayback](https://developer.apple.com/documentation/webkit/wkwebview/3752240-pauseallmediaplayback)).
|
||||||
Future<void> pauseAllMediaPlayback() async {
|
Future<void> pauseAllMediaPlayback() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('pauseAllMediaPlayback', args);
|
return await _channel?.invokeMethod('pauseAllMediaPlayback', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Changes whether the webpage is suspending playback of all media in the page.
|
///Changes whether the webpage is suspending playback of all media in the page.
|
||||||
|
@ -3500,7 +3559,7 @@ class InAppWebViewController {
|
||||||
Future<void> setAllMediaPlaybackSuspended({required bool suspended}) async {
|
Future<void> setAllMediaPlaybackSuspended({required bool suspended}) async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent("suspended", () => suspended);
|
args.putIfAbsent("suspended", () => suspended);
|
||||||
return await _channel.invokeMethod('setAllMediaPlaybackSuspended', args);
|
return await _channel?.invokeMethod('setAllMediaPlaybackSuspended', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Closes all media the web view is presenting, including picture-in-picture video and fullscreen video.
|
///Closes all media the web view is presenting, including picture-in-picture video and fullscreen video.
|
||||||
|
@ -3514,7 +3573,7 @@ class InAppWebViewController {
|
||||||
///- MacOS ([Official API - WKWebView.closeAllMediaPresentations](https://developer.apple.com/documentation/webkit/wkwebview/3752235-closeallmediapresentations)).
|
///- MacOS ([Official API - WKWebView.closeAllMediaPresentations](https://developer.apple.com/documentation/webkit/wkwebview/3752235-closeallmediapresentations)).
|
||||||
Future<void> closeAllMediaPresentations() async {
|
Future<void> closeAllMediaPresentations() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('closeAllMediaPresentations', args);
|
return await _channel?.invokeMethod('closeAllMediaPresentations', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Requests the playback status of media in the web view.
|
///Requests the playback status of media in the web view.
|
||||||
|
@ -3531,7 +3590,7 @@ class InAppWebViewController {
|
||||||
Future<MediaPlaybackState?> requestMediaPlaybackState() async {
|
Future<MediaPlaybackState?> requestMediaPlaybackState() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return MediaPlaybackState.fromNativeValue(
|
return MediaPlaybackState.fromNativeValue(
|
||||||
await _channel.invokeMethod('requestMediaPlaybackState', args));
|
await _channel?.invokeMethod('requestMediaPlaybackState', args));
|
||||||
}
|
}
|
||||||
|
|
||||||
///Returns `true` if the [WebView] is in fullscreen mode, otherwise `false`.
|
///Returns `true` if the [WebView] is in fullscreen mode, otherwise `false`.
|
||||||
|
@ -3542,7 +3601,7 @@ class InAppWebViewController {
|
||||||
///- MacOS
|
///- MacOS
|
||||||
Future<bool> isInFullscreen() async {
|
Future<bool> isInFullscreen() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('isInFullscreen', args);
|
return await _channel?.invokeMethod('isInFullscreen', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Returns a [MediaCaptureState] that indicates whether the webpage is using the camera to capture images or video.
|
///Returns a [MediaCaptureState] that indicates whether the webpage is using the camera to capture images or video.
|
||||||
|
@ -3557,7 +3616,7 @@ class InAppWebViewController {
|
||||||
Future<MediaCaptureState?> getCameraCaptureState() async {
|
Future<MediaCaptureState?> getCameraCaptureState() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return MediaCaptureState.fromNativeValue(
|
return MediaCaptureState.fromNativeValue(
|
||||||
await _channel.invokeMethod('getCameraCaptureState', args));
|
await _channel?.invokeMethod('getCameraCaptureState', args));
|
||||||
}
|
}
|
||||||
|
|
||||||
///Changes whether the webpage is using the camera to capture images or video.
|
///Changes whether the webpage is using the camera to capture images or video.
|
||||||
|
@ -3572,7 +3631,7 @@ class InAppWebViewController {
|
||||||
Future<void> setCameraCaptureState({required MediaCaptureState state}) async {
|
Future<void> setCameraCaptureState({required MediaCaptureState state}) async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('state', () => state.toNativeValue());
|
args.putIfAbsent('state', () => state.toNativeValue());
|
||||||
await _channel.invokeMethod('setCameraCaptureState', args);
|
await _channel?.invokeMethod('setCameraCaptureState', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Returns a [MediaCaptureState] that indicates whether the webpage is using the microphone to capture audio.
|
///Returns a [MediaCaptureState] that indicates whether the webpage is using the microphone to capture audio.
|
||||||
|
@ -3587,7 +3646,7 @@ class InAppWebViewController {
|
||||||
Future<MediaCaptureState?> getMicrophoneCaptureState() async {
|
Future<MediaCaptureState?> getMicrophoneCaptureState() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return MediaCaptureState.fromNativeValue(
|
return MediaCaptureState.fromNativeValue(
|
||||||
await _channel.invokeMethod('getMicrophoneCaptureState', args));
|
await _channel?.invokeMethod('getMicrophoneCaptureState', args));
|
||||||
}
|
}
|
||||||
|
|
||||||
///Changes whether the webpage is using the microphone to capture audio.
|
///Changes whether the webpage is using the microphone to capture audio.
|
||||||
|
@ -3603,7 +3662,7 @@ class InAppWebViewController {
|
||||||
{required MediaCaptureState state}) async {
|
{required MediaCaptureState state}) async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('state', () => state.toNativeValue());
|
args.putIfAbsent('state', () => state.toNativeValue());
|
||||||
await _channel.invokeMethod('setMicrophoneCaptureState', args);
|
await _channel?.invokeMethod('setMicrophoneCaptureState', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Loads the web content from the data you provide as if the data were the response to the request.
|
///Loads the web content from the data you provide as if the data were the response to the request.
|
||||||
|
@ -3639,7 +3698,7 @@ class InAppWebViewController {
|
||||||
args.putIfAbsent('urlRequest', () => urlRequest.toMap());
|
args.putIfAbsent('urlRequest', () => urlRequest.toMap());
|
||||||
args.putIfAbsent('data', () => data);
|
args.putIfAbsent('data', () => data);
|
||||||
args.putIfAbsent('urlResponse', () => urlResponse?.toMap());
|
args.putIfAbsent('urlResponse', () => urlResponse?.toMap());
|
||||||
await _channel.invokeMethod('loadSimulatedRequest', args);
|
await _channel?.invokeMethod('loadSimulatedRequest', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Returns the iframe `id` attribute used on the Web platform.
|
///Returns the iframe `id` attribute used on the Web platform.
|
||||||
|
@ -3648,7 +3707,7 @@ class InAppWebViewController {
|
||||||
///- Web
|
///- Web
|
||||||
Future<String?> getIFrameId() async {
|
Future<String?> getIFrameId() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('getIFrameId', args);
|
return await _channel?.invokeMethod('getIFrameId', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Gets the default user agent.
|
///Gets the default user agent.
|
||||||
|
@ -3812,6 +3871,19 @@ class InAppWebViewController {
|
||||||
return await _staticChannel.invokeMethod('handlesURLScheme', args);
|
return await _staticChannel.invokeMethod('handlesURLScheme', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///Disposes the WebView that is using the [keepAlive] instance
|
||||||
|
///for the keep alive feature.
|
||||||
|
///
|
||||||
|
///**Supported Platforms/Implementations**:
|
||||||
|
///- Android native WebView
|
||||||
|
///- iOS
|
||||||
|
static Future<void> disposeKeepAlive(InAppWebViewKeepAlive keepAlive) async {
|
||||||
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
|
args.putIfAbsent('keepAliveId', () => keepAlive.id);
|
||||||
|
await _staticChannel.invokeMethod('disposeKeepAlive', args);
|
||||||
|
_keepAliveMap[keepAlive] = null;
|
||||||
|
}
|
||||||
|
|
||||||
///Gets the html (with javascript) of the Chromium's t-rex runner game. Used in combination with [tRexRunnerCss].
|
///Gets the html (with javascript) of the Chromium's t-rex runner game. Used in combination with [tRexRunnerCss].
|
||||||
///
|
///
|
||||||
///**Supported Platforms/Implementations**:
|
///**Supported Platforms/Implementations**:
|
||||||
|
@ -3831,7 +3903,7 @@ class InAppWebViewController {
|
||||||
'packages/flutter_inappwebview/assets/t_rex_runner/t-rex.css');
|
'packages/flutter_inappwebview/assets/t_rex_runner/t-rex.css');
|
||||||
|
|
||||||
///Used internally.
|
///Used internally.
|
||||||
MethodChannel getChannel() {
|
MethodChannel? getChannel() {
|
||||||
return _channel;
|
return _channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3839,4 +3911,23 @@ class InAppWebViewController {
|
||||||
dynamic getViewId() {
|
dynamic getViewId() {
|
||||||
return _id;
|
return _id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///Disposes the controller.
|
||||||
|
void dispose({bool isKeepAlive = false}) {
|
||||||
|
if (!isKeepAlive) {
|
||||||
|
_channel?.setMethodCallHandler(null);
|
||||||
|
}
|
||||||
|
android.dispose();
|
||||||
|
ios.dispose();
|
||||||
|
_channel = null;
|
||||||
|
_webview = null;
|
||||||
|
_inAppBrowser = null;
|
||||||
|
webStorage.dispose();
|
||||||
|
if (!isKeepAlive) {
|
||||||
|
_javaScriptHandlersMap.clear();
|
||||||
|
_userScripts.clear();
|
||||||
|
_webMessageListenerObjNames.clear();
|
||||||
|
_injectedScriptsFromURL.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
import '../types/main.dart';
|
||||||
|
import '../util.dart';
|
||||||
|
import 'in_app_webview.dart';
|
||||||
|
import 'in_app_webview_controller.dart';
|
||||||
|
|
||||||
|
///Class used to keep alive a [InAppWebView].
|
||||||
|
class InAppWebViewKeepAlive {
|
||||||
|
String _id = IdGenerator.generate();
|
||||||
|
}
|
||||||
|
|
||||||
|
///Used internally
|
||||||
|
extension InternalInAppWebViewKeepAlive on InAppWebViewKeepAlive {
|
||||||
|
set id(String id) {
|
||||||
|
_id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
String get id => _id;
|
||||||
|
}
|
||||||
|
|
||||||
|
///Used internally to save and restore [InAppWebViewController] properties
|
||||||
|
///for the keep alive feature.
|
||||||
|
class InAppWebViewControllerKeepAliveProps {
|
||||||
|
Map<String, JavaScriptHandlerCallback> javaScriptHandlersMap;
|
||||||
|
Map<UserScriptInjectionTime, List<UserScript>> userScripts;
|
||||||
|
Set<String> webMessageListenerObjNames;
|
||||||
|
Map<String, ScriptHtmlTagAttributes> injectedScriptsFromURL;
|
||||||
|
|
||||||
|
InAppWebViewControllerKeepAliveProps(
|
||||||
|
{required this.javaScriptHandlersMap,
|
||||||
|
required this.userScripts,
|
||||||
|
required this.webMessageListenerObjNames,
|
||||||
|
required this.injectedScriptsFromURL});
|
||||||
|
}
|
|
@ -11,3 +11,4 @@ export 'headless_in_app_webview.dart' hide InternalHeadlessInAppWebView;
|
||||||
export 'android/main.dart';
|
export 'android/main.dart';
|
||||||
export 'apple/main.dart';
|
export 'apple/main.dart';
|
||||||
export '../find_interaction/find_interaction_controller.dart';
|
export '../find_interaction/find_interaction_controller.dart';
|
||||||
|
export 'in_app_webview_keep_alive.dart' show InAppWebViewKeepAlive;
|
||||||
|
|
|
@ -1191,12 +1191,6 @@ abstract class WebView {
|
||||||
///{@endtemplate}
|
///{@endtemplate}
|
||||||
final FindInteractionController? findInteractionController;
|
final FindInteractionController? findInteractionController;
|
||||||
|
|
||||||
///{@template flutter_inappwebview.WebView.implementation}
|
|
||||||
///Represents the WebView native implementation to be used.
|
|
||||||
///The default value is [WebViewImplementation.NATIVE].
|
|
||||||
///{@endtemplate}
|
|
||||||
final WebViewImplementation implementation;
|
|
||||||
|
|
||||||
///{@macro flutter_inappwebview.WebView}
|
///{@macro flutter_inappwebview.WebView}
|
||||||
WebView(
|
WebView(
|
||||||
{this.windowId,
|
{this.windowId,
|
||||||
|
@ -1314,6 +1308,5 @@ abstract class WebView {
|
||||||
this.contextMenu,
|
this.contextMenu,
|
||||||
this.initialUserScripts,
|
this.initialUserScripts,
|
||||||
this.pullToRefreshController,
|
this.pullToRefreshController,
|
||||||
this.findInteractionController,
|
this.findInteractionController});
|
||||||
this.implementation = WebViewImplementation.NATIVE});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ class PrintJobController implements Disposable {
|
||||||
///Print job ID.
|
///Print job ID.
|
||||||
final String id;
|
final String id;
|
||||||
|
|
||||||
late MethodChannel _channel;
|
MethodChannel? _channel;
|
||||||
|
|
||||||
///A completion handler used to handle the conclusion of the print job (for instance, to reset state) and to handle any errors encountered in printing.
|
///A completion handler used to handle the conclusion of the print job (for instance, to reset state) and to handle any errors encountered in printing.
|
||||||
///
|
///
|
||||||
|
@ -29,7 +29,7 @@ class PrintJobController implements Disposable {
|
||||||
PrintJobController({required this.id}) {
|
PrintJobController({required this.id}) {
|
||||||
this._channel = MethodChannel(
|
this._channel = MethodChannel(
|
||||||
'com.pichillilorenzo/flutter_inappwebview_printjobcontroller_$id');
|
'com.pichillilorenzo/flutter_inappwebview_printjobcontroller_$id');
|
||||||
this._channel.setMethodCallHandler((call) async {
|
this._channel?.setMethodCallHandler((call) async {
|
||||||
try {
|
try {
|
||||||
return await _handleMethod(call);
|
return await _handleMethod(call);
|
||||||
} on Error catch (e) {
|
} on Error catch (e) {
|
||||||
|
@ -60,7 +60,7 @@ class PrintJobController implements Disposable {
|
||||||
///- Android native WebView ([Official API - PrintJob.cancel](https://developer.android.com/reference/android/print/PrintJob#cancel()))
|
///- Android native WebView ([Official API - PrintJob.cancel](https://developer.android.com/reference/android/print/PrintJob#cancel()))
|
||||||
Future<void> cancel() async {
|
Future<void> cancel() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('cancel', args);
|
await _channel?.invokeMethod('cancel', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Restarts this print job.
|
///Restarts this print job.
|
||||||
|
@ -70,7 +70,7 @@ class PrintJobController implements Disposable {
|
||||||
///- Android native WebView ([Official API - PrintJob.restart](https://developer.android.com/reference/android/print/PrintJob#restart()))
|
///- Android native WebView ([Official API - PrintJob.restart](https://developer.android.com/reference/android/print/PrintJob#restart()))
|
||||||
Future<void> restart() async {
|
Future<void> restart() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('restart', args);
|
await _channel?.invokeMethod('restart', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Dismisses the printing-options sheet or popover.
|
///Dismisses the printing-options sheet or popover.
|
||||||
|
@ -85,7 +85,7 @@ class PrintJobController implements Disposable {
|
||||||
Future<void> dismiss({bool animated: true}) async {
|
Future<void> dismiss({bool animated: true}) async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent("animated", () => animated);
|
args.putIfAbsent("animated", () => animated);
|
||||||
await _channel.invokeMethod('dismiss', args);
|
await _channel?.invokeMethod('dismiss', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Gets the [PrintJobInfo] that describes this job.
|
///Gets the [PrintJobInfo] that describes this job.
|
||||||
|
@ -101,7 +101,7 @@ class PrintJobController implements Disposable {
|
||||||
Future<PrintJobInfo?> getInfo() async {
|
Future<PrintJobInfo?> getInfo() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
Map<String, dynamic>? infoMap =
|
Map<String, dynamic>? infoMap =
|
||||||
(await _channel.invokeMethod('getInfo', args))?.cast<String, dynamic>();
|
(await _channel?.invokeMethod('getInfo', args))?.cast<String, dynamic>();
|
||||||
return PrintJobInfo.fromMap(infoMap);
|
return PrintJobInfo.fromMap(infoMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,6 +114,8 @@ class PrintJobController implements Disposable {
|
||||||
@override
|
@override
|
||||||
Future<void> dispose() async {
|
Future<void> dispose() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('dispose', args);
|
await _channel?.invokeMethod('dispose', args);
|
||||||
|
_channel?.setMethodCallHandler(null);
|
||||||
|
_channel = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
export 'pull_to_refresh_controller.dart';
|
export 'pull_to_refresh_controller.dart'
|
||||||
|
show PullToRefreshController;
|
||||||
export 'pull_to_refresh_settings.dart'
|
export 'pull_to_refresh_settings.dart'
|
||||||
show PullToRefreshSettings, PullToRefreshOptions;
|
show PullToRefreshSettings, PullToRefreshOptions;
|
||||||
|
|
|
@ -44,19 +44,6 @@ class PullToRefreshController {
|
||||||
this.settings = settings ?? PullToRefreshSettings();
|
this.settings = settings ?? PullToRefreshSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void initMethodChannel(dynamic id) {
|
|
||||||
this._channel = MethodChannel(
|
|
||||||
'com.pichillilorenzo/flutter_inappwebview_pull_to_refresh_$id');
|
|
||||||
this._channel?.setMethodCallHandler((call) async {
|
|
||||||
try {
|
|
||||||
return await _handleMethod(call);
|
|
||||||
} on Error catch (e) {
|
|
||||||
print(e);
|
|
||||||
print(e.stackTrace);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_debugLog(String method, dynamic args) {
|
_debugLog(String method, dynamic args) {
|
||||||
debugLog(
|
debugLog(
|
||||||
className: this.runtimeType.toString(),
|
className: this.runtimeType.toString(),
|
||||||
|
@ -228,4 +215,28 @@ class PullToRefreshController {
|
||||||
args.putIfAbsent('attributedTitle', () => attributedTitle.toMap());
|
args.putIfAbsent('attributedTitle', () => attributedTitle.toMap());
|
||||||
await _channel?.invokeMethod('setStyledTitle', args);
|
await _channel?.invokeMethod('setStyledTitle', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///Disposes the controller.
|
||||||
|
void dispose({bool isKeepAlive = false}) {
|
||||||
|
if (!isKeepAlive) {
|
||||||
|
_channel?.setMethodCallHandler(null);
|
||||||
|
}
|
||||||
|
_channel = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension InternalPullToRefreshController on PullToRefreshController {
|
||||||
|
void init(dynamic id) {
|
||||||
|
this._channel = MethodChannel(
|
||||||
|
'com.pichillilorenzo/flutter_inappwebview_pull_to_refresh_$id');
|
||||||
|
this._channel?.setMethodCallHandler((call) async {
|
||||||
|
if (_channel == null) return null;
|
||||||
|
try {
|
||||||
|
return await _handleMethod(call);
|
||||||
|
} on Error catch (e) {
|
||||||
|
print(e);
|
||||||
|
print(e.stackTrace);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -198,7 +198,6 @@ export 'web_storage_type.dart' show WebStorageType;
|
||||||
export 'website_data_record.dart'
|
export 'website_data_record.dart'
|
||||||
show WebsiteDataRecord, IOSWKWebsiteDataRecord;
|
show WebsiteDataRecord, IOSWKWebsiteDataRecord;
|
||||||
export 'website_data_type.dart' show WebsiteDataType, IOSWKWebsiteDataType;
|
export 'website_data_type.dart' show WebsiteDataType, IOSWKWebsiteDataType;
|
||||||
export 'webview_implementation.dart' show WebViewImplementation;
|
|
||||||
export 'webview_package_info.dart'
|
export 'webview_package_info.dart'
|
||||||
show WebViewPackageInfo, AndroidWebViewPackageInfo;
|
show WebViewPackageInfo, AndroidWebViewPackageInfo;
|
||||||
export 'webview_render_process_action.dart' show WebViewRenderProcessAction;
|
export 'webview_render_process_action.dart' show WebViewRenderProcessAction;
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
import 'package:flutter_inappwebview_internal_annotations/flutter_inappwebview_internal_annotations.dart';
|
|
||||||
|
|
||||||
import '../in_app_webview/webview.dart';
|
|
||||||
|
|
||||||
part 'webview_implementation.g.dart';
|
|
||||||
|
|
||||||
///Class that represents the [WebView] native implementation to be used.
|
|
||||||
@ExchangeableEnum()
|
|
||||||
class WebViewImplementation_ {
|
|
||||||
// ignore: unused_field
|
|
||||||
final int _value;
|
|
||||||
const WebViewImplementation_._internal(this._value);
|
|
||||||
|
|
||||||
///Default native implementation, such as `WKWebView` for iOS and `android.webkit.WebView` for Android.
|
|
||||||
static const NATIVE = const WebViewImplementation_._internal(0);
|
|
||||||
}
|
|
|
@ -1,73 +0,0 @@
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'webview_implementation.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// ExchangeableEnumGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
///Class that represents the [WebView] native implementation to be used.
|
|
||||||
class WebViewImplementation {
|
|
||||||
final int _value;
|
|
||||||
final int _nativeValue;
|
|
||||||
const WebViewImplementation._internal(this._value, this._nativeValue);
|
|
||||||
// ignore: unused_element
|
|
||||||
factory WebViewImplementation._internalMultiPlatform(
|
|
||||||
int value, Function nativeValue) =>
|
|
||||||
WebViewImplementation._internal(value, nativeValue());
|
|
||||||
|
|
||||||
///Default native implementation, such as `WKWebView` for iOS and `android.webkit.WebView` for Android.
|
|
||||||
static const NATIVE = WebViewImplementation._internal(0, 0);
|
|
||||||
|
|
||||||
///Set of all values of [WebViewImplementation].
|
|
||||||
static final Set<WebViewImplementation> values = [
|
|
||||||
WebViewImplementation.NATIVE,
|
|
||||||
].toSet();
|
|
||||||
|
|
||||||
///Gets a possible [WebViewImplementation] instance from [int] value.
|
|
||||||
static WebViewImplementation? fromValue(int? value) {
|
|
||||||
if (value != null) {
|
|
||||||
try {
|
|
||||||
return WebViewImplementation.values
|
|
||||||
.firstWhere((element) => element.toValue() == value);
|
|
||||||
} catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
///Gets a possible [WebViewImplementation] instance from a native value.
|
|
||||||
static WebViewImplementation? fromNativeValue(int? value) {
|
|
||||||
if (value != null) {
|
|
||||||
try {
|
|
||||||
return WebViewImplementation.values
|
|
||||||
.firstWhere((element) => element.toNativeValue() == value);
|
|
||||||
} catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
///Gets [int] value.
|
|
||||||
int toValue() => _value;
|
|
||||||
|
|
||||||
///Gets [int] native value.
|
|
||||||
int toNativeValue() => _nativeValue;
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode => _value.hashCode;
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(value) => value == _value;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
switch (_value) {
|
|
||||||
case 0:
|
|
||||||
return 'NATIVE';
|
|
||||||
}
|
|
||||||
return _value.toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -56,7 +56,7 @@ class WebAuthenticationSession implements Disposable {
|
||||||
///A completion handler the session calls when it completes successfully, or when the user cancels the session.
|
///A completion handler the session calls when it completes successfully, or when the user cancels the session.
|
||||||
WebAuthenticationSessionCompletionHandler onComplete;
|
WebAuthenticationSessionCompletionHandler onComplete;
|
||||||
|
|
||||||
late MethodChannel _channel;
|
MethodChannel? _channel;
|
||||||
static const MethodChannel _sharedChannel = const MethodChannel(
|
static const MethodChannel _sharedChannel = const MethodChannel(
|
||||||
'com.pichillilorenzo/flutter_webauthenticationsession');
|
'com.pichillilorenzo/flutter_webauthenticationsession');
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ class WebAuthenticationSession implements Disposable {
|
||||||
initialSettings ?? WebAuthenticationSessionSettings();
|
initialSettings ?? WebAuthenticationSessionSettings();
|
||||||
this._channel = MethodChannel(
|
this._channel = MethodChannel(
|
||||||
'com.pichillilorenzo/flutter_webauthenticationsession_$id');
|
'com.pichillilorenzo/flutter_webauthenticationsession_$id');
|
||||||
this._channel.setMethodCallHandler((call) async {
|
this._channel?.setMethodCallHandler((call) async {
|
||||||
try {
|
try {
|
||||||
return await _handleMethod(call);
|
return await _handleMethod(call);
|
||||||
} on Error catch (e) {
|
} on Error catch (e) {
|
||||||
|
@ -147,10 +147,10 @@ class WebAuthenticationSession implements Disposable {
|
||||||
///- iOS ([Official API - ASWebAuthenticationSession.canStart](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession/3516277-canstart))
|
///- iOS ([Official API - ASWebAuthenticationSession.canStart](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession/3516277-canstart))
|
||||||
Future<bool> canStart() async {
|
Future<bool> canStart() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('canStart', args);
|
return await _channel?.invokeMethod('canStart', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Starts a web authentication session.
|
///Starts the web authentication session.
|
||||||
///
|
///
|
||||||
///Returns a boolean value indicating whether the web authentication session started successfully.
|
///Returns a boolean value indicating whether the web authentication session started successfully.
|
||||||
///
|
///
|
||||||
|
@ -161,10 +161,10 @@ class WebAuthenticationSession implements Disposable {
|
||||||
///- iOS ([Official API - ASWebAuthenticationSession.start](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession/2990953-start))
|
///- iOS ([Official API - ASWebAuthenticationSession.start](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession/2990953-start))
|
||||||
Future<bool> start() async {
|
Future<bool> start() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
return await _channel.invokeMethod('start', args);
|
return await _channel?.invokeMethod('start', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Cancels a web authentication session.
|
///Cancels the web authentication session.
|
||||||
///
|
///
|
||||||
///If the session has already presented a view with the authentication webpage, calling this method dismisses that view.
|
///If the session has already presented a view with the authentication webpage, calling this method dismisses that view.
|
||||||
///Calling [cancel] on an already canceled session has no effect.
|
///Calling [cancel] on an already canceled session has no effect.
|
||||||
|
@ -173,17 +173,19 @@ class WebAuthenticationSession implements Disposable {
|
||||||
///- iOS ([Official API - ASWebAuthenticationSession.cancel](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession/2990951-cancel))
|
///- iOS ([Official API - ASWebAuthenticationSession.cancel](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession/2990951-cancel))
|
||||||
Future<void> cancel() async {
|
Future<void> cancel() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod("cancel", args);
|
await _channel?.invokeMethod("cancel", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Disposes a web authentication session.
|
///Disposes the web authentication session.
|
||||||
///
|
///
|
||||||
///**Supported Platforms/Implementations**:
|
///**Supported Platforms/Implementations**:
|
||||||
///- iOS
|
///- iOS
|
||||||
@override
|
@override
|
||||||
Future<void> dispose() async {
|
Future<void> dispose() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod("dispose", args);
|
await _channel?.invokeMethod("dispose", args);
|
||||||
|
_channel?.setMethodCallHandler(null);
|
||||||
|
_channel = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
///Returns `true` if [ASWebAuthenticationSession](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession)
|
///Returns `true` if [ASWebAuthenticationSession](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession)
|
||||||
|
|
|
@ -18,13 +18,13 @@ class WebMessageChannel {
|
||||||
///The second [WebMessagePort] object of the channel.
|
///The second [WebMessagePort] object of the channel.
|
||||||
final WebMessagePort port2;
|
final WebMessagePort port2;
|
||||||
|
|
||||||
late MethodChannel _channel;
|
MethodChannel? _channel;
|
||||||
|
|
||||||
WebMessageChannel(
|
WebMessageChannel(
|
||||||
{required this.id, required this.port1, required this.port2}) {
|
{required this.id, required this.port1, required this.port2}) {
|
||||||
this._channel = MethodChannel(
|
this._channel = MethodChannel(
|
||||||
'com.pichillilorenzo/flutter_inappwebview_web_message_channel_$id');
|
'com.pichillilorenzo/flutter_inappwebview_web_message_channel_$id');
|
||||||
this._channel.setMethodCallHandler((call) async {
|
this._channel?.setMethodCallHandler((call) async {
|
||||||
try {
|
try {
|
||||||
return await _handleMethod(call);
|
return await _handleMethod(call);
|
||||||
} on Error catch (e) {
|
} on Error catch (e) {
|
||||||
|
@ -97,7 +97,7 @@ class WebMessagePort {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('index', () => this._index);
|
args.putIfAbsent('index', () => this._index);
|
||||||
await _webMessageChannel._channel
|
await _webMessageChannel._channel
|
||||||
.invokeMethod('setWebMessageCallback', args);
|
?.invokeMethod('setWebMessageCallback', args);
|
||||||
this._onMessage = onMessage;
|
this._onMessage = onMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,14 +106,14 @@ class WebMessagePort {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('index', () => this._index);
|
args.putIfAbsent('index', () => this._index);
|
||||||
args.putIfAbsent('message', () => message.toMap());
|
args.putIfAbsent('message', () => message.toMap());
|
||||||
await _webMessageChannel._channel.invokeMethod('postMessage', args);
|
await _webMessageChannel._channel?.invokeMethod('postMessage', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Close the message port and free any resources associated with it.
|
///Close the message port and free any resources associated with it.
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('index', () => this._index);
|
args.putIfAbsent('index', () => this._index);
|
||||||
await _webMessageChannel._channel.invokeMethod('close', args);
|
await _webMessageChannel._channel?.invokeMethod('close', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toMap() {
|
Map<String, dynamic> toMap() {
|
||||||
|
|
|
@ -34,7 +34,7 @@ class WebMessageListener {
|
||||||
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/WebViewCompat.WebMessageListener#onPostMessage(android.webkit.WebView,%20androidx.webkit.WebMessageCompat,%20android.net.Uri,%20boolean,%20androidx.webkit.JavaScriptReplyProxy)
|
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/WebViewCompat.WebMessageListener#onPostMessage(android.webkit.WebView,%20androidx.webkit.WebMessageCompat,%20android.net.Uri,%20boolean,%20androidx.webkit.JavaScriptReplyProxy)
|
||||||
OnPostMessageCallback? onPostMessage;
|
OnPostMessageCallback? onPostMessage;
|
||||||
|
|
||||||
late MethodChannel _channel;
|
MethodChannel? _channel;
|
||||||
|
|
||||||
WebMessageListener(
|
WebMessageListener(
|
||||||
{required this.jsObjectName,
|
{required this.jsObjectName,
|
||||||
|
@ -47,7 +47,7 @@ class WebMessageListener {
|
||||||
"allowedOriginRules cannot contain empty strings");
|
"allowedOriginRules cannot contain empty strings");
|
||||||
this._channel = MethodChannel(
|
this._channel = MethodChannel(
|
||||||
'com.pichillilorenzo/flutter_inappwebview_web_message_listener_${id}_$jsObjectName');
|
'com.pichillilorenzo/flutter_inappwebview_web_message_listener_${id}_$jsObjectName');
|
||||||
this._channel.setMethodCallHandler((call) async {
|
this._channel?.setMethodCallHandler((call) async {
|
||||||
try {
|
try {
|
||||||
return await _handleMethod(call);
|
return await _handleMethod(call);
|
||||||
} on Error catch (e) {
|
} on Error catch (e) {
|
||||||
|
@ -114,6 +114,6 @@ class JavaScriptReplyProxy {
|
||||||
Future<void> postMessage(String message) async {
|
Future<void> postMessage(String message) async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
args.putIfAbsent('message', () => message);
|
args.putIfAbsent('message', () => message);
|
||||||
await _webMessageListener._channel.invokeMethod('postMessage', args);
|
await _webMessageListener._channel?.invokeMethod('postMessage', args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,12 @@ class WebStorage {
|
||||||
SessionStorage sessionStorage;
|
SessionStorage sessionStorage;
|
||||||
|
|
||||||
WebStorage({required this.localStorage, required this.sessionStorage});
|
WebStorage({required this.localStorage, required this.sessionStorage});
|
||||||
|
|
||||||
|
///Disposes the web storage.
|
||||||
|
void dispose() {
|
||||||
|
localStorage.dispose();
|
||||||
|
sessionStorage.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///Class that represents a single web storage item of the JavaScript `window.sessionStorage` and `window.localStorage` objects.
|
///Class that represents a single web storage item of the JavaScript `window.sessionStorage` and `window.localStorage` objects.
|
||||||
|
@ -51,7 +57,7 @@ class WebStorageItem {
|
||||||
///Class that provides methods to manage the JavaScript [Storage](https://developer.mozilla.org/en-US/docs/Web/API/Storage) object.
|
///Class that provides methods to manage the JavaScript [Storage](https://developer.mozilla.org/en-US/docs/Web/API/Storage) object.
|
||||||
///It is used by [LocalStorage] and [SessionStorage].
|
///It is used by [LocalStorage] and [SessionStorage].
|
||||||
class Storage {
|
class Storage {
|
||||||
late InAppWebViewController _controller;
|
InAppWebViewController? _controller;
|
||||||
|
|
||||||
///The web storage type: `window.sessionStorage` or `window.localStorage`.
|
///The web storage type: `window.sessionStorage` or `window.localStorage`.
|
||||||
WebStorageType webStorageType;
|
WebStorageType webStorageType;
|
||||||
|
@ -69,7 +75,7 @@ class Storage {
|
||||||
///- iOS
|
///- iOS
|
||||||
///- Web
|
///- Web
|
||||||
Future<int?> length() async {
|
Future<int?> length() async {
|
||||||
var result = await _controller.evaluateJavascript(source: """
|
var result = await _controller?.evaluateJavascript(source: """
|
||||||
window.$webStorageType.length;
|
window.$webStorageType.length;
|
||||||
""");
|
""");
|
||||||
return result != null ? int.parse(json.decode(result)) : null;
|
return result != null ? int.parse(json.decode(result)) : null;
|
||||||
|
@ -85,7 +91,7 @@ class Storage {
|
||||||
///- Web
|
///- Web
|
||||||
Future<void> setItem({required String key, required dynamic value}) async {
|
Future<void> setItem({required String key, required dynamic value}) async {
|
||||||
var encodedValue = json.encode(value);
|
var encodedValue = json.encode(value);
|
||||||
await _controller.evaluateJavascript(source: """
|
await _controller?.evaluateJavascript(source: """
|
||||||
window.$webStorageType.setItem("$key", ${value is String ? encodedValue : "JSON.stringify($encodedValue)"});
|
window.$webStorageType.setItem("$key", ${value is String ? encodedValue : "JSON.stringify($encodedValue)"});
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
|
@ -99,7 +105,7 @@ class Storage {
|
||||||
///- iOS
|
///- iOS
|
||||||
///- Web
|
///- Web
|
||||||
Future<dynamic> getItem({required String key}) async {
|
Future<dynamic> getItem({required String key}) async {
|
||||||
var itemValue = await _controller.evaluateJavascript(source: """
|
var itemValue = await _controller?.evaluateJavascript(source: """
|
||||||
window.$webStorageType.getItem("$key");
|
window.$webStorageType.getItem("$key");
|
||||||
""");
|
""");
|
||||||
|
|
||||||
|
@ -123,7 +129,7 @@ class Storage {
|
||||||
///- iOS
|
///- iOS
|
||||||
///- Web
|
///- Web
|
||||||
Future<void> removeItem({required String key}) async {
|
Future<void> removeItem({required String key}) async {
|
||||||
await _controller.evaluateJavascript(source: """
|
await _controller?.evaluateJavascript(source: """
|
||||||
window.$webStorageType.removeItem("$key");
|
window.$webStorageType.removeItem("$key");
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
|
@ -140,7 +146,7 @@ class Storage {
|
||||||
var webStorageItems = <WebStorageItem>[];
|
var webStorageItems = <WebStorageItem>[];
|
||||||
|
|
||||||
List<Map<dynamic, dynamic>>? items =
|
List<Map<dynamic, dynamic>>? items =
|
||||||
(await _controller.evaluateJavascript(source: """
|
(await _controller?.evaluateJavascript(source: """
|
||||||
(function() {
|
(function() {
|
||||||
var webStorageItems = [];
|
var webStorageItems = [];
|
||||||
for(var i = 0; i < window.$webStorageType.length; i++){
|
for(var i = 0; i < window.$webStorageType.length; i++){
|
||||||
|
@ -177,7 +183,7 @@ class Storage {
|
||||||
///- iOS
|
///- iOS
|
||||||
///- Web
|
///- Web
|
||||||
Future<void> clear() async {
|
Future<void> clear() async {
|
||||||
await _controller.evaluateJavascript(source: """
|
await _controller?.evaluateJavascript(source: """
|
||||||
window.$webStorageType.clear();
|
window.$webStorageType.clear();
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
|
@ -192,11 +198,16 @@ class Storage {
|
||||||
///- iOS
|
///- iOS
|
||||||
///- Web
|
///- Web
|
||||||
Future<String> key({required int index}) async {
|
Future<String> key({required int index}) async {
|
||||||
var result = await _controller.evaluateJavascript(source: """
|
var result = await _controller?.evaluateJavascript(source: """
|
||||||
window.$webStorageType.key($index);
|
window.$webStorageType.key($index);
|
||||||
""");
|
""");
|
||||||
return result != null ? json.decode(result) : null;
|
return result != null ? json.decode(result) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///Disposes the storage.
|
||||||
|
void dispose() {
|
||||||
|
_controller = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///Class that provides methods to manage the JavaScript `window.localStorage` object.
|
///Class that provides methods to manage the JavaScript `window.localStorage` object.
|
||||||
|
|
|
@ -11,6 +11,7 @@ import FlutterMacOS
|
||||||
public class FindInteractionController : NSObject, Disposable {
|
public class FindInteractionController : NSObject, Disposable {
|
||||||
|
|
||||||
static var METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_find_interaction_";
|
static var METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_find_interaction_";
|
||||||
|
var plugin: InAppWebViewFlutterPlugin?
|
||||||
var webView: InAppWebView?
|
var webView: InAppWebView?
|
||||||
var channelDelegate: FindInteractionChannelDelegate?
|
var channelDelegate: FindInteractionChannelDelegate?
|
||||||
var settings: FindInteractionSettings?
|
var settings: FindInteractionSettings?
|
||||||
|
@ -18,14 +19,17 @@ public class FindInteractionController : NSObject, Disposable {
|
||||||
var searchText: String?
|
var searchText: String?
|
||||||
var activeFindSession: FindSession?
|
var activeFindSession: FindSession?
|
||||||
|
|
||||||
public init(registrar: FlutterPluginRegistrar, id: Any, webView: InAppWebView, settings: FindInteractionSettings?) {
|
public init(plugin: InAppWebViewFlutterPlugin, id: Any, webView: InAppWebView, settings: FindInteractionSettings?) {
|
||||||
super.init()
|
super.init()
|
||||||
|
self.plugin = plugin
|
||||||
self.webView = webView
|
self.webView = webView
|
||||||
self.settings = settings
|
self.settings = settings
|
||||||
|
if let registrar = plugin.registrar {
|
||||||
let channel = FlutterMethodChannel(name: FindInteractionController.METHOD_CHANNEL_NAME_PREFIX + String(describing: id),
|
let channel = FlutterMethodChannel(name: FindInteractionController.METHOD_CHANNEL_NAME_PREFIX + String(describing: id),
|
||||||
binaryMessenger: registrar.messenger)
|
binaryMessenger: registrar.messenger)
|
||||||
self.channelDelegate = FindInteractionChannelDelegate(findInteractionController: self, channel: channel)
|
self.channelDelegate = FindInteractionChannelDelegate(findInteractionController: self, channel: channel)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func prepare() {
|
public func prepare() {
|
||||||
// if let settings = settings {
|
// if let settings = settings {
|
||||||
|
@ -87,6 +91,7 @@ public class FindInteractionController : NSObject, Disposable {
|
||||||
channelDelegate = nil
|
channelDelegate = nil
|
||||||
webView = nil
|
webView = nil
|
||||||
activeFindSession = nil
|
activeFindSession = nil
|
||||||
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
|
|
@ -81,7 +81,7 @@ public class HeadlessInAppWebView : Disposable {
|
||||||
public func dispose() {
|
public func dispose() {
|
||||||
channelDelegate?.dispose()
|
channelDelegate?.dispose()
|
||||||
channelDelegate = nil
|
channelDelegate = nil
|
||||||
HeadlessInAppWebViewManager.webViews[id] = nil
|
plugin?.headlessInAppWebViewManager?.webViews[id] = nil
|
||||||
if let view = flutterWebView?.view() {
|
if let view = flutterWebView?.view() {
|
||||||
view.superview?.removeFromSuperview()
|
view.superview?.removeFromSuperview()
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ import AVFoundation
|
||||||
public class HeadlessInAppWebViewManager: ChannelDelegate {
|
public class HeadlessInAppWebViewManager: ChannelDelegate {
|
||||||
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_headless_inappwebview"
|
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_headless_inappwebview"
|
||||||
var plugin: InAppWebViewFlutterPlugin?
|
var plugin: InAppWebViewFlutterPlugin?
|
||||||
static var webViews: [String: HeadlessInAppWebView?] = [:]
|
var webViews: [String: HeadlessInAppWebView?] = [:]
|
||||||
|
|
||||||
init(plugin: InAppWebViewFlutterPlugin) {
|
init(plugin: InAppWebViewFlutterPlugin) {
|
||||||
super.init(channel: FlutterMethodChannel(name: HeadlessInAppWebViewManager.METHOD_CHANNEL_NAME, binaryMessenger: plugin.registrar!.messenger))
|
super.init(channel: FlutterMethodChannel(name: HeadlessInAppWebViewManager.METHOD_CHANNEL_NAME, binaryMessenger: plugin.registrar!.messenger))
|
||||||
|
@ -40,15 +40,15 @@ public class HeadlessInAppWebViewManager: ChannelDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
public func run(id: String, params: [String: Any?]) {
|
public func run(id: String, params: [String: Any?]) {
|
||||||
guard let plugin = plugin, let registrar = plugin.registrar else {
|
guard let plugin = plugin else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let flutterWebView = FlutterWebViewController(registrar: registrar,
|
let flutterWebView = FlutterWebViewController(plugin: plugin,
|
||||||
withFrame: CGRect.zero,
|
withFrame: CGRect.zero,
|
||||||
viewIdentifier: id,
|
viewIdentifier: id,
|
||||||
params: params as NSDictionary)
|
params: params as NSDictionary)
|
||||||
let headlessInAppWebView = HeadlessInAppWebView(plugin: plugin, id: id, flutterWebView: flutterWebView)
|
let headlessInAppWebView = HeadlessInAppWebView(plugin: plugin, id: id, flutterWebView: flutterWebView)
|
||||||
HeadlessInAppWebViewManager.webViews[id] = headlessInAppWebView
|
webViews[id] = headlessInAppWebView
|
||||||
|
|
||||||
headlessInAppWebView.prepare(params: params as NSDictionary)
|
headlessInAppWebView.prepare(params: params as NSDictionary)
|
||||||
headlessInAppWebView.onWebViewCreated()
|
headlessInAppWebView.onWebViewCreated()
|
||||||
|
@ -57,11 +57,11 @@ public class HeadlessInAppWebViewManager: ChannelDelegate {
|
||||||
|
|
||||||
public override func dispose() {
|
public override func dispose() {
|
||||||
super.dispose()
|
super.dispose()
|
||||||
let headlessWebViews = HeadlessInAppWebViewManager.webViews.values
|
let headlessWebViews = webViews.values
|
||||||
headlessWebViews.forEach { (headlessWebView: HeadlessInAppWebView?) in
|
headlessWebViews.forEach { (headlessWebView: HeadlessInAppWebView?) in
|
||||||
headlessWebView?.dispose()
|
headlessWebView?.dispose()
|
||||||
}
|
}
|
||||||
HeadlessInAppWebViewManager.webViews.removeAll()
|
webViews.removeAll()
|
||||||
plugin = nil
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ public class InAppBrowserWebViewController: NSViewController, InAppBrowserDelega
|
||||||
var isHidden = false
|
var isHidden = false
|
||||||
|
|
||||||
public override func loadView() {
|
public override func loadView() {
|
||||||
guard let registrar = plugin?.registrar else {
|
guard let plugin = plugin, let registrar = plugin.registrar else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,12 +46,12 @@ public class InAppBrowserWebViewController: NSViewController, InAppBrowserDelega
|
||||||
}
|
}
|
||||||
|
|
||||||
let preWebviewConfiguration = InAppWebView.preWKWebViewConfiguration(settings: webViewSettings)
|
let preWebviewConfiguration = InAppWebView.preWKWebViewConfiguration(settings: webViewSettings)
|
||||||
if let wId = windowId, let webViewTransport = InAppWebView.windowWebViews[wId] {
|
if let wId = windowId, let webViewTransport = plugin.inAppWebViewManager?.windowWebViews[wId] {
|
||||||
webView = webViewTransport.webView
|
webView = webViewTransport.webView
|
||||||
webView!.initialUserScripts = userScripts
|
webView!.initialUserScripts = userScripts
|
||||||
} else {
|
} else {
|
||||||
webView = InAppWebView(id: nil,
|
webView = InAppWebView(id: nil,
|
||||||
registrar: nil,
|
plugin: nil,
|
||||||
frame: .zero,
|
frame: .zero,
|
||||||
configuration: preWebviewConfiguration,
|
configuration: preWebviewConfiguration,
|
||||||
userScripts: userScripts)
|
userScripts: userScripts)
|
||||||
|
@ -63,10 +63,11 @@ public class InAppBrowserWebViewController: NSViewController, InAppBrowserDelega
|
||||||
|
|
||||||
webView.inAppBrowserDelegate = self
|
webView.inAppBrowserDelegate = self
|
||||||
webView.id = id
|
webView.id = id
|
||||||
|
webView.plugin = plugin
|
||||||
webView.channelDelegate = WebViewChannelDelegate(webView: webView, channel: channel)
|
webView.channelDelegate = WebViewChannelDelegate(webView: webView, channel: channel)
|
||||||
|
|
||||||
let findInteractionController = FindInteractionController(
|
let findInteractionController = FindInteractionController(
|
||||||
registrar: registrar,
|
plugin: plugin,
|
||||||
id: id, webView: webView, settings: nil)
|
id: id, webView: webView, settings: nil)
|
||||||
webView.findInteractionController = findInteractionController
|
webView.findInteractionController = findInteractionController
|
||||||
findInteractionController.prepare()
|
findInteractionController.prepare()
|
||||||
|
@ -99,7 +100,7 @@ public class InAppBrowserWebViewController: NSViewController, InAppBrowserDelega
|
||||||
progressBar.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 0.0).isActive = true
|
progressBar.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 0.0).isActive = true
|
||||||
progressBar.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 0.0).isActive = true
|
progressBar.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 0.0).isActive = true
|
||||||
|
|
||||||
if let wId = windowId, let webViewTransport = InAppWebView.windowWebViews[wId] {
|
if let wId = windowId, let webViewTransport = plugin?.inAppWebViewManager?.windowWebViews[wId] {
|
||||||
webView?.load(webViewTransport.request)
|
webView?.load(webViewTransport.request)
|
||||||
channelDelegate?.onBrowserCreated()
|
channelDelegate?.onBrowserCreated()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -12,12 +12,15 @@ import FlutterMacOS
|
||||||
public class FlutterWebViewController: NSObject, /*FlutterPlatformView,*/ Disposable {
|
public class FlutterWebViewController: NSObject, /*FlutterPlatformView,*/ Disposable {
|
||||||
|
|
||||||
var myView: NSView?
|
var myView: NSView?
|
||||||
|
var keepAliveId: String?
|
||||||
|
|
||||||
init(registrar: FlutterPluginRegistrar, withFrame frame: CGRect, viewIdentifier viewId: Any, params: NSDictionary) {
|
init(plugin: InAppWebViewFlutterPlugin, withFrame frame: CGRect, viewIdentifier viewId: Any, params: NSDictionary) {
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
myView = NSView(frame: frame)
|
myView = NSView(frame: frame)
|
||||||
|
|
||||||
|
keepAliveId = params["keepAliveId"] as? String
|
||||||
|
|
||||||
let initialSettings = params["initialSettings"] as! [String: Any?]
|
let initialSettings = params["initialSettings"] as! [String: Any?]
|
||||||
let windowId = params["windowId"] as? Int64
|
let windowId = params["windowId"] as? Int64
|
||||||
let initialUserScripts = params["initialUserScripts"] as? [[String: Any]]
|
let initialUserScripts = params["initialUserScripts"] as? [[String: Any]]
|
||||||
|
@ -35,24 +38,27 @@ public class FlutterWebViewController: NSObject, /*FlutterPlatformView,*/ Dispos
|
||||||
|
|
||||||
var webView: InAppWebView?
|
var webView: InAppWebView?
|
||||||
|
|
||||||
if let wId = windowId, let webViewTransport = InAppWebView.windowWebViews[wId] {
|
if let wId = windowId, let webViewTransport = plugin.inAppWebViewManager?.windowWebViews[wId] {
|
||||||
webView = webViewTransport.webView
|
webView = webViewTransport.webView
|
||||||
webView!.id = viewId
|
webView!.id = viewId
|
||||||
|
webView!.plugin = plugin
|
||||||
|
if let registrar = plugin.registrar {
|
||||||
let channel = FlutterMethodChannel(name: InAppWebView.METHOD_CHANNEL_NAME_PREFIX + String(describing: viewId),
|
let channel = FlutterMethodChannel(name: InAppWebView.METHOD_CHANNEL_NAME_PREFIX + String(describing: viewId),
|
||||||
binaryMessenger: registrar.messenger)
|
binaryMessenger: registrar.messenger)
|
||||||
webView!.channelDelegate = WebViewChannelDelegate(webView: webView!, channel: channel)
|
webView!.channelDelegate = WebViewChannelDelegate(webView: webView!, channel: channel)
|
||||||
|
}
|
||||||
webView!.frame = myView!.bounds
|
webView!.frame = myView!.bounds
|
||||||
webView!.initialUserScripts = userScripts
|
webView!.initialUserScripts = userScripts
|
||||||
} else {
|
} else {
|
||||||
webView = InAppWebView(id: viewId,
|
webView = InAppWebView(id: viewId,
|
||||||
registrar: registrar,
|
plugin: plugin,
|
||||||
frame: myView!.bounds,
|
frame: myView!.bounds,
|
||||||
configuration: preWebviewConfiguration,
|
configuration: preWebviewConfiguration,
|
||||||
userScripts: userScripts)
|
userScripts: userScripts)
|
||||||
}
|
}
|
||||||
|
|
||||||
let findInteractionController = FindInteractionController(
|
let findInteractionController = FindInteractionController(
|
||||||
registrar: registrar,
|
plugin: plugin,
|
||||||
id: viewId, webView: webView!, settings: nil)
|
id: viewId, webView: webView!, settings: nil)
|
||||||
webView!.findInteractionController = findInteractionController
|
webView!.findInteractionController = findInteractionController
|
||||||
findInteractionController.prepare()
|
findInteractionController.prepare()
|
||||||
|
@ -121,7 +127,7 @@ public class FlutterWebViewController: NSObject, /*FlutterPlatformView,*/ Dispos
|
||||||
}
|
}
|
||||||
load(initialUrlRequest: initialUrlRequest, initialFile: initialFile, initialData: initialData)
|
load(initialUrlRequest: initialUrlRequest, initialFile: initialFile, initialData: initialData)
|
||||||
}
|
}
|
||||||
else if let wId = windowId, let webViewTransport = InAppWebView.windowWebViews[wId] {
|
else if let wId = windowId, let webViewTransport = webView.plugin?.inAppWebViewManager?.windowWebViews[wId] {
|
||||||
webView.load(webViewTransport.request)
|
webView.load(webViewTransport.request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,11 +175,13 @@ public class FlutterWebViewController: NSObject, /*FlutterPlatformView,*/ Dispos
|
||||||
}
|
}
|
||||||
|
|
||||||
public func dispose() {
|
public func dispose() {
|
||||||
|
if keepAliveId == nil {
|
||||||
if let webView = webView() {
|
if let webView = webView() {
|
||||||
webView.dispose()
|
webView.dispose()
|
||||||
}
|
}
|
||||||
myView = nil
|
myView = nil
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
debugPrint("FlutterWebViewController - dealloc")
|
debugPrint("FlutterWebViewController - dealloc")
|
||||||
|
|
|
@ -12,11 +12,11 @@ import Foundation
|
||||||
|
|
||||||
public class FlutterWebViewFactory: NSObject, FlutterPlatformViewFactory {
|
public class FlutterWebViewFactory: NSObject, FlutterPlatformViewFactory {
|
||||||
static let VIEW_TYPE_ID = "com.pichillilorenzo/flutter_inappwebview"
|
static let VIEW_TYPE_ID = "com.pichillilorenzo/flutter_inappwebview"
|
||||||
private var registrar: FlutterPluginRegistrar?
|
private var plugin: InAppWebViewFlutterPlugin
|
||||||
|
|
||||||
init(registrar: FlutterPluginRegistrar?) {
|
init(plugin: InAppWebViewFlutterPlugin) {
|
||||||
|
self.plugin = plugin
|
||||||
super.init()
|
super.init()
|
||||||
self.registrar = registrar
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func createArgsCodec() -> (FlutterMessageCodec & NSObjectProtocol)? {
|
public func createArgsCodec() -> (FlutterMessageCodec & NSObjectProtocol)? {
|
||||||
|
@ -25,18 +25,48 @@ public class FlutterWebViewFactory: NSObject, FlutterPlatformViewFactory {
|
||||||
|
|
||||||
public func create(withViewIdentifier viewId: Int64, arguments args: Any?) -> NSView {
|
public func create(withViewIdentifier viewId: Int64, arguments args: Any?) -> NSView {
|
||||||
let arguments = args as? NSDictionary
|
let arguments = args as? NSDictionary
|
||||||
|
var flutterWebView: FlutterWebViewController?
|
||||||
|
var id: Any = viewId
|
||||||
|
|
||||||
if let headlessWebViewId = arguments?["headlessWebViewId"] as? String,
|
let keepAliveId = arguments?["keepAliveId"] as? String
|
||||||
let headlessWebView = HeadlessInAppWebViewManager.webViews[headlessWebViewId],
|
let headlessWebViewId = arguments?["headlessWebViewId"] as? String
|
||||||
|
|
||||||
|
if let headlessWebViewId = headlessWebViewId,
|
||||||
|
let headlessWebView = plugin.headlessInAppWebViewManager?.webViews[headlessWebViewId],
|
||||||
let platformView = headlessWebView?.disposeAndGetFlutterWebView(withFrame: .zero) {
|
let platformView = headlessWebView?.disposeAndGetFlutterWebView(withFrame: .zero) {
|
||||||
return platformView.view()
|
flutterWebView = platformView
|
||||||
|
flutterWebView?.keepAliveId = keepAliveId
|
||||||
}
|
}
|
||||||
|
|
||||||
let webviewController = FlutterWebViewController(registrar: registrar!,
|
if let keepAliveId = keepAliveId,
|
||||||
|
flutterWebView == nil,
|
||||||
|
let keepAliveWebView = plugin.inAppWebViewManager?.keepAliveWebViews[keepAliveId] {
|
||||||
|
flutterWebView = keepAliveWebView
|
||||||
|
if let view = flutterWebView?.view() {
|
||||||
|
// remove from parent
|
||||||
|
view.removeFromSuperview()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let shouldMakeInitialLoad = flutterWebView == nil
|
||||||
|
if flutterWebView == nil {
|
||||||
|
if let keepAliveId = keepAliveId {
|
||||||
|
id = keepAliveId
|
||||||
|
}
|
||||||
|
flutterWebView = FlutterWebViewController(plugin: plugin,
|
||||||
withFrame: .zero,
|
withFrame: .zero,
|
||||||
viewIdentifier: viewId,
|
viewIdentifier: id,
|
||||||
params: arguments!)
|
params: arguments!)
|
||||||
webviewController.makeInitialLoad(params: arguments!)
|
}
|
||||||
return webviewController.view()
|
|
||||||
|
if let keepAliveId = keepAliveId {
|
||||||
|
plugin.inAppWebViewManager?.keepAliveWebViews[keepAliveId] = flutterWebView!
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldMakeInitialLoad {
|
||||||
|
flutterWebView?.makeInitialLoad(params: arguments!)
|
||||||
|
}
|
||||||
|
|
||||||
|
return flutterWebView!.view()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ public class InAppWebView: WKWebView, WKUIDelegate,
|
||||||
static var METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_"
|
static var METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_"
|
||||||
|
|
||||||
var id: Any? // viewId
|
var id: Any? // viewId
|
||||||
var registrar: FlutterPluginRegistrar?
|
var plugin: InAppWebViewFlutterPlugin?
|
||||||
var windowId: Int64?
|
var windowId: Int64?
|
||||||
var windowCreated = false
|
var windowCreated = false
|
||||||
var inAppBrowserDelegate: InAppBrowserDelegate?
|
var inAppBrowserDelegate: InAppBrowserDelegate?
|
||||||
|
@ -43,19 +43,16 @@ public class InAppWebView: WKWebView, WKUIDelegate,
|
||||||
|
|
||||||
var customIMPs: [IMP] = []
|
var customIMPs: [IMP] = []
|
||||||
|
|
||||||
static var windowWebViews: [Int64:WebViewTransport] = [:]
|
|
||||||
static var windowAutoincrementId: Int64 = 0;
|
|
||||||
|
|
||||||
var callAsyncJavaScriptBelowIOS14Results: [String:((Any?) -> Void)] = [:]
|
var callAsyncJavaScriptBelowIOS14Results: [String:((Any?) -> Void)] = [:]
|
||||||
|
|
||||||
var currentOpenPanel: NSOpenPanel?
|
var currentOpenPanel: NSOpenPanel?
|
||||||
|
|
||||||
init(id: Any?, registrar: FlutterPluginRegistrar?, frame: CGRect, configuration: WKWebViewConfiguration,
|
init(id: Any?, plugin: InAppWebViewFlutterPlugin?, frame: CGRect, configuration: WKWebViewConfiguration,
|
||||||
userScripts: [UserScript] = []) {
|
userScripts: [UserScript] = []) {
|
||||||
super.init(frame: frame, configuration: configuration)
|
super.init(frame: frame, configuration: configuration)
|
||||||
self.id = id
|
self.id = id
|
||||||
self.registrar = registrar
|
self.plugin = plugin
|
||||||
if let id = id, let registrar = registrar {
|
if let id = id, let registrar = plugin?.registrar {
|
||||||
let channel = FlutterMethodChannel(name: InAppWebView.METHOD_CHANNEL_NAME_PREFIX + String(describing: id),
|
let channel = FlutterMethodChannel(name: InAppWebView.METHOD_CHANNEL_NAME_PREFIX + String(describing: id),
|
||||||
binaryMessenger: registrar.messenger)
|
binaryMessenger: registrar.messenger)
|
||||||
self.channelDelegate = WebViewChannelDelegate(webView: self, channel: channel)
|
self.channelDelegate = WebViewChannelDelegate(webView: self, channel: channel)
|
||||||
|
@ -1788,10 +1785,14 @@ public class InAppWebView: WKWebView, WKUIDelegate,
|
||||||
createWebViewWith configuration: WKWebViewConfiguration,
|
createWebViewWith configuration: WKWebViewConfiguration,
|
||||||
for navigationAction: WKNavigationAction,
|
for navigationAction: WKNavigationAction,
|
||||||
windowFeatures: WKWindowFeatures) -> WKWebView? {
|
windowFeatures: WKWindowFeatures) -> WKWebView? {
|
||||||
InAppWebView.windowAutoincrementId += 1
|
var windowId: Int64 = 0
|
||||||
let windowId = InAppWebView.windowAutoincrementId
|
let inAppWebViewManager = plugin?.inAppWebViewManager
|
||||||
|
if let inAppWebViewManager = inAppWebViewManager {
|
||||||
|
inAppWebViewManager.windowAutoincrementId += 1
|
||||||
|
windowId = inAppWebViewManager.windowAutoincrementId
|
||||||
|
}
|
||||||
|
|
||||||
let windowWebView = InAppWebView(id: nil, registrar: nil, frame: CGRect.zero, configuration: configuration)
|
let windowWebView = InAppWebView(id: nil, plugin: nil, frame: CGRect.zero, configuration: configuration)
|
||||||
windowWebView.windowId = windowId
|
windowWebView.windowId = windowId
|
||||||
|
|
||||||
let webViewTransport = WebViewTransport(
|
let webViewTransport = WebViewTransport(
|
||||||
|
@ -1799,7 +1800,7 @@ public class InAppWebView: WKWebView, WKUIDelegate,
|
||||||
request: navigationAction.request
|
request: navigationAction.request
|
||||||
)
|
)
|
||||||
|
|
||||||
InAppWebView.windowWebViews[windowId] = webViewTransport
|
inAppWebViewManager?.windowWebViews[windowId] = webViewTransport
|
||||||
windowWebView.stopLoading()
|
windowWebView.stopLoading()
|
||||||
|
|
||||||
let createWindowAction = CreateWindowAction(navigationAction: navigationAction, windowId: windowId, windowFeatures: windowFeatures, isDialog: nil)
|
let createWindowAction = CreateWindowAction(navigationAction: navigationAction, windowId: windowId, windowFeatures: windowFeatures, isDialog: nil)
|
||||||
|
@ -1809,8 +1810,8 @@ public class InAppWebView: WKWebView, WKUIDelegate,
|
||||||
return !handledByClient
|
return !handledByClient
|
||||||
}
|
}
|
||||||
callback.defaultBehaviour = { (handledByClient: Bool?) in
|
callback.defaultBehaviour = { (handledByClient: Bool?) in
|
||||||
if InAppWebView.windowWebViews[windowId] != nil {
|
if inAppWebViewManager?.windowWebViews[windowId] != nil {
|
||||||
InAppWebView.windowWebViews.removeValue(forKey: windowId)
|
inAppWebViewManager?.windowWebViews.removeValue(forKey: windowId)
|
||||||
}
|
}
|
||||||
self.loadUrl(urlRequest: navigationAction.request, allowingReadAccessTo: nil)
|
self.loadUrl(urlRequest: navigationAction.request, allowingReadAccessTo: nil)
|
||||||
}
|
}
|
||||||
|
@ -2066,7 +2067,7 @@ public class InAppWebView: WKWebView, WKUIDelegate,
|
||||||
|
|
||||||
let _windowId = body["_windowId"] as? Int64
|
let _windowId = body["_windowId"] as? Int64
|
||||||
var webView = self
|
var webView = self
|
||||||
if let wId = _windowId, let webViewTransport = InAppWebView.windowWebViews[wId] {
|
if let wId = _windowId, let webViewTransport = plugin?.inAppWebViewManager?.windowWebViews[wId] {
|
||||||
webView = webViewTransport.webView
|
webView = webViewTransport.webView
|
||||||
}
|
}
|
||||||
webView.channelDelegate?.onConsoleMessage(message: consoleMessage, messageLevel: messageLevel)
|
webView.channelDelegate?.onConsoleMessage(message: consoleMessage, messageLevel: messageLevel)
|
||||||
|
@ -2083,7 +2084,7 @@ public class InAppWebView: WKWebView, WKUIDelegate,
|
||||||
return !handledByClient
|
return !handledByClient
|
||||||
}
|
}
|
||||||
callback.defaultBehaviour = { (handledByClient: Bool?) in
|
callback.defaultBehaviour = { (handledByClient: Bool?) in
|
||||||
if let printJob = PrintJobManager.jobs[printJobId] {
|
if let printJob = self.plugin?.printJobManager?.jobs[printJobId] {
|
||||||
printJob?.disposeNoDismiss()
|
printJob?.disposeNoDismiss()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2101,7 +2102,7 @@ public class InAppWebView: WKWebView, WKUIDelegate,
|
||||||
|
|
||||||
let _windowId = body["_windowId"] as? Int64
|
let _windowId = body["_windowId"] as? Int64
|
||||||
var webView = self
|
var webView = self
|
||||||
if let wId = _windowId, let webViewTransport = InAppWebView.windowWebViews[wId] {
|
if let wId = _windowId, let webViewTransport = plugin?.inAppWebViewManager?.windowWebViews[wId] {
|
||||||
webView = webViewTransport.webView
|
webView = webViewTransport.webView
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2143,7 +2144,7 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
|
||||||
|
|
||||||
let _windowId = body["_windowId"] as? Int64
|
let _windowId = body["_windowId"] as? Int64
|
||||||
var webView = self
|
var webView = self
|
||||||
if let wId = _windowId, let webViewTransport = InAppWebView.windowWebViews[wId] {
|
if let wId = _windowId, let webViewTransport = plugin?.inAppWebViewManager?.windowWebViews[wId] {
|
||||||
webView = webViewTransport.webView
|
webView = webViewTransport.webView
|
||||||
}
|
}
|
||||||
webView.findInteractionController?.channelDelegate?.onFindResultReceived(activeMatchOrdinal: activeMatchOrdinal, numberOfMatches: numberOfMatches, isDoneCounting: isDoneCounting)
|
webView.findInteractionController?.channelDelegate?.onFindResultReceived(activeMatchOrdinal: activeMatchOrdinal, numberOfMatches: numberOfMatches, isDoneCounting: isDoneCounting)
|
||||||
|
@ -2155,7 +2156,7 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
|
||||||
|
|
||||||
let _windowId = body["_windowId"] as? Int64
|
let _windowId = body["_windowId"] as? Int64
|
||||||
var webView = self
|
var webView = self
|
||||||
if let wId = _windowId, let webViewTransport = InAppWebView.windowWebViews[wId] {
|
if let wId = _windowId, let webViewTransport = plugin?.inAppWebViewManager?.windowWebViews[wId] {
|
||||||
webView = webViewTransport.webView
|
webView = webViewTransport.webView
|
||||||
}
|
}
|
||||||
webView.channelDelegate?.onScrollChanged(x: x, y: y)
|
webView.channelDelegate?.onScrollChanged(x: x, y: y)
|
||||||
|
@ -2358,9 +2359,9 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let id = printJobId, let registrar = registrar {
|
if let id = printJobId, let plugin = plugin {
|
||||||
let printJob = PrintJobController(registrar: registrar, id: id, job: printOperation, settings: settings)
|
let printJob = PrintJobController(plugin: plugin, id: id, job: printOperation, settings: settings)
|
||||||
PrintJobManager.jobs[id] = printJob
|
plugin.printJobManager?.jobs[id] = printJob
|
||||||
printJob.present(parentWindow: window, completionHandler: completionHandler)
|
printJob.present(parentWindow: window, completionHandler: completionHandler)
|
||||||
} else if let window = window {
|
} else if let window = window {
|
||||||
printJobCompletionHandler = completionHandler
|
printJobCompletionHandler = completionHandler
|
||||||
|
@ -2458,12 +2459,12 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public func createWebMessageChannel(completionHandler: ((WebMessageChannel?) -> Void)? = nil) -> WebMessageChannel? {
|
public func createWebMessageChannel(completionHandler: ((WebMessageChannel?) -> Void)? = nil) -> WebMessageChannel? {
|
||||||
guard let registrar = registrar else {
|
guard let plugin = plugin else {
|
||||||
completionHandler?(nil)
|
completionHandler?(nil)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
let id = NSUUID().uuidString
|
let id = NSUUID().uuidString
|
||||||
let webMessageChannel = WebMessageChannel(registrar: registrar, id: id)
|
let webMessageChannel = WebMessageChannel(plugin: plugin, id: id)
|
||||||
webMessageChannel.initJsInstance(webView: self, completionHandler: completionHandler)
|
webMessageChannel.initJsInstance(webView: self, completionHandler: completionHandler)
|
||||||
webMessageChannels[id] = webMessageChannel
|
webMessageChannels[id] = webMessageChannel
|
||||||
|
|
||||||
|
@ -2567,8 +2568,8 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
|
||||||
if #available(macOS 10.13, *) {
|
if #available(macOS 10.13, *) {
|
||||||
configuration.userContentController.removeAllContentRuleLists()
|
configuration.userContentController.removeAllContentRuleLists()
|
||||||
}
|
}
|
||||||
} else if let wId = windowId, InAppWebView.windowWebViews[wId] != nil {
|
} else if let wId = windowId, plugin?.inAppWebViewManager?.windowWebViews[wId] != nil {
|
||||||
InAppWebView.windowWebViews.removeValue(forKey: wId)
|
plugin?.inAppWebViewManager?.windowWebViews.removeValue(forKey: wId)
|
||||||
}
|
}
|
||||||
configuration.userContentController.dispose(windowId: windowId)
|
configuration.userContentController.dispose(windowId: windowId)
|
||||||
NotificationCenter.default.removeObserver(self)
|
NotificationCenter.default.removeObserver(self)
|
||||||
|
@ -2582,7 +2583,7 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
|
||||||
isPausedTimersCompletionHandler = nil
|
isPausedTimersCompletionHandler = nil
|
||||||
callAsyncJavaScriptBelowIOS14Results.removeAll()
|
callAsyncJavaScriptBelowIOS14Results.removeAll()
|
||||||
super.removeFromSuperview()
|
super.removeFromSuperview()
|
||||||
registrar = nil
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
// InAppWebViewStatic.swift
|
// InAppWebViewManager.swift
|
||||||
// flutter_inappwebview
|
// flutter_inappwebview
|
||||||
//
|
//
|
||||||
// Created by Lorenzo Pichilli on 08/12/2019.
|
// Created by Lorenzo Pichilli on 08/12/2019.
|
||||||
|
@ -9,14 +9,18 @@ import Foundation
|
||||||
import WebKit
|
import WebKit
|
||||||
import FlutterMacOS
|
import FlutterMacOS
|
||||||
|
|
||||||
public class InAppWebViewStatic: ChannelDelegate {
|
public class InAppWebViewManager: ChannelDelegate {
|
||||||
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappwebview_static"
|
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappwebview_manager"
|
||||||
var plugin: InAppWebViewFlutterPlugin?
|
var plugin: InAppWebViewFlutterPlugin?
|
||||||
var webViewForUserAgent: WKWebView?
|
var webViewForUserAgent: WKWebView?
|
||||||
var defaultUserAgent: String?
|
var defaultUserAgent: String?
|
||||||
|
|
||||||
|
var keepAliveWebViews: [String:FlutterWebViewController?] = [:]
|
||||||
|
var windowWebViews: [Int64:WebViewTransport] = [:]
|
||||||
|
var windowAutoincrementId: Int64 = 0
|
||||||
|
|
||||||
init(plugin: InAppWebViewFlutterPlugin) {
|
init(plugin: InAppWebViewFlutterPlugin) {
|
||||||
super.init(channel: FlutterMethodChannel(name: InAppWebViewStatic.METHOD_CHANNEL_NAME, binaryMessenger: plugin.registrar!.messenger))
|
super.init(channel: FlutterMethodChannel(name: InAppWebViewManager.METHOD_CHANNEL_NAME, binaryMessenger: plugin.registrar!.messenger))
|
||||||
self.plugin = plugin
|
self.plugin = plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +41,11 @@ public class InAppWebViewStatic: ChannelDelegate {
|
||||||
result(false)
|
result(false)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
case "disposeKeepAlive":
|
||||||
|
let keepAliveId = arguments!["keepAliveId"] as! String
|
||||||
|
disposeKeepAlive(keepAliveId: keepAliveId)
|
||||||
|
result(true)
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
result(FlutterMethodNotImplemented)
|
result(FlutterMethodNotImplemented)
|
||||||
break
|
break
|
||||||
|
@ -68,11 +77,27 @@ public class InAppWebViewStatic: ChannelDelegate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func disposeKeepAlive(keepAliveId: String) {
|
||||||
|
if let flutterWebView = keepAliveWebViews[keepAliveId] as? FlutterWebViewController {
|
||||||
|
flutterWebView.keepAliveId = nil
|
||||||
|
flutterWebView.dispose()
|
||||||
|
keepAliveWebViews[keepAliveId] = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override func dispose() {
|
public override func dispose() {
|
||||||
super.dispose()
|
super.dispose()
|
||||||
plugin = nil
|
let keepAliveWebViewValues = keepAliveWebViews.values
|
||||||
|
keepAliveWebViewValues.forEach {(keepAliveWebView: FlutterWebViewController?) in
|
||||||
|
if let keepAliveId = keepAliveWebView?.keepAliveId {
|
||||||
|
disposeKeepAlive(keepAliveId: keepAliveId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keepAliveWebViews.removeAll()
|
||||||
|
windowWebViews.removeAll()
|
||||||
webViewForUserAgent = nil
|
webViewForUserAgent = nil
|
||||||
defaultUserAgent = nil
|
defaultUserAgent = nil
|
||||||
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
|
@ -11,18 +11,20 @@ import FlutterMacOS
|
||||||
public class WebMessageChannel : FlutterMethodCallDelegate {
|
public class WebMessageChannel : FlutterMethodCallDelegate {
|
||||||
static var METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_web_message_channel_"
|
static var METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_web_message_channel_"
|
||||||
var id: String
|
var id: String
|
||||||
|
var plugin: InAppWebViewFlutterPlugin?
|
||||||
var channelDelegate: WebMessageChannelChannelDelegate?
|
var channelDelegate: WebMessageChannelChannelDelegate?
|
||||||
weak var webView: InAppWebView?
|
weak var webView: InAppWebView?
|
||||||
var ports: [WebMessagePort] = []
|
var ports: [WebMessagePort] = []
|
||||||
var registrar: FlutterPluginRegistrar?
|
|
||||||
|
|
||||||
public init(registrar: FlutterPluginRegistrar, id: String) {
|
public init(plugin: InAppWebViewFlutterPlugin, id: String) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.registrar = registrar
|
self.plugin = plugin
|
||||||
super.init()
|
super.init()
|
||||||
|
if let registrar = plugin.registrar {
|
||||||
let channel = FlutterMethodChannel(name: WebMessageChannel.METHOD_CHANNEL_NAME_PREFIX + id,
|
let channel = FlutterMethodChannel(name: WebMessageChannel.METHOD_CHANNEL_NAME_PREFIX + id,
|
||||||
binaryMessenger: registrar.messenger)
|
binaryMessenger: registrar.messenger)
|
||||||
self.channelDelegate = WebMessageChannelChannelDelegate(webMessageChannel: self, channel: channel)
|
self.channelDelegate = WebMessageChannelChannelDelegate(webMessageChannel: self, channel: channel)
|
||||||
|
}
|
||||||
self.ports = [
|
self.ports = [
|
||||||
WebMessagePort(name: "port1", webMessageChannel: self),
|
WebMessagePort(name: "port1", webMessageChannel: self),
|
||||||
WebMessagePort(name: "port2", webMessageChannel: self)
|
WebMessagePort(name: "port2", webMessageChannel: self)
|
||||||
|
@ -68,7 +70,7 @@ public class WebMessageChannel : FlutterMethodCallDelegate {
|
||||||
})();
|
})();
|
||||||
""")
|
""")
|
||||||
webView = nil
|
webView = nil
|
||||||
registrar = nil
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
|
|
@ -16,18 +16,20 @@ public class WebMessageListener : FlutterMethodCallDelegate {
|
||||||
var allowedOriginRules: Set<String>
|
var allowedOriginRules: Set<String>
|
||||||
var channelDelegate: WebMessageListenerChannelDelegate?
|
var channelDelegate: WebMessageListenerChannelDelegate?
|
||||||
weak var webView: InAppWebView?
|
weak var webView: InAppWebView?
|
||||||
var registrar: FlutterPluginRegistrar?
|
var plugin: InAppWebViewFlutterPlugin?
|
||||||
|
|
||||||
public init(registrar: FlutterPluginRegistrar, id: String, jsObjectName: String, allowedOriginRules: Set<String>) {
|
public init(plugin: InAppWebViewFlutterPlugin, id: String, jsObjectName: String, allowedOriginRules: Set<String>) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.registrar = registrar
|
self.plugin = plugin
|
||||||
self.jsObjectName = jsObjectName
|
self.jsObjectName = jsObjectName
|
||||||
self.allowedOriginRules = allowedOriginRules
|
self.allowedOriginRules = allowedOriginRules
|
||||||
super.init()
|
super.init()
|
||||||
|
if let registrar = plugin.registrar {
|
||||||
let channel = FlutterMethodChannel(name: WebMessageListener.METHOD_CHANNEL_NAME_PREFIX + self.id + "_" + self.jsObjectName,
|
let channel = FlutterMethodChannel(name: WebMessageListener.METHOD_CHANNEL_NAME_PREFIX + self.id + "_" + self.jsObjectName,
|
||||||
binaryMessenger: registrar.messenger)
|
binaryMessenger: registrar.messenger)
|
||||||
self.channelDelegate = WebMessageListenerChannelDelegate(webMessageListener: self, channel: channel)
|
self.channelDelegate = WebMessageListenerChannelDelegate(webMessageListener: self, channel: channel)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func assertOriginRulesValid() throws {
|
public func assertOriginRulesValid() throws {
|
||||||
for (index, originRule) in allowedOriginRules.enumerated() {
|
for (index, originRule) in allowedOriginRules.enumerated() {
|
||||||
|
@ -117,12 +119,12 @@ public class WebMessageListener : FlutterMethodCallDelegate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func fromMap(registrar: FlutterPluginRegistrar, map: [String:Any?]?) -> WebMessageListener? {
|
public static func fromMap(plugin: InAppWebViewFlutterPlugin, map: [String:Any?]?) -> WebMessageListener? {
|
||||||
guard let map = map else {
|
guard let map = map else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return WebMessageListener(
|
return WebMessageListener(
|
||||||
registrar: registrar,
|
plugin: plugin,
|
||||||
id: map["id"] as! String,
|
id: map["id"] as! String,
|
||||||
jsObjectName: map["jsObjectName"] as! String,
|
jsObjectName: map["jsObjectName"] as! String,
|
||||||
allowedOriginRules: Set(map["allowedOriginRules"] as! [String])
|
allowedOriginRules: Set(map["allowedOriginRules"] as! [String])
|
||||||
|
@ -181,7 +183,7 @@ public class WebMessageListener : FlutterMethodCallDelegate {
|
||||||
channelDelegate?.dispose()
|
channelDelegate?.dispose()
|
||||||
channelDelegate = nil
|
channelDelegate = nil
|
||||||
webView = nil
|
webView = nil
|
||||||
registrar = nil
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
|
|
@ -507,9 +507,9 @@ public class WebViewChannelDelegate : ChannelDelegate {
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case .addWebMessageListener:
|
case .addWebMessageListener:
|
||||||
if let webView = webView, let registrar = webView.registrar {
|
if let webView = webView, let plugin = webView.plugin {
|
||||||
let webMessageListenerMap = arguments!["webMessageListener"] as! [String: Any?]
|
let webMessageListenerMap = arguments!["webMessageListener"] as! [String: Any?]
|
||||||
let webMessageListener = WebMessageListener.fromMap(registrar: registrar, map: webMessageListenerMap)!
|
let webMessageListener = WebMessageListener.fromMap(plugin: plugin, map: webMessageListenerMap)!
|
||||||
do {
|
do {
|
||||||
try webView.addWebMessageListener(webMessageListener: webMessageListener)
|
try webView.addWebMessageListener(webMessageListener: webMessageListener)
|
||||||
result(false)
|
result(false)
|
||||||
|
|
|
@ -27,14 +27,14 @@ public class InAppWebViewFlutterPlugin: NSObject, FlutterPlugin {
|
||||||
|
|
||||||
var registrar: FlutterPluginRegistrar?
|
var registrar: FlutterPluginRegistrar?
|
||||||
var platformUtil: PlatformUtil?
|
var platformUtil: PlatformUtil?
|
||||||
var inAppWebViewStatic: InAppWebViewStatic?
|
var inAppWebViewManager: InAppWebViewManager?
|
||||||
var myCookieManager: Any?
|
var myCookieManager: Any?
|
||||||
var myWebStorageManager: MyWebStorageManager?
|
var myWebStorageManager: MyWebStorageManager?
|
||||||
var credentialDatabase: CredentialDatabase?
|
var credentialDatabase: CredentialDatabase?
|
||||||
var inAppBrowserManager: InAppBrowserManager?
|
var inAppBrowserManager: InAppBrowserManager?
|
||||||
var headlessInAppWebViewManager: HeadlessInAppWebViewManager?
|
var headlessInAppWebViewManager: HeadlessInAppWebViewManager?
|
||||||
var webAuthenticationSessionManager: WebAuthenticationSessionManager?
|
var webAuthenticationSessionManager: WebAuthenticationSessionManager?
|
||||||
// var printJobManager: PrintJobManager?
|
var printJobManager: PrintJobManager?
|
||||||
|
|
||||||
var webViewControllers: [String: InAppBrowserWebViewController?] = [:]
|
var webViewControllers: [String: InAppBrowserWebViewController?] = [:]
|
||||||
var safariViewControllers: [String: Any?] = [:]
|
var safariViewControllers: [String: Any?] = [:]
|
||||||
|
@ -42,19 +42,19 @@ public class InAppWebViewFlutterPlugin: NSObject, FlutterPlugin {
|
||||||
public init(with registrar: FlutterPluginRegistrar) {
|
public init(with registrar: FlutterPluginRegistrar) {
|
||||||
super.init()
|
super.init()
|
||||||
self.registrar = registrar
|
self.registrar = registrar
|
||||||
registrar.register(FlutterWebViewFactory(registrar: registrar) as FlutterPlatformViewFactory, withId: FlutterWebViewFactory.VIEW_TYPE_ID)
|
registrar.register(FlutterWebViewFactory(plugin: self) as FlutterPlatformViewFactory, withId: FlutterWebViewFactory.VIEW_TYPE_ID)
|
||||||
|
|
||||||
platformUtil = PlatformUtil(plugin: self)
|
platformUtil = PlatformUtil(plugin: self)
|
||||||
inAppBrowserManager = InAppBrowserManager(plugin: self)
|
inAppBrowserManager = InAppBrowserManager(plugin: self)
|
||||||
headlessInAppWebViewManager = HeadlessInAppWebViewManager(plugin: self)
|
headlessInAppWebViewManager = HeadlessInAppWebViewManager(plugin: self)
|
||||||
inAppWebViewStatic = InAppWebViewStatic(plugin: self)
|
inAppWebViewManager = InAppWebViewManager(plugin: self)
|
||||||
credentialDatabase = CredentialDatabase(plugin: self)
|
credentialDatabase = CredentialDatabase(plugin: self)
|
||||||
if #available(macOS 10.13, *) {
|
if #available(macOS 10.13, *) {
|
||||||
myCookieManager = MyCookieManager(plugin: self)
|
myCookieManager = MyCookieManager(plugin: self)
|
||||||
}
|
}
|
||||||
myWebStorageManager = MyWebStorageManager(plugin: self)
|
myWebStorageManager = MyWebStorageManager(plugin: self)
|
||||||
webAuthenticationSessionManager = WebAuthenticationSessionManager(plugin: self)
|
webAuthenticationSessionManager = WebAuthenticationSessionManager(plugin: self)
|
||||||
// printJobManager = PrintJobManager()
|
printJobManager = PrintJobManager(plugin: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||||
|
@ -68,8 +68,8 @@ public class InAppWebViewFlutterPlugin: NSObject, FlutterPlugin {
|
||||||
inAppBrowserManager = nil
|
inAppBrowserManager = nil
|
||||||
headlessInAppWebViewManager?.dispose()
|
headlessInAppWebViewManager?.dispose()
|
||||||
headlessInAppWebViewManager = nil
|
headlessInAppWebViewManager = nil
|
||||||
inAppWebViewStatic?.dispose()
|
inAppWebViewManager?.dispose()
|
||||||
inAppWebViewStatic = nil
|
inAppWebViewManager = nil
|
||||||
credentialDatabase?.dispose()
|
credentialDatabase?.dispose()
|
||||||
credentialDatabase = nil
|
credentialDatabase = nil
|
||||||
if #available(macOS 10.13, *) {
|
if #available(macOS 10.13, *) {
|
||||||
|
@ -80,7 +80,7 @@ public class InAppWebViewFlutterPlugin: NSObject, FlutterPlugin {
|
||||||
myWebStorageManager = nil
|
myWebStorageManager = nil
|
||||||
webAuthenticationSessionManager?.dispose()
|
webAuthenticationSessionManager?.dispose()
|
||||||
webAuthenticationSessionManager = nil
|
webAuthenticationSessionManager = nil
|
||||||
// printJobManager?.dispose()
|
printJobManager?.dispose()
|
||||||
// printJobManager = nil
|
printJobManager = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ public enum PrintJobState: Int {
|
||||||
public class PrintJobController : NSObject, Disposable {
|
public class PrintJobController : NSObject, Disposable {
|
||||||
static let METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_printjobcontroller_"
|
static let METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_printjobcontroller_"
|
||||||
var id: String
|
var id: String
|
||||||
var registrar: FlutterPluginRegistrar?
|
var plugin: InAppWebViewFlutterPlugin?
|
||||||
var job: NSPrintOperation?
|
var job: NSPrintOperation?
|
||||||
var settings: PrintJobSettings?
|
var settings: PrintJobSettings?
|
||||||
var channelDelegate: PrintJobChannelDelegate?
|
var channelDelegate: PrintJobChannelDelegate?
|
||||||
|
@ -30,16 +30,18 @@ public class PrintJobController : NSObject, Disposable {
|
||||||
_ success: Bool,
|
_ success: Bool,
|
||||||
_ contextInfo: UnsafeMutableRawPointer?) -> Void
|
_ contextInfo: UnsafeMutableRawPointer?) -> Void
|
||||||
|
|
||||||
public init(registrar: FlutterPluginRegistrar, id: String, job: NSPrintOperation? = nil, settings: PrintJobSettings? = nil) {
|
public init(plugin: InAppWebViewFlutterPlugin, id: String, job: NSPrintOperation? = nil, settings: PrintJobSettings? = nil) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.registrar = registrar
|
self.plugin = plugin
|
||||||
super.init()
|
super.init()
|
||||||
self.job = job
|
self.job = job
|
||||||
self.settings = settings
|
self.settings = settings
|
||||||
|
if let registrar = plugin.registrar {
|
||||||
let channel = FlutterMethodChannel(name: PrintJobController.METHOD_CHANNEL_NAME_PREFIX + id,
|
let channel = FlutterMethodChannel(name: PrintJobController.METHOD_CHANNEL_NAME_PREFIX + id,
|
||||||
binaryMessenger: registrar.messenger)
|
binaryMessenger: registrar.messenger)
|
||||||
self.channelDelegate = PrintJobChannelDelegate(printJobController: self, channel: channel)
|
self.channelDelegate = PrintJobChannelDelegate(printJobController: self, channel: channel)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func present(parentWindow: NSWindow? = nil, completionHandler: PrintJobController.CompletionHandler? = nil) {
|
public func present(parentWindow: NSWindow? = nil, completionHandler: PrintJobController.CompletionHandler? = nil) {
|
||||||
guard let job = job else {
|
guard let job = job else {
|
||||||
|
@ -76,7 +78,8 @@ public class PrintJobController : NSObject, Disposable {
|
||||||
channelDelegate = nil
|
channelDelegate = nil
|
||||||
completionHandler = nil
|
completionHandler = nil
|
||||||
job = nil
|
job = nil
|
||||||
PrintJobManager.jobs[id] = nil
|
plugin?.printJobManager?.jobs[id] = nil
|
||||||
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
public func dispose() {
|
public func dispose() {
|
||||||
|
@ -84,7 +87,7 @@ public class PrintJobController : NSObject, Disposable {
|
||||||
channelDelegate = nil
|
channelDelegate = nil
|
||||||
completionHandler = nil
|
completionHandler = nil
|
||||||
job = nil
|
job = nil
|
||||||
PrintJobManager.jobs[id] = nil
|
plugin?.printJobManager?.jobs[id] = nil
|
||||||
registrar = nil
|
plugin = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,18 +8,21 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public class PrintJobManager: NSObject, Disposable {
|
public class PrintJobManager: NSObject, Disposable {
|
||||||
static var jobs: [String: PrintJobController?] = [:]
|
var plugin: InAppWebViewFlutterPlugin?
|
||||||
|
var jobs: [String: PrintJobController?] = [:]
|
||||||
|
|
||||||
public override init() {
|
public init(plugin: InAppWebViewFlutterPlugin?) {
|
||||||
super.init()
|
super.init()
|
||||||
|
self.plugin = plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
public func dispose() {
|
public func dispose() {
|
||||||
let jobs = PrintJobManager.jobs.values
|
let jobValues = jobs.values
|
||||||
jobs.forEach { (job: PrintJobController?) in
|
jobValues.forEach { (job: PrintJobController?) in
|
||||||
job?.dispose()
|
job?.dispose()
|
||||||
}
|
}
|
||||||
PrintJobManager.jobs.removeAll()
|
jobs.removeAll()
|
||||||
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
|
|
@ -91,7 +91,7 @@ public class WebAuthenticationSession : NSObject, ASWebAuthenticationPresentatio
|
||||||
channelDelegate?.dispose()
|
channelDelegate?.dispose()
|
||||||
channelDelegate = nil
|
channelDelegate = nil
|
||||||
session = nil
|
session = nil
|
||||||
WebAuthenticationSessionManager.sessions[id] = nil
|
plugin?.webAuthenticationSessionManager?.sessions[id] = nil
|
||||||
plugin = nil
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ import SafariServices
|
||||||
public class WebAuthenticationSessionManager: ChannelDelegate {
|
public class WebAuthenticationSessionManager: ChannelDelegate {
|
||||||
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_webauthenticationsession"
|
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_webauthenticationsession"
|
||||||
var plugin: InAppWebViewFlutterPlugin?
|
var plugin: InAppWebViewFlutterPlugin?
|
||||||
static var sessions: [String: WebAuthenticationSession?] = [:]
|
var sessions: [String: WebAuthenticationSession?] = [:]
|
||||||
|
|
||||||
init(plugin: InAppWebViewFlutterPlugin) {
|
init(plugin: InAppWebViewFlutterPlugin) {
|
||||||
super.init(channel: FlutterMethodChannel(name: WebAuthenticationSessionManager.METHOD_CHANNEL_NAME, binaryMessenger: plugin.registrar!.messenger))
|
super.init(channel: FlutterMethodChannel(name: WebAuthenticationSessionManager.METHOD_CHANNEL_NAME, binaryMessenger: plugin.registrar!.messenger))
|
||||||
|
@ -53,7 +53,7 @@ public class WebAuthenticationSessionManager: ChannelDelegate {
|
||||||
let _ = initialSettings.parse(settings: settings)
|
let _ = initialSettings.parse(settings: settings)
|
||||||
let session = WebAuthenticationSession(plugin: plugin, id: id, url: sessionUrl, callbackURLScheme: callbackURLScheme, settings: initialSettings)
|
let session = WebAuthenticationSession(plugin: plugin, id: id, url: sessionUrl, callbackURLScheme: callbackURLScheme, settings: initialSettings)
|
||||||
session.prepare()
|
session.prepare()
|
||||||
WebAuthenticationSessionManager.sessions[id] = session
|
sessions[id] = session
|
||||||
result(true)
|
result(true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -63,12 +63,12 @@ public class WebAuthenticationSessionManager: ChannelDelegate {
|
||||||
|
|
||||||
public override func dispose() {
|
public override func dispose() {
|
||||||
super.dispose()
|
super.dispose()
|
||||||
let sessions = WebAuthenticationSessionManager.sessions.values
|
let sessionValues = sessions.values
|
||||||
sessions.forEach { (session: WebAuthenticationSession?) in
|
sessionValues.forEach { (session: WebAuthenticationSession?) in
|
||||||
session?.cancel()
|
session?.cancel()
|
||||||
session?.dispose()
|
session?.dispose()
|
||||||
}
|
}
|
||||||
WebAuthenticationSessionManager.sessions.removeAll()
|
sessions.removeAll()
|
||||||
plugin = nil
|
plugin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue