Updated onCreateWindow, onJsAlert, onJsConfirm, and onJsPrompt webview events, added onCloseWindow, onTitleChanged, onWindowFocus, and onWindowBlur webview events, added androidOnRequestFocus, androidOnReceivedIcon, androidOnReceivedTouchIconUrl, androidOnJsBeforeUnload, and androidOnReceivedLoginRequest Android-specific webview events, fix #403
This commit is contained in:
parent
9d92911ab2
commit
eea691664b
20
CHANGELOG.md
20
CHANGELOG.md
|
@ -1,12 +1,24 @@
|
|||
## 4.0.0
|
||||
|
||||
- Updated `onCreateWindow`, `onJsAlert`, `onJsConfirm`, `onJsPrompt` webview events
|
||||
- Added `onCloseWindow`, `onTitleChanged`, `onWindowFocus`, `onWindowBlur` webview events
|
||||
- Added `androidOnRequestFocus`, `androidOnReceivedIcon`, `androidOnReceivedTouchIconUrl`, `androidOnJsBeforeUnload`, `androidOnReceivedLoginRequest` Android-specific webview events
|
||||
- Fixed "SFSafariViewController doesn't open like a native iOS modal" [#403](https://github.com/pichillilorenzo/flutter_inappwebview/issues/403)
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
- Updated `onCreateWindow`, `onJsAlert`, `onJsConfirm`, `onJsPrompt` webview event
|
||||
- Renamed `OnCreateWindowRequest` class to `CreateWindowRequest`
|
||||
|
||||
## 3.4.0+2
|
||||
|
||||
- Revert default `InAppWebView.gestureRecognizers` value to null on Android
|
||||
- Reverted default `InAppWebView.gestureRecognizers` value to null on Android
|
||||
|
||||
## 3.4.0+1
|
||||
|
||||
- Update README.md
|
||||
- Update missing docs
|
||||
- Fix pub.dev Health suggestions and Analysis suggestions
|
||||
- Updated README.md
|
||||
- Updated missing docs
|
||||
- Fixed pub.dev Health suggestions and Analysis suggestions
|
||||
|
||||
## 3.4.0
|
||||
|
||||
|
|
|
@ -628,6 +628,7 @@ Event names that starts with `android` or `ios` are events platform-specific.
|
|||
* `onDownloadStart`: Event fired when InAppWebView recognizes a downloadable file (to use this event, the `useOnDownloadStart` option must be `true`). To download the file, you can use the [flutter_downloader](https://pub.dev/packages/flutter_downloader) plugin.
|
||||
* `onLoadResourceCustomScheme`: Event fired when the InAppWebView finds the `custom-scheme` while loading a resource. Here you can handle the url request and return a CustomSchemeResponse to load a specific resource encoded to `base64`.
|
||||
* `onCreateWindow`: Event fired when the InAppWebView requests the host application to create a new window, for example when trying to open a link with `target="_blank"` or when `window.open()` is called by JavaScript side.
|
||||
* `onCloseWindow`: Event fired when the host application should close the given WebView and remove it from the view system if necessary.
|
||||
* `onJsAlert`: Event fired when javascript calls the `alert()` method to display an alert dialog.
|
||||
* `onJsConfirm`: Event fired when javascript calls the `confirm()` method to display a confirm dialog.
|
||||
* `onJsPrompt`: Event fired when javascript calls the `prompt()` method to display a prompt dialog.
|
||||
|
@ -644,6 +645,9 @@ Event names that starts with `android` or `ios` are events platform-specific.
|
|||
* `onEnterFullscreen`: Event fired when the current page has entered full screen mode.
|
||||
* `onExitFullscreen`: Event fired when the current page has exited full screen mode.
|
||||
* `onPageCommitVisible`: Called when the web view begins to receive web content.
|
||||
* `onTitleChanged`: Event fired when a change in the document title occurred.
|
||||
* `onWindowFocus`: Event fired when the JavaScript `window` object of the WebView has received focus. This is the result of the `focus` JavaScript event applied to the `window` object.
|
||||
* `onWindowBlur`: Event fired when the JavaScript `window` object of the WebView has lost focus. This is the result of the `blur` JavaScript event applied to the `window` object.
|
||||
* `androidOnSafeBrowsingHit`: Event fired when the webview notifies that a loading URL has been flagged by Safe Browsing (available only on Android).
|
||||
* `androidOnPermissionRequest`: Event fired when the webview is requesting permission to access the specified resources and the permission currently isn't granted or denied (available only on Android).
|
||||
* `androidOnGeolocationPermissionsShowPrompt`: Event that notifies the host application that web content from the specified origin is attempting to use the Geolocation API, but no permission state is currently set for that origin (available only on Android).
|
||||
|
@ -654,6 +658,11 @@ Event names that starts with `android` or `ios` are events platform-specific.
|
|||
* `androidOnRenderProcessUnresponsive`: Event called when the renderer currently associated with the WebView becomes unresponsive as a result of a long running blocking task such as the execution of JavaScript (available only on Android).
|
||||
* `androidOnFormResubmission`: As the host application if the browser should resend data as the requested page was a result of a POST. The default is to not resend the data (available only on Android).
|
||||
* `androidOnScaleChanged`: Event fired when the scale applied to the WebView has changed (available only on Android).
|
||||
* `androidOnRequestFocus`: Event fired when there is a request to display and focus for this WebView (available only on Android).
|
||||
* `androidOnReceivedIcon`: Event fired when there is new favicon for the current page (available only on Android).
|
||||
* `androidOnReceivedTouchIconUrl`: Event fired when there is an url for an apple-touch-icon (available only on Android).
|
||||
* `androidOnJsBeforeUnload`: Event fired when the client should display a dialog to confirm navigation away from the current page. This is the result of the `onbeforeunload` javascript event (available only on Android).
|
||||
* `androidOnReceivedLoginRequest`: Event fired when a request to automatically log in the user has been processed (available only on Android).
|
||||
* `iosOnWebContentProcessDidTerminate`: Invoked when the web view's web content process is terminated (available only on iOS).
|
||||
* `iosOnDidReceiveServerRedirectForProvisionalNavigation`: Called when a web view receives a server redirect (available only on iOS).
|
||||
|
||||
|
|
|
@ -45,7 +45,8 @@ public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandl
|
|||
Map<String, String> headersFallback = (Map<String, String>) call.argument("headersFallback");
|
||||
HashMap<String, Object> optionsFallback = (HashMap<String, Object>) call.argument("optionsFallback");
|
||||
HashMap<String, Object> contextMenuFallback = (HashMap<String, Object>) call.argument("contextMenuFallback");
|
||||
open(activity, uuid, url, options, menuItemList, uuidFallback, headersFallback, optionsFallback, contextMenuFallback, result);
|
||||
Integer windowIdFallback = (Integer) call.argument("windowIdFallback");
|
||||
open(activity, uuid, url, options, menuItemList, uuidFallback, headersFallback, optionsFallback, contextMenuFallback, windowIdFallback, result);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -54,7 +55,8 @@ public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandl
|
|||
}
|
||||
|
||||
public void open(Activity activity, String uuid, String url, HashMap<String, Object> options, List<HashMap<String, Object>> menuItemList, String uuidFallback,
|
||||
Map<String, String> headersFallback, HashMap<String, Object> optionsFallback, HashMap<String, Object> contextMenuFallback, MethodChannel.Result result) {
|
||||
Map<String, String> headersFallback, HashMap<String, Object> optionsFallback, HashMap<String, Object> contextMenuFallback, Integer windowIdFallback,
|
||||
MethodChannel.Result result) {
|
||||
|
||||
Intent intent = null;
|
||||
Bundle extras = new Bundle();
|
||||
|
@ -68,6 +70,8 @@ public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandl
|
|||
extras.putSerializable("headers", (Serializable) headersFallback);
|
||||
extras.putSerializable("contextMenu", (Serializable) contextMenuFallback);
|
||||
|
||||
extras.putInt("windowId", windowIdFallback != null ? windowIdFallback : -1);
|
||||
|
||||
if (CustomTabActivityHelper.isAvailable(activity)) {
|
||||
intent = new Intent(activity, ChromeCustomTabsActivity.class);
|
||||
}
|
||||
|
|
|
@ -5,12 +5,14 @@ import android.graphics.Color;
|
|||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.webkit.ValueCallback;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebView;
|
||||
|
@ -25,6 +27,7 @@ import androidx.webkit.WebViewCompat;
|
|||
import androidx.webkit.WebViewFeature;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.InAppWebView;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.InAppWebViewChromeClient;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.InAppWebViewOptions;
|
||||
import com.pichillilorenzo.flutter_inappwebview.R;
|
||||
import com.pichillilorenzo.flutter_inappwebview.Shared;
|
||||
|
@ -41,6 +44,7 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
|
|||
|
||||
static final String LOG_TAG = "InAppBrowserActivity";
|
||||
public MethodChannel channel;
|
||||
public Integer windowId;
|
||||
public String uuid;
|
||||
public InAppWebView webView;
|
||||
public ActionBar actionBar;
|
||||
|
@ -63,6 +67,7 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
|
|||
|
||||
Bundle b = getIntent().getExtras();
|
||||
uuid = b.getString("uuid");
|
||||
windowId = b.getInt("windowId");
|
||||
|
||||
channel = new MethodChannel(Shared.messenger, "com.pichillilorenzo/flutter_inappbrowser_" + uuid);
|
||||
channel.setMethodCallHandler(this);
|
||||
|
@ -70,6 +75,7 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
|
|||
setContentView(R.layout.activity_web_view);
|
||||
|
||||
webView = findViewById(R.id.webView);
|
||||
webView.windowId = windowId;
|
||||
webView.inAppBrowserActivity = this;
|
||||
webView.channel = channel;
|
||||
|
||||
|
@ -90,19 +96,27 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
|
|||
|
||||
prepareView();
|
||||
|
||||
Boolean isData = b.getBoolean("isData");
|
||||
if (!isData) {
|
||||
headers = (HashMap<String, String>) b.getSerializable("headers");
|
||||
String url = b.getString("url");
|
||||
webView.loadUrl(url, headers);
|
||||
}
|
||||
else {
|
||||
String data = b.getString("data");
|
||||
String mimeType = b.getString("mimeType");
|
||||
String encoding = b.getString("encoding");
|
||||
String baseUrl = b.getString("baseUrl");
|
||||
String historyUrl = b.getString("historyUrl");
|
||||
webView.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);
|
||||
if (windowId != -1) {
|
||||
Message resultMsg = InAppWebViewChromeClient.windowWebViewMessages.get(windowId);
|
||||
if (resultMsg != null) {
|
||||
((WebView.WebViewTransport) resultMsg.obj).setWebView(webView);
|
||||
resultMsg.sendToTarget();
|
||||
}
|
||||
} else {
|
||||
Boolean isData = b.getBoolean("isData");
|
||||
if (!isData) {
|
||||
headers = (HashMap<String, String>) b.getSerializable("headers");
|
||||
String url = b.getString("url");
|
||||
webView.loadUrl(url, headers);
|
||||
}
|
||||
else {
|
||||
String data = b.getString("data");
|
||||
String mimeType = b.getString("mimeType");
|
||||
String encoding = b.getString("encoding");
|
||||
String baseUrl = b.getString("baseUrl");
|
||||
String historyUrl = b.getString("historyUrl");
|
||||
webView.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
|
@ -565,30 +579,14 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
|
|||
}
|
||||
|
||||
public void close(final MethodChannel.Result result) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
channel.invokeMethod("onExit", obj);
|
||||
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
channel.invokeMethod("onExit", obj);
|
||||
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
// NB: wait for about:blank before dismissing
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
hide();
|
||||
finish();
|
||||
}
|
||||
});
|
||||
// NB: From SDK 19: "If you call methods on WebView from any thread
|
||||
// other than your app's UI thread, it can cause unexpected results."
|
||||
// http://developer.android.com/guide/webapps/migrating.html#Threads
|
||||
webView.loadUrl("about:blank");
|
||||
if (result != null) {
|
||||
result.success(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
dispose();
|
||||
|
||||
if (result != null) {
|
||||
result.success(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
|
@ -984,6 +982,8 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
|
|||
if (Shared.activityPluginBinding != null) {
|
||||
Shared.activityPluginBinding.removeActivityResultListener(webView.inAppWebViewChromeClient);
|
||||
}
|
||||
ViewGroup vg = (ViewGroup) (webView.getParent());
|
||||
vg.removeView(webView);
|
||||
webView.setWebChromeClient(new WebChromeClient());
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
|
@ -993,6 +993,7 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
|
|||
}
|
||||
});
|
||||
webView.loadUrl("about:blank");
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,8 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler {
|
|||
HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options");
|
||||
Map<String, String> headers = (Map<String, String>) call.argument("headers");
|
||||
HashMap<String, Object> contextMenu = (HashMap<String, Object>) call.argument("contextMenu");
|
||||
openUrl(activity, uuid, url, options, headers, contextMenu);
|
||||
Integer windowId = (Integer) call.argument("windowId");
|
||||
openUrl(activity, uuid, url, options, headers, contextMenu, windowId);
|
||||
}
|
||||
result.success(true);
|
||||
break;
|
||||
|
@ -88,7 +89,8 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler {
|
|||
HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options");
|
||||
Map<String, String> headers = (Map<String, String>) call.argument("headers");
|
||||
HashMap<String, Object> contextMenu = (HashMap<String, Object>) call.argument("contextMenu");
|
||||
openUrl(activity, uuid, url, options, headers, contextMenu);
|
||||
Integer windowId = (Integer) call.argument("windowId");
|
||||
openUrl(activity, uuid, url, options, headers, contextMenu, windowId);
|
||||
}
|
||||
result.success(true);
|
||||
break;
|
||||
|
@ -101,7 +103,8 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler {
|
|||
String baseUrl = (String) call.argument("baseUrl");
|
||||
String historyUrl = (String) call.argument("historyUrl");
|
||||
HashMap<String, Object> contextMenu = (HashMap<String, Object>) call.argument("contextMenu");
|
||||
openData(activity, uuid, options, data, mimeType, encoding, baseUrl, historyUrl, contextMenu);
|
||||
Integer windowId = (Integer) call.argument("windowId");
|
||||
openData(activity, uuid, options, data, mimeType, encoding, baseUrl, historyUrl, contextMenu, windowId);
|
||||
}
|
||||
result.success(true);
|
||||
break;
|
||||
|
@ -192,7 +195,8 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler {
|
|||
}
|
||||
}
|
||||
|
||||
public void openUrl(Activity activity, String uuid, String url, HashMap<String, Object> options, Map<String, String> headers, HashMap<String, Object> contextMenu) {
|
||||
public void openUrl(Activity activity, String uuid, String url, HashMap<String, Object> options, Map<String, String> headers,
|
||||
HashMap<String, Object> contextMenu, Integer windowId) {
|
||||
Bundle extras = new Bundle();
|
||||
extras.putString("fromActivity", activity.getClass().getName());
|
||||
extras.putString("url", url);
|
||||
|
@ -201,10 +205,12 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler {
|
|||
extras.putSerializable("options", options);
|
||||
extras.putSerializable("headers", (Serializable) headers);
|
||||
extras.putSerializable("contextMenu", (Serializable) contextMenu);
|
||||
extras.putInt("windowId", windowId != null ? windowId : -1);
|
||||
startInAppBrowserActivity(activity, extras);
|
||||
}
|
||||
|
||||
public void openData(Activity activity, String uuid, HashMap<String, Object> options, String data, String mimeType, String encoding, String baseUrl, String historyUrl, HashMap<String, Object> contextMenu) {
|
||||
public void openData(Activity activity, String uuid, HashMap<String, Object> options, String data, String mimeType, String encoding,
|
||||
String baseUrl, String historyUrl, HashMap<String, Object> contextMenu, Integer windowId) {
|
||||
Bundle extras = new Bundle();
|
||||
extras.putBoolean("isData", true);
|
||||
extras.putString("uuid", uuid);
|
||||
|
@ -215,6 +221,7 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler {
|
|||
extras.putString("baseUrl", baseUrl);
|
||||
extras.putString("historyUrl", historyUrl);
|
||||
extras.putSerializable("contextMenu", (Serializable) contextMenu);
|
||||
extras.putInt("windowId", windowId != null ? windowId : -1);
|
||||
startInAppBrowserActivity(activity, extras);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.InAppWebView;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.MutableContextWrapper;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.webkit.ValueCallback;
|
||||
|
@ -25,6 +25,7 @@ import java.lang.reflect.Field;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import io.flutter.embedding.android.FlutterView;
|
||||
import io.flutter.plugin.common.BinaryMessenger;
|
||||
import io.flutter.plugin.common.MethodCall;
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
|
@ -54,6 +55,7 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
|
|||
final Map<String, String> initialHeaders = (Map<String, String>) params.get("initialHeaders");
|
||||
Map<String, Object> initialOptions = (Map<String, Object>) params.get("initialOptions");
|
||||
Map<String, Object> contextMenu = (Map<String, Object>) params.get("contextMenu");
|
||||
Integer windowId = (Integer) params.get("windowId");
|
||||
|
||||
InAppWebViewOptions options = new InAppWebViewOptions();
|
||||
options.parse(initialOptions);
|
||||
|
@ -70,7 +72,7 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
|
|||
// displayListenerProxy.onPostWebViewInitialization(displayManager);
|
||||
// mMutableContext.setBaseContext(context);
|
||||
|
||||
webView = new InAppWebView(Shared.activity, this, id, options, contextMenu, containerView);
|
||||
webView = new InAppWebView(Shared.activity, this, id, windowId, options, contextMenu, containerView);
|
||||
displayListenerProxy.onPostWebViewInitialization(displayManager);
|
||||
|
||||
// fix https://github.com/pichillilorenzo/flutter_inappwebview/issues/182
|
||||
|
@ -89,33 +91,41 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
|
|||
|
||||
webView.prepare();
|
||||
|
||||
if (initialFile != null) {
|
||||
try {
|
||||
initialUrl = Util.getUrlAsset(initialFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Log.e(LOG_TAG, initialFile + " asset file cannot be found!", e);
|
||||
return;
|
||||
if (windowId != null) {
|
||||
Message resultMsg = InAppWebViewChromeClient.windowWebViewMessages.get(windowId);
|
||||
if (resultMsg != null) {
|
||||
((WebView.WebViewTransport) resultMsg.obj).setWebView(webView);
|
||||
resultMsg.sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
final String finalInitialUrl = initialUrl;
|
||||
Handler handler = new Handler(Looper.getMainLooper());
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (initialData != null) {
|
||||
String data = initialData.get("data");
|
||||
String mimeType = initialData.get("mimeType");
|
||||
String encoding = initialData.get("encoding");
|
||||
String baseUrl = initialData.get("baseUrl");
|
||||
String historyUrl = initialData.get("historyUrl");
|
||||
webView.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);
|
||||
} else {
|
||||
if (initialFile != null) {
|
||||
try {
|
||||
initialUrl = Util.getUrlAsset(initialFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Log.e(LOG_TAG, initialFile + " asset file cannot be found!", e);
|
||||
return;
|
||||
}
|
||||
else
|
||||
webView.loadUrl(finalInitialUrl, initialHeaders);
|
||||
}
|
||||
});
|
||||
|
||||
final String finalInitialUrl = initialUrl;
|
||||
Handler handler = new Handler(Looper.getMainLooper());
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (initialData != null) {
|
||||
String data = initialData.get("data");
|
||||
String mimeType = initialData.get("mimeType");
|
||||
String encoding = initialData.get("encoding");
|
||||
String baseUrl = initialData.get("baseUrl");
|
||||
String historyUrl = initialData.get("historyUrl");
|
||||
webView.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);
|
||||
}
|
||||
else
|
||||
webView.loadUrl(finalInitialUrl, initialHeaders);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (containerView == null && id instanceof String) {
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
|
@ -513,6 +523,7 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
|
|||
}
|
||||
webView.setWebChromeClient(new WebChromeClient());
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
webView.dispose();
|
||||
webView.destroy();
|
||||
|
|
|
@ -35,9 +35,11 @@ import android.webkit.CookieManager;
|
|||
import android.webkit.DownloadListener;
|
||||
import android.webkit.ValueCallback;
|
||||
import android.webkit.WebBackForwardList;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebHistoryItem;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebStorage;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.HorizontalScrollView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
@ -46,6 +48,7 @@ import androidx.annotation.Keep;
|
|||
import androidx.annotation.RequiresApi;
|
||||
import androidx.webkit.WebViewCompat;
|
||||
import androidx.webkit.WebViewFeature;
|
||||
import androidx.webkit.WebViewRenderProcessClient;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.ContentBlocker.ContentBlocker;
|
||||
import com.pichillilorenzo.flutter_inappwebview.ContentBlocker.ContentBlockerAction;
|
||||
|
@ -84,6 +87,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
public FlutterWebView flutterWebView;
|
||||
public MethodChannel channel;
|
||||
public Object id;
|
||||
public Integer windowId;
|
||||
public InAppWebViewClient inAppWebViewClient;
|
||||
public InAppWebViewChromeClient inAppWebViewChromeClient;
|
||||
public InAppWebViewRenderProcessClient inAppWebViewRenderProcessClient;
|
||||
|
@ -108,6 +112,13 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
public Runnable checkContextMenuShouldBeClosedTask;
|
||||
public int newCheckContextMenuShouldBeClosedTaskTask = 100; // ms
|
||||
|
||||
static final String scriptsWrapperJS = "(function(){" +
|
||||
" if (window." + JavaScriptBridgeInterface.name + "._scriptsLoaded == null) {" +
|
||||
" $PLACEHOLDER_VALUE" +
|
||||
" window." + JavaScriptBridgeInterface.name + "._scriptsLoaded = true;" +
|
||||
" }" +
|
||||
"})();";
|
||||
|
||||
static final String consoleLogJS = "(function(console) {" +
|
||||
" var oldLogs = {" +
|
||||
" 'log': console.log," +
|
||||
|
@ -138,7 +149,12 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
" window." + JavaScriptBridgeInterface.name + ".callHandler('onPrint', window.location.href);" +
|
||||
"};";
|
||||
|
||||
static final String platformReadyJS = "window.dispatchEvent(new Event('flutterInAppWebViewPlatformReady'));";
|
||||
static final String platformReadyJS = "(function() {" +
|
||||
" if (window." + JavaScriptBridgeInterface.name + "._platformReady == null) {" +
|
||||
" window.dispatchEvent(new Event('flutterInAppWebViewPlatformReady'));" +
|
||||
" window." + JavaScriptBridgeInterface.name + "._platformReady = true;" +
|
||||
" }" +
|
||||
"})();";
|
||||
|
||||
static final String variableForOnLoadResourceJS = "window._flutter_inappwebview_useOnLoadResource";
|
||||
static final String enableVariableForOnLoadResourceJS = variableForOnLoadResourceJS + " = $PLACEHOLDER_VALUE;";
|
||||
|
@ -592,6 +608,18 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
" });" +
|
||||
"})();";
|
||||
|
||||
static final String onWindowFocusEventJS = "(function(){" +
|
||||
" window.addEventListener('focus', function(e) {" +
|
||||
" window." + JavaScriptBridgeInterface.name + ".callHandler('onWindowFocus');" +
|
||||
" });" +
|
||||
"})();";
|
||||
|
||||
static final String onWindowBlurEventJS = "(function(){" +
|
||||
" window.addEventListener('blur', function(e) {" +
|
||||
" window." + JavaScriptBridgeInterface.name + ".callHandler('onWindowBlur');" +
|
||||
" });" +
|
||||
"})();";
|
||||
|
||||
public InAppWebView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
@ -604,7 +632,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
super(context, attrs, defaultStyle);
|
||||
}
|
||||
|
||||
public InAppWebView(Context context, Object obj, Object id, InAppWebViewOptions options, Map<String, Object> contextMenu, View containerView) {
|
||||
public InAppWebView(Context context, Object obj, Object id, Integer windowId, InAppWebViewOptions options, Map<String, Object> contextMenu, View containerView) {
|
||||
super(context, containerView);
|
||||
if (obj instanceof InAppBrowserActivity)
|
||||
this.inAppBrowserActivity = (InAppBrowserActivity) obj;
|
||||
|
@ -612,6 +640,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
this.flutterWebView = (FlutterWebView) obj;
|
||||
this.channel = (this.inAppBrowserActivity != null) ? this.inAppBrowserActivity.channel : this.flutterWebView.channel;
|
||||
this.id = id;
|
||||
this.windowId = windowId;
|
||||
this.options = options;
|
||||
this.contextMenu = contextMenu;
|
||||
Shared.activity.registerForContextMenu(this);
|
||||
|
@ -1949,12 +1978,22 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (windowId != null && InAppWebViewChromeClient.windowWebViewMessages.containsKey(windowId)) {
|
||||
InAppWebViewChromeClient.windowWebViewMessages.remove(windowId);
|
||||
}
|
||||
headlessHandler.removeCallbacksAndMessages(null);
|
||||
mHandler.removeCallbacksAndMessages(null);
|
||||
removeJavascriptInterface(JavaScriptBridgeInterface.name);
|
||||
removeAllViews();
|
||||
if (checkContextMenuShouldBeClosedTask != null)
|
||||
removeCallbacks(checkContextMenuShouldBeClosedTask);
|
||||
if (checkScrollStoppedTask != null)
|
||||
removeCallbacks(checkScrollStoppedTask);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
headlessHandler.removeCallbacksAndMessages(null);
|
||||
super.destroy();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package com.pichillilorenzo.flutter_inappwebview.InAppWebView;
|
|||
import android.Manifest;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
|
@ -30,11 +29,11 @@ import android.webkit.PermissionRequest;
|
|||
import android.webkit.ValueCallback;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
@ -45,6 +44,7 @@ import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
|
|||
import com.pichillilorenzo.flutter_inappwebview.R;
|
||||
import com.pichillilorenzo.flutter_inappwebview.Shared;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -64,6 +64,8 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
|||
private FlutterWebView flutterWebView;
|
||||
private InAppBrowserActivity inAppBrowserActivity;
|
||||
public MethodChannel channel;
|
||||
public static Map<Integer, Message> windowWebViewMessages = new HashMap<>();
|
||||
private static int windowAutoincrementId = 0;
|
||||
|
||||
private static final String fileProviderAuthorityExtension = "flutter_inappwebview.fileprovider";
|
||||
|
||||
|
@ -132,7 +134,6 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
|||
this.mCustomViewCallback.onCustomViewHidden();
|
||||
this.mCustomViewCallback = null;
|
||||
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
|
||||
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
|
@ -175,7 +176,9 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
|||
Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
obj.put("url", url);
|
||||
obj.put("message", message);
|
||||
obj.put("iosIsMainFrame", null);
|
||||
|
||||
channel.invokeMethod("onJsAlert", obj, new MethodChannel.Result() {
|
||||
@Override
|
||||
|
@ -260,7 +263,9 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
|||
Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
obj.put("url", url);
|
||||
obj.put("message", message);
|
||||
obj.put("iosIsMainFrame", null);
|
||||
|
||||
channel.invokeMethod("onJsConfirm", obj, new MethodChannel.Result() {
|
||||
@Override
|
||||
|
@ -358,8 +363,10 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
|||
Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
obj.put("url", url);
|
||||
obj.put("message", message);
|
||||
obj.put("defaultValue", defaultValue);
|
||||
obj.put("iosIsMainFrame", null);
|
||||
|
||||
channel.invokeMethod("onJsPrompt", obj, new MethodChannel.Result() {
|
||||
@Override
|
||||
|
@ -472,47 +479,172 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
|||
alertDialog.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onJsBeforeUnload(final WebView view, String url, final String message,
|
||||
final JsResult result) {
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
obj.put("url", url);
|
||||
obj.put("message", message);
|
||||
obj.put("iosIsMainFrame", null);
|
||||
|
||||
channel.invokeMethod("onJsBeforeUnload", obj, new MethodChannel.Result() {
|
||||
@Override
|
||||
public void success(Object response) {
|
||||
String responseMessage = null;
|
||||
String confirmButtonTitle = null;
|
||||
String cancelButtonTitle = null;
|
||||
|
||||
if (response != null) {
|
||||
Map<String, Object> responseMap = (Map<String, Object>) response;
|
||||
responseMessage = (String) responseMap.get("message");
|
||||
confirmButtonTitle = (String) responseMap.get("confirmButtonTitle");
|
||||
cancelButtonTitle = (String) responseMap.get("cancelButtonTitle");
|
||||
Boolean handledByClient = (Boolean) responseMap.get("handledByClient");
|
||||
if (handledByClient != null && handledByClient) {
|
||||
Integer action = (Integer) responseMap.get("action");
|
||||
action = action != null ? action : 1;
|
||||
switch (action) {
|
||||
case 0:
|
||||
result.confirm();
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
result.cancel();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
createBeforeUnloadDialog(view, message, result, responseMessage, confirmButtonTitle, cancelButtonTitle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String s, String s1, Object o) {
|
||||
Log.e(LOG_TAG, s + ", " + s1);
|
||||
result.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notImplemented() {
|
||||
createConfirmDialog(view, message, result, null, null, null);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void createBeforeUnloadDialog(WebView view, String message, final JsResult result, String responseMessage, String confirmButtonTitle, String cancelButtonTitle) {
|
||||
String alertMessage = (responseMessage != null && !responseMessage.isEmpty()) ? responseMessage : message;
|
||||
DialogInterface.OnClickListener confirmClickListener = new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
result.confirm();
|
||||
dialog.dismiss();
|
||||
}
|
||||
};
|
||||
DialogInterface.OnClickListener cancelClickListener = new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
result.cancel();
|
||||
dialog.dismiss();
|
||||
}
|
||||
};
|
||||
|
||||
Activity activity = inAppBrowserActivity != null ? inAppBrowserActivity : Shared.activity;
|
||||
|
||||
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(activity, R.style.Theme_AppCompat_Dialog_Alert);
|
||||
alertDialogBuilder.setMessage(alertMessage);
|
||||
if (confirmButtonTitle != null && !confirmButtonTitle.isEmpty()) {
|
||||
alertDialogBuilder.setPositiveButton(confirmButtonTitle, confirmClickListener);
|
||||
} else {
|
||||
alertDialogBuilder.setPositiveButton(android.R.string.ok, confirmClickListener);
|
||||
}
|
||||
if (cancelButtonTitle != null && !cancelButtonTitle.isEmpty()) {
|
||||
alertDialogBuilder.setNegativeButton(cancelButtonTitle, cancelClickListener);
|
||||
} else {
|
||||
alertDialogBuilder.setNegativeButton(android.R.string.cancel, cancelClickListener);
|
||||
}
|
||||
|
||||
alertDialogBuilder.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
result.cancel();
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
AlertDialog alertDialog = alertDialogBuilder.create();
|
||||
alertDialog.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, final Message resultMsg) {
|
||||
windowAutoincrementId++;
|
||||
final int windowId = windowAutoincrementId;
|
||||
|
||||
WebView.HitTestResult result = view.getHitTestResult();
|
||||
String url = result.getExtra();
|
||||
|
||||
final Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
obj.put("url", url);
|
||||
obj.put("windowId", windowId);
|
||||
obj.put("androidIsDialog", isDialog);
|
||||
obj.put("androidIsUserGesture", isUserGesture);
|
||||
obj.put("iosWKNavigationType", null);
|
||||
obj.put("iosIsForMainFrame", null);
|
||||
|
||||
WebView.HitTestResult result = view.getHitTestResult();
|
||||
String data = result.getExtra();
|
||||
windowWebViewMessages.put(windowId, resultMsg);
|
||||
|
||||
if (data == null) {
|
||||
// to get the URL, create a temp weview
|
||||
final WebView tempWebView = new WebView(view.getContext());
|
||||
// disable javascript
|
||||
tempWebView.getSettings().setJavaScriptEnabled(false);
|
||||
tempWebView.setWebViewClient(new WebViewClient(){
|
||||
@Override
|
||||
public void onPageStarted(WebView v, String url, Bitmap favicon) {
|
||||
super.onPageStarted(v, url, favicon);
|
||||
|
||||
obj.put("url", url);
|
||||
channel.invokeMethod("onCreateWindow", obj);
|
||||
|
||||
// stop webview loading
|
||||
v.stopLoading();
|
||||
|
||||
// this will throw the error "Application attempted to call on a destroyed AwAutofillManager" that will kill the webview.
|
||||
// that's ok.
|
||||
v.destroy();
|
||||
channel.invokeMethod("onCreateWindow", obj, new MethodChannel.Result() {
|
||||
@Override
|
||||
public void success(@Nullable Object result) {
|
||||
if (result == null && InAppWebViewChromeClient.windowWebViewMessages.containsKey(windowId)) {
|
||||
InAppWebViewChromeClient.windowWebViewMessages.remove(windowId);
|
||||
}
|
||||
});
|
||||
((WebView.WebViewTransport) resultMsg.obj).setWebView(tempWebView);
|
||||
resultMsg.sendToTarget();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
obj.put("url", data);
|
||||
channel.invokeMethod("onCreateWindow", obj);
|
||||
return false;
|
||||
@Override
|
||||
public void error(String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails) {
|
||||
if (InAppWebViewChromeClient.windowWebViewMessages.containsKey(windowId)) {
|
||||
InAppWebViewChromeClient.windowWebViewMessages.remove(windowId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notImplemented() {
|
||||
if (InAppWebViewChromeClient.windowWebViewMessages.containsKey(windowId)) {
|
||||
InAppWebViewChromeClient.windowWebViewMessages.remove(windowId);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCloseWindow(WebView window) {
|
||||
final Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
|
||||
channel.invokeMethod("onCloseWindow", obj);
|
||||
|
||||
super.onCloseWindow(window);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestFocus(WebView view) {
|
||||
final Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
|
||||
channel.invokeMethod("onRequestFocus", obj);
|
||||
|
||||
super.onCloseWindow(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -588,13 +720,53 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
|||
@Override
|
||||
public void onReceivedTitle(WebView view, String title) {
|
||||
super.onReceivedTitle(view, title);
|
||||
if (inAppBrowserActivity != null && inAppBrowserActivity.actionBar != null && inAppBrowserActivity.options.toolbarTopFixedTitle.isEmpty())
|
||||
if (inAppBrowserActivity != null && inAppBrowserActivity.actionBar != null && inAppBrowserActivity.options.toolbarTopFixedTitle.isEmpty()) {
|
||||
inAppBrowserActivity.actionBar.setTitle(title);
|
||||
}
|
||||
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
obj.put("title", title);
|
||||
channel.invokeMethod("onTitleChanged", obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedIcon(WebView view, Bitmap icon) {
|
||||
super.onReceivedIcon(view, icon);
|
||||
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
icon.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
|
||||
try {
|
||||
byteArrayOutputStream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
String errorMessage = e.getMessage();
|
||||
if (errorMessage != null) {
|
||||
Log.e(LOG_TAG, errorMessage);
|
||||
}
|
||||
}
|
||||
icon.recycle();
|
||||
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
obj.put("icon", byteArrayOutputStream.toByteArray());
|
||||
channel.invokeMethod("onReceivedIcon", obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedTouchIconUrl(WebView view,
|
||||
String url,
|
||||
boolean precomposed) {
|
||||
super.onReceivedTouchIconUrl(view, url, precomposed);
|
||||
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
obj.put("url", url);
|
||||
obj.put("precomposed", precomposed);
|
||||
channel.invokeMethod("onReceivedTouchIconUrl", obj);
|
||||
}
|
||||
|
||||
protected ViewGroup getRootView() {
|
||||
|
|
|
@ -2,10 +2,8 @@ package com.pichillilorenzo.flutter_inappwebview.InAppWebView;
|
|||
|
||||
import android.annotation.TargetApi;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.http.SslCertificate;
|
||||
import android.net.http.SslError;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
|
@ -29,20 +27,13 @@ import com.pichillilorenzo.flutter_inappwebview.CredentialDatabase.Credential;
|
|||
import com.pichillilorenzo.flutter_inappwebview.CredentialDatabase.CredentialDatabase;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppBrowser.InAppBrowserActivity;
|
||||
import com.pichillilorenzo.flutter_inappwebview.JavaScriptBridgeInterface;
|
||||
import com.pichillilorenzo.flutter_inappwebview.Shared;
|
||||
import com.pichillilorenzo.flutter_inappwebview.Util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -185,8 +176,14 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
js += InAppWebView.resourceObserverJS.replaceAll("[\r\n]+", "");
|
||||
}
|
||||
js += InAppWebView.checkGlobalKeyDownEventToHideContextMenuJS.replaceAll("[\r\n]+", "");
|
||||
js += InAppWebView.onWindowFocusEventJS.replaceAll("[\r\n]+", "");
|
||||
js += InAppWebView.onWindowBlurEventJS.replaceAll("[\r\n]+", "");
|
||||
js += InAppWebView.printJS.replaceAll("[\r\n]+", "");
|
||||
|
||||
js = InAppWebView.scriptsWrapperJS
|
||||
.replace("$PLACEHOLDER_VALUE", js)
|
||||
.replaceAll("[\r\n]+", "");
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
webView.evaluateJavascript(js, (ValueCallback<String>) null);
|
||||
} else {
|
||||
|
@ -817,6 +814,18 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
return super.onRenderProcessGone(view, detail);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedLoginRequest(WebView view, String realm, String account, String args) {
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
obj.put("realm", realm);
|
||||
obj.put("account", account);
|
||||
obj.put("args", args);
|
||||
|
||||
channel.invokeMethod("onReceivedLoginRequest", obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.10/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1/","dependencies":[]}],"android":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.10/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+3/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+1/","dependencies":[]}],"windows":[],"web":[]},"dependencyGraph":[{"name":"e2e","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"permission_handler","dependencies":[]}],"date_created":"2020-06-23 10:38:00.775824","version":"1.17.4"}
|
||||
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.10/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1/","dependencies":[]}],"android":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.10/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+3/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+1/","dependencies":[]}],"windows":[],"web":[]},"dependencyGraph":[{"name":"e2e","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"permission_handler","dependencies":[]}],"date_created":"2020-06-29 16:24:39.876196","version":"1.17.4"}
|
|
@ -48,8 +48,9 @@ class InAppWebViewOnCreateWindowTestState extends WidgetTestState {
|
|||
});
|
||||
}
|
||||
},
|
||||
onCreateWindow: (InAppWebViewController controller, OnCreateWindowRequest onCreateWindowRequest) {
|
||||
controller.loadUrl(url: onCreateWindowRequest.url);
|
||||
onCreateWindow: (InAppWebViewController controller, CreateWindowRequest createWindowRequest) async {
|
||||
controller.loadUrl(url: createWindowRequest.url);
|
||||
return null;
|
||||
},
|
||||
),
|
||||
),
|
||||
|
|
|
@ -66,24 +66,23 @@ class InAppWebViewOnJsDialogTestState extends WidgetTestState {
|
|||
});
|
||||
},
|
||||
onJsAlert:
|
||||
(InAppWebViewController controller, String message) async {
|
||||
(InAppWebViewController controller, JsAlertRequest jsAlertRequest) async {
|
||||
JsAlertResponseAction action =
|
||||
await createAlertDialog(context, message);
|
||||
await createAlertDialog(context, jsAlertRequest.message);
|
||||
return JsAlertResponse(
|
||||
handledByClient: true, action: action);
|
||||
},
|
||||
onJsConfirm:
|
||||
(InAppWebViewController controller, String message) async {
|
||||
(InAppWebViewController controller, JsConfirmRequest jsConfirmRequest) async {
|
||||
JsConfirmResponseAction action =
|
||||
await createConfirmDialog(context, message);
|
||||
await createConfirmDialog(context, jsConfirmRequest.message);
|
||||
return JsConfirmResponse(
|
||||
handledByClient: true, action: action);
|
||||
},
|
||||
onJsPrompt: (InAppWebViewController controller, String message,
|
||||
String defaultValue) async {
|
||||
_textFieldController.text = defaultValue;
|
||||
onJsPrompt: (InAppWebViewController controller, JsPromptRequest jsPromptRequest) async {
|
||||
_textFieldController.text = jsPromptRequest.defaultValue;
|
||||
JsPromptResponseAction action =
|
||||
await createPromptDialog(context, message);
|
||||
await createPromptDialog(context, jsPromptRequest.message);
|
||||
return JsPromptResponse(
|
||||
handledByClient: true,
|
||||
action: action,
|
||||
|
|
|
@ -16,9 +16,6 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin {
|
|||
static var registrar: FlutterPluginRegistrar?
|
||||
static var channel: FlutterMethodChannel?
|
||||
|
||||
var tmpWindow: UIWindow?
|
||||
private var previousStatusBarStyle = -1
|
||||
|
||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||
|
||||
}
|
||||
|
@ -43,7 +40,10 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin {
|
|||
let headersFallback = arguments!["headersFallback"] as? [String: String]
|
||||
let optionsFallback = arguments!["optionsFallback"] as? [String: Any?]
|
||||
let contextMenuFallback = arguments!["contextMenuFallback"] as? [String: Any]
|
||||
open(uuid: uuid, url: url, options: options, menuItemList: menuItemList, uuidFallback: uuidFallback, headersFallback: headersFallback, optionsFallback: optionsFallback, contextMenuFallback: contextMenuFallback, result: result)
|
||||
let windowIdFallback = arguments!["windowIdFallback"] as? Int64
|
||||
open(uuid: uuid, url: url, options: options, menuItemList: menuItemList, uuidFallback: uuidFallback,
|
||||
headersFallback: headersFallback, optionsFallback: optionsFallback, contextMenuFallback: contextMenuFallback,
|
||||
windowIdFallback: windowIdFallback, result: result)
|
||||
break
|
||||
default:
|
||||
result(FlutterMethodNotImplemented)
|
||||
|
@ -51,51 +51,40 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
public func open(uuid: String, url: String, options: [String: Any?], menuItemList: [[String: Any]], uuidFallback: String?, headersFallback: [String: String]?, optionsFallback: [String: Any?]?, contextMenuFallback: [String: Any]?, result: @escaping FlutterResult) {
|
||||
public func open(uuid: String, url: String, options: [String: Any?], menuItemList: [[String: Any]], uuidFallback: String?,
|
||||
headersFallback: [String: String]?, optionsFallback: [String: Any?]?, contextMenuFallback: [String: Any]?,
|
||||
windowIdFallback: Int64?, result: @escaping FlutterResult) {
|
||||
let absoluteUrl = URL(string: url)!.absoluteURL
|
||||
|
||||
if self.previousStatusBarStyle == -1 {
|
||||
self.previousStatusBarStyle = UIApplication.shared.statusBarStyle.rawValue
|
||||
}
|
||||
|
||||
if !(self.tmpWindow != nil) {
|
||||
let frame: CGRect = UIScreen.main.bounds
|
||||
self.tmpWindow = UIWindow(frame: frame)
|
||||
}
|
||||
|
||||
let tmpController = UIViewController()
|
||||
let baseWindowLevel = UIApplication.shared.keyWindow?.windowLevel
|
||||
self.tmpWindow!.rootViewController = tmpController
|
||||
self.tmpWindow!.windowLevel = UIWindow.Level(baseWindowLevel!.rawValue + 1.0)
|
||||
self.tmpWindow!.makeKeyAndVisible()
|
||||
|
||||
if #available(iOS 9.0, *) {
|
||||
let safariOptions = SafariBrowserOptions()
|
||||
let _ = safariOptions.parse(options: options)
|
||||
|
||||
let safari: SafariViewController
|
||||
|
||||
if #available(iOS 11.0, *) {
|
||||
let config = SFSafariViewController.Configuration()
|
||||
config.entersReaderIfAvailable = safariOptions.entersReaderIfAvailable
|
||||
config.barCollapsingEnabled = safariOptions.barCollapsingEnabled
|
||||
if let flutterViewController = UIApplication.shared.delegate?.window.unsafelyUnwrapped?.rootViewController as? FlutterViewController {
|
||||
let safariOptions = SafariBrowserOptions()
|
||||
let _ = safariOptions.parse(options: options)
|
||||
|
||||
safari = SafariViewController(url: absoluteUrl, configuration: config)
|
||||
} else {
|
||||
// Fallback on earlier versions
|
||||
safari = SafariViewController(url: absoluteUrl)
|
||||
}
|
||||
|
||||
safari.uuid = uuid
|
||||
safari.menuItemList = menuItemList
|
||||
safari.prepareMethodChannel()
|
||||
safari.delegate = safari
|
||||
safari.tmpWindow = tmpWindow
|
||||
safari.safariOptions = safariOptions
|
||||
safari.prepareSafariBrowser()
|
||||
|
||||
tmpController.present(safari, animated: true) {
|
||||
result(true)
|
||||
let safari: SafariViewController
|
||||
|
||||
if #available(iOS 11.0, *) {
|
||||
let config = SFSafariViewController.Configuration()
|
||||
config.entersReaderIfAvailable = safariOptions.entersReaderIfAvailable
|
||||
config.barCollapsingEnabled = safariOptions.barCollapsingEnabled
|
||||
|
||||
safari = SafariViewController(url: absoluteUrl, configuration: config)
|
||||
} else {
|
||||
// Fallback on earlier versions
|
||||
safari = SafariViewController(url: absoluteUrl)
|
||||
}
|
||||
|
||||
safari.uuid = uuid
|
||||
safari.menuItemList = menuItemList
|
||||
safari.prepareMethodChannel()
|
||||
safari.delegate = safari
|
||||
safari.safariOptions = safariOptions
|
||||
safari.prepareSafariBrowser()
|
||||
|
||||
flutterViewController.present(safari, animated: true) {
|
||||
result(true)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -106,7 +95,7 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin {
|
|||
|
||||
return
|
||||
}
|
||||
SwiftFlutterPlugin.instance!.inAppBrowserManager!.openUrl(uuid: uuidFallback!, url: url, options: optionsFallback ?? [:], headers: headersFallback ?? [:], contextMenu: contextMenuFallback ?? [:])
|
||||
SwiftFlutterPlugin.instance!.inAppBrowserManager!.openUrl(uuid: uuidFallback!, url: url, options: optionsFallback ?? [:], headers: headersFallback ?? [:], contextMenu: contextMenuFallback ?? [:], windowId: windowIdFallback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,47 +39,62 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor
|
|||
let initialHeaders = args["initialHeaders"] as? [String: String]
|
||||
let initialOptions = args["initialOptions"] as! [String: Any?]
|
||||
let contextMenu = args["contextMenu"] as? [String: Any]
|
||||
let windowId = args["windowId"] as? Int64
|
||||
|
||||
let options = InAppWebViewOptions()
|
||||
let _ = options.parse(options: initialOptions)
|
||||
let preWebviewConfiguration = InAppWebView.preWKWebViewConfiguration(options: options)
|
||||
|
||||
if let wId = windowId, let webViewTransport = InAppWebView.windowWebViews[wId] {
|
||||
webView = webViewTransport.webView
|
||||
webView!.frame = myView!.bounds
|
||||
webView!.IABController = nil
|
||||
webView!.contextMenu = contextMenu
|
||||
webView!.channel = channel!
|
||||
} else {
|
||||
webView = InAppWebView(frame: myView!.bounds, configuration: preWebviewConfiguration, IABController: nil, contextMenu: contextMenu, channel: channel!)
|
||||
}
|
||||
|
||||
webView = InAppWebView(frame: myView!.bounds, configuration: preWebviewConfiguration, IABController: nil, contextMenu: contextMenu, channel: channel!)
|
||||
webView!.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
myView!.autoresizesSubviews = true
|
||||
myView!.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
myView!.addSubview(webView!)
|
||||
|
||||
|
||||
webView!.options = options
|
||||
webView!.prepare()
|
||||
|
||||
if windowId == nil {
|
||||
if #available(iOS 11.0, *) {
|
||||
self.webView!.configuration.userContentController.removeAllContentRuleLists()
|
||||
if let contentBlockers = webView!.options?.contentBlockers, contentBlockers.count > 0 {
|
||||
do {
|
||||
let jsonData = try JSONSerialization.data(withJSONObject: contentBlockers, options: [])
|
||||
let blockRules = String(data: jsonData, encoding: String.Encoding.utf8)
|
||||
WKContentRuleListStore.default().compileContentRuleList(
|
||||
forIdentifier: "ContentBlockingRules",
|
||||
encodedContentRuleList: blockRules) { (contentRuleList, error) in
|
||||
|
||||
if #available(iOS 11.0, *) {
|
||||
self.webView!.configuration.userContentController.removeAllContentRuleLists()
|
||||
if let contentBlockers = webView!.options?.contentBlockers, contentBlockers.count > 0 {
|
||||
do {
|
||||
let jsonData = try JSONSerialization.data(withJSONObject: contentBlockers, options: [])
|
||||
let blockRules = String(data: jsonData, encoding: String.Encoding.utf8)
|
||||
WKContentRuleListStore.default().compileContentRuleList(
|
||||
forIdentifier: "ContentBlockingRules",
|
||||
encodedContentRuleList: blockRules) { (contentRuleList, error) in
|
||||
if let error = error {
|
||||
print(error.localizedDescription)
|
||||
return
|
||||
}
|
||||
|
||||
if let error = error {
|
||||
print(error.localizedDescription)
|
||||
return
|
||||
}
|
||||
let configuration = self.webView!.configuration
|
||||
configuration.userContentController.add(contentRuleList!)
|
||||
|
||||
let configuration = self.webView!.configuration
|
||||
configuration.userContentController.add(contentRuleList!)
|
||||
|
||||
self.load(initialUrl: initialUrl, initialFile: initialFile, initialData: initialData, initialHeaders: initialHeaders)
|
||||
self.load(initialUrl: initialUrl, initialFile: initialFile, initialData: initialData, initialHeaders: initialHeaders)
|
||||
}
|
||||
return
|
||||
} catch {
|
||||
print(error.localizedDescription)
|
||||
}
|
||||
return
|
||||
} catch {
|
||||
print(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
load(initialUrl: initialUrl, initialFile: initialFile, initialData: initialData, initialHeaders: initialHeaders)
|
||||
}
|
||||
else if let wId = windowId, let webViewTransport = InAppWebView.windowWebViews[wId] {
|
||||
webView!.load(webViewTransport.request)
|
||||
}
|
||||
load(initialUrl: initialUrl, initialFile: initialFile, initialData: initialData, initialHeaders: initialHeaders)
|
||||
|
||||
if (frame.isEmpty && viewId is String) {
|
||||
/// Note: The WKWebView behaves very unreliable when rendering offscreen
|
||||
|
|
|
@ -18,7 +18,7 @@ public class InAppBrowserManager: NSObject, FlutterPlugin {
|
|||
static var registrar: FlutterPluginRegistrar?
|
||||
static var channel: FlutterMethodChannel?
|
||||
|
||||
var tmpWindow: UIWindow?
|
||||
// var tmpWindow: UIWindow?
|
||||
private var previousStatusBarStyle = -1
|
||||
|
||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||
|
@ -42,7 +42,8 @@ public class InAppBrowserManager: NSObject, FlutterPlugin {
|
|||
let options = arguments!["options"] as! [String: Any?]
|
||||
let headers = arguments!["headers"] as! [String: String]
|
||||
let contextMenu = arguments!["contextMenu"] as! [String: Any]
|
||||
openUrl(uuid: uuid, url: url, options: options, headers: headers, contextMenu: contextMenu)
|
||||
let windowId = arguments!["windowId"] as? Int64
|
||||
openUrl(uuid: uuid, url: url, options: options, headers: headers, contextMenu: contextMenu, windowId: windowId)
|
||||
result(true)
|
||||
break
|
||||
case "openFile":
|
||||
|
@ -59,7 +60,8 @@ public class InAppBrowserManager: NSObject, FlutterPlugin {
|
|||
let options = arguments!["options"] as! [String: Any?]
|
||||
let headers = arguments!["headers"] as! [String: String]
|
||||
let contextMenu = arguments!["contextMenu"] as! [String: Any]
|
||||
openUrl(uuid: uuid, url: url, options: options, headers: headers, contextMenu: contextMenu)
|
||||
let windowId = arguments!["windowId"] as? Int64
|
||||
openUrl(uuid: uuid, url: url, options: options, headers: headers, contextMenu: contextMenu, windowId: windowId)
|
||||
result(true)
|
||||
break
|
||||
case "openData":
|
||||
|
@ -70,7 +72,8 @@ public class InAppBrowserManager: NSObject, FlutterPlugin {
|
|||
let encoding = arguments!["encoding"] as! String
|
||||
let baseUrl = arguments!["baseUrl"] as! String
|
||||
let contextMenu = arguments!["contextMenu"] as! [String: Any]
|
||||
openData(uuid: uuid, options: options, data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl, contextMenu: contextMenu)
|
||||
let windowId = arguments!["windowId"] as? Int64
|
||||
openData(uuid: uuid, options: options, data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl, contextMenu: contextMenu, windowId: windowId)
|
||||
result(true)
|
||||
break
|
||||
case "openWithSystemBrowser":
|
||||
|
@ -88,16 +91,14 @@ public class InAppBrowserManager: NSObject, FlutterPlugin {
|
|||
self.previousStatusBarStyle = UIApplication.shared.statusBarStyle.rawValue
|
||||
}
|
||||
|
||||
if !(self.tmpWindow != nil) {
|
||||
let frame: CGRect = UIScreen.main.bounds
|
||||
self.tmpWindow = UIWindow(frame: frame)
|
||||
}
|
||||
let frame: CGRect = UIScreen.main.bounds
|
||||
let tmpWindow = UIWindow(frame: frame)
|
||||
|
||||
let tmpController = UIViewController()
|
||||
let baseWindowLevel = UIApplication.shared.keyWindow?.windowLevel
|
||||
self.tmpWindow!.rootViewController = tmpController
|
||||
self.tmpWindow!.windowLevel = UIWindow.Level(baseWindowLevel!.rawValue + 1.0)
|
||||
self.tmpWindow!.makeKeyAndVisible()
|
||||
tmpWindow.rootViewController = tmpController
|
||||
tmpWindow.windowLevel = UIWindow.Level(baseWindowLevel!.rawValue + 1.0)
|
||||
tmpWindow.makeKeyAndVisible()
|
||||
|
||||
let browserOptions = InAppBrowserOptions()
|
||||
let _ = browserOptions.parse(options: options)
|
||||
|
@ -107,6 +108,7 @@ public class InAppBrowserManager: NSObject, FlutterPlugin {
|
|||
|
||||
let storyboard = UIStoryboard(name: WEBVIEW_STORYBOARD, bundle: Bundle(for: InAppWebViewFlutterPlugin.self))
|
||||
let webViewController = storyboard.instantiateViewController(withIdentifier: WEBVIEW_STORYBOARD_CONTROLLER_ID) as! InAppBrowserWebViewController
|
||||
webViewController.tmpWindow = tmpWindow
|
||||
webViewController.browserOptions = browserOptions
|
||||
webViewController.webViewOptions = webViewOptions
|
||||
webViewController.isHidden = browserOptions.hidden
|
||||
|
@ -115,57 +117,60 @@ public class InAppBrowserManager: NSObject, FlutterPlugin {
|
|||
return webViewController
|
||||
}
|
||||
|
||||
public func openUrl(uuid: String, url: String, options: [String: Any?], headers: [String: String], contextMenu: [String: Any]) {
|
||||
public func openUrl(uuid: String, url: String, options: [String: Any?], headers: [String: String],
|
||||
contextMenu: [String: Any], windowId: Int64?) {
|
||||
let absoluteUrl = URL(string: url)!.absoluteURL
|
||||
let webViewController = prepareInAppBrowserWebViewController(options: options)
|
||||
|
||||
webViewController.uuid = uuid
|
||||
webViewController.prepareMethodChannel()
|
||||
webViewController.tmpWindow = tmpWindow
|
||||
webViewController.initURL = absoluteUrl
|
||||
webViewController.initHeaders = headers
|
||||
webViewController.contextMenu = contextMenu
|
||||
webViewController.windowId = windowId
|
||||
|
||||
if webViewController.isHidden {
|
||||
webViewController.view.isHidden = true
|
||||
tmpWindow!.rootViewController!.present(webViewController, animated: false, completion: {() -> Void in
|
||||
webViewController.tmpWindow!.rootViewController!.present(webViewController, animated: false, completion: {() -> Void in
|
||||
|
||||
})
|
||||
webViewController.presentingViewController?.dismiss(animated: false, completion: {() -> Void in
|
||||
self.tmpWindow?.windowLevel = UIWindow.Level(rawValue: 0.0)
|
||||
webViewController.tmpWindow?.windowLevel = UIWindow.Level(rawValue: 0.0)
|
||||
UIApplication.shared.delegate?.window??.makeKeyAndVisible()
|
||||
})
|
||||
}
|
||||
else {
|
||||
tmpWindow!.rootViewController!.present(webViewController, animated: true, completion: {() -> Void in
|
||||
webViewController.tmpWindow!.rootViewController!.present(webViewController, animated: true, completion: {() -> Void in
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
public func openData(uuid: String, options: [String: Any?], data: String, mimeType: String, encoding: String, baseUrl: String, contextMenu: [String: Any]) {
|
||||
public func openData(uuid: String, options: [String: Any?], data: String, mimeType: String, encoding: String,
|
||||
baseUrl: String, contextMenu: [String: Any], windowId: Int64?) {
|
||||
let webViewController = prepareInAppBrowserWebViewController(options: options)
|
||||
|
||||
webViewController.uuid = uuid
|
||||
webViewController.tmpWindow = tmpWindow
|
||||
webViewController.prepareMethodChannel()
|
||||
webViewController.initData = data
|
||||
webViewController.initMimeType = mimeType
|
||||
webViewController.initEncoding = encoding
|
||||
webViewController.initBaseUrl = baseUrl
|
||||
webViewController.contextMenu = contextMenu
|
||||
webViewController.windowId = windowId
|
||||
|
||||
if webViewController.isHidden {
|
||||
webViewController.view.isHidden = true
|
||||
tmpWindow!.rootViewController!.present(webViewController, animated: false, completion: {() -> Void in
|
||||
webViewController.tmpWindow!.rootViewController!.present(webViewController, animated: false, completion: {() -> Void in
|
||||
webViewController.webView.loadData(data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl)
|
||||
})
|
||||
webViewController.presentingViewController?.dismiss(animated: false, completion: {() -> Void in
|
||||
self.tmpWindow?.windowLevel = UIWindow.Level(rawValue: 0.0)
|
||||
webViewController.tmpWindow?.windowLevel = UIWindow.Level(rawValue: 0.0)
|
||||
UIApplication.shared.delegate?.window??.makeKeyAndVisible()
|
||||
})
|
||||
}
|
||||
else {
|
||||
tmpWindow!.rootViewController!.present(webViewController, animated: true, completion: {() -> Void in
|
||||
webViewController.tmpWindow!.rootViewController!.present(webViewController, animated: true, completion: {() -> Void in
|
||||
webViewController.webView.loadData(data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -14,17 +14,16 @@ import AVFoundation
|
|||
typealias OlderClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, Bool, Bool, Any?) -> Void
|
||||
typealias NewerClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, Bool, Bool, Bool, Any?) -> Void
|
||||
|
||||
public class InAppWebView_IBWrapper: InAppWebView {
|
||||
required init(coder: NSCoder) {
|
||||
let config = WKWebViewConfiguration()
|
||||
super.init(frame: .zero, configuration: config, IABController: nil, contextMenu: nil, channel: nil)
|
||||
public class InAppWebView_IBWrapper: UIView {
|
||||
required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
self.translatesAutoresizingMaskIntoConstraints = false
|
||||
}
|
||||
}
|
||||
|
||||
public class InAppBrowserWebViewController: UIViewController, FlutterPlugin, UIScrollViewDelegate, WKUIDelegate, UITextFieldDelegate {
|
||||
|
||||
@IBOutlet var containerWebView: UIView!
|
||||
@IBOutlet var containerWebView: InAppWebView_IBWrapper!
|
||||
@IBOutlet var closeButton: UIButton!
|
||||
@IBOutlet var reloadButton: UIBarButtonItem!
|
||||
@IBOutlet var backButton: UIBarButtonItem!
|
||||
|
@ -43,6 +42,7 @@ public class InAppBrowserWebViewController: UIViewController, FlutterPlugin, UIS
|
|||
@IBOutlet var webView_TopFullScreenConstraint: NSLayoutConstraint!
|
||||
|
||||
var uuid: String = ""
|
||||
var windowId: Int64?
|
||||
var webView: InAppWebView!
|
||||
var channel: FlutterMethodChannel?
|
||||
var initURL: URL?
|
||||
|
@ -385,42 +385,58 @@ public class InAppBrowserWebViewController: UIViewController, FlutterPlugin, UIS
|
|||
|
||||
public override func viewWillAppear(_ animated: Bool) {
|
||||
if !viewPrepared {
|
||||
print(containerWebView)
|
||||
let preWebviewConfiguration = InAppWebView.preWKWebViewConfiguration(options: webViewOptions)
|
||||
self.webView = InAppWebView(frame: .zero, configuration: preWebviewConfiguration, IABController: self, contextMenu: contextMenu, channel: channel!)
|
||||
if let wId = windowId, let webViewTransport = InAppWebView.windowWebViews[wId] {
|
||||
self.webView = webViewTransport.webView
|
||||
self.webView.IABController = self
|
||||
self.webView.contextMenu = contextMenu
|
||||
self.webView.channel = channel!
|
||||
} else {
|
||||
self.webView = InAppWebView(frame: .zero,
|
||||
configuration: preWebviewConfiguration,
|
||||
IABController: self,
|
||||
contextMenu: contextMenu,
|
||||
channel: channel!)
|
||||
}
|
||||
self.containerWebView.addSubview(self.webView)
|
||||
prepareConstraints()
|
||||
prepareWebView()
|
||||
|
||||
if #available(iOS 11.0, *) {
|
||||
if let contentBlockers = webView.options?.contentBlockers, contentBlockers.count > 0 {
|
||||
do {
|
||||
let jsonData = try JSONSerialization.data(withJSONObject: contentBlockers, options: [])
|
||||
let blockRules = String(data: jsonData, encoding: String.Encoding.utf8)
|
||||
WKContentRuleListStore.default().compileContentRuleList(
|
||||
forIdentifier: "ContentBlockingRules",
|
||||
encodedContentRuleList: blockRules) { (contentRuleList, error) in
|
||||
|
||||
if let error = error {
|
||||
print(error.localizedDescription)
|
||||
return
|
||||
}
|
||||
|
||||
let configuration = self.webView!.configuration
|
||||
configuration.userContentController.add(contentRuleList!)
|
||||
|
||||
self.initLoad(initURL: self.initURL, initData: self.initData, initMimeType: self.initMimeType, initEncoding: self.initEncoding, initBaseUrl: self.initBaseUrl, initHeaders: self.initHeaders)
|
||||
|
||||
self.onBrowserCreated()
|
||||
if let wId = windowId, let webViewTransport = InAppWebView.windowWebViews[wId] {
|
||||
self.webView.load(webViewTransport.request)
|
||||
} else {
|
||||
if #available(iOS 11.0, *) {
|
||||
if let contentBlockers = webView.options?.contentBlockers, contentBlockers.count > 0 {
|
||||
do {
|
||||
let jsonData = try JSONSerialization.data(withJSONObject: contentBlockers, options: [])
|
||||
let blockRules = String(data: jsonData, encoding: String.Encoding.utf8)
|
||||
WKContentRuleListStore.default().compileContentRuleList(
|
||||
forIdentifier: "ContentBlockingRules",
|
||||
encodedContentRuleList: blockRules) { (contentRuleList, error) in
|
||||
|
||||
if let error = error {
|
||||
print(error.localizedDescription)
|
||||
return
|
||||
}
|
||||
|
||||
let configuration = self.webView!.configuration
|
||||
configuration.userContentController.add(contentRuleList!)
|
||||
|
||||
self.initLoad(initURL: self.initURL, initData: self.initData, initMimeType: self.initMimeType, initEncoding: self.initEncoding, initBaseUrl: self.initBaseUrl, initHeaders: self.initHeaders)
|
||||
|
||||
self.onBrowserCreated()
|
||||
}
|
||||
return
|
||||
} catch {
|
||||
print(error.localizedDescription)
|
||||
}
|
||||
return
|
||||
} catch {
|
||||
print(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
|
||||
initLoad(initURL: initURL, initData: initData, initMimeType: initMimeType, initEncoding: initEncoding, initBaseUrl: initBaseUrl, initHeaders: initHeaders)
|
||||
}
|
||||
|
||||
initLoad(initURL: initURL, initData: initData, initMimeType: initMimeType, initEncoding: initEncoding, initBaseUrl: initBaseUrl, initHeaders: initHeaders)
|
||||
|
||||
onBrowserCreated()
|
||||
}
|
||||
viewPrepared = true
|
||||
|
|
|
@ -791,10 +791,37 @@ window.\(JAVASCRIPT_BRIDGE_NAME)._originalViewPortMetaTagContent = "";
|
|||
})();
|
||||
"""
|
||||
|
||||
let onWindowFocusEventJS = """
|
||||
(function(){
|
||||
window.addEventListener('focus', function(e) {
|
||||
window.\(JAVASCRIPT_BRIDGE_NAME).callHandler('onWindowFocus');
|
||||
});
|
||||
})();
|
||||
"""
|
||||
|
||||
let onWindowBlurEventJS = """
|
||||
(function(){
|
||||
window.addEventListener('blur', function(e) {
|
||||
window.\(JAVASCRIPT_BRIDGE_NAME).callHandler('onWindowBlur');
|
||||
});
|
||||
})();
|
||||
"""
|
||||
|
||||
var SharedLastTouchPointTimestamp: [InAppWebView: Int64] = [:]
|
||||
|
||||
public class WebViewTransport: NSObject {
|
||||
var webView: InAppWebView
|
||||
var request: URLRequest
|
||||
|
||||
init(webView: InAppWebView, request: URLRequest) {
|
||||
self.webView = webView
|
||||
self.request = request
|
||||
}
|
||||
}
|
||||
|
||||
public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler, UIGestureRecognizerDelegate {
|
||||
|
||||
var windowId: Int64?
|
||||
var IABController: InAppBrowserWebViewController?
|
||||
var channel: FlutterMethodChannel?
|
||||
var options: InAppWebViewOptions?
|
||||
|
@ -826,6 +853,9 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
|
||||
var customIMPs: [IMP] = []
|
||||
|
||||
static var windowWebViews: [Int64:WebViewTransport] = [:]
|
||||
static var windowAutoincrementId: Int64 = 0;
|
||||
|
||||
init(frame: CGRect, configuration: WKWebViewConfiguration, IABController: InAppBrowserWebViewController?, contextMenu: [String: Any]?, channel: FlutterMethodChannel?) {
|
||||
super.init(frame: frame, configuration: configuration)
|
||||
self.channel = channel
|
||||
|
@ -1000,6 +1030,11 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
forKeyPath: #keyPath(WKWebView.url),
|
||||
options: [.new, .old],
|
||||
context: nil)
|
||||
|
||||
addObserver(self,
|
||||
forKeyPath: #keyPath(WKWebView.title),
|
||||
options: [.new, .old],
|
||||
context: nil)
|
||||
|
||||
NotificationCenter.default.addObserver(
|
||||
self,
|
||||
|
@ -1026,9 +1061,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
name: UIWindow.didBecomeHiddenNotification,
|
||||
object: window)
|
||||
|
||||
configuration.userContentController = WKUserContentController()
|
||||
configuration.preferences = WKPreferences()
|
||||
|
||||
if let options = options {
|
||||
if options.transparentBackground {
|
||||
isOpaque = false
|
||||
|
@ -1050,6 +1082,55 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
}
|
||||
}
|
||||
|
||||
if #available(iOS 11.0, *) {
|
||||
accessibilityIgnoresInvertColors = options.accessibilityIgnoresInvertColors
|
||||
scrollView.contentInsetAdjustmentBehavior =
|
||||
UIScrollView.ContentInsetAdjustmentBehavior.init(rawValue: options.contentInsetAdjustmentBehavior)!
|
||||
}
|
||||
|
||||
allowsBackForwardNavigationGestures = options.allowsBackForwardNavigationGestures
|
||||
if #available(iOS 9.0, *) {
|
||||
allowsLinkPreview = options.allowsLinkPreview
|
||||
if !options.userAgent.isEmpty {
|
||||
customUserAgent = options.userAgent
|
||||
}
|
||||
}
|
||||
|
||||
if #available(iOS 13.0, *) {
|
||||
scrollView.automaticallyAdjustsScrollIndicatorInsets = options.automaticallyAdjustsScrollIndicatorInsets
|
||||
}
|
||||
|
||||
scrollView.showsVerticalScrollIndicator = !options.disableVerticalScroll
|
||||
scrollView.showsHorizontalScrollIndicator = !options.disableHorizontalScroll
|
||||
scrollView.showsVerticalScrollIndicator = options.verticalScrollBarEnabled
|
||||
scrollView.showsHorizontalScrollIndicator = options.horizontalScrollBarEnabled
|
||||
|
||||
scrollView.decelerationRate = InAppWebView.getDecelerationRate(type: options.decelerationRate)
|
||||
scrollView.alwaysBounceVertical = options.alwaysBounceVertical
|
||||
scrollView.alwaysBounceHorizontal = options.alwaysBounceHorizontal
|
||||
scrollView.scrollsToTop = options.scrollsToTop
|
||||
scrollView.isPagingEnabled = options.isPagingEnabled
|
||||
scrollView.maximumZoomScale = CGFloat(options.maximumZoomScale)
|
||||
scrollView.minimumZoomScale = CGFloat(options.minimumZoomScale)
|
||||
|
||||
// options.debuggingEnabled is always enabled for iOS,
|
||||
// there isn't any option to set about it such as on Android.
|
||||
|
||||
if options.clearCache {
|
||||
clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
if windowId != nil {
|
||||
// the new created window webview has the same WKWebViewConfiguration variable reference
|
||||
return
|
||||
}
|
||||
|
||||
configuration.userContentController = WKUserContentController()
|
||||
configuration.preferences = WKPreferences()
|
||||
|
||||
if let options = options {
|
||||
|
||||
let originalViewPortMetaTagContentJSScript = WKUserScript(source: originalViewPortMetaTagContentJS, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
|
||||
configuration.userContentController.addUserScript(originalViewPortMetaTagContentJSScript)
|
||||
|
||||
|
@ -1096,6 +1177,12 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
configuration.userContentController.addUserScript(findTextHighlightJSScript)
|
||||
configuration.userContentController.add(self, name: "onFindResultReceived")
|
||||
|
||||
let onWindowFocusEventJSScript = WKUserScript(source: onWindowFocusEventJS, injectionTime: .atDocumentStart, forMainFrameOnly: false)
|
||||
configuration.userContentController.addUserScript(onWindowFocusEventJSScript)
|
||||
|
||||
let onWindowBlurEventJSScript = WKUserScript(source: onWindowBlurEventJS, injectionTime: .atDocumentStart, forMainFrameOnly: false)
|
||||
configuration.userContentController.addUserScript(onWindowBlurEventJSScript)
|
||||
|
||||
if options.useShouldInterceptAjaxRequest {
|
||||
let interceptAjaxRequestsJSScript = WKUserScript(source: interceptAjaxRequestsJS, injectionTime: .atDocumentStart, forMainFrameOnly: false)
|
||||
configuration.userContentController.addUserScript(interceptAjaxRequestsJSScript)
|
||||
|
@ -1106,23 +1193,12 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
configuration.userContentController.addUserScript(interceptFetchRequestsJSScript)
|
||||
}
|
||||
|
||||
if #available(iOS 11.0, *) {
|
||||
accessibilityIgnoresInvertColors = options.accessibilityIgnoresInvertColors
|
||||
scrollView.contentInsetAdjustmentBehavior =
|
||||
UIScrollView.ContentInsetAdjustmentBehavior.init(rawValue: options.contentInsetAdjustmentBehavior)!
|
||||
}
|
||||
|
||||
allowsBackForwardNavigationGestures = options.allowsBackForwardNavigationGestures
|
||||
if #available(iOS 9.0, *) {
|
||||
allowsLinkPreview = options.allowsLinkPreview
|
||||
configuration.allowsAirPlayForMediaPlayback = options.allowsAirPlayForMediaPlayback
|
||||
configuration.allowsPictureInPictureMediaPlayback = options.allowsPictureInPictureMediaPlayback
|
||||
if !options.applicationNameForUserAgent.isEmpty {
|
||||
configuration.applicationNameForUserAgent = options.applicationNameForUserAgent
|
||||
}
|
||||
if !options.userAgent.isEmpty {
|
||||
customUserAgent = options.userAgent
|
||||
}
|
||||
}
|
||||
|
||||
configuration.preferences.javaScriptCanOpenWindowsAutomatically = options.javaScriptCanOpenWindowsAutomatically
|
||||
|
@ -1132,26 +1208,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
if #available(iOS 13.0, *) {
|
||||
configuration.preferences.isFraudulentWebsiteWarningEnabled = options.isFraudulentWebsiteWarningEnabled
|
||||
configuration.defaultWebpagePreferences.preferredContentMode = WKWebpagePreferences.ContentMode(rawValue: options.preferredContentMode)!
|
||||
scrollView.automaticallyAdjustsScrollIndicatorInsets = options.automaticallyAdjustsScrollIndicatorInsets
|
||||
}
|
||||
|
||||
scrollView.showsVerticalScrollIndicator = !options.disableVerticalScroll
|
||||
scrollView.showsHorizontalScrollIndicator = !options.disableHorizontalScroll
|
||||
scrollView.showsVerticalScrollIndicator = options.verticalScrollBarEnabled
|
||||
scrollView.showsHorizontalScrollIndicator = options.horizontalScrollBarEnabled
|
||||
|
||||
scrollView.decelerationRate = InAppWebView.getDecelerationRate(type: options.decelerationRate)
|
||||
scrollView.alwaysBounceVertical = options.alwaysBounceVertical
|
||||
scrollView.alwaysBounceHorizontal = options.alwaysBounceHorizontal
|
||||
scrollView.scrollsToTop = options.scrollsToTop
|
||||
scrollView.isPagingEnabled = options.isPagingEnabled
|
||||
scrollView.maximumZoomScale = CGFloat(options.maximumZoomScale)
|
||||
scrollView.minimumZoomScale = CGFloat(options.minimumZoomScale)
|
||||
|
||||
// options.debuggingEnabled is always enabled for iOS.
|
||||
|
||||
if options.clearCache {
|
||||
clearCache()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1348,8 +1404,11 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
onProgressChanged(progress: progress)
|
||||
} else if keyPath == #keyPath(WKWebView.url) && change?[NSKeyValueChangeKey.newKey] is URL {
|
||||
let newUrl = change?[NSKeyValueChangeKey.newKey] as? URL
|
||||
onUpdateVisitedHistory(url: newUrl!.absoluteString)
|
||||
}
|
||||
onUpdateVisitedHistory(url: newUrl?.absoluteString)
|
||||
} else if keyPath == #keyPath(WKWebView.title) && change?[NSKeyValueChangeKey.newKey] is String {
|
||||
let newTitle = change?[NSKeyValueChangeKey.newKey] as? String
|
||||
onTitleChanged(title: newTitle)
|
||||
}
|
||||
replaceGestureHandlerIfNeeded()
|
||||
}
|
||||
|
||||
|
@ -1831,7 +1890,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
if navigationAction.navigationType == .linkActivated || navigationAction.navigationType == .backForward {
|
||||
currentURL = url
|
||||
if IABController != nil {
|
||||
IABController!.updateUrlTextField(url: (currentURL?.absoluteString)!)
|
||||
IABController!.updateUrlTextField(url: currentURL?.absoluteString ?? "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1841,7 +1900,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
|
||||
if navigationResponse.isForMainFrame, let response = navigationResponse.response as? HTTPURLResponse {
|
||||
if response.statusCode >= 400 {
|
||||
onLoadHttpError(url: response.url!.absoluteString, statusCode: response.statusCode, description: "")
|
||||
onLoadHttpError(url: response.url?.absoluteString, statusCode: response.statusCode, description: "")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1863,7 +1922,8 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
self.x509CertificateData = nil
|
||||
|
||||
self.startPageTime = currentTimeInMilliSeconds()
|
||||
onLoadStart(url: (currentURL?.absoluteString)!)
|
||||
|
||||
onLoadStart(url: url?.absoluteString)
|
||||
|
||||
if IABController != nil {
|
||||
// loading url, start spinner, update back/forward
|
||||
|
@ -1880,10 +1940,10 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
currentURL = url
|
||||
InAppWebView.credentialsProposed = []
|
||||
evaluateJavaScript(platformReadyJS, completionHandler: nil)
|
||||
onLoadStop(url: (currentURL?.absoluteString)!)
|
||||
onLoadStop(url: url?.absoluteString)
|
||||
|
||||
if IABController != nil {
|
||||
IABController!.updateUrlTextField(url: (currentURL?.absoluteString)!)
|
||||
IABController!.updateUrlTextField(url: currentURL?.absoluteString ?? "")
|
||||
IABController!.backButton.isEnabled = canGoBack
|
||||
IABController!.forwardButton.isEnabled = canGoForward
|
||||
IABController!.spinner.stopAnimating()
|
||||
|
@ -1899,7 +1959,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
public func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
|
||||
InAppWebView.credentialsProposed = []
|
||||
|
||||
onLoadError(url: (currentURL?.absoluteString)!, error: error)
|
||||
onLoadError(url: url?.absoluteString, error: error)
|
||||
|
||||
if IABController != nil {
|
||||
IABController!.backButton.isEnabled = canGoBack
|
||||
|
@ -2138,7 +2198,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
return
|
||||
}
|
||||
|
||||
onJsAlert(message: message, result: {(result) -> Void in
|
||||
onJsAlert(frame: frame, message: message, result: {(result) -> Void in
|
||||
if result is FlutterError {
|
||||
print((result as! FlutterError).message ?? "")
|
||||
}
|
||||
|
@ -2195,8 +2255,8 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
|
||||
public func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo,
|
||||
completionHandler: @escaping (Bool) -> Void) {
|
||||
|
||||
onJsConfirm(message: message, result: {(result) -> Void in
|
||||
|
||||
onJsConfirm(frame: frame, message: message, result: {(result) -> Void in
|
||||
if result is FlutterError {
|
||||
print((result as! FlutterError).message ?? "")
|
||||
}
|
||||
|
@ -2268,7 +2328,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
|
||||
public func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt message: String, defaultText defaultValue: String?, initiatedByFrame frame: WKFrameInfo,
|
||||
completionHandler: @escaping (String?) -> Void) {
|
||||
onJsPrompt(message: message, defaultValue: defaultValue, result: {(result) -> Void in
|
||||
onJsPrompt(frame: frame, message: message, defaultValue: defaultValue, result: {(result) -> Void in
|
||||
if result is FlutterError {
|
||||
print((result as! FlutterError).message ?? "")
|
||||
}
|
||||
|
@ -2341,8 +2401,56 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
createWebViewWith configuration: WKWebViewConfiguration,
|
||||
for navigationAction: WKNavigationAction,
|
||||
windowFeatures: WKWindowFeatures) -> WKWebView? {
|
||||
onCreateWindow(url: navigationAction.request.url!, navigationType: navigationAction.navigationType)
|
||||
return nil
|
||||
InAppWebView.windowAutoincrementId += 1
|
||||
let windowId = InAppWebView.windowAutoincrementId
|
||||
|
||||
let windowWebView = InAppWebView(frame: CGRect.zero, configuration: configuration, IABController: nil, contextMenu: nil, channel: nil)
|
||||
windowWebView.windowId = windowId
|
||||
|
||||
let webViewTransport = WebViewTransport(
|
||||
webView: windowWebView,
|
||||
request: navigationAction.request
|
||||
)
|
||||
|
||||
InAppWebView.windowWebViews[windowId] = webViewTransport
|
||||
windowWebView.stopLoading()
|
||||
|
||||
let arguments: [String: Any?] = [
|
||||
"url": navigationAction.request.url?.absoluteString,
|
||||
"windowId": windowId,
|
||||
"androidIsDialog": nil,
|
||||
"androidIsUserGesture": nil,
|
||||
"iosWKNavigationType": navigationAction.navigationType.rawValue,
|
||||
"iosIsForMainFrame": navigationAction.targetFrame?.isMainFrame ?? false
|
||||
]
|
||||
channel?.invokeMethod("onCreateWindow", arguments: arguments, result: { (result) -> Void in
|
||||
if result is FlutterError {
|
||||
print((result as! FlutterError).message ?? "")
|
||||
if InAppWebView.windowWebViews[windowId] != nil {
|
||||
InAppWebView.windowWebViews.removeValue(forKey: windowId)
|
||||
}
|
||||
return
|
||||
}
|
||||
else if (result as? NSObject) == FlutterMethodNotImplemented {
|
||||
self.updateUrlTextFieldForIABController(navigationAction: navigationAction)
|
||||
if InAppWebView.windowWebViews[windowId] != nil {
|
||||
InAppWebView.windowWebViews.removeValue(forKey: windowId)
|
||||
}
|
||||
return
|
||||
}
|
||||
else {
|
||||
if result == nil, InAppWebView.windowWebViews[windowId] != nil {
|
||||
InAppWebView.windowWebViews.removeValue(forKey: windowId)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return windowWebView
|
||||
}
|
||||
|
||||
public func webViewDidClose(_ webView: WKWebView) {
|
||||
let arguments: [String: Any?] = [:]
|
||||
channel?.invokeMethod("onCloseWindow", arguments: arguments)
|
||||
}
|
||||
|
||||
public func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
|
||||
|
@ -2461,23 +2569,23 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
// //onContextMenuWillPresentForElement(linkURL: elementInfo.linkURL?.absoluteString)
|
||||
// }
|
||||
|
||||
public func onLoadStart(url: String) {
|
||||
let arguments: [String: Any] = ["url": url]
|
||||
public func onLoadStart(url: String?) {
|
||||
let arguments: [String: Any?] = ["url": url]
|
||||
channel?.invokeMethod("onLoadStart", arguments: arguments)
|
||||
}
|
||||
|
||||
public func onLoadStop(url: String) {
|
||||
let arguments: [String: Any] = ["url": url]
|
||||
public func onLoadStop(url: String?) {
|
||||
let arguments: [String: Any?] = ["url": url]
|
||||
channel?.invokeMethod("onLoadStop", arguments: arguments)
|
||||
}
|
||||
|
||||
public func onLoadError(url: String, error: Error) {
|
||||
let arguments: [String: Any] = ["url": url, "code": error._code, "message": error.localizedDescription]
|
||||
public func onLoadError(url: String?, error: Error) {
|
||||
let arguments: [String: Any?] = ["url": url, "code": error._code, "message": error.localizedDescription]
|
||||
channel?.invokeMethod("onLoadError", arguments: arguments)
|
||||
}
|
||||
|
||||
public func onLoadHttpError(url: String, statusCode: Int, description: String) {
|
||||
let arguments: [String: Any] = ["url": url, "statusCode": statusCode, "description": description]
|
||||
public func onLoadHttpError(url: String?, statusCode: Int, description: String) {
|
||||
let arguments: [String: Any?] = ["url": url, "statusCode": statusCode, "description": description]
|
||||
channel?.invokeMethod("onLoadHttpError", arguments: arguments)
|
||||
}
|
||||
|
||||
|
@ -2523,16 +2631,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
channel?.invokeMethod("shouldOverrideUrlLoading", arguments: arguments, result: result)
|
||||
}
|
||||
|
||||
public func onCreateWindow(url: URL, navigationType: WKNavigationType) {
|
||||
let arguments: [String: Any?] = [
|
||||
"url": url.absoluteString,
|
||||
"androidIsDialog": nil,
|
||||
"androidIsUserGesture": nil,
|
||||
"iosWKNavigationType": navigationType.rawValue
|
||||
]
|
||||
channel?.invokeMethod("onCreateWindow", arguments: arguments)
|
||||
}
|
||||
|
||||
public func onReceivedHttpAuthRequest(challenge: URLAuthenticationChallenge, result: FlutterResult?) {
|
||||
let arguments: [String: Any?] = [
|
||||
"host": challenge.protectionSpace.host,
|
||||
|
@ -2613,18 +2711,31 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
channel?.invokeMethod("onReceivedClientCertRequest", arguments: arguments, result: result)
|
||||
}
|
||||
|
||||
public func onJsAlert(message: String, result: FlutterResult?) {
|
||||
let arguments: [String: Any] = ["message": message]
|
||||
public func onJsAlert(frame: WKFrameInfo, message: String, result: FlutterResult?) {
|
||||
let arguments: [String: Any?] = [
|
||||
"url": frame.request.url?.absoluteString,
|
||||
"message": message,
|
||||
"iosIsMainFrame": frame.isMainFrame
|
||||
]
|
||||
channel?.invokeMethod("onJsAlert", arguments: arguments, result: result)
|
||||
}
|
||||
|
||||
public func onJsConfirm(message: String, result: FlutterResult?) {
|
||||
let arguments: [String: Any] = ["message": message]
|
||||
public func onJsConfirm(frame: WKFrameInfo, message: String, result: FlutterResult?) {
|
||||
let arguments: [String: Any?] = [
|
||||
"url": frame.request.url?.absoluteString,
|
||||
"message": message,
|
||||
"iosIsMainFrame": frame.isMainFrame
|
||||
]
|
||||
channel?.invokeMethod("onJsConfirm", arguments: arguments, result: result)
|
||||
}
|
||||
|
||||
public func onJsPrompt(message: String, defaultValue: String?, result: FlutterResult?) {
|
||||
let arguments: [String: Any] = ["message": message, "defaultValue": defaultValue as Any]
|
||||
public func onJsPrompt(frame: WKFrameInfo, message: String, defaultValue: String?, result: FlutterResult?) {
|
||||
let arguments: [String: Any?] = [
|
||||
"url": frame.request.url?.absoluteString,
|
||||
"message": message,
|
||||
"defaultValue": defaultValue as Any,
|
||||
"iosIsMainFrame": frame.isMainFrame
|
||||
]
|
||||
channel?.invokeMethod("onJsPrompt", arguments: arguments, result: result)
|
||||
}
|
||||
|
||||
|
@ -2633,7 +2744,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
channel?.invokeMethod("onConsoleMessage", arguments: arguments)
|
||||
}
|
||||
|
||||
public func onUpdateVisitedHistory(url: String) {
|
||||
public func onUpdateVisitedHistory(url: String?) {
|
||||
let arguments: [String: Any?] = [
|
||||
"url": url,
|
||||
"androidIsReload": nil
|
||||
|
@ -2641,6 +2752,13 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
channel?.invokeMethod("onUpdateVisitedHistory", arguments: arguments)
|
||||
}
|
||||
|
||||
public func onTitleChanged(title: String?) {
|
||||
let arguments: [String: Any?] = [
|
||||
"title": title
|
||||
]
|
||||
channel?.invokeMethod("onTitleChanged", arguments: arguments)
|
||||
}
|
||||
|
||||
public func onLongPressHitTestResult(hitTestResult: [String: Any?]) {
|
||||
let arguments: [String: Any?] = [
|
||||
"hitTestResult": hitTestResult
|
||||
|
@ -2929,19 +3047,22 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
completionHandler()
|
||||
}
|
||||
stopLoading()
|
||||
configuration.userContentController.removeScriptMessageHandler(forName: "consoleLog")
|
||||
configuration.userContentController.removeScriptMessageHandler(forName: "consoleDebug")
|
||||
configuration.userContentController.removeScriptMessageHandler(forName: "consoleError")
|
||||
configuration.userContentController.removeScriptMessageHandler(forName: "consoleInfo")
|
||||
configuration.userContentController.removeScriptMessageHandler(forName: "consoleWarn")
|
||||
configuration.userContentController.removeScriptMessageHandler(forName: "callHandler")
|
||||
configuration.userContentController.removeScriptMessageHandler(forName: "onFindResultReceived")
|
||||
configuration.userContentController.removeAllUserScripts()
|
||||
if windowId == nil {
|
||||
configuration.userContentController.removeScriptMessageHandler(forName: "consoleLog")
|
||||
configuration.userContentController.removeScriptMessageHandler(forName: "consoleDebug")
|
||||
configuration.userContentController.removeScriptMessageHandler(forName: "consoleError")
|
||||
configuration.userContentController.removeScriptMessageHandler(forName: "consoleInfo")
|
||||
configuration.userContentController.removeScriptMessageHandler(forName: "consoleWarn")
|
||||
configuration.userContentController.removeScriptMessageHandler(forName: "callHandler")
|
||||
configuration.userContentController.removeScriptMessageHandler(forName: "onFindResultReceived")
|
||||
configuration.userContentController.removeAllUserScripts()
|
||||
if #available(iOS 11.0, *) {
|
||||
configuration.userContentController.removeAllContentRuleLists()
|
||||
}
|
||||
}
|
||||
removeObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress))
|
||||
removeObserver(self, forKeyPath: #keyPath(WKWebView.url))
|
||||
if #available(iOS 11.0, *) {
|
||||
configuration.userContentController.removeAllContentRuleLists()
|
||||
}
|
||||
removeObserver(self, forKeyPath: #keyPath(WKWebView.title))
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
for imp in customIMPs {
|
||||
imp_removeBlock(imp)
|
||||
|
@ -2956,6 +3077,9 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
isPausedTimersCompletionHandler = nil
|
||||
channel = nil
|
||||
SharedLastTouchPointTimestamp.removeValue(forKey: self)
|
||||
if let wId = windowId, InAppWebView.windowWebViews[wId] != nil {
|
||||
InAppWebView.windowWebViews.removeValue(forKey: wId)
|
||||
}
|
||||
super.removeFromSuperview()
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import SafariServices
|
|||
public class SafariViewController: SFSafariViewController, FlutterPlugin, SFSafariViewControllerDelegate {
|
||||
|
||||
var channel: FlutterMethodChannel?
|
||||
var tmpWindow: UIWindow?
|
||||
var safariOptions: SafariBrowserOptions?
|
||||
var uuid: String = ""
|
||||
var menuItemList: [[String: Any]] = []
|
||||
|
@ -48,6 +47,13 @@ public class SafariViewController: SFSafariViewController, FlutterPlugin, SFSafa
|
|||
onChromeSafariBrowserOpened()
|
||||
}
|
||||
|
||||
public override func viewDidDisappear(_ animated: Bool) {
|
||||
super.viewDidDisappear(animated)
|
||||
self.onChromeSafariBrowserClosed()
|
||||
self.dispose()
|
||||
}
|
||||
|
||||
|
||||
func prepareSafariBrowser() {
|
||||
if #available(iOS 11.0, *) {
|
||||
self.dismissButtonStyle = SFSafariViewController.DismissButtonStyle(rawValue: (safariOptions?.dismissButtonStyle)!)!
|
||||
|
@ -69,11 +75,8 @@ public class SafariViewController: SFSafariViewController, FlutterPlugin, SFSafa
|
|||
func close(result: FlutterResult?) {
|
||||
dismiss(animated: true)
|
||||
|
||||
// wait for the animation
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(400), execute: {() -> Void in
|
||||
self.tmpWindow?.windowLevel = UIWindow.Level(rawValue: 0.0)
|
||||
UIApplication.shared.delegate?.window??.makeKeyAndVisible()
|
||||
self.onChromeSafariBrowserClosed()
|
||||
self.dispose()
|
||||
if result != nil {
|
||||
result!(true)
|
||||
}
|
||||
|
|
|
@ -37,9 +37,6 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
|||
var webViewControllers: [String: InAppBrowserWebViewController?] = [:]
|
||||
var safariViewControllers: [String: Any?] = [:]
|
||||
|
||||
var tmpWindow: UIWindow?
|
||||
private var previousStatusBarStyle = -1
|
||||
|
||||
public init(with registrar: FlutterPluginRegistrar) {
|
||||
super.init()
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'context_menu.dart';
|
||||
|
@ -18,8 +20,12 @@ class HeadlessInAppWebView implements WebView {
|
|||
///WebView Controller that can be used to access the [InAppWebViewController] API.
|
||||
InAppWebViewController webViewController;
|
||||
|
||||
///The window id of a [CreateWindowRequest.windowId].
|
||||
final int windowId;
|
||||
|
||||
HeadlessInAppWebView(
|
||||
{this.onWebViewCreated,
|
||||
{this.windowId,
|
||||
this.onWebViewCreated,
|
||||
this.onLoadStart,
|
||||
this.onLoadStop,
|
||||
this.onLoadError,
|
||||
|
@ -32,6 +38,7 @@ class HeadlessInAppWebView implements WebView {
|
|||
this.onDownloadStart,
|
||||
this.onLoadResourceCustomScheme,
|
||||
this.onCreateWindow,
|
||||
this.onCloseWindow,
|
||||
this.onJsAlert,
|
||||
this.onJsConfirm,
|
||||
this.onJsPrompt,
|
||||
|
@ -49,6 +56,9 @@ class HeadlessInAppWebView implements WebView {
|
|||
this.onEnterFullscreen,
|
||||
this.onExitFullscreen,
|
||||
this.onPageCommitVisible,
|
||||
this.onTitleChanged,
|
||||
this.onWindowFocus,
|
||||
this.onWindowBlur,
|
||||
this.androidOnSafeBrowsingHit,
|
||||
this.androidOnPermissionRequest,
|
||||
this.androidOnGeolocationPermissionsShowPrompt,
|
||||
|
@ -59,6 +69,11 @@ class HeadlessInAppWebView implements WebView {
|
|||
this.androidOnRenderProcessUnresponsive,
|
||||
this.androidOnFormResubmission,
|
||||
this.androidOnScaleChanged,
|
||||
this.androidOnRequestFocus,
|
||||
this.androidOnReceivedIcon,
|
||||
this.androidOnReceivedTouchIconUrl,
|
||||
this.androidOnJsBeforeUnload,
|
||||
this.androidOnReceivedLoginRequest,
|
||||
this.iosOnWebContentProcessDidTerminate,
|
||||
this.iosOnDidReceiveServerRedirectForProvisionalNavigation,
|
||||
this.initialUrl,
|
||||
|
@ -114,7 +129,7 @@ class HeadlessInAppWebView implements WebView {
|
|||
}
|
||||
|
||||
@override
|
||||
final Future<void> Function(InAppWebViewController controller)
|
||||
final void Function(InAppWebViewController controller)
|
||||
androidOnGeolocationPermissionsHidePrompt;
|
||||
|
||||
@override
|
||||
|
@ -151,15 +166,19 @@ class HeadlessInAppWebView implements WebView {
|
|||
final String initialUrl;
|
||||
|
||||
@override
|
||||
final Future<void> Function(InAppWebViewController controller, String url)
|
||||
final void Function(InAppWebViewController controller, String url)
|
||||
onPageCommitVisible;
|
||||
|
||||
@override
|
||||
final Future<void> Function(InAppWebViewController controller)
|
||||
final void Function(InAppWebViewController controller, String title)
|
||||
onTitleChanged;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller)
|
||||
iosOnDidReceiveServerRedirectForProvisionalNavigation;
|
||||
|
||||
@override
|
||||
final Future<void> Function(InAppWebViewController controller)
|
||||
final void Function(InAppWebViewController controller)
|
||||
iosOnWebContentProcessDidTerminate;
|
||||
|
||||
@override
|
||||
|
@ -178,8 +197,24 @@ class HeadlessInAppWebView implements WebView {
|
|||
onConsoleMessage;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller,
|
||||
OnCreateWindowRequest onCreateWindowRequest) onCreateWindow;
|
||||
final Future<WebView> Function(InAppWebViewController controller,
|
||||
CreateWindowRequest onCreateWindowRequest) onCreateWindow;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller)
|
||||
onCloseWindow;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller)
|
||||
onWindowFocus;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller)
|
||||
onWindowBlur;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller)
|
||||
androidOnRequestFocus;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url)
|
||||
|
@ -191,15 +226,15 @@ class HeadlessInAppWebView implements WebView {
|
|||
|
||||
@override
|
||||
final Future<JsAlertResponse> Function(
|
||||
InAppWebViewController controller, String message) onJsAlert;
|
||||
InAppWebViewController controller, JsAlertRequest jsAlertRequest) onJsAlert;
|
||||
|
||||
@override
|
||||
final Future<JsConfirmResponse> Function(
|
||||
InAppWebViewController controller, String message) onJsConfirm;
|
||||
InAppWebViewController controller, JsConfirmRequest jsConfirmRequest) onJsConfirm;
|
||||
|
||||
@override
|
||||
final Future<JsPromptResponse> Function(InAppWebViewController controller,
|
||||
String message, String defaultValue) onJsPrompt;
|
||||
JsPromptRequest jsPromptRequest) onJsPrompt;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url, int code,
|
||||
|
@ -302,7 +337,7 @@ class HeadlessInAppWebView implements WebView {
|
|||
androidOnRenderProcessResponsive;
|
||||
|
||||
@override
|
||||
final Future<void> Function(
|
||||
final void Function(
|
||||
InAppWebViewController controller, RenderProcessGoneDetail detail)
|
||||
androidOnRenderProcessGone;
|
||||
|
||||
|
@ -311,7 +346,24 @@ class HeadlessInAppWebView implements WebView {
|
|||
InAppWebViewController controller, String url) androidOnFormResubmission;
|
||||
|
||||
@override
|
||||
final Future<void> Function(
|
||||
final void Function(
|
||||
InAppWebViewController controller, double oldScale, double newScale)
|
||||
androidOnScaleChanged;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, Uint8List icon)
|
||||
androidOnReceivedIcon;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url, bool precomposed)
|
||||
androidOnReceivedTouchIconUrl;
|
||||
|
||||
@override
|
||||
final Future<JsBeforeUnloadResponse> Function(
|
||||
InAppWebViewController controller, JsBeforeUnloadRequest jsBeforeUnloadRequest)
|
||||
androidOnJsBeforeUnload;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, LoginRequest loginRequest)
|
||||
androidOnReceivedLoginRequest;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
import 'context_menu.dart';
|
||||
import 'in_app_webview_controller.dart';
|
||||
import 'webview_options.dart';
|
||||
|
@ -28,8 +30,11 @@ class InAppBrowser {
|
|||
/// WebView Controller that can be used to access the [InAppWebViewController] API.
|
||||
InAppWebViewController webViewController;
|
||||
|
||||
///The window id of a [CreateWindowRequest.windowId].
|
||||
final int windowId;
|
||||
|
||||
///
|
||||
InAppBrowser() {
|
||||
InAppBrowser({this.windowId}) {
|
||||
uuid = uuidGenerator.v4();
|
||||
this._channel =
|
||||
MethodChannel('com.pichillilorenzo/flutter_inappbrowser_$uuid');
|
||||
|
@ -74,6 +79,7 @@ class InAppBrowser {
|
|||
args.putIfAbsent('headers', () => headers);
|
||||
args.putIfAbsent('options', () => options?.toMap() ?? {});
|
||||
args.putIfAbsent('contextMenu', () => contextMenu?.toMap() ?? {});
|
||||
args.putIfAbsent('windowId', () => windowId);
|
||||
await _sharedChannel.invokeMethod('openUrl', args);
|
||||
}
|
||||
|
||||
|
@ -123,6 +129,7 @@ class InAppBrowser {
|
|||
args.putIfAbsent('headers', () => headers);
|
||||
args.putIfAbsent('options', () => options?.toMap() ?? {});
|
||||
args.putIfAbsent('contextMenu', () => contextMenu?.toMap() ?? {});
|
||||
args.putIfAbsent('windowId', () => windowId);
|
||||
await _sharedChannel.invokeMethod('openFile', args);
|
||||
}
|
||||
|
||||
|
@ -153,6 +160,7 @@ class InAppBrowser {
|
|||
args.putIfAbsent('baseUrl', () => baseUrl);
|
||||
args.putIfAbsent('historyUrl', () => androidHistoryUrl);
|
||||
args.putIfAbsent('contextMenu', () => contextMenu?.toMap() ?? {});
|
||||
args.putIfAbsent('windowId', () => windowId);
|
||||
await _sharedChannel.invokeMethod('openData', args);
|
||||
}
|
||||
|
||||
|
@ -231,18 +239,21 @@ class InAppBrowser {
|
|||
///Event fired when the [InAppBrowser] starts to load an [url].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onPageStarted(android.webkit.WebView,%20java.lang.String,%20android.graphics.Bitmap)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455621-webview
|
||||
void onLoadStart(String url) {}
|
||||
|
||||
///Event fired when the [InAppBrowser] finishes loading an [url].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onPageFinished(android.webkit.WebView,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455629-webview
|
||||
void onLoadStop(String url) {}
|
||||
|
||||
///Event fired when the [InAppBrowser] encounters an error loading an [url].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedError(android.webkit.WebView,%20int,%20java.lang.String,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455623-webview
|
||||
void onLoadError(String url, int code, String message) {}
|
||||
|
||||
|
@ -257,6 +268,7 @@ class InAppBrowser {
|
|||
///**NOTE**: available on Android 23+.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedHttpError(android.webkit.WebView,%20android.webkit.WebResourceRequest,%20android.webkit.WebResourceResponse)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455643-webview
|
||||
void onLoadHttpError(String url, int statusCode, String description) {}
|
||||
|
||||
|
@ -283,6 +295,7 @@ class InAppBrowser {
|
|||
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldOverrideUrlLoading] option to `true`.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#shouldOverrideUrlLoading(android.webkit.WebView,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455641-webview
|
||||
// ignore: missing_return
|
||||
Future<ShouldOverrideUrlLoadingAction> shouldOverrideUrlLoading(
|
||||
|
@ -300,6 +313,7 @@ class InAppBrowser {
|
|||
///[y] represents the current vertical scroll origin in pixels.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#onScrollChanged(int,%20int,%20int,%20int)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollviewdelegate/1619392-scrollviewdidscroll
|
||||
void onScrollChanged(int x, int y) {}
|
||||
|
||||
|
@ -310,6 +324,7 @@ class InAppBrowser {
|
|||
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnDownloadStart] option to `true`.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#setDownloadListener(android.webkit.DownloadListener)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455643-webview
|
||||
void onDownloadStart(String url) {}
|
||||
|
||||
|
@ -326,51 +341,91 @@ class InAppBrowser {
|
|||
|
||||
///Event fired when the [InAppBrowser] webview requests the host application to create a new window,
|
||||
///for example when trying to open a link with `target="_blank"` or when `window.open()` is called by JavaScript side.
|
||||
///The return type should be an [InAppBrowser] instance, a [HeadlessInAppWebView] instance or `null`. If it returns `null`, then nothing will happen.
|
||||
///If it returns an [InAppBrowser] instance, the new [InAppBrowser] will be immediately opened.
|
||||
///If it returns a [HeadlessInAppWebView] instance, the [HeadlessInAppWebView.run] method will be immediately called.
|
||||
///Remember to use the [CreateWindowRequest.windowId] to create the new WebView instance.
|
||||
///
|
||||
///[onCreateWindowRequest] represents the request.
|
||||
///[createWindowRequest] represents the request.
|
||||
///
|
||||
///**NOTE**: on Android you need to set [AndroidInAppWebViewOptions.supportMultipleWindows] option to `true`.
|
||||
///
|
||||
///**NOTE**: on iOS, setting these initial options: [InAppWebViewOptions.supportZoom], [InAppWebViewOptions.useOnLoadResource], [InAppWebViewOptions.useShouldInterceptAjaxRequest],
|
||||
///[InAppWebViewOptions.useShouldInterceptFetchRequest], [InAppWebViewOptions.applicationNameForUserAgent], [InAppWebViewOptions.javaScriptCanOpenWindowsAutomatically],
|
||||
///[InAppWebViewOptions.javaScriptEnabled], [InAppWebViewOptions.minimumFontSize], [InAppWebViewOptions.preferredContentMode], [InAppWebViewOptions.incognito],
|
||||
///[InAppWebViewOptions.cacheEnabled], [InAppWebViewOptions.mediaPlaybackRequiresUserGesture],
|
||||
///[InAppWebViewOptions.resourceCustomSchemes], [IOSInAppWebViewOptions.sharedCookiesEnabled],
|
||||
///[IOSInAppWebViewOptions.enableViewportScale], [IOSInAppWebViewOptions.allowsAirPlayForMediaPlayback],
|
||||
///[IOSInAppWebViewOptions.allowsPictureInPictureMediaPlayback], [IOSInAppWebViewOptions.isFraudulentWebsiteWarningEnabled],
|
||||
///[IOSInAppWebViewOptions.allowsInlineMediaPlayback], [IOSInAppWebViewOptions.suppressesIncrementalRendering], [IOSInAppWebViewOptions.selectionGranularity],
|
||||
///[IOSInAppWebViewOptions.ignoresViewportScaleLimits],
|
||||
///will have no effect due to a `WKWebView` limitation when creating a new window WebView: it's impossible to return a new `WKWebView`
|
||||
///with a different `WKWebViewConfiguration` instance (see https://developer.apple.com/documentation/webkit/wkuidelegate/1536907-webview).
|
||||
///So, these options will be inherited from the caller WebView.
|
||||
///Also, note that calling [InAppWebViewController.setOptions] method using the controller of the new created WebView,
|
||||
///it will update also the WebView options of the caller WebView.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onCreateWindow(android.webkit.WebView,%20boolean,%20boolean,%20android.os.Message)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1536907-webview
|
||||
void onCreateWindow(OnCreateWindowRequest onCreateWindowRequest) {}
|
||||
// ignore: missing_return
|
||||
Future<dynamic> onCreateWindow(CreateWindowRequest createWindowRequest) {}
|
||||
|
||||
///Event fired when the host application should close the given WebView and remove it from the view system if necessary.
|
||||
///At this point, WebCore has stopped any loading in this window and has removed any cross-scripting ability in javascript.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onCloseWindow(android.webkit.WebView)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1537390-webviewdidclose
|
||||
void onCloseWindow() {}
|
||||
|
||||
///Event fired when the JavaScript `window` object of the WebView has received focus.
|
||||
///This is the result of the `focus` javascript event applied to the `window` object.
|
||||
void onWindowFocus() {}
|
||||
|
||||
///Event fired when the JavaScript `window` object of the WebView has lost focus.
|
||||
///This is the result of the `blur` javascript event applied to the `window` object.
|
||||
void onWindowBlur() {}
|
||||
|
||||
///Event fired when javascript calls the `alert()` method to display an alert dialog.
|
||||
///If [JsAlertResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
|
||||
///
|
||||
///[message] represents the message to be displayed in the alert dialog.
|
||||
///[jsAlertRequest] contains the message to be displayed in the alert dialog and the of the page requesting the dialog.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onJsAlert(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20android.webkit.JsResult)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1537406-webview
|
||||
// ignore: missing_return
|
||||
Future<JsAlertResponse> onJsAlert(String message) {}
|
||||
Future<JsAlertResponse> onJsAlert(JsAlertRequest jsAlertRequest) {}
|
||||
|
||||
///Event fired when javascript calls the `confirm()` method to display a confirm dialog.
|
||||
///If [JsConfirmResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
|
||||
///
|
||||
///[message] represents the message to be displayed in the alert dialog.
|
||||
///[jsConfirmRequest] contains the message to be displayed in the confirm dialog and the of the page requesting the dialog.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onJsConfirm(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20android.webkit.JsResult)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1536489-webview
|
||||
// ignore: missing_return
|
||||
Future<JsConfirmResponse> onJsConfirm(String message) {}
|
||||
Future<JsConfirmResponse> onJsConfirm(JsConfirmRequest jsConfirmRequest) {}
|
||||
|
||||
///Event fired when javascript calls the `prompt()` method to display a prompt dialog.
|
||||
///If [JsPromptResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
|
||||
///
|
||||
///[message] represents the message to be displayed in the alert dialog.
|
||||
///[defaultValue] represents the default value displayed in the prompt dialog.
|
||||
///[jsPromptRequest] contains the message to be displayed in the prompt dialog, the default value displayed in the prompt dialog, and the of the page requesting the dialog.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onJsPrompt(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20java.lang.String,%20android.webkit.JsPromptResult)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1538086-webview
|
||||
// ignore: missing_return
|
||||
Future<JsPromptResponse> onJsPrompt(String message, String defaultValue) {}
|
||||
Future<JsPromptResponse> onJsPrompt(JsPromptRequest jsPromptRequest) {}
|
||||
|
||||
///Event fired when the WebView received an HTTP authentication request. The default behavior is to cancel the request.
|
||||
///
|
||||
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [HttpAuthChallenge].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedHttpAuthRequest(android.webkit.WebView,%20android.webkit.HttpAuthHandler,%20java.lang.String,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455638-webview
|
||||
// ignore: missing_return
|
||||
Future<HttpAuthResponse> onReceivedHttpAuthRequest(
|
||||
|
@ -382,6 +437,7 @@ class InAppBrowser {
|
|||
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [ServerTrustChallenge].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedSslError(android.webkit.WebView,%20android.webkit.SslErrorHandler,%20android.net.http.SslError)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455638-webview
|
||||
// ignore: missing_return
|
||||
Future<ServerTrustAuthResponse> onReceivedServerTrustAuthRequest(
|
||||
|
@ -395,6 +451,7 @@ class InAppBrowser {
|
|||
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [ClientCertChallenge].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedClientCertRequest(android.webkit.WebView,%20android.webkit.ClientCertRequest)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455638-webview
|
||||
// ignore: missing_return
|
||||
Future<ClientCertResponse> onReceivedClientCertRequest(
|
||||
|
@ -473,18 +530,21 @@ class InAppBrowser {
|
|||
///[hitTestResult] represents the hit result for hitting an HTML elements.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/view/View#setOnLongClickListener(android.view.View.OnLongClickListener)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uilongpressgesturerecognizer
|
||||
void onLongPressHitTestResult(InAppWebViewHitTestResult hitTestResult) {}
|
||||
|
||||
///Event fired when the current page has entered full screen mode.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onShowCustomView(android.view.View,%20android.webkit.WebChromeClient.CustomViewCallback)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiwindow/1621621-didbecomevisiblenotification
|
||||
void onEnterFullscreen() {}
|
||||
|
||||
///Event fired when the current page has exited full screen mode.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onHideCustomView()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiwindow/1621617-didbecomehiddennotification
|
||||
void onExitFullscreen() {}
|
||||
|
||||
|
@ -496,9 +556,18 @@ class InAppBrowser {
|
|||
///[url] represents the URL corresponding to the page navigation that triggered this callback.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onPageCommitVisible(android.webkit.WebView,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455635-webview
|
||||
void onPageCommitVisible(String url) {}
|
||||
|
||||
///Event fired when a change in the document title occurred.
|
||||
///
|
||||
///[title] represents the string containing the new title of the document.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onReceivedTitle(android.webkit.WebView,%20java.lang.String)
|
||||
void onTitleChanged(String title) {}
|
||||
|
||||
|
||||
///Event fired when the WebView notifies that a loading URL has been flagged by Safe Browsing.
|
||||
///The default behavior is to show an interstitial to the user, with the reporting checkbox visible.
|
||||
///
|
||||
|
@ -636,6 +705,60 @@ class InAppBrowser {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onScaleChanged(android.webkit.WebView,%20float,%20float)
|
||||
void androidOnScaleChanged(double oldScale, double newScale) {}
|
||||
|
||||
///Event fired when there is a request to display and focus for this WebView.
|
||||
///This may happen due to another WebView opening a link in this WebView and requesting that this WebView be displayed.
|
||||
///
|
||||
///**NOTE**: available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onRequestFocus(android.webkit.WebView)
|
||||
void androidOnRequestFocus() {}
|
||||
|
||||
///Event fired when there is new favicon for the current page.
|
||||
///
|
||||
///[icon] represents the favicon for the current page.
|
||||
///
|
||||
///**NOTE**: available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onReceivedIcon(android.webkit.WebView,%20android.graphics.Bitmap)
|
||||
void androidOnReceivedIcon(Uint8List icon) {}
|
||||
|
||||
///Event fired when there is an url for an apple-touch-icon.
|
||||
///
|
||||
///[url] represents the icon url.
|
||||
///
|
||||
///[precomposed] is `true` if the url is for a precomposed touch icon.
|
||||
///
|
||||
///**NOTE**: available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onReceivedTouchIconUrl(android.webkit.WebView,%20java.lang.String,%20boolean)
|
||||
void androidOnReceivedTouchIconUrl(String url, bool precomposed) {}
|
||||
|
||||
///Event fired when the client should display a dialog to confirm navigation away from the current page.
|
||||
///This is the result of the `onbeforeunload` javascript event.
|
||||
///If [JsBeforeUnloadResponse.handledByClient] is `true`, WebView will assume that the client will handle the confirm dialog.
|
||||
///If [JsBeforeUnloadResponse.handledByClient] is `false`, a default value of `true` will be returned to javascript to accept navigation away from the current page.
|
||||
///The default behavior is to return `false`.
|
||||
///Setting the [JsBeforeUnloadResponse.action] to [JsBeforeUnloadResponseAction.CONFIRM] will navigate away from the current page,
|
||||
///[JsBeforeUnloadResponseAction.CANCEL] will cancel the navigation.
|
||||
///
|
||||
///[jsBeforeUnloadRequest] contains the message to be displayed in the alert dialog and the of the page requesting the dialog.
|
||||
///
|
||||
///**NOTE**: available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onJsBeforeUnload(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20android.webkit.JsResult)
|
||||
// ignore: missing_return
|
||||
Future<JsBeforeUnloadResponse> androidOnJsBeforeUnload(
|
||||
JsBeforeUnloadRequest jsBeforeUnloadRequest) {}
|
||||
|
||||
///Event fired when a request to automatically log in the user has been processed.
|
||||
///
|
||||
///[loginRequest] contains the realm, account and args of the login request.
|
||||
///
|
||||
///**NOTE**: available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedLoginRequest(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20java.lang.String)
|
||||
void androidOnReceivedLoginRequest(LoginRequest loginRequest) {}
|
||||
|
||||
///Invoked when the web view's web content process is terminated.
|
||||
///
|
||||
///**NOTE**: available only on iOS.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -22,8 +23,12 @@ class InAppWebView extends StatefulWidget implements WebView {
|
|||
/// were not claimed by any other gesture recognizer.
|
||||
final Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers;
|
||||
|
||||
///The window id of a [CreateWindowRequest.windowId].
|
||||
final int windowId;
|
||||
|
||||
const InAppWebView({
|
||||
Key key,
|
||||
this.windowId,
|
||||
this.initialUrl = "about:blank",
|
||||
this.initialFile,
|
||||
this.initialData,
|
||||
|
@ -43,6 +48,7 @@ class InAppWebView extends StatefulWidget implements WebView {
|
|||
this.onDownloadStart,
|
||||
this.onLoadResourceCustomScheme,
|
||||
this.onCreateWindow,
|
||||
this.onCloseWindow,
|
||||
this.onJsAlert,
|
||||
this.onJsConfirm,
|
||||
this.onJsPrompt,
|
||||
|
@ -60,6 +66,9 @@ class InAppWebView extends StatefulWidget implements WebView {
|
|||
this.onEnterFullscreen,
|
||||
this.onExitFullscreen,
|
||||
this.onPageCommitVisible,
|
||||
this.onTitleChanged,
|
||||
this.onWindowFocus,
|
||||
this.onWindowBlur,
|
||||
this.androidOnSafeBrowsingHit,
|
||||
this.androidOnPermissionRequest,
|
||||
this.androidOnGeolocationPermissionsShowPrompt,
|
||||
|
@ -70,6 +79,11 @@ class InAppWebView extends StatefulWidget implements WebView {
|
|||
this.androidOnRenderProcessUnresponsive,
|
||||
this.androidOnFormResubmission,
|
||||
this.androidOnScaleChanged,
|
||||
this.androidOnRequestFocus,
|
||||
this.androidOnReceivedIcon,
|
||||
this.androidOnReceivedTouchIconUrl,
|
||||
this.androidOnJsBeforeUnload,
|
||||
this.androidOnReceivedLoginRequest,
|
||||
this.iosOnWebContentProcessDidTerminate,
|
||||
this.iosOnDidReceiveServerRedirectForProvisionalNavigation,
|
||||
this.gestureRecognizers,
|
||||
|
@ -79,7 +93,7 @@ class InAppWebView extends StatefulWidget implements WebView {
|
|||
_InAppWebViewState createState() => _InAppWebViewState();
|
||||
|
||||
@override
|
||||
final Future<void> Function(InAppWebViewController controller)
|
||||
final void Function(InAppWebViewController controller)
|
||||
androidOnGeolocationPermissionsHidePrompt;
|
||||
|
||||
@override
|
||||
|
@ -116,15 +130,19 @@ class InAppWebView extends StatefulWidget implements WebView {
|
|||
final ContextMenu contextMenu;
|
||||
|
||||
@override
|
||||
final Future<void> Function(InAppWebViewController controller, String url)
|
||||
final void Function(InAppWebViewController controller, String url)
|
||||
onPageCommitVisible;
|
||||
|
||||
@override
|
||||
final Future<void> Function(InAppWebViewController controller)
|
||||
final void Function(InAppWebViewController controller, String title)
|
||||
onTitleChanged;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller)
|
||||
iosOnDidReceiveServerRedirectForProvisionalNavigation;
|
||||
|
||||
@override
|
||||
final Future<void> Function(InAppWebViewController controller)
|
||||
final void Function(InAppWebViewController controller)
|
||||
iosOnWebContentProcessDidTerminate;
|
||||
|
||||
@override
|
||||
|
@ -143,8 +161,32 @@ class InAppWebView extends StatefulWidget implements WebView {
|
|||
onConsoleMessage;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller,
|
||||
OnCreateWindowRequest onCreateWindowRequest) onCreateWindow;
|
||||
final Future<WebView> Function(InAppWebViewController controller,
|
||||
CreateWindowRequest onCreateWindowRequest) onCreateWindow;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller)
|
||||
onCloseWindow;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller)
|
||||
onWindowFocus;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller)
|
||||
onWindowBlur;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller)
|
||||
androidOnRequestFocus;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, Uint8List icon)
|
||||
androidOnReceivedIcon;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url, bool precomposed)
|
||||
androidOnReceivedTouchIconUrl;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url)
|
||||
|
@ -156,15 +198,15 @@ class InAppWebView extends StatefulWidget implements WebView {
|
|||
|
||||
@override
|
||||
final Future<JsAlertResponse> Function(
|
||||
InAppWebViewController controller, String message) onJsAlert;
|
||||
InAppWebViewController controller, JsAlertRequest jsAlertRequest) onJsAlert;
|
||||
|
||||
@override
|
||||
final Future<JsConfirmResponse> Function(
|
||||
InAppWebViewController controller, String message) onJsConfirm;
|
||||
InAppWebViewController controller, JsConfirmRequest jsConfirmRequest) onJsConfirm;
|
||||
|
||||
@override
|
||||
final Future<JsPromptResponse> Function(InAppWebViewController controller,
|
||||
String message, String defaultValue) onJsPrompt;
|
||||
JsPromptRequest jsPromptRequest) onJsPrompt;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url, int code,
|
||||
|
@ -267,7 +309,7 @@ class InAppWebView extends StatefulWidget implements WebView {
|
|||
androidOnRenderProcessResponsive;
|
||||
|
||||
@override
|
||||
final Future<void> Function(
|
||||
final void Function(
|
||||
InAppWebViewController controller, RenderProcessGoneDetail detail)
|
||||
androidOnRenderProcessGone;
|
||||
|
||||
|
@ -276,9 +318,18 @@ class InAppWebView extends StatefulWidget implements WebView {
|
|||
InAppWebViewController controller, String url) androidOnFormResubmission;
|
||||
|
||||
@override
|
||||
final Future<void> Function(
|
||||
final void Function(
|
||||
InAppWebViewController controller, double oldScale, double newScale)
|
||||
androidOnScaleChanged;
|
||||
|
||||
@override
|
||||
final Future<JsBeforeUnloadResponse> Function(
|
||||
InAppWebViewController controller, JsBeforeUnloadRequest jsBeforeUnloadRequest)
|
||||
androidOnJsBeforeUnload;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, LoginRequest loginRequest)
|
||||
androidOnReceivedLoginRequest;
|
||||
}
|
||||
|
||||
class _InAppWebViewState extends State<InAppWebView> {
|
||||
|
@ -298,7 +349,8 @@ class _InAppWebViewState extends State<InAppWebView> {
|
|||
'initialData': widget.initialData?.toMap(),
|
||||
'initialHeaders': widget.initialHeaders,
|
||||
'initialOptions': widget.initialOptions?.toMap() ?? {},
|
||||
'contextMenu': widget.contextMenu?.toMap() ?? {}
|
||||
'contextMenu': widget.contextMenu?.toMap() ?? {},
|
||||
'windowId': widget.windowId
|
||||
},
|
||||
creationParamsCodec: const StandardMessageCodec(),
|
||||
);
|
||||
|
@ -332,7 +384,8 @@ class _InAppWebViewState extends State<InAppWebView> {
|
|||
'initialData': widget.initialData?.toMap(),
|
||||
'initialHeaders': widget.initialHeaders,
|
||||
'initialOptions': widget.initialOptions?.toMap() ?? {},
|
||||
'contextMenu': widget.contextMenu?.toMap() ?? {}
|
||||
'contextMenu': widget.contextMenu?.toMap() ?? {},
|
||||
'windowId': widget.windowId
|
||||
},
|
||||
creationParamsCodec: const StandardMessageCodec(),
|
||||
);
|
||||
|
|
|
@ -30,7 +30,8 @@ const javaScriptHandlerForbiddenNames = [
|
|||
"onAjaxProgress",
|
||||
"shouldInterceptFetchRequest",
|
||||
"onPrint",
|
||||
"androidKeyboardWorkaroundFocusoutEvent"
|
||||
"onWindowFocus",
|
||||
"onWindowBlur",
|
||||
];
|
||||
|
||||
///Controls a WebView, such as an [InAppWebView] widget instance, a [HeadlessInAppWebView] instance or [InAppBrowser] WebView instance.
|
||||
|
@ -206,21 +207,74 @@ class InAppWebViewController {
|
|||
break;
|
||||
case "onCreateWindow":
|
||||
String url = call.arguments["url"];
|
||||
int windowId = call.arguments["windowId"];
|
||||
bool androidIsDialog = call.arguments["androidIsDialog"];
|
||||
bool androidIsUserGesture = call.arguments["androidIsUserGesture"];
|
||||
int iosWKNavigationType = call.arguments["iosWKNavigationType"];
|
||||
bool iosIsForMainFrame = call.arguments["iosIsForMainFrame"];
|
||||
|
||||
OnCreateWindowRequest onCreateWindowRequest = OnCreateWindowRequest(
|
||||
CreateWindowRequest createWindowRequest = CreateWindowRequest(
|
||||
url: url,
|
||||
windowId: windowId,
|
||||
androidIsDialog: androidIsDialog,
|
||||
androidIsUserGesture: androidIsUserGesture,
|
||||
iosWKNavigationType:
|
||||
IOSWKNavigationType.fromValue(iosWKNavigationType));
|
||||
IOSWKNavigationType.fromValue(iosWKNavigationType),
|
||||
iosIsForMainFrame: iosIsForMainFrame);
|
||||
|
||||
WebView webView;
|
||||
dynamic inAppBrowserWindow;
|
||||
|
||||
if (_webview != null && _webview.onCreateWindow != null)
|
||||
_webview.onCreateWindow(this, onCreateWindowRequest);
|
||||
webView = await _webview.onCreateWindow(this, createWindowRequest);
|
||||
else if (_inAppBrowser != null) {
|
||||
inAppBrowserWindow = await _inAppBrowser.onCreateWindow(createWindowRequest);
|
||||
assert(
|
||||
inAppBrowserWindow is InAppBrowser || inAppBrowserWindow is HeadlessInAppWebView,
|
||||
"InAppBrowser.onCreateWindow should return an \"InAppBrowser\" instance or a \"HeadlessInAppWebView\" instance."
|
||||
);
|
||||
}
|
||||
|
||||
int webViewWindowId;
|
||||
|
||||
if (webView != null) {
|
||||
webViewWindowId = webView.windowId;
|
||||
assert(webViewWindowId !=
|
||||
null, "If you are returning a WebView, then WebView.windowId should be not null. To set the " +
|
||||
"WebView.windowId property, you should use the CreateWindowRequest.windowId property.");
|
||||
if (webView is HeadlessInAppWebView) {
|
||||
webView.run();
|
||||
}
|
||||
} else if (inAppBrowserWindow != null) {
|
||||
if (inAppBrowserWindow is InAppBrowser) {
|
||||
webViewWindowId = inAppBrowserWindow.windowId;
|
||||
assert(webViewWindowId !=
|
||||
null, "If you are returning an InAppBrowser, then InAppBrowser.windowId should be not null. To set the " +
|
||||
"InAppBrowser.windowId property, you should use the CreateWindowRequest.windowId property.");
|
||||
inAppBrowserWindow.openUrl(url: "about:blank");
|
||||
}
|
||||
else if (inAppBrowserWindow is HeadlessInAppWebView) {
|
||||
webViewWindowId = inAppBrowserWindow.windowId;
|
||||
assert(webViewWindowId !=
|
||||
null, "If you are returning a HeadlessInAppWebView, then HeadlessInAppWebView.windowId should be not null. To set the " +
|
||||
"HeadlessInAppWebView.windowId property, you should use the CreateWindowRequest.windowId property.");
|
||||
inAppBrowserWindow.run();
|
||||
}
|
||||
}
|
||||
|
||||
return webViewWindowId;
|
||||
case "onCloseWindow":
|
||||
if (_webview != null && _webview.onCloseWindow != null)
|
||||
_webview.onCloseWindow(this);
|
||||
else if (_inAppBrowser != null)
|
||||
_inAppBrowser.onCreateWindow(onCreateWindowRequest);
|
||||
_inAppBrowser.onCloseWindow();
|
||||
break;
|
||||
case "onTitleChanged":
|
||||
String title = call.arguments["title"];
|
||||
if (_webview != null && _webview.onTitleChanged != null)
|
||||
_webview.onTitleChanged(this, title);
|
||||
else if (_inAppBrowser != null)
|
||||
_inAppBrowser.onTitleChanged(title);
|
||||
break;
|
||||
case "onGeolocationPermissionsShowPrompt":
|
||||
String origin = call.arguments["origin"];
|
||||
|
@ -312,30 +366,98 @@ class InAppWebViewController {
|
|||
else if (_inAppBrowser != null)
|
||||
_inAppBrowser.androidOnScaleChanged(oldScale, newScale);
|
||||
break;
|
||||
case "onJsAlert":
|
||||
String message = call.arguments["message"];
|
||||
if (_webview != null && _webview.onJsAlert != null)
|
||||
return (await _webview.onJsAlert(this, message))?.toMap();
|
||||
case "onRequestFocus":
|
||||
if (_webview != null && _webview.androidOnRequestFocus != null)
|
||||
_webview.androidOnRequestFocus(this);
|
||||
else if (_inAppBrowser != null)
|
||||
return (await _inAppBrowser.onJsAlert(message))?.toMap();
|
||||
_inAppBrowser.androidOnRequestFocus();
|
||||
break;
|
||||
case "onReceivedIcon":
|
||||
Uint8List icon = Uint8List.fromList(call.arguments["icon"].cast<int>());
|
||||
|
||||
if (_webview != null && _webview.androidOnReceivedIcon != null)
|
||||
_webview.androidOnReceivedIcon(this, icon);
|
||||
else if (_inAppBrowser != null)
|
||||
_inAppBrowser.androidOnReceivedIcon(icon);
|
||||
break;
|
||||
case "onReceivedTouchIconUrl":
|
||||
String url = call.arguments["url"];
|
||||
bool precomposed = call.arguments["precomposed"];
|
||||
if (_webview != null && _webview.androidOnReceivedTouchIconUrl != null)
|
||||
_webview.androidOnReceivedTouchIconUrl(this, url, precomposed);
|
||||
else if (_inAppBrowser != null)
|
||||
_inAppBrowser.androidOnReceivedTouchIconUrl(url, precomposed);
|
||||
break;
|
||||
case "onJsAlert":
|
||||
String url = call.arguments["url"];
|
||||
String message = call.arguments["message"];
|
||||
bool iosIsMainFrame = call.arguments["iosIsMainFrame"];
|
||||
|
||||
JsAlertRequest jsAlertRequest = JsAlertRequest(
|
||||
url: url,
|
||||
message: message,
|
||||
iosIsMainFrame: iosIsMainFrame
|
||||
);
|
||||
|
||||
if (_webview != null && _webview.onJsAlert != null)
|
||||
return (await _webview.onJsAlert(this, jsAlertRequest))?.toMap();
|
||||
else if (_inAppBrowser != null)
|
||||
return (await _inAppBrowser.onJsAlert(jsAlertRequest))?.toMap();
|
||||
break;
|
||||
case "onJsConfirm":
|
||||
String url = call.arguments["url"];
|
||||
String message = call.arguments["message"];
|
||||
bool iosIsMainFrame = call.arguments["iosIsMainFrame"];
|
||||
|
||||
JsConfirmRequest jsConfirmRequest = JsConfirmRequest(
|
||||
url: url,
|
||||
message: message,
|
||||
iosIsMainFrame: iosIsMainFrame
|
||||
);
|
||||
|
||||
if (_webview != null && _webview.onJsConfirm != null)
|
||||
return (await _webview.onJsConfirm(this, message))?.toMap();
|
||||
return (await _webview.onJsConfirm(this, jsConfirmRequest))?.toMap();
|
||||
else if (_inAppBrowser != null)
|
||||
return (await _inAppBrowser.onJsConfirm(message))?.toMap();
|
||||
return (await _inAppBrowser.onJsConfirm(jsConfirmRequest))?.toMap();
|
||||
break;
|
||||
case "onJsPrompt":
|
||||
String url = call.arguments["url"];
|
||||
String message = call.arguments["message"];
|
||||
String defaultValue = call.arguments["defaultValue"];
|
||||
bool iosIsMainFrame = call.arguments["iosIsMainFrame"];
|
||||
|
||||
JsPromptRequest jsPromptRequest = JsPromptRequest(
|
||||
url: url,
|
||||
message: message,
|
||||
defaultValue: defaultValue,
|
||||
iosIsMainFrame: iosIsMainFrame
|
||||
);
|
||||
|
||||
if (_webview != null && _webview.onJsPrompt != null)
|
||||
return (await _webview.onJsPrompt(this, message, defaultValue))
|
||||
return (await _webview.onJsPrompt(this, jsPromptRequest))
|
||||
?.toMap();
|
||||
else if (_inAppBrowser != null)
|
||||
return (await _inAppBrowser.onJsPrompt(message, defaultValue))
|
||||
return (await _inAppBrowser.onJsPrompt(jsPromptRequest))
|
||||
?.toMap();
|
||||
break;
|
||||
case "onJsBeforeUnload":
|
||||
String url = call.arguments["url"];
|
||||
String message = call.arguments["message"];
|
||||
bool iosIsMainFrame = call.arguments["iosIsMainFrame"];
|
||||
|
||||
JsBeforeUnloadRequest jsBeforeUnloadRequest = JsBeforeUnloadRequest(
|
||||
url: url,
|
||||
message: message,
|
||||
iosIsMainFrame: iosIsMainFrame
|
||||
);
|
||||
|
||||
print(jsBeforeUnloadRequest);
|
||||
|
||||
if (_webview != null && _webview.androidOnJsBeforeUnload != null)
|
||||
return (await _webview.androidOnJsBeforeUnload(this, jsBeforeUnloadRequest))?.toMap();
|
||||
else if (_inAppBrowser != null)
|
||||
return (await _inAppBrowser.androidOnJsBeforeUnload(jsBeforeUnloadRequest))?.toMap();
|
||||
break;
|
||||
case "onSafeBrowsingHit":
|
||||
String url = call.arguments["url"];
|
||||
SafeBrowsingThreat threatType =
|
||||
|
@ -348,6 +470,22 @@ class InAppWebViewController {
|
|||
return (await _inAppBrowser.androidOnSafeBrowsingHit(url, threatType))
|
||||
?.toMap();
|
||||
break;
|
||||
case "onReceivedLoginRequest":
|
||||
String realm = call.arguments["realm"];
|
||||
String account = call.arguments["account"];
|
||||
String args = call.arguments["args"];
|
||||
|
||||
LoginRequest loginRequest = LoginRequest(
|
||||
realm: realm,
|
||||
account: account,
|
||||
args: args
|
||||
);
|
||||
|
||||
if (_webview != null && _webview.androidOnReceivedLoginRequest != null)
|
||||
_webview.androidOnReceivedLoginRequest(this, loginRequest);
|
||||
else if (_inAppBrowser != null)
|
||||
_inAppBrowser.androidOnReceivedLoginRequest(loginRequest);
|
||||
break;
|
||||
case "onReceivedHttpAuthRequest":
|
||||
String host = call.arguments["host"];
|
||||
String protocol = call.arguments["protocol"];
|
||||
|
@ -801,6 +939,18 @@ class InAppWebViewController {
|
|||
_webview.onPrint(this, url);
|
||||
else if (_inAppBrowser != null) _inAppBrowser.onPrint(url);
|
||||
return null;
|
||||
case "onWindowFocus":
|
||||
if (_webview != null && _webview.onWindowFocus != null)
|
||||
_webview.onWindowFocus(this);
|
||||
else if (_inAppBrowser != null)
|
||||
_inAppBrowser.onWindowFocus();
|
||||
return null;
|
||||
case "onWindowBlur":
|
||||
if (_webview != null && _webview.onWindowBlur != null)
|
||||
_webview.onWindowBlur(this);
|
||||
else if (_inAppBrowser != null)
|
||||
_inAppBrowser.onWindowBlur();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (javaScriptHandlersMap.containsKey(handlerName)) {
|
||||
|
@ -822,6 +972,7 @@ class InAppWebViewController {
|
|||
///This is not always the same as the URL passed to [WebView.onLoadStart] because although the load for that URL has begun, the current page may not have changed.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#getUrl()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1415005-url
|
||||
Future<String> getUrl() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -831,6 +982,7 @@ class InAppWebViewController {
|
|||
///Gets the title for the current page.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#getTitle()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1415015-title
|
||||
Future<String> getTitle() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -840,6 +992,7 @@ class InAppWebViewController {
|
|||
///Gets the progress for the current page. The progress value is between 0 and 100.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#getProgress()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1415007-estimatedprogress
|
||||
Future<int> getProgress() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -1039,6 +1192,7 @@ class InAppWebViewController {
|
|||
///Loads the given [url] with optional [headers] specified as a map from name to value.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#loadUrl(java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1414954-load
|
||||
Future<void> loadUrl(
|
||||
{@required String url, Map<String, String> headers = const {}}) async {
|
||||
|
@ -1071,6 +1225,7 @@ class InAppWebViewController {
|
|||
///The [androidHistoryUrl] parameter is the URL to use as the history entry. The default value is `about:blank`. If non-null, this must be a valid URL. This parameter is used only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#loadDataWithBaseURL(java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**:
|
||||
///- https://developer.apple.com/documentation/webkit/wkwebview/1415004-loadhtmlstring
|
||||
///- https://developer.apple.com/documentation/webkit/wkwebview/1415011-load
|
||||
|
@ -1132,6 +1287,7 @@ class InAppWebViewController {
|
|||
///Reloads the WebView.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#reload()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1414969-reload
|
||||
Future<void> reload() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -1141,6 +1297,7 @@ class InAppWebViewController {
|
|||
///Goes back in the history of the WebView.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#goBack()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1414952-goback
|
||||
Future<void> goBack() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -1150,6 +1307,7 @@ class InAppWebViewController {
|
|||
///Returns a boolean value indicating whether the WebView can move backward.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#canGoBack()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1414966-cangoback
|
||||
Future<bool> canGoBack() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -1159,6 +1317,7 @@ class InAppWebViewController {
|
|||
///Goes forward in the history of the WebView.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#goForward()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1414993-goforward
|
||||
Future<void> goForward() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -1168,6 +1327,7 @@ class InAppWebViewController {
|
|||
///Returns a boolean value indicating whether the WebView can move forward.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#canGoForward()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1414962-cangoforward
|
||||
Future<bool> canGoForward() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -1177,6 +1337,7 @@ class InAppWebViewController {
|
|||
///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.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#goBackOrForward(int)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1414991-go
|
||||
Future<void> goBackOrForward({@required int steps}) async {
|
||||
assert(steps != null);
|
||||
|
@ -1211,6 +1372,7 @@ class InAppWebViewController {
|
|||
///Stops the WebView from loading.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#stopLoading()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1414981-stoploading
|
||||
Future<void> stopLoading() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -1225,6 +1387,7 @@ class InAppWebViewController {
|
|||
///where you know the page is ready "enough".
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#evaluateJavascript(java.lang.String,%20android.webkit.ValueCallback%3Cjava.lang.String%3E)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1415017-evaluatejavascript
|
||||
Future<dynamic> evaluateJavascript({@required String source}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -1396,6 +1559,7 @@ class InAppWebViewController {
|
|||
///The object returned from this method will not be updated to reflect any new state.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#copyBackForwardList()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1414977-backforwardlist
|
||||
Future<WebHistory> getCopyBackForwardList() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -1488,6 +1652,7 @@ class InAppWebViewController {
|
|||
///[animated] `true` to animate the scroll transition, `false` to make the scoll transition immediate.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/view/View#scrollTo(int,%20int)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollview/1619400-setcontentoffset
|
||||
Future<void> scrollTo(
|
||||
{@required int x, @required int y, bool animated = false}) async {
|
||||
|
@ -1508,6 +1673,7 @@ class InAppWebViewController {
|
|||
///[animated] `true` to animate the scroll transition, `false` to make the scoll transition immediate.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/view/View#scrollBy(int,%20int)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollview/1619400-setcontentoffset
|
||||
Future<void> scrollBy(
|
||||
{@required int x, @required int y, bool animated = false}) async {
|
||||
|
@ -1545,6 +1711,7 @@ class InAppWebViewController {
|
|||
///**NOTE**: available on Android 21+.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/print/PrintManager
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiprintinteractioncontroller
|
||||
Future<void> printCurrentPage() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -1554,6 +1721,7 @@ class InAppWebViewController {
|
|||
///Gets the height of the HTML content.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#getContentHeight()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollview/1619399-contentsize
|
||||
Future<int> getContentHeight() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -1567,6 +1735,7 @@ class InAppWebViewController {
|
|||
///**NOTE**: available on Android 21+.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#zoomBy(float)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollview/1619412-setzoomscale
|
||||
Future<void> zoomBy(double zoomFactor) async {
|
||||
assert(!Platform.isAndroid ||
|
||||
|
@ -1582,6 +1751,7 @@ class InAppWebViewController {
|
|||
///**Official Android API**:
|
||||
///- https://developer.android.com/reference/android/util/DisplayMetrics#density
|
||||
///- https://developer.android.com/reference/android/webkit/WebViewClient#onScaleChanged(android.webkit.WebView,%20float,%20float)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollview/1619419-zoomscale
|
||||
Future<double> getScale() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -1616,6 +1786,7 @@ class InAppWebViewController {
|
|||
///Clears the current focus. It will clear also, for example, the current text selection.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/view/ViewGroup#clearFocus()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiresponder/1621097-resignfirstresponder
|
||||
Future<void> clearFocus() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -1753,6 +1924,7 @@ class InAppWebViewController {
|
|||
///Returns the scrolled left position of the current WebView.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/view/View#getScrollX()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollview/1619404-contentoffset
|
||||
Future<int> getScrollX() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -1762,6 +1934,7 @@ class InAppWebViewController {
|
|||
///Returns the scrolled top position of the current WebView.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/view/View#getScrollY()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollview/1619404-contentoffset
|
||||
Future<int> getScrollY() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
|
|
@ -439,6 +439,37 @@ class GeolocationPermissionShowPromptResponse {
|
|||
}
|
||||
}
|
||||
|
||||
///Class that represents the request of the [WebView.onJsAlert] event.
|
||||
class JsAlertRequest {
|
||||
///The url of the page requesting the dialog.
|
||||
String url;
|
||||
|
||||
///Message to be displayed in the window.
|
||||
String message;
|
||||
|
||||
///Indicates whether the request was made for the main frame. Available only on iOS.
|
||||
bool iosIsMainFrame;
|
||||
|
||||
JsAlertRequest({
|
||||
this.url,
|
||||
this.message,
|
||||
this.iosIsMainFrame
|
||||
});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {"url": url, "message": message, "iosIsMainFrame": iosIsMainFrame};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
}
|
||||
|
||||
///Class used by [JsAlertResponse] class.
|
||||
class JsAlertResponseAction {
|
||||
final int _value;
|
||||
|
@ -494,6 +525,37 @@ class JsAlertResponse {
|
|||
}
|
||||
}
|
||||
|
||||
///Class that represents the request of the [WebView.onJsConfirm] event.
|
||||
class JsConfirmRequest {
|
||||
///The url of the page requesting the dialog.
|
||||
String url;
|
||||
|
||||
///Message to be displayed in the window.
|
||||
String message;
|
||||
|
||||
///Indicates whether the request was made for the main frame. Available only on iOS.
|
||||
bool iosIsMainFrame;
|
||||
|
||||
JsConfirmRequest({
|
||||
this.url,
|
||||
this.message,
|
||||
this.iosIsMainFrame
|
||||
});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {"url": url, "message": message, "iosIsMainFrame": iosIsMainFrame};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
}
|
||||
|
||||
///Class used by [JsConfirmResponse] class.
|
||||
class JsConfirmResponseAction {
|
||||
final int _value;
|
||||
|
@ -555,6 +617,41 @@ class JsConfirmResponse {
|
|||
}
|
||||
}
|
||||
|
||||
///Class that represents the request of the [WebView.onJsPrompt] event.
|
||||
class JsPromptRequest {
|
||||
///The url of the page requesting the dialog.
|
||||
String url;
|
||||
|
||||
///Message to be displayed in the window.
|
||||
String message;
|
||||
|
||||
///The default value displayed in the prompt dialog.
|
||||
String defaultValue;
|
||||
|
||||
///Indicates whether the request was made for the main frame. Available only on iOS.
|
||||
bool iosIsMainFrame;
|
||||
|
||||
JsPromptRequest({
|
||||
this.url,
|
||||
this.message,
|
||||
this.defaultValue,
|
||||
this.iosIsMainFrame
|
||||
});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {"url": url, "message": message, "defaultValue": defaultValue, "iosIsMainFrame": iosIsMainFrame};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
}
|
||||
|
||||
///Class used by [JsPromptResponse] class.
|
||||
class JsPromptResponseAction {
|
||||
final int _value;
|
||||
|
@ -626,6 +723,98 @@ class JsPromptResponse {
|
|||
}
|
||||
}
|
||||
|
||||
///Class that represents the request of the [WebView.androidOnJsBeforeUnload] event.
|
||||
class JsBeforeUnloadRequest {
|
||||
///The url of the page requesting the dialog.
|
||||
String url;
|
||||
|
||||
///Message to be displayed in the window.
|
||||
String message;
|
||||
|
||||
///Indicates whether the request was made for the main frame. Available only on iOS.
|
||||
bool iosIsMainFrame;
|
||||
|
||||
JsBeforeUnloadRequest({
|
||||
this.url,
|
||||
this.message,
|
||||
this.iosIsMainFrame
|
||||
});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {"url": url, "message": message, "iosIsMainFrame": iosIsMainFrame};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
}
|
||||
|
||||
///Class used by [JsBeforeUnloadResponse] class.
|
||||
class JsBeforeUnloadResponseAction {
|
||||
final int _value;
|
||||
|
||||
const JsBeforeUnloadResponseAction._internal(this._value);
|
||||
|
||||
int toValue() => _value;
|
||||
|
||||
static const CONFIRM = const JsBeforeUnloadResponseAction._internal(0);
|
||||
static const CANCEL = const JsBeforeUnloadResponseAction._internal(1);
|
||||
|
||||
bool operator ==(value) => value == _value;
|
||||
|
||||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///Class that represents the response used by the [WebView.androidOnJsBeforeUnload] event to control a JavaScript alert dialog.
|
||||
class JsBeforeUnloadResponse {
|
||||
///Message to be displayed in the window.
|
||||
String message;
|
||||
|
||||
///Title of the confirm button.
|
||||
String confirmButtonTitle;
|
||||
|
||||
///Title of the cancel button.
|
||||
String cancelButtonTitle;
|
||||
|
||||
///Whether the client will handle the alert dialog.
|
||||
bool handledByClient;
|
||||
|
||||
///Action used to confirm that the user hit confirm button.
|
||||
JsBeforeUnloadResponseAction action;
|
||||
|
||||
JsBeforeUnloadResponse(
|
||||
{this.message = "",
|
||||
this.handledByClient = false,
|
||||
this.confirmButtonTitle = "",
|
||||
this.cancelButtonTitle = "",
|
||||
this.action = JsBeforeUnloadResponseAction.CONFIRM});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"message": message,
|
||||
"confirmButtonTitle": confirmButtonTitle,
|
||||
"cancelButtonTitle": cancelButtonTitle,
|
||||
"handledByClient": handledByClient,
|
||||
"action": action?.toValue()
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
}
|
||||
|
||||
///Class that represents the reason the resource was caught by Safe Browsing.
|
||||
class SafeBrowsingThreat {
|
||||
final int _value;
|
||||
|
@ -2954,10 +3143,15 @@ class ShouldOverrideUrlLoadingRequest {
|
|||
}
|
||||
|
||||
///Class that represents the navigation request used by the [WebView.onCreateWindow] event.
|
||||
class OnCreateWindowRequest {
|
||||
///Represents the url of the navigation request.
|
||||
class CreateWindowRequest {
|
||||
///The URL of the request.
|
||||
///
|
||||
///**NOTE**: On Android, if the window has been created using JavaScript, this will be `null`.
|
||||
String url;
|
||||
|
||||
///The window id. Used by [WebView] to create a new WebView.
|
||||
int windowId;
|
||||
|
||||
///Indicates if the new window should be a dialog, rather than a full-size window. Available only on Android.
|
||||
bool androidIsDialog;
|
||||
|
||||
|
@ -2967,18 +3161,24 @@ class OnCreateWindowRequest {
|
|||
///The type of action triggering the navigation. Available only on iOS.
|
||||
IOSWKNavigationType iosWKNavigationType;
|
||||
|
||||
OnCreateWindowRequest(
|
||||
///Whether the request was made in order to fetch the main frame's document. Available only on iOS.
|
||||
bool iosIsForMainFrame;
|
||||
|
||||
CreateWindowRequest(
|
||||
{this.url,
|
||||
this.windowId,
|
||||
this.androidIsDialog,
|
||||
this.androidIsUserGesture,
|
||||
this.iosWKNavigationType});
|
||||
this.iosWKNavigationType,
|
||||
this.iosIsForMainFrame});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"url": url,
|
||||
"androidIsDialog": androidIsDialog,
|
||||
"androidIsUserGesture": androidIsUserGesture,
|
||||
"iosWKNavigationType": iosWKNavigationType?.toValue()
|
||||
"iosWKNavigationType": iosWKNavigationType?.toValue(),
|
||||
"iosUrl": url,
|
||||
"windowId": windowId
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -4163,3 +4363,39 @@ class SslCertificateDName {
|
|||
return toMap().toString();
|
||||
}
|
||||
}
|
||||
|
||||
///Class used by [WebView.androidOnReceivedLoginRequest] event.
|
||||
class LoginRequest {
|
||||
///The account realm used to look up accounts.
|
||||
String realm;
|
||||
|
||||
///An optional account. If not `null`, the account should be checked against accounts on the device.
|
||||
///If it is a valid account, it should be used to log in the user. This value may be `null`.
|
||||
String account;
|
||||
|
||||
///Authenticator specific arguments used to log in the user.
|
||||
String args;
|
||||
|
||||
LoginRequest({
|
||||
this.realm,
|
||||
this.account,
|
||||
this.args
|
||||
});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"realm": realm,
|
||||
"account": account,
|
||||
"args": args
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'context_menu.dart';
|
||||
|
||||
import 'types.dart';
|
||||
|
@ -7,12 +9,16 @@ import 'headless_in_app_webview.dart';
|
|||
|
||||
///Abstract class that represents a WebView. Used by [WebView] and [HeadlessInAppWebView].
|
||||
abstract class WebView {
|
||||
///The window id of a [CreateWindowRequest.windowId].
|
||||
final int windowId;
|
||||
|
||||
///Event fired when the [WebView] is created.
|
||||
final void Function(InAppWebViewController controller) onWebViewCreated;
|
||||
|
||||
///Event fired when the [WebView] starts to load an [url].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onPageStarted(android.webkit.WebView,%20java.lang.String,%20android.graphics.Bitmap)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455621-webview
|
||||
final void Function(InAppWebViewController controller, String url)
|
||||
onLoadStart;
|
||||
|
@ -20,12 +26,14 @@ abstract class WebView {
|
|||
///Event fired when the [WebView] finishes loading an [url].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onPageFinished(android.webkit.WebView,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455629-webview
|
||||
final void Function(InAppWebViewController controller, String url) onLoadStop;
|
||||
|
||||
///Event fired when the [WebView] encounters an error loading an [url].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedError(android.webkit.WebView,%20int,%20java.lang.String,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455623-webview
|
||||
final void Function(InAppWebViewController controller, String url, int code,
|
||||
String message) onLoadError;
|
||||
|
@ -41,6 +49,7 @@ abstract class WebView {
|
|||
///**NOTE**: available on Android 23+.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedHttpError(android.webkit.WebView,%20android.webkit.WebResourceRequest,%20android.webkit.WebResourceResponse)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455643-webview
|
||||
final void Function(InAppWebViewController controller, String url,
|
||||
int statusCode, String description) onLoadHttpError;
|
||||
|
@ -71,6 +80,7 @@ abstract class WebView {
|
|||
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldOverrideUrlLoading] option to `true`.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#shouldOverrideUrlLoading(android.webkit.WebView,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455641-webview
|
||||
final Future<ShouldOverrideUrlLoadingAction> Function(
|
||||
InAppWebViewController controller,
|
||||
|
@ -91,6 +101,7 @@ abstract class WebView {
|
|||
///[y] represents the current vertical scroll origin in pixels.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#onScrollChanged(int,%20int,%20int,%20int)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollviewdelegate/1619392-scrollviewdidscroll
|
||||
final void Function(InAppWebViewController controller, int x, int y)
|
||||
onScrollChanged;
|
||||
|
@ -103,6 +114,7 @@ abstract class WebView {
|
|||
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnDownloadStart] option to `true`.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#setDownloadListener(android.webkit.DownloadListener)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455643-webview
|
||||
final void Function(InAppWebViewController controller, String url)
|
||||
onDownloadStart;
|
||||
|
@ -120,53 +132,91 @@ abstract class WebView {
|
|||
|
||||
///Event fired when the [WebView] requests the host application to create a new window,
|
||||
///for example when trying to open a link with `target="_blank"` or when `window.open()` is called by JavaScript side.
|
||||
///The return value should be a [WebView] instance or `null`. If it returns `null`, then nothing will happen.
|
||||
///If it returns an [InAppWebView] instance, when it will be added to the widget tree, it will load the request.
|
||||
///If it returns a [HeadlessInAppWebView] instance, the [HeadlessInAppWebView.run] method will be immediately called.
|
||||
///Remember to use the [CreateWindowRequest.windowId] to create the new WebView instance.
|
||||
///
|
||||
///[onCreateWindowRequest] represents the request.
|
||||
///[createWindowRequest] represents the request.
|
||||
///
|
||||
///**NOTE**: on Android you need to set [AndroidInAppWebViewOptions.supportMultipleWindows] option to `true`.
|
||||
///
|
||||
///**NOTE**: on iOS, setting these initial options: [InAppWebViewOptions.supportZoom], [InAppWebViewOptions.useOnLoadResource], [InAppWebViewOptions.useShouldInterceptAjaxRequest],
|
||||
///[InAppWebViewOptions.useShouldInterceptFetchRequest], [InAppWebViewOptions.applicationNameForUserAgent], [InAppWebViewOptions.javaScriptCanOpenWindowsAutomatically],
|
||||
///[InAppWebViewOptions.javaScriptEnabled], [InAppWebViewOptions.minimumFontSize], [InAppWebViewOptions.preferredContentMode], [InAppWebViewOptions.incognito],
|
||||
///[InAppWebViewOptions.cacheEnabled], [InAppWebViewOptions.mediaPlaybackRequiresUserGesture],
|
||||
///[InAppWebViewOptions.resourceCustomSchemes], [IOSInAppWebViewOptions.sharedCookiesEnabled],
|
||||
///[IOSInAppWebViewOptions.enableViewportScale], [IOSInAppWebViewOptions.allowsAirPlayForMediaPlayback],
|
||||
///[IOSInAppWebViewOptions.allowsPictureInPictureMediaPlayback], [IOSInAppWebViewOptions.isFraudulentWebsiteWarningEnabled],
|
||||
///[IOSInAppWebViewOptions.allowsInlineMediaPlayback], [IOSInAppWebViewOptions.suppressesIncrementalRendering], [IOSInAppWebViewOptions.selectionGranularity],
|
||||
///[IOSInAppWebViewOptions.ignoresViewportScaleLimits],
|
||||
///will have no effect due to a `WKWebView` limitation when creating a new window WebView: it's impossible to return a new `WKWebView`
|
||||
///with a different `WKWebViewConfiguration` instance (see https://developer.apple.com/documentation/webkit/wkuidelegate/1536907-webview).
|
||||
///So, these options will be inherited from the caller WebView.
|
||||
///Also, note that calling [InAppWebViewController.setOptions] method using the controller of the new created WebView,
|
||||
///it will update also the WebView options of the caller WebView.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onCreateWindow(android.webkit.WebView,%20boolean,%20boolean,%20android.os.Message)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1536907-webview
|
||||
final void Function(InAppWebViewController controller,
|
||||
OnCreateWindowRequest onCreateWindowRequest) onCreateWindow;
|
||||
final Future<WebView> Function(InAppWebViewController controller,
|
||||
CreateWindowRequest createWindowRequest) onCreateWindow;
|
||||
|
||||
///Event fired when the host application should close the given WebView and remove it from the view system if necessary.
|
||||
///At this point, WebCore has stopped any loading in this window and has removed any cross-scripting ability in javascript.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onCloseWindow(android.webkit.WebView)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1537390-webviewdidclose
|
||||
final void Function(InAppWebViewController controller) onCloseWindow;
|
||||
|
||||
///Event fired when the JavaScript `window` object of the WebView has received focus.
|
||||
///This is the result of the `focus` JavaScript event applied to the `window` object.
|
||||
final void Function(InAppWebViewController controller) onWindowFocus;
|
||||
|
||||
///Event fired when the JavaScript `window` object of the WebView has lost focus.
|
||||
///This is the result of the `blur` JavaScript event applied to the `window` object.
|
||||
final void Function(InAppWebViewController controller) onWindowBlur;
|
||||
|
||||
///Event fired when javascript calls the `alert()` method to display an alert dialog.
|
||||
///If [JsAlertResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
|
||||
///
|
||||
///[message] represents the message to be displayed in the alert dialog.
|
||||
///[jsAlertRequest] contains the message to be displayed in the alert dialog and the of the page requesting the dialog.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onJsAlert(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20android.webkit.JsResult)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1537406-webview
|
||||
final Future<JsAlertResponse> Function(
|
||||
InAppWebViewController controller, String message) onJsAlert;
|
||||
InAppWebViewController controller, JsAlertRequest jsAlertRequest) onJsAlert;
|
||||
|
||||
///Event fired when javascript calls the `confirm()` method to display a confirm dialog.
|
||||
///If [JsConfirmResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
|
||||
///
|
||||
///[message] represents the message to be displayed in the alert dialog.
|
||||
///[jsConfirmRequest] contains the message to be displayed in the confirm dialog and the of the page requesting the dialog.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onJsConfirm(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20android.webkit.JsResult)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1536489-webview
|
||||
final Future<JsConfirmResponse> Function(
|
||||
InAppWebViewController controller, String message) onJsConfirm;
|
||||
InAppWebViewController controller, JsConfirmRequest jsConfirmRequest) onJsConfirm;
|
||||
|
||||
///Event fired when javascript calls the `prompt()` method to display a prompt dialog.
|
||||
///If [JsPromptResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
|
||||
///
|
||||
///[message] represents the message to be displayed in the alert dialog.
|
||||
///
|
||||
///[defaultValue] represents the default value displayed in the prompt dialog.
|
||||
///[jsPromptRequest] contains the message to be displayed in the prompt dialog, the default value displayed in the prompt dialog, and the of the page requesting the dialog.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onJsPrompt(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20java.lang.String,%20android.webkit.JsPromptResult)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1538086-webview
|
||||
final Future<JsPromptResponse> Function(InAppWebViewController controller,
|
||||
String message, String defaultValue) onJsPrompt;
|
||||
JsPromptRequest jsPromptRequest) onJsPrompt;
|
||||
|
||||
///Event fired when the WebView received an HTTP authentication request. The default behavior is to cancel the request.
|
||||
///
|
||||
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [HttpAuthChallenge].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedHttpAuthRequest(android.webkit.WebView,%20android.webkit.HttpAuthHandler,%20java.lang.String,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455638-webview
|
||||
final Future<HttpAuthResponse> Function(
|
||||
InAppWebViewController controller, HttpAuthChallenge challenge)
|
||||
|
@ -178,6 +228,7 @@ abstract class WebView {
|
|||
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [ServerTrustChallenge].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedSslError(android.webkit.WebView,%20android.webkit.SslErrorHandler,%20android.net.http.SslError)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455638-webview
|
||||
final Future<ServerTrustAuthResponse> Function(
|
||||
InAppWebViewController controller, ServerTrustChallenge challenge)
|
||||
|
@ -191,6 +242,7 @@ abstract class WebView {
|
|||
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [ClientCertChallenge].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedClientCertRequest(android.webkit.WebView,%20android.webkit.ClientCertRequest)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455638-webview
|
||||
final Future<ClientCertResponse> Function(
|
||||
InAppWebViewController controller, ClientCertChallenge challenge)
|
||||
|
@ -291,6 +343,7 @@ abstract class WebView {
|
|||
///[hitTestResult] represents the hit result for hitting an HTML elements.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/view/View#setOnLongClickListener(android.view.View.OnLongClickListener)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uilongpressgesturerecognizer
|
||||
final void Function(InAppWebViewController controller,
|
||||
InAppWebViewHitTestResult hitTestResult) onLongPressHitTestResult;
|
||||
|
@ -298,12 +351,14 @@ abstract class WebView {
|
|||
///Event fired when the current page has entered full screen mode.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onShowCustomView(android.view.View,%20android.webkit.WebChromeClient.CustomViewCallback)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiwindow/1621621-didbecomevisiblenotification
|
||||
final void Function(InAppWebViewController controller) onEnterFullscreen;
|
||||
|
||||
///Event fired when the current page has exited full screen mode.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onHideCustomView()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiwindow/1621617-didbecomehiddennotification
|
||||
final void Function(InAppWebViewController controller) onExitFullscreen;
|
||||
|
||||
|
@ -315,10 +370,19 @@ abstract class WebView {
|
|||
///[url] represents the URL corresponding to the page navigation that triggered this callback.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onPageCommitVisible(android.webkit.WebView,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455635-webview
|
||||
final Future<void> Function(InAppWebViewController controller, String url)
|
||||
final void Function(InAppWebViewController controller, String url)
|
||||
onPageCommitVisible;
|
||||
|
||||
///Event fired when a change in the document title occurred.
|
||||
///
|
||||
///[title] represents the string containing the new title of the document.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onReceivedTitle(android.webkit.WebView,%20java.lang.String)
|
||||
final void Function(InAppWebViewController controller, String title)
|
||||
onTitleChanged;
|
||||
|
||||
///Event fired when the webview notifies that a loading URL has been flagged by Safe Browsing.
|
||||
///The default behavior is to show an interstitial to the user, with the reporting checkbox visible.
|
||||
///
|
||||
|
@ -435,7 +499,7 @@ abstract class WebView {
|
|||
///**NOTE**: available only on Android 26+.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onRenderProcessGone(android.webkit.WebView,%20android.webkit.RenderProcessGoneDetail)
|
||||
final Future<void> Function(
|
||||
final void Function(
|
||||
InAppWebViewController controller, RenderProcessGoneDetail detail)
|
||||
androidOnRenderProcessGone;
|
||||
|
||||
|
@ -456,16 +520,69 @@ abstract class WebView {
|
|||
///**NOTE**: available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onScaleChanged(android.webkit.WebView,%20float,%20float)
|
||||
final Future<void> Function(
|
||||
final void Function(
|
||||
InAppWebViewController controller, double oldScale, double newScale)
|
||||
androidOnScaleChanged;
|
||||
|
||||
///Event fired when there is a request to display and focus for this WebView.
|
||||
///This may happen due to another WebView opening a link in this WebView and requesting that this WebView be displayed.
|
||||
///
|
||||
///**NOTE**: available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onRequestFocus(android.webkit.WebView)
|
||||
final void Function(InAppWebViewController controller) androidOnRequestFocus;
|
||||
|
||||
///Event fired when there is new favicon for the current page.
|
||||
///
|
||||
///[icon] represents the favicon for the current page.
|
||||
///
|
||||
///**NOTE**: available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onReceivedIcon(android.webkit.WebView,%20android.graphics.Bitmap)
|
||||
final void Function(InAppWebViewController controller, Uint8List icon) androidOnReceivedIcon;
|
||||
|
||||
///Event fired when there is an url for an apple-touch-icon.
|
||||
///
|
||||
///[url] represents the icon url.
|
||||
///
|
||||
///[precomposed] is `true` if the url is for a precomposed touch icon.
|
||||
///
|
||||
///**NOTE**: available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onReceivedTouchIconUrl(android.webkit.WebView,%20java.lang.String,%20boolean)
|
||||
final void Function(InAppWebViewController controller, String url, bool precomposed) androidOnReceivedTouchIconUrl;
|
||||
|
||||
///Event fired when the client should display a dialog to confirm navigation away from the current page.
|
||||
///This is the result of the `onbeforeunload` javascript event.
|
||||
///If [JsBeforeUnloadResponse.handledByClient] is `true`, WebView will assume that the client will handle the confirm dialog.
|
||||
///If [JsBeforeUnloadResponse.handledByClient] is `false`, a default value of `true` will be returned to javascript to accept navigation away from the current page.
|
||||
///The default behavior is to return `false`.
|
||||
///Setting the [JsBeforeUnloadResponse.action] to [JsBeforeUnloadResponseAction.CONFIRM] will navigate away from the current page,
|
||||
///[JsBeforeUnloadResponseAction.CANCEL] will cancel the navigation.
|
||||
///
|
||||
///[jsBeforeUnloadRequest] contains the message to be displayed in the alert dialog and the of the page requesting the dialog.
|
||||
///
|
||||
///**NOTE**: available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onJsBeforeUnload(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20android.webkit.JsResult)
|
||||
final Future<JsBeforeUnloadResponse> Function(
|
||||
InAppWebViewController controller, JsBeforeUnloadRequest jsBeforeUnloadRequest) androidOnJsBeforeUnload;
|
||||
|
||||
///Event fired when a request to automatically log in the user has been processed.
|
||||
///
|
||||
///[loginRequest] contains the realm, account and args of the login request.
|
||||
///
|
||||
///**NOTE**: available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedLoginRequest(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20java.lang.String)
|
||||
final void Function(InAppWebViewController controller, LoginRequest loginRequest) androidOnReceivedLoginRequest;
|
||||
|
||||
///Invoked when the web view's web content process is terminated.
|
||||
///
|
||||
///**NOTE**: available only on iOS.
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455639-webviewwebcontentprocessdidtermi
|
||||
final Future<void> Function(InAppWebViewController controller)
|
||||
final void Function(InAppWebViewController controller)
|
||||
iosOnWebContentProcessDidTerminate;
|
||||
|
||||
///Called when a web view receives a server redirect.
|
||||
|
@ -473,7 +590,7 @@ abstract class WebView {
|
|||
///**NOTE**: available only on iOS.
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455627-webview
|
||||
final Future<void> Function(InAppWebViewController controller)
|
||||
final void Function(InAppWebViewController controller)
|
||||
iosOnDidReceiveServerRedirectForProvisionalNavigation;
|
||||
|
||||
///Initial url that will be loaded.
|
||||
|
@ -495,7 +612,8 @@ abstract class WebView {
|
|||
final ContextMenu contextMenu;
|
||||
|
||||
WebView(
|
||||
{this.onWebViewCreated,
|
||||
{this.windowId,
|
||||
this.onWebViewCreated,
|
||||
this.onLoadStart,
|
||||
this.onLoadStop,
|
||||
this.onLoadError,
|
||||
|
@ -508,6 +626,7 @@ abstract class WebView {
|
|||
this.onDownloadStart,
|
||||
this.onLoadResourceCustomScheme,
|
||||
this.onCreateWindow,
|
||||
this.onCloseWindow,
|
||||
this.onJsAlert,
|
||||
this.onJsConfirm,
|
||||
this.onJsPrompt,
|
||||
|
@ -525,6 +644,9 @@ abstract class WebView {
|
|||
this.onEnterFullscreen,
|
||||
this.onExitFullscreen,
|
||||
this.onPageCommitVisible,
|
||||
this.onTitleChanged,
|
||||
this.onWindowFocus,
|
||||
this.onWindowBlur,
|
||||
this.androidOnSafeBrowsingHit,
|
||||
this.androidOnPermissionRequest,
|
||||
this.androidOnGeolocationPermissionsShowPrompt,
|
||||
|
@ -535,6 +657,11 @@ abstract class WebView {
|
|||
this.androidOnRenderProcessUnresponsive,
|
||||
this.androidOnFormResubmission,
|
||||
this.androidOnScaleChanged,
|
||||
this.androidOnRequestFocus,
|
||||
this.androidOnReceivedIcon,
|
||||
this.androidOnReceivedTouchIconUrl,
|
||||
this.androidOnJsBeforeUnload,
|
||||
this.androidOnReceivedLoginRequest,
|
||||
this.iosOnWebContentProcessDidTerminate,
|
||||
this.iosOnDidReceiveServerRedirectForProvisionalNavigation,
|
||||
this.initialUrl,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: flutter_inappwebview
|
||||
description: A Flutter plugin that allows you to add an inline webview, to use an headless webview, and to open an in-app browser window.
|
||||
version: 3.4.0+2
|
||||
version: 4.0.0
|
||||
homepage: https://github.com/pichillilorenzo/flutter_inappwebview
|
||||
|
||||
environment:
|
||||
|
|
Loading…
Reference in New Issue