Commit eea69166 authored by Lorenzo Pichilli's avatar Lorenzo Pichilli

Updated onCreateWindow, onJsAlert, onJsConfirm, and onJsPrompt webview events,...

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
parent 9d92911a
## 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);
}
......
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();
}
}
......@@ -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) {
......
{"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"}
\ No newline at end of file
{"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"}
\ No newline at end of file
......@@ -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
......
This diff is collapsed.
......@@ -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()
......
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;
}
This diff is collapsed.
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(),
);
......
This diff is collapsed.
......@@ -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();
}
}
\ No newline at end of file
This diff is collapsed.
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:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment