Commit 0e30767c authored by Lorenzo Pichilli's avatar Lorenzo Pichilli

code refactoring, added InAppBrowserManager and ChromeSafariBrowserManager...

code refactoring, added InAppBrowserManager and ChromeSafariBrowserManager classes on native code, updated webview options class names
parent 4d752ee9
......@@ -81,7 +81,7 @@ See the online [API Reference](https://pub.dartlang.org/documentation/flutter_in
The API showed in this `README.md` file shows only a part of the documentation that conforms to the master branch only.
So, here you could have methods, options, and events that aren't published yet.
If you need a specific version, change the **GitHub branch** to your version or use the **online API Reference** (recommended).
If you need a specific version, change the **GitHub branch** to your version or use the **online API Reference** (recommended).
### Load a file inside `assets` folder
......@@ -530,8 +530,7 @@ class MyInAppBrowser extends InAppBrowser {
@override
Future<ShouldOverrideUrlLoadingAction> shouldOverrideUrlLoading(ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest) async {
print("\n\n override ${shouldOverrideUrlLoadingRequest.url}\n\n");
this.webViewController.loadUrl(url: shouldOverrideUrlLoadingRequest.url);
return ShouldOverrideUrlLoadingAction.CANCEL;
return ShouldOverrideUrlLoadingAction.ALLOW;
}
@override
......
......@@ -5,7 +5,6 @@ import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import androidx.browser.customtabs.CustomTabsCallback;
import androidx.browser.customtabs.CustomTabsIntent;
......@@ -14,16 +13,21 @@ import androidx.browser.customtabs.CustomTabsSession;
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
import com.pichillilorenzo.flutter_inappwebview.R;
import com.pichillilorenzo.flutter_inappwebview.Shared;
import java.util.HashMap;
import java.util.Map;
public class ChromeCustomTabsActivity extends Activity {
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
public class ChromeCustomTabsActivity extends Activity implements MethodChannel.MethodCallHandler {
protected static final String LOG_TAG = "CustomTabsActivity";
String uuid;
CustomTabsIntent.Builder builder;
ChromeCustomTabsOptions options;
public MethodChannel channel;
public String uuid;
private CustomTabsIntent.Builder builder;
private ChromeCustomTabsOptions options;
private CustomTabActivityHelper customTabActivityHelper;
private CustomTabsSession customTabsSession;
private final int CHROME_CUSTOM_TAB_REQUEST_CODE = 100;
......@@ -39,13 +43,15 @@ public class ChromeCustomTabsActivity extends Activity {
Bundle b = getIntent().getExtras();
assert b != null;
uuid = b.getString("uuid");
channel = new MethodChannel(Shared.messenger, "com.pichillilorenzo/flutter_chromesafaribrowser_" + uuid);
channel.setMethodCallHandler(this);
final String url = b.getString("url");
options = new ChromeCustomTabsOptions();
options.parse((HashMap<String, Object>) b.getSerializable("options"));
InAppWebViewFlutterPlugin.inAppBrowser.chromeCustomTabsActivities.put(uuid, this);
final ChromeCustomTabsActivity chromeCustomTabsActivity = this;
customTabActivityHelper = new CustomTabActivityHelper();
......@@ -68,7 +74,7 @@ public class ChromeCustomTabsActivity extends Activity {
finish();
Map<String, Object> obj = new HashMap<>();
obj.put("uuid", uuid);
InAppWebViewFlutterPlugin.inAppBrowser.channel.invokeMethod("onChromeSafariBrowserClosed", obj);
channel.invokeMethod("onChromeSafariBrowserClosed", obj);
}
});
......@@ -79,14 +85,14 @@ public class ChromeCustomTabsActivity extends Activity {
onChromeSafariBrowserOpened = true;
Map<String, Object> obj = new HashMap<>();
obj.put("uuid", uuid);
InAppWebViewFlutterPlugin.inAppBrowser.channel.invokeMethod("onChromeSafariBrowserOpened", obj);
channel.invokeMethod("onChromeSafariBrowserOpened", obj);
}
if (navigationEvent == NAVIGATION_FINISHED && !onChromeSafariBrowserCompletedInitialLoad) {
onChromeSafariBrowserCompletedInitialLoad = true;
Map<String, Object> obj = new HashMap<>();
obj.put("uuid", uuid);
InAppWebViewFlutterPlugin.inAppBrowser.channel.invokeMethod("onChromeSafariBrowserCompletedInitialLoad", obj);
channel.invokeMethod("onChromeSafariBrowserCompletedInitialLoad", obj);
}
}
......@@ -113,6 +119,14 @@ public class ChromeCustomTabsActivity extends Activity {
});
}
@Override
public void onMethodCall(final MethodCall call, final MethodChannel.Result result) {
switch (call.method) {
default:
result.notImplemented();
}
}
private void prepareCustomTabs(CustomTabsIntent customTabsIntent) {
if (options.addDefaultShareMenuItem)
builder.addDefaultShareMenuItem();
......@@ -155,7 +169,7 @@ public class ChromeCustomTabsActivity extends Activity {
finish();
Map<String, Object> obj = new HashMap<>();
obj.put("uuid", uuid);
InAppWebViewFlutterPlugin.inAppBrowser.channel.invokeMethod("onChromeSafariBrowserClosed", obj);
InAppWebViewFlutterPlugin.inAppBrowserManager.channel.invokeMethod("onChromeSafariBrowserClosed", obj);
}
}
......
package com.pichillilorenzo.flutter_inappwebview;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ChromeCustomTabsActivity;
import com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.CustomTabActivityHelper;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandler {
public MethodChannel channel;
protected static final String LOG_TAG = "ChromeBrowserManager";
public ChromeSafariBrowserManager(BinaryMessenger messenger) {
channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_chromesafaribrowser");
channel.setMethodCallHandler(this);
}
@Override
public void onMethodCall(final MethodCall call, final MethodChannel.Result result) {
final Activity activity = Shared.activity;
final String uuid = (String) call.argument("uuid");
switch (call.method) {
case "open":
{
String url = (String) call.argument("url");
HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options");
String uuidFallback = (String) call.argument("uuidFallback");
Map<String, String> headersFallback = (Map<String, String>) call.argument("headersFallback");
HashMap<String, Object> optionsFallback = (HashMap<String, Object>) call.argument("optionsFallback");
open(activity, uuid, url, options, uuidFallback, headersFallback, optionsFallback, result);
}
break;
default:
result.notImplemented();
}
}
public void open(Activity activity, String uuid, String url, HashMap<String, Object> options, String uuidFallback, Map<String, String> headersFallback, HashMap<String, Object> optionsFallback, MethodChannel.Result result) {
Intent intent = null;
Bundle extras = new Bundle();
extras.putString("fromActivity", activity.getClass().getName());
extras.putString("url", url);
extras.putBoolean("isData", false);
extras.putString("uuid", uuid);
extras.putSerializable("options", options);
extras.putSerializable("headers", (Serializable) headersFallback);
if (CustomTabActivityHelper.isAvailable(activity)) {
intent = new Intent(activity, ChromeCustomTabsActivity.class);
}
// check for webview fallback
else if (!CustomTabActivityHelper.isAvailable(activity) && !uuidFallback.isEmpty()) {
Log.d(LOG_TAG, "WebView fallback declared.");
// overwrite with extras fallback parameters
extras.putString("uuid", uuidFallback);
if (optionsFallback != null)
extras.putSerializable("options", optionsFallback);
else
extras.putSerializable("options", (new InAppBrowserOptions()).getHashMap());
intent = new Intent(activity, InAppBrowserActivity.class);
}
if (intent != null) {
intent.putExtras(extras);
activity.startActivity(intent);
result.success(true);
return;
}
result.error(LOG_TAG, "No WebView fallback declared.", null);
}
public void dispose() {
channel.setMethodCallHandler(null);
}
}
......@@ -38,6 +38,9 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
public final MethodChannel channel;
public FlutterWebView(BinaryMessenger messenger, final Context context, int id, HashMap<String, Object> params, View containerView) {
channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_inappwebview_" + id);
channel.setMethodCallHandler(this);
DisplayListenerProxy displayListenerProxy = new DisplayListenerProxy();
DisplayManager displayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
displayListenerProxy.onPreWebViewInitialization(displayManager);
......@@ -70,9 +73,6 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
webView.prepare();
channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_inappwebview_" + id);
channel.setMethodCallHandler(this);
if (initialFile != null) {
try {
initialUrl = Util.getUrlAsset(initialFile);
......
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package com.pichillilorenzo.flutter_inappwebview;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Parcelable;
import android.provider.Browser;
import android.net.Uri;
import android.os.Bundle;
import android.webkit.MimeTypeMap;
import android.util.Log;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.Result;
/**
* InAppBrowserManager
*/
public class InAppBrowserManager implements MethodChannel.MethodCallHandler {
public MethodChannel channel;
protected static final String LOG_TAG = "InAppBrowserManager";
public InAppBrowserManager(BinaryMessenger messenger) {
channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_inappbrowser");
channel.setMethodCallHandler(this);
}
@Override
public void onMethodCall(final MethodCall call, final Result result) {
final Activity activity = Shared.activity;
final String uuid = (String) call.argument("uuid");
switch (call.method) {
case "openUrl":
{
String url = (String) call.argument("url");
HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options");
Map<String, String> headers = (Map<String, String>) call.argument("headers");
openUrl(activity, uuid, url, options, headers);
}
result.success(true);
break;
case "openFile":
{
String url = (String) call.argument("url");
try {
url = Util.getUrlAsset(url);
} catch (IOException e) {
e.printStackTrace();
result.error(LOG_TAG, url + " asset file cannot be found!", e);
return;
}
HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options");
Map<String, String> headers = (Map<String, String>) call.argument("headers");
openUrl(activity, uuid, url, options, headers);
}
result.success(true);
break;
case "openData":
{
HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options");
String data = (String) call.argument("data");
String mimeType = (String) call.argument("mimeType");
String encoding = (String) call.argument("encoding");
String baseUrl = (String) call.argument("baseUrl");
String historyUrl = (String) call.argument("historyUrl");
openData(activity, uuid, options, data, mimeType, encoding, baseUrl, historyUrl);
}
result.success(true);
break;
case "openWithSystemBrowser":
{
String url = (String) call.argument("url");
openWithSystemBrowser(activity, url, result);
}
break;
default:
result.notImplemented();
}
}
public static String getMimeType(String url) {
String type = null;
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
if (extension != null) {
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
return type;
}
/**
* Display a new browser with the specified URL.
*
* @param url the url to load.
* @param result
* @return "" if ok, or error message.
*/
public void openWithSystemBrowser(Activity activity, String url, Result result) {
try {
Intent intent;
intent = new Intent(Intent.ACTION_VIEW);
// Omitting the MIME type for file: URLs causes "No Activity found to handle Intent".
// Adding the MIME type to http: URLs causes them to not be handled by the downloader.
Uri uri = Uri.parse(url);
if ("file".equals(uri.getScheme())) {
intent.setDataAndType(uri, getMimeType(url));
} else {
intent.setData(uri);
}
intent.putExtra(Browser.EXTRA_APPLICATION_ID, activity.getPackageName());
// CB-10795: Avoid circular loops by preventing it from opening in the current app
this.openExternalExcludeCurrentApp(activity, intent);
result.success(true);
// not catching FileUriExposedException explicitly because buildtools<24 doesn't know about it
} catch (java.lang.RuntimeException e) {
Log.d(LOG_TAG, url + " cannot be opened: " + e.toString());
result.error(LOG_TAG, url + " cannot be opened!", null);
}
}
/**
* Opens the intent, providing a chooser that excludes the current app to avoid
* circular loops.
*/
public void openExternalExcludeCurrentApp(Activity activity, Intent intent) {
String currentPackage = activity.getPackageName();
boolean hasCurrentPackage = false;
PackageManager pm = activity.getPackageManager();
List<ResolveInfo> activities = pm.queryIntentActivities(intent, 0);
ArrayList<Intent> targetIntents = new ArrayList<Intent>();
for (ResolveInfo ri : activities) {
if (!currentPackage.equals(ri.activityInfo.packageName)) {
Intent targetIntent = (Intent) intent.clone();
targetIntent.setPackage(ri.activityInfo.packageName);
targetIntents.add(targetIntent);
} else {
hasCurrentPackage = true;
}
}
// If the current app package isn't a target for this URL, then use
// the normal launch behavior
if (!hasCurrentPackage || targetIntents.size() == 0) {
activity.startActivity(intent);
}
// If there's only one possible intent, launch it directly
else if (targetIntents.size() == 1) {
activity.startActivity(targetIntents.get(0));
}
// Otherwise, show a custom chooser without the current app listed
else if (targetIntents.size() > 0) {
Intent chooser = Intent.createChooser(targetIntents.remove(targetIntents.size() - 1), null);
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toArray(new Parcelable[]{}));
activity.startActivity(chooser);
}
}
public void openUrl(Activity activity, String uuid, String url, HashMap<String, Object> options, Map<String, String> headers) {
Bundle extras = new Bundle();
extras.putString("fromActivity", activity.getClass().getName());
extras.putString("url", url);
extras.putBoolean("isData", false);
extras.putString("uuid", uuid);
extras.putSerializable("options", options);
extras.putSerializable("headers", (Serializable) headers);
startInAppBrowserActivity(activity, extras);
}
public void openData(Activity activity, String uuid, HashMap<String, Object> options, String data, String mimeType, String encoding, String baseUrl, String historyUrl) {
Bundle extras = new Bundle();
extras.putBoolean("isData", true);
extras.putString("uuid", uuid);
extras.putSerializable("options", options);
extras.putString("data", data);
extras.putString("mimeType", mimeType);
extras.putString("encoding", encoding);
extras.putString("baseUrl", baseUrl);
extras.putString("historyUrl", historyUrl);
startInAppBrowserActivity(activity, extras);
}
public void startInAppBrowserActivity(Activity activity, Bundle extras) {
Intent intent = new Intent(activity, InAppBrowserActivity.class);
if (extras != null)
intent.putExtras(extras);
activity.startActivity(intent);
}
public void dispose() {
channel.setMethodCallHandler(null);
}
}
package com.pichillilorenzo.flutter_inappwebview.InAppWebView;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
......@@ -21,13 +19,8 @@ import android.webkit.WebBackForwardList;
import android.webkit.WebHistoryItem;
import android.webkit.WebSettings;
import android.webkit.WebStorage;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
import android.widget.ListView;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AlertDialog;
import com.pichillilorenzo.flutter_inappwebview.ContentBlocker.ContentBlocker;
import com.pichillilorenzo.flutter_inappwebview.ContentBlocker.ContentBlockerAction;
......@@ -37,7 +30,6 @@ import com.pichillilorenzo.flutter_inappwebview.FlutterWebView;
import com.pichillilorenzo.flutter_inappwebview.InAppBrowserActivity;
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
import com.pichillilorenzo.flutter_inappwebview.JavaScriptBridgeInterface;
import com.pichillilorenzo.flutter_inappwebview.R;
import com.pichillilorenzo.flutter_inappwebview.Shared;
import com.pichillilorenzo.flutter_inappwebview.Util;
......@@ -50,7 +42,6 @@ import java.util.Map;
import java.util.regex.Pattern;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.PluginRegistry;
import okhttp3.OkHttpClient;
import static com.pichillilorenzo.flutter_inappwebview.InAppWebView.PreferredContentModeOptionType.fromValue;
......@@ -61,6 +52,7 @@ final public class InAppWebView extends InputAwareWebView {
public InAppBrowserActivity inAppBrowserActivity;
public FlutterWebView flutterWebView;
public MethodChannel channel;
public int id;
public InAppWebViewClient inAppWebViewClient;
public InAppWebViewChromeClient inAppWebViewChromeClient;
......@@ -123,7 +115,7 @@ final public class InAppWebView extends InputAwareWebView {
static final String interceptAjaxRequestsJS = "(function(ajax) {" +
" var send = ajax.prototype.send;" +
" var open = ajax.prototype.open;" +
" var openUrl = ajax.prototype.openUrl;" +
" var setRequestHeader = ajax.prototype.setRequestHeader;" +
" ajax.prototype._flutter_inappwebview_url = null;" +
" ajax.prototype._flutter_inappwebview_method = null;" +
......@@ -156,7 +148,7 @@ final public class InAppWebView extends InputAwareWebView {
" }" +
" callback(null);" +
" };" +
" ajax.prototype.open = function(method, url, isAsync, user, password) {" +
" ajax.prototype.openUrl = function(method, url, isAsync, user, password) {" +
" isAsync = (isAsync != null) ? isAsync : true;" +
" this._flutter_inappwebview_url = url;" +
" this._flutter_inappwebview_method = method;" +
......@@ -164,7 +156,7 @@ final public class InAppWebView extends InputAwareWebView {
" this._flutter_inappwebview_user = user;" +
" this._flutter_inappwebview_password = password;" +
" this._flutter_inappwebview_request_headers = {};" +
" open.call(this, method, url, isAsync, user, password);" +
" openUrl.call(this, method, url, isAsync, user, password);" +
" };" +
" ajax.prototype.setRequestHeader = function(header, value) {" +
" this._flutter_inappwebview_request_headers[header] = value;" +
......@@ -319,7 +311,7 @@ final public class InAppWebView extends InputAwareWebView {
" };" +
" if ((self._flutter_inappwebview_method != result.method && result.method != null) || (self._flutter_inappwebview_url != result.url && result.url != null)) {" +
" self.abort();" +
" self.open(result.method, result.url, result.isAsync, result.user, result.password);" +
" self.openUrl(result.method, result.url, result.isAsync, result.user, result.password);" +
" return;" +
" }" +
" }" +
......@@ -532,6 +524,7 @@ final public class InAppWebView extends InputAwareWebView {
this.inAppBrowserActivity = (InAppBrowserActivity) obj;
else if (obj instanceof FlutterWebView)
this.flutterWebView = (FlutterWebView) obj;
this.channel = (this.inAppBrowserActivity != null) ? this.inAppBrowserActivity.channel : this.flutterWebView.channel;
this.id = id;
this.options = options;
}
......@@ -689,7 +682,7 @@ final public class InAppWebView extends InputAwareWebView {
obj.put("activeMatchOrdinal", activeMatchOrdinal);
obj.put("numberOfMatches", numberOfMatches);
obj.put("isDoneCounting", isDoneCounting);
getChannel().invokeMethod("onFindResultReceived", obj);
channel.invokeMethod("onFindResultReceived", obj);
}
});
......@@ -1264,11 +1257,7 @@ final public class InAppWebView extends InputAwareWebView {
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("x", x);
obj.put("y", y);
getChannel().invokeMethod("onScrollChanged", obj);
}
private MethodChannel getChannel() {
return (inAppBrowserActivity != null) ? InAppWebViewFlutterPlugin.inAppBrowser.channel : flutterWebView.channel;
channel.invokeMethod("onScrollChanged", obj);
}
public void startSafeBrowsing(final MethodChannel.Result result) {
......@@ -1304,7 +1293,7 @@ final public class InAppWebView extends InputAwareWebView {
if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("url", url);
getChannel().invokeMethod("onDownloadStart", obj);
channel.invokeMethod("onDownloadStart", obj);
}
}
......
......@@ -2,7 +2,6 @@ package com.pichillilorenzo.flutter_inappwebview.InAppWebView;
import android.annotation.TargetApi;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
......@@ -33,7 +32,6 @@ import com.pichillilorenzo.flutter_inappwebview.InAppBrowserActivity;
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
import com.pichillilorenzo.flutter_inappwebview.R;
import com.pichillilorenzo.flutter_inappwebview.Shared;
import com.pichillilorenzo.flutter_inappwebview.Util;
import java.util.ArrayList;
import java.util.Arrays;
......@@ -52,6 +50,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
protected static final String LOG_TAG = "IABWebChromeClient";
private FlutterWebView flutterWebView;
private InAppBrowserActivity inAppBrowserActivity;
public MethodChannel channel;
private ValueCallback<Uri> mUploadMessage;
private final static int FILECHOOSER_RESULTCODE = 1;
......@@ -65,6 +64,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
this.inAppBrowserActivity = (InAppBrowserActivity) obj;
else if (obj instanceof FlutterWebView)
this.flutterWebView = (FlutterWebView) obj;
this.channel = (this.inAppBrowserActivity != null) ? this.inAppBrowserActivity.channel : this.flutterWebView.channel;
if (Shared.registrar != null)
Shared.registrar.addActivityResultListener(this);
......@@ -121,7 +121,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("message", message);
getChannel().invokeMethod("onJsAlert", obj, new MethodChannel.Result() {
channel.invokeMethod("onJsAlert", obj, new MethodChannel.Result() {
@Override
public void success(Object response) {
String responseMessage = null;
......@@ -204,7 +204,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("message", message);
getChannel().invokeMethod("onJsConfirm", obj, new MethodChannel.Result() {
channel.invokeMethod("onJsConfirm", obj, new MethodChannel.Result() {
@Override
public void success(Object response) {
String responseMessage = null;
......@@ -301,7 +301,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
obj.put("message", message);
obj.put("defaultValue", defaultValue);
getChannel().invokeMethod("onJsPrompt", obj, new MethodChannel.Result() {
channel.invokeMethod("onJsPrompt", obj, new MethodChannel.Result() {
@Override
public void success(Object response) {
String responseMessage = null;
......@@ -433,7 +433,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
super.onPageStarted(v, url, favicon);
obj.put("url", url);
getChannel().invokeMethod("onCreateWindow", obj);
channel.invokeMethod("onCreateWindow", obj);
// stop webview loading
v.stopLoading();
......@@ -449,7 +449,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
}
obj.put("url", data);
getChannel().invokeMethod("onCreateWindow", obj);
channel.invokeMethod("onCreateWindow", obj);
return false;
}
......@@ -459,7 +459,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("origin", origin);
getChannel().invokeMethod("onGeolocationPermissionsShowPrompt", obj, new MethodChannel.Result() {
channel.invokeMethod("onGeolocationPermissionsShowPrompt", obj, new MethodChannel.Result() {
@Override
public void success(Object o) {
Map<String, Object> response = (Map<String, Object>) o;
......@@ -486,7 +486,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
Map<String, Object> obj = new HashMap<>();
if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
getChannel().invokeMethod("onGeolocationPermissionsHidePrompt", obj);
channel.invokeMethod("onGeolocationPermissionsHidePrompt", obj);
}
@Override
......@@ -496,7 +496,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("message", consoleMessage.message());
obj.put("messageLevel", consoleMessage.messageLevel().ordinal());
getChannel().invokeMethod("onConsoleMessage", obj);
channel.invokeMethod("onConsoleMessage", obj);
return true;
}
......@@ -518,7 +518,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("progress", progress);
getChannel().invokeMethod("onProgressChanged", obj);
channel.invokeMethod("onProgressChanged", obj);
super.onProgressChanged(view, progress);
}
......@@ -608,7 +608,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("origin", request.getOrigin().toString());
obj.put("resources", Arrays.asList(request.getResources()));
getChannel().invokeMethod("onPermissionRequest", obj, new MethodChannel.Result() {
channel.invokeMethod("onPermissionRequest", obj, new MethodChannel.Result() {
@Override
public void success(Object response) {
if (response != null) {
......@@ -646,8 +646,4 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
});
}
}
private MethodChannel getChannel() {
return (inAppBrowserActivity != null) ? InAppWebViewFlutterPlugin.inAppBrowser.channel : flutterWebView.channel;
}
}
......@@ -17,7 +17,6 @@ import android.webkit.SslErrorHandler;
import android.webkit.ValueCallback;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebStorage;
import android.webkit.WebView;
import android.webkit.WebViewClient;
......@@ -53,6 +52,7 @@ public class InAppWebViewClient extends WebViewClient {
protected static final String LOG_TAG = "IABWebViewClient";
private FlutterWebView flutterWebView;
private InAppBrowserActivity inAppBrowserActivity;
public MethodChannel channel;
private static int previousAuthRequestFailureCount = 0;
private static List<Credential> credentialsProposed = null;
......@@ -62,6 +62,7 @@ public class InAppWebViewClient extends WebViewClient {
this.inAppBrowserActivity = (InAppBrowserActivity) obj;
else if (obj instanceof FlutterWebView)
this.flutterWebView = (FlutterWebView) obj;
this.channel = (this.inAppBrowserActivity != null) ? this.inAppBrowserActivity.channel : this.flutterWebView.channel;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
......@@ -125,7 +126,7 @@ public class InAppWebViewClient extends WebViewClient {
obj.put("androidHasGesture", hasGesture);
obj.put("androidIsRedirect", isRedirect);
obj.put("iosWKNavigationType", null);
getChannel().invokeMethod("shouldOverrideUrlLoading", obj, new MethodChannel.Result() {
channel.invokeMethod("shouldOverrideUrlLoading", obj, new MethodChannel.Result() {
@Override
public void success(Object response) {
if (response != null) {
......@@ -199,7 +200,7 @@ public class InAppWebViewClient extends WebViewClient {
if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("url", url);
getChannel().invokeMethod("onLoadStart", obj);
channel.invokeMethod("onLoadStart", obj);
}
......@@ -212,7 +213,7 @@ public class InAppWebViewClient extends WebViewClient {
previousAuthRequestFailureCount = 0;
credentialsProposed = null;
// CB-10395 InAppBrowser's WebView not storing cookies reliable to local device storage
// CB-10395 InAppBrowserManager's WebView not storing cookies reliable to local device storage
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
CookieManager.getInstance().flush();
} else {
......@@ -235,7 +236,7 @@ public class InAppWebViewClient extends WebViewClient {
if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("url", url);
getChannel().invokeMethod("onLoadStop", obj);
channel.invokeMethod("onLoadStop", obj);
}
@Override
......@@ -245,7 +246,7 @@ public class InAppWebViewClient extends WebViewClient {
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("url", url);
obj.put("androidIsReload", isReload);
getChannel().invokeMethod("onUpdateVisitedHistory", obj);
channel.invokeMethod("onUpdateVisitedHistory", obj);
super.doUpdateVisitedHistory(view, url, isReload);
}
......@@ -264,7 +265,7 @@ public class InAppWebViewClient extends WebViewClient {
obj.put("url", failingUrl);
obj.put("code", errorCode);
obj.put("message", description);
getChannel().invokeMethod("onLoadError", obj);
channel.invokeMethod("onLoadError", obj);
}
@RequiresApi(api = Build.VERSION_CODES.M)
......@@ -278,7 +279,7 @@ public class InAppWebViewClient extends WebViewClient {
obj.put("url", request.getUrl().toString());
obj.put("statusCode", errorResponse.getStatusCode());
obj.put("description", errorResponse.getReasonPhrase());
getChannel().invokeMethod("onLoadHttpError", obj);
channel.invokeMethod("onLoadHttpError", obj);
}
}
......@@ -316,7 +317,7 @@ public class InAppWebViewClient extends WebViewClient {
obj.put("port", port);
obj.put("previousFailureCount", previousAuthRequestFailureCount);
getChannel().invokeMethod("onReceivedHttpAuthRequest", obj, new MethodChannel.Result() {
channel.invokeMethod("onReceivedHttpAuthRequest", obj, new MethodChannel.Result() {
@Override
public void success(Object response) {
if (response != null) {
......@@ -461,7 +462,7 @@ public class InAppWebViewClient extends WebViewClient {
Log.d(LOG_TAG, obj.toString());
getChannel().invokeMethod("onReceivedServerTrustAuthRequest", obj, new MethodChannel.Result() {
channel.invokeMethod("onReceivedServerTrustAuthRequest", obj, new MethodChannel.Result() {
@Override
public void success(Object response) {
if (response != null) {
......@@ -520,7 +521,7 @@ public class InAppWebViewClient extends WebViewClient {
obj.put("realm", realm);
obj.put("port", request.getPort());
getChannel().invokeMethod("onReceivedClientCertRequest", obj, new MethodChannel.Result() {
channel.invokeMethod("onReceivedClientCertRequest", obj, new MethodChannel.Result() {
@Override
public void success(Object response) {
if (response != null) {
......@@ -579,7 +580,7 @@ public class InAppWebViewClient extends WebViewClient {
obj.put("url", request.getUrl().toString());
obj.put("threatType", threatType);
getChannel().invokeMethod("onSafeBrowsingHit", obj, new MethodChannel.Result() {
channel.invokeMethod("onSafeBrowsingHit", obj, new MethodChannel.Result() {
@Override
public void success(Object response) {
if (response != null) {
......@@ -652,7 +653,7 @@ public class InAppWebViewClient extends WebViewClient {
Util.WaitFlutterResult flutterResult;
try {
flutterResult = Util.invokeMethodAndWait(getChannel(), "onLoadResourceCustomScheme", obj);
flutterResult = Util.invokeMethodAndWait(channel, "onLoadResourceCustomScheme", obj);
} catch (InterruptedException e) {
e.printStackTrace();
Log.e(LOG_TAG, e.getMessage());
......@@ -701,9 +702,4 @@ public class InAppWebViewClient extends WebViewClient {
public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
}
private MethodChannel getChannel() {
return (inAppBrowserActivity != null) ? InAppWebViewFlutterPlugin.inAppBrowser.channel : flutterWebView.channel;
}
}
......@@ -4,7 +4,6 @@ import android.app.Activity;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
import android.webkit.ValueCallback;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
......@@ -19,7 +18,8 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
protected static final String LOG_TAG = "InAppWebViewFlutterPL";
public static InAppBrowser inAppBrowser;
public static InAppBrowserManager inAppBrowserManager;
public static ChromeSafariBrowserManager chromeSafariBrowserManager;
public static InAppWebViewStatic inAppWebViewStatic;
public static MyCookieManager myCookieManager;
public static CredentialDatabaseHandler credentialDatabaseHandler;
......@@ -46,8 +46,10 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
private void onAttachedToEngine(Context applicationContext, BinaryMessenger messenger, Activity activity, PlatformViewRegistry platformViewRegistry, FlutterView flutterView) {
Shared.applicationContext = applicationContext;
Shared.activity = activity;
Shared.messenger = messenger;
inAppBrowser = new InAppBrowser(messenger);
inAppBrowserManager = new InAppBrowserManager(messenger);
chromeSafariBrowserManager = new ChromeSafariBrowserManager(messenger);
platformViewRegistry.registerViewFactory(
"com.pichillilorenzo/flutter_inappwebview", new FlutterWebViewFactory(messenger, flutterView));
......@@ -61,9 +63,13 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
@Override
public void onDetachedFromEngine(FlutterPluginBinding binding) {
if (inAppBrowser != null) {
inAppBrowser.dispose();
inAppBrowser = null;
if (inAppBrowserManager != null) {
inAppBrowserManager.dispose();
inAppBrowserManager = null;
}
if (chromeSafariBrowserManager != null) {
chromeSafariBrowserManager.dispose();
chromeSafariBrowserManager = null;
}
if (myCookieManager != null) {
myCookieManager.dispose();
......
......@@ -9,13 +9,7 @@ import android.webkit.ValueCallback;
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.InAppWebView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.flutter.plugin.common.MethodChannel;
......@@ -25,6 +19,7 @@ public class JavaScriptBridgeInterface {
public static final String name = "flutter_inappwebview";
private FlutterWebView flutterWebView;
private InAppBrowserActivity inAppBrowserActivity;
public MethodChannel channel;
// https://github.com/taylorhakes/promise-polyfill/blob/master/src/index.js
public static final String promisePolyfillJS = "if (window.Promise == null) {" +
......@@ -254,6 +249,7 @@ public class JavaScriptBridgeInterface {
this.inAppBrowserActivity = (InAppBrowserActivity) obj;
else if (obj instanceof FlutterWebView)
this.flutterWebView = (FlutterWebView) obj;
this.channel = (this.inAppBrowserActivity != null) ? this.inAppBrowserActivity.channel : this.flutterWebView.channel;
}
@JavascriptInterface
......@@ -277,7 +273,7 @@ public class JavaScriptBridgeInterface {
webView.printCurrentPage();
}
getChannel().invokeMethod("onCallJsHandler", obj, new MethodChannel.Result() {
channel.invokeMethod("onCallJsHandler", obj, new MethodChannel.Result() {
@Override
public void success(Object json) {
if (webView == null) {
......@@ -305,8 +301,4 @@ public class JavaScriptBridgeInterface {
}
});
}
private MethodChannel getChannel() {
return (inAppBrowserActivity != null) ? InAppWebViewFlutterPlugin.inAppBrowser.channel : flutterWebView.channel;
}
}
......@@ -5,11 +5,13 @@ import android.content.Context;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.PluginRegistry;
public class Shared {
public static Context applicationContext;
public static PluginRegistry.Registrar registrar;
public static BinaryMessenger messenger;
public static FlutterPlugin.FlutterAssets flutterAssets;
public static ActivityPluginBinding activityPluginBinding;
public static Activity activity;
......
......@@ -196,10 +196,9 @@
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
Base,
);
......
......@@ -38,9 +38,8 @@ class MyInAppBrowser extends InAppBrowser {
@override
Future<ShouldOverrideUrlLoadingAction> shouldOverrideUrlLoading(ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest) async {
print("\n\n override ${shouldOverrideUrlLoadingRequest.url}\n\n");
this.webViewController.loadUrl(url: shouldOverrideUrlLoadingRequest.url);
return ShouldOverrideUrlLoadingAction.CANCEL;
print("\n\nOverride ${shouldOverrideUrlLoadingRequest.url}\n\n");
return ShouldOverrideUrlLoadingAction.ALLOW;
}
@override
......@@ -87,14 +86,15 @@ class _InAppBrowserExampleScreenState extends State<InAppBrowserExampleScreen> {
drawer: myDrawer(context: context),
body: Center(
child: RaisedButton(
onPressed: () {
widget.browser.openFile(
onPressed: () async {
await widget.browser.openFile(
assetFilePath: "assets/index.html",
options: InAppBrowserClassOptions(
inAppWebViewWidgetOptions: InAppWebViewWidgetOptions(
crossPlatform: InAppWebViewOptions(
useShouldOverrideUrlLoading: true,
useOnLoadResource: true,
debuggingEnabled: true,
useShouldOverrideUrlLoading: true,
useOnLoadResource: true,
))));
},
child: Text("Open Webview Browser")),
......
......@@ -59,6 +59,7 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
print("onWebViewCreated");
},
onLoadStart: (InAppWebViewController controller, String url) {
print("onLoadStart $url");
......@@ -71,6 +72,29 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
setState(() {
this.url = url;
});
/*var origins = await WebStorageManager.instance().android.getOrigins();
for (var origin in origins) {
print(origin);
print(await WebStorageManager.instance().android.getQuotaForOrigin(origin: origin.origin));
print(await WebStorageManager.instance().android.getUsageForOrigin(origin: origin.origin));
}
await WebStorageManager.instance().android.deleteAllData();
print("\n\nDELETED\n\n");
origins = await WebStorageManager.instance().android.getOrigins();
for (var origin in origins) {
print(origin);
await WebStorageManager.instance().android.deleteOrigin(origin: origin.origin);
}*/
/*var records = await WebStorageManager.instance().ios.fetchDataRecords(dataTypes: IOSWKWebsiteDataType.ALL);
for(var record in records) {
print(record);
}
await WebStorageManager.instance().ios.removeDataModifiedSince(dataTypes: IOSWKWebsiteDataType.ALL, date: DateTime(0));
print("\n\nDELETED\n\n");
records = await WebStorageManager.instance().ios.fetchDataRecords(dataTypes: IOSWKWebsiteDataType.ALL);
for(var record in records) {
print(record);
}*/
},
onProgressChanged: (InAppWebViewController controller, int progress) {
setState(() {
......
//
// ChromeSafariBrowserManager.swift
// flutter_inappwebview
//
// Created by Lorenzo Pichilli on 18/12/2019.
//
import Flutter
import UIKit
import WebKit
import Foundation
import AVFoundation
import SafariServices
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) {
}
init(registrar: FlutterPluginRegistrar) {
super.init()
ChromeSafariBrowserManager.registrar = registrar
ChromeSafariBrowserManager.channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_chromesafaribrowser", binaryMessenger: registrar.messenger())
registrar.addMethodCallDelegate(self, channel: ChromeSafariBrowserManager.channel!)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as? NSDictionary
let uuid: String = arguments!["uuid"] as! String
switch call.method {
case "open":
let url = arguments!["url"] as! String
let options = arguments!["options"] as! [String: Any?]
let uuidFallback: String = arguments!["uuidFallback"] as! String
let headersFallback = arguments!["headersFallback"] as! [String: String]
let optionsFallback = arguments!["optionsFallback"] as! [String: Any?]
open(uuid: uuid, url: url, options: options, uuidFallback: uuidFallback, headersFallback: headersFallback, optionsFallback: optionsFallback, result: result)
break
default:
result(FlutterMethodNotImplemented)
break
}
}
public func open(uuid: String, url: String, options: [String: Any?], uuidFallback: String?, headersFallback: [String: String], optionsFallback: [String: Any?], 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
safari = SafariViewController(url: absoluteUrl, configuration: config)
} else {
// Fallback on earlier versions
safari = SafariViewController(url: absoluteUrl)
}
safari.uuid = uuid
safari.prepareMethodChannel()
safari.delegate = safari
safari.tmpWindow = tmpWindow
safari.safariOptions = safariOptions
tmpController.present(safari, animated: true) {
result(true)
}
return
}
else {
if uuidFallback == nil {
print("No WebView fallback declared.")
result(true)
return
}
SwiftFlutterPlugin.instance!.inAppBrowserManager!.openUrl(uuid: uuidFallback!, url: url, options: optionsFallback, headers: headersFallback)
}
}
}
......@@ -19,14 +19,14 @@ class CustomeSchemeHandler : NSObject, WKURLSchemeHandler {
if let url = urlSchemeTask.request.url, let scheme = url.scheme {
inAppWebView.onLoadResourceCustomScheme(scheme: scheme, url: url.absoluteString, result: {(result) -> Void in
if result is FlutterError {
print((result as! FlutterError).message)
print((result as! FlutterError).message ?? "")
}
else if (result as? NSObject) == FlutterMethodNotImplemented {}
else {
let json: [String: Any]
if let r = result {
json = r as! [String: Any]
let urlResponse = URLResponse(url: url, mimeType: json["content-type"] as! String, expectedContentLength: -1, textEncodingName: json["content-encoding"] as! String)
let urlResponse = URLResponse(url: url, mimeType: (json["content-type"] as! String), expectedContentLength: -1, textEncodingName: (json["content-encoding"] as! String))
let data = json["data"] as! FlutterStandardTypedData
if (self.schemeHandlers[urlSchemeTask.hash] != nil) {
urlSchemeTask.didReceive(urlResponse)
......
......@@ -25,20 +25,20 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor
myView = UIView(frame: frame)
let channelName = "com.pichillilorenzo/flutter_inappwebview_" + String(viewId)
self.channel = FlutterMethodChannel(name: channelName, binaryMessenger: registrar.messenger())
self.channel?.setMethodCallHandler(LeakAvoider(delegate: self).handle)
channel = FlutterMethodChannel(name: channelName, binaryMessenger: registrar.messenger())
channel!.setMethodCallHandler(LeakAvoider(delegate: self).handle)
let initialUrl = (args["initialUrl"] as? String)!
let initialUrl = args["initialUrl"] as? String
let initialFile = args["initialFile"] as? String
let initialData = args["initialData"] as? [String: String]
let initialHeaders = (args["initialHeaders"] as? [String: String])!
let initialOptions = (args["initialOptions"] as? [String: Any])!
let initialHeaders = args["initialHeaders"] as? [String: String]
let initialOptions = args["initialOptions"] as! [String: Any?]
let options = InAppWebViewOptions()
options.parse(options: initialOptions)
let _ = options.parse(options: initialOptions)
let preWebviewConfiguration = InAppWebView.preWKWebViewConfiguration(options: options)
webView = InAppWebView(frame: myView!.bounds, configuration: preWebviewConfiguration, IABController: nil, channel: self.channel)
webView = InAppWebView(frame: myView!.bounds, configuration: preWebviewConfiguration, IABController: nil, channel: channel!)
webView!.autoresizingMask = [.flexibleWidth, .flexibleHeight]
myView!.addSubview(webView!)
......@@ -76,7 +76,7 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor
deinit {
print("FlutterWebViewController - dealloc")
self.channel?.setMethodCallHandler(nil)
channel?.setMethodCallHandler(nil)
webView!.dispose()
webView = nil
myView = nil
......@@ -86,7 +86,7 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor
return myView!
}
public func load(initialUrl: String, initialFile: String?, initialData: [String: String]?, initialHeaders: [String: String]) {
public func load(initialUrl: String?, initialFile: String?, initialData: [String: String]?, initialHeaders: [String: String]?) {
if initialFile != nil {
do {
try webView!.loadFile(url: initialFile!, headers: initialHeaders)
......@@ -98,14 +98,14 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor
}
if initialData != nil {
let data = (initialData!["data"] as? String)!
let mimeType = (initialData!["mimeType"] as? String)!
let encoding = (initialData!["encoding"] as? String)!
let baseUrl = (initialData!["baseUrl"] as? String)!
let data = initialData!["data"]!
let mimeType = initialData!["mimeType"]!
let encoding = initialData!["encoding"]!
let baseUrl = initialData!["baseUrl"]!
webView!.loadData(data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl)
}
else {
webView!.loadUrl(url: URL(string: initialUrl)!, headers: initialHeaders)
webView!.loadUrl(url: URL(string: initialUrl!)!, headers: initialHeaders)
}
}
......@@ -263,7 +263,7 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor
if webView != nil {
let inAppWebViewOptions = InAppWebViewOptions()
let inAppWebViewOptionsMap = arguments!["options"] as! [String: Any]
inAppWebViewOptions.parse(options: inAppWebViewOptionsMap)
let _ = inAppWebViewOptions.parse(options: inAppWebViewOptionsMap)
webView!.setOptions(newOptions: inAppWebViewOptions, newOptionsMap: inAppWebViewOptionsMap)
}
result(true)
......@@ -277,8 +277,13 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor
case "findAllAsync":
if webView != nil {
let find = arguments!["find"] as! String
webView!.findAllAsync(find: find, completionHandler: nil)
webView!.findAllAsync(find: find, completionHandler: {(value, error) in
if error != nil {
result(FlutterError(code: "FlutterWebViewController", message: error?.localizedDescription, details: nil))
return
}
result(true)
})
} else {
result(false)
}
......@@ -347,13 +352,12 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor
case "printCurrentPage":
if webView != nil {
webView!.printCurrentPage(printCompletionHandler: {(completed, error) in
if !completed, let e = error {
if !completed, let _ = error {
result(false)
return
}
result(true)
})
} else {
result(false)
}
......
//
// InAppBrowserManager.swift
// flutter_inappwebview
//
// Created by Lorenzo Pichilli on 18/12/2019.
//
import Flutter
import UIKit
import WebKit
import Foundation
import AVFoundation
let WEBVIEW_STORYBOARD = "WebView"
let WEBVIEW_STORYBOARD_CONTROLLER_ID = "viewController"
public class InAppBrowserManager: NSObject, FlutterPlugin {
static var registrar: FlutterPluginRegistrar?
static var channel: FlutterMethodChannel?
var tmpWindow: UIWindow?
private var previousStatusBarStyle = -1
public static func register(with registrar: FlutterPluginRegistrar) {
}
init(registrar: FlutterPluginRegistrar) {
super.init()
InAppBrowserManager.registrar = registrar
InAppBrowserManager.channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_inappbrowser", binaryMessenger: registrar.messenger())
registrar.addMethodCallDelegate(self, channel: InAppBrowserManager.channel!)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as? NSDictionary
let uuid: String = arguments!["uuid"] as! String
switch call.method {
case "openUrl":
let url = arguments!["url"] as! String
let options = arguments!["options"] as! [String: Any?]
let headers = arguments!["headers"] as! [String: String]
openUrl(uuid: uuid, url: url, options: options, headers: headers)
result(true)
break
case "openFile":
var url = arguments!["url"] as! String
let key = InAppBrowserManager.registrar!.lookupKey(forAsset: url)
let assetURL = Bundle.main.url(forResource: key, withExtension: nil)
if assetURL == nil {
result(FlutterError(code: "InAppBrowserFlutterPlugin", message: url + " asset file cannot be found!", details: nil))
return
} else {
url = assetURL!.absoluteString
}
let options = arguments!["options"] as! [String: Any?]
let headers = arguments!["headers"] as! [String: String]
openUrl(uuid: uuid, url: url, options: options, headers: headers)
result(true)
break
case "openData":
let options = arguments!["options"] as! [String: Any?]
let data = arguments!["data"] as! String
let mimeType = arguments!["mimeType"] as! String
let encoding = arguments!["encoding"] as! String
let baseUrl = arguments!["baseUrl"] as! String
openData(uuid: uuid, options: options, data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl)
result(true)
break
case "openWithSystemBrowser":
let url = arguments!["url"] as! String
openWithSystemBrowser(url: url, result: result)
break
default:
result(FlutterMethodNotImplemented)
break
}
}
public func prepareInAppBrowserWebViewController(options: [String: Any?]) -> InAppBrowserWebViewController {
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()
let browserOptions = InAppBrowserOptions()
let _ = browserOptions.parse(options: options)
let webViewOptions = InAppWebViewOptions()
let _ = webViewOptions.parse(options: options)
let storyboard = UIStoryboard(name: WEBVIEW_STORYBOARD, bundle: Bundle(for: InAppWebViewFlutterPlugin.self))
let webViewController = storyboard.instantiateViewController(withIdentifier: WEBVIEW_STORYBOARD_CONTROLLER_ID) as! InAppBrowserWebViewController
webViewController.browserOptions = browserOptions
webViewController.webViewOptions = webViewOptions
webViewController.isHidden = browserOptions.hidden
webViewController.previousStatusBarStyle = previousStatusBarStyle
return webViewController
}
public func openUrl(uuid: String, url: String, options: [String: Any?], headers: [String: String]) {
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
if webViewController.isHidden {
webViewController.view.isHidden = true
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)
UIApplication.shared.delegate?.window??.makeKeyAndVisible()
})
}
else {
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) {
let webViewController = prepareInAppBrowserWebViewController(options: options)
webViewController.uuid = uuid
webViewController.tmpWindow = tmpWindow
webViewController.initData = data
webViewController.initMimeType = mimeType
webViewController.initEncoding = encoding
webViewController.initBaseUrl = baseUrl
if webViewController.isHidden {
webViewController.view.isHidden = true
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)
UIApplication.shared.delegate?.window??.makeKeyAndVisible()
})
}
else {
tmpWindow!.rootViewController!.present(webViewController, animated: true, completion: {() -> Void in
webViewController.webView.loadData(data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl)
})
}
}
public func openWithSystemBrowser(url: String, result: @escaping FlutterResult) {
let absoluteUrl = URL(string: url)!.absoluteURL
if !UIApplication.shared.canOpenURL(absoluteUrl) {
result(FlutterError(code: "InAppBrowserManager", message: url + " cannot be opened!", details: nil))
return
}
else {
if #available(iOS 10.0, *) {
UIApplication.shared.open(absoluteUrl, options: convertToUIApplicationOpenExternalURLOptionsKeyDictionary([:]), completionHandler: nil)
} else {
UIApplication.shared.openURL(absoluteUrl)
}
}
result(true)
}
}
// Helper function inserted by Swift 4.2 migrator.
fileprivate func convertToUIApplicationOpenExternalURLOptionsKeyDictionary(_ input: [String: Any]) -> [UIApplication.OpenExternalURLOptionsKey: Any] {
return Dictionary(uniqueKeysWithValues: input.map { key, value in (UIApplication.OpenExternalURLOptionsKey(rawValue: key), value)})
}
This diff is collapsed.
......@@ -14,7 +14,7 @@ public class Options: NSObject {
super.init()
}
func parse(options: [String: Any]) -> Options {
func parse(options: [String: Any?]) -> Options {
for (key, value) in options {
if self.responds(to: Selector(key)) {
self.setValue(value, forKey: key)
......@@ -23,8 +23,8 @@ public class Options: NSObject {
return self
}
func getHashMap() -> [String: Any] {
var options: [String: Any] = [:]
func getHashMap() -> [String: Any?] {
var options: [String: Any?] = [:]
var counts = UInt32();
let properties = class_copyPropertyList(object_getClass(self), &counts);
for i in 0..<counts {
......
......@@ -9,16 +9,34 @@ import Foundation
import SafariServices
@available(iOS 9.0, *)
class SafariViewController: SFSafariViewController, SFSafariViewControllerDelegate {
public class SafariViewController: SFSafariViewController, FlutterPlugin, SFSafariViewControllerDelegate {
weak var statusDelegate: SwiftFlutterPlugin?
var channel: FlutterMethodChannel?
var tmpWindow: UIWindow?
var safariOptions: SafariBrowserOptions?
var uuid: String = ""
override func viewWillAppear(_ animated: Bool) {
public static func register(with registrar: FlutterPluginRegistrar) {
}
deinit {
print("SafariViewController - dealloc")
}
public func prepareMethodChannel() {
channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_chromesafaribrowser_" + uuid, binaryMessenger: SwiftFlutterPlugin.instance!.registrar!.messenger())
SwiftFlutterPlugin.instance!.registrar!.addMethodCallDelegate(self, channel: channel!)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
}
public override func viewWillAppear(_ animated: Bool) {
prepareSafariBrowser()
super.viewWillAppear(animated)
onChromeSafariBrowserOpened()
}
func prepareSafariBrowser() {
......@@ -45,50 +63,64 @@ class SafariViewController: SFSafariViewController, SFSafariViewControllerDelega
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(400), execute: {() -> Void in
self.tmpWindow?.windowLevel = UIWindow.Level(rawValue: 0.0)
UIApplication.shared.delegate?.window??.makeKeyAndVisible()
if (self.statusDelegate != nil) {
self.statusDelegate?.safariExit(uuid: self.uuid)
}
self.onChromeSafariBrowserClosed()
self.dispose()
})
}
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
public func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
close()
}
func safariViewController(_ controller: SFSafariViewController,
public func safariViewController(_ controller: SFSafariViewController,
didCompleteInitialLoad didLoadSuccessfully: Bool) {
if didLoadSuccessfully {
statusDelegate?.onChromeSafariBrowserCompletedInitialLoad(uuid: self.uuid)
onChromeSafariBrowserCompletedInitialLoad()
}
else {
print("Cant load successfully the 'SafariViewController'.")
}
}
func safariViewController(_ controller: SFSafariViewController, activityItemsFor URL: URL, title: String?) -> [UIActivity] {
public func safariViewController(_ controller: SFSafariViewController, activityItemsFor URL: URL, title: String?) -> [UIActivity] {
// print("activityItemsFor")
// print(URL)
// print(title)
return []
}
func safariViewController(_ controller: SFSafariViewController, excludedActivityTypesFor URL: URL, title: String?) -> [UIActivity.ActivityType] {
public func safariViewController(_ controller: SFSafariViewController, excludedActivityTypesFor URL: URL, title: String?) -> [UIActivity.ActivityType] {
// print("excludedActivityTypesFor")
// print(URL)
// print(title)
return []
}
func safariViewController(_ controller: SFSafariViewController, initialLoadDidRedirectTo URL: URL) {
public func safariViewController(_ controller: SFSafariViewController, initialLoadDidRedirectTo URL: URL) {
// print("initialLoadDidRedirectTo")
// print(URL)
}
public func onChromeSafariBrowserOpened() {
channel!.invokeMethod("onChromeSafariBrowserOpened", arguments: [])
}
public func onChromeSafariBrowserCompletedInitialLoad() {
channel!.invokeMethod("onChromeSafariBrowserCompletedInitialLoad", arguments: [])
}
public func onChromeSafariBrowserClosed() {
channel!.invokeMethod("onChromeSafariBrowserClosed", arguments: [])
}
public func dispose() {
delegate = nil
channel!.setMethodCallHandler(nil)
}
// Helper function to convert hex color string to UIColor
// Assumes input like "#00FF00" (#RRGGBB).
// Taken from https://stackoverflow.com/questions/1560081/how-can-i-create-a-uicolor-from-a-hex-string
func color(fromHexString: String, alpha:CGFloat? = 1.0) -> UIColor {
// Convert hex string to an integer
......
This diff is collapsed.
......@@ -24,7 +24,6 @@ library flutter_inappwebview;
export 'src/types.dart';
export 'src/in_app_webview.dart';
export 'src/in_app_browser.dart';
export 'src/channel_manager.dart';
export 'src/cookie_manager.dart';
export 'src/chrome_safari_browser.dart';
export 'src/chrome_safari_browser.dart';
......
import 'dart:async';
import 'dart:collection';
import 'package:flutter/services.dart';
import 'types.dart' show ListenerCallback;
class ChannelManager {
static const MethodChannel channel =
const MethodChannel('com.pichillilorenzo/flutter_inappbrowser');
static bool initialized = false;
static final listeners = HashMap<String, ListenerCallback>();
static Future<dynamic> _handleMethod(MethodCall call) async {
String uuid = call.arguments["uuid"];
return await listeners[uuid](call);
}
static void addListener(String key, ListenerCallback callback) {
if (!initialized) init();
listeners.putIfAbsent(key, () => callback);
}
static void init() {
channel.setMethodCallHandler(_handleMethod);
initialized = true;
}
}
......@@ -5,7 +5,6 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'types.dart';
import 'channel_manager.dart';
import 'in_app_browser.dart';
///ChromeSafariBrowser class.
......@@ -18,12 +17,16 @@ class ChromeSafariBrowser {
String uuid;
InAppBrowser browserFallback;
bool _isOpened = false;
MethodChannel _channel;
static const MethodChannel _sharedChannel = const MethodChannel('com.pichillilorenzo/flutter_chromesafaribrowser');
///Initialize the [ChromeSafariBrowser] instance with an [InAppBrowser] fallback instance or `null`.
ChromeSafariBrowser({bFallback}) {
uuid = uuidGenerator.v4();
browserFallback = bFallback;
ChannelManager.addListener(uuid, handleMethod);
this._channel =
MethodChannel('com.pichillilorenzo/flutter_chromesafaribrowser_$uuid');
this._channel.setMethodCallHandler(handleMethod);
_isOpened = false;
}
......@@ -94,15 +97,13 @@ class ChromeSafariBrowser {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('uuidFallback',
() => (browserFallback != null) ? browserFallback.uuid : '');
args.putIfAbsent('url', () => url);
args.putIfAbsent('headers', () => headersFallback);
args.putIfAbsent('options', () => optionsMap);
args.putIfAbsent('uuidFallback',
() => (browserFallback != null) ? browserFallback.uuid : '');
args.putIfAbsent('headersFallback', () => headersFallback);
args.putIfAbsent('optionsFallback', () => optionsFallbackMap);
args.putIfAbsent('isData', () => false);
args.putIfAbsent('useChromeSafariBrowser', () => true);
await ChannelManager.channel.invokeMethod('open', args);
await _sharedChannel.invokeMethod('open', args);
this._isOpened = true;
}
......
......@@ -7,7 +7,6 @@ import 'package:flutter/services.dart';
import 'webview_options.dart';
import 'types.dart';
import 'channel_manager.dart';
import 'in_app_webview.dart' show InAppWebViewController;
///InAppBrowser class. [webViewController] can be used to access the [InAppWebView] API.
......@@ -18,6 +17,8 @@ class InAppBrowser {
Map<String, JavaScriptHandlerCallback> javaScriptHandlersMap =
HashMap<String, JavaScriptHandlerCallback>();
bool _isOpened = false;
MethodChannel _channel;
static const MethodChannel _sharedChannel = const MethodChannel('com.pichillilorenzo/flutter_inappbrowser');
/// WebView Controller that can be used to access the [InAppWebView] API.
InAppWebViewController webViewController;
......@@ -25,10 +26,12 @@ class InAppBrowser {
///
InAppBrowser() {
uuid = uuidGenerator.v4();
ChannelManager.addListener(uuid, handleMethod);
this._channel =
MethodChannel('com.pichillilorenzo/flutter_inappbrowser_$uuid');
this._channel.setMethodCallHandler(handleMethod);
_isOpened = false;
webViewController = new InAppWebViewController.fromInAppBrowser(
uuid, ChannelManager.channel, this);
uuid, this._channel, this);
}
Future<dynamic> handleMethod(MethodCall call) async {
......@@ -53,8 +56,8 @@ class InAppBrowser {
///[headers]: The additional headers to be used in the HTTP request for this URL, specified as a map from name to value.
///
///[options]: Options for the [InAppBrowser].
Future<void> open(
{String url = "about:blank",
Future<void> openUrl(
{@required String url,
Map<String, String> headers = const {},
InAppBrowserClassOptions options}) async {
assert(url != null && url.isNotEmpty);
......@@ -83,14 +86,10 @@ class InAppBrowser {
args.putIfAbsent('url', () => url);
args.putIfAbsent('headers', () => headers);
args.putIfAbsent('options', () => optionsMap);
args.putIfAbsent('openWithSystemBrowser', () => false);
args.putIfAbsent('isLocalFile', () => false);
args.putIfAbsent('isData', () => false);
args.putIfAbsent('useChromeSafariBrowser', () => false);
await ChannelManager.channel.invokeMethod('open', args);
await _sharedChannel.invokeMethod('openUrl', args);
}
///Opens the given [assetFilePath] file in a new [InAppBrowser] instance. The other arguments are the same of [InAppBrowser.open].
///Opens the given [assetFilePath] file in a new [InAppBrowser] instance. The other arguments are the same of [InAppBrowser.openUrl].
///
///To be able to load your local files (assets, js, css, etc.), you need to add them in the `assets` section of the `pubspec.yaml` file, otherwise they cannot be found!
///
......@@ -153,11 +152,7 @@ class InAppBrowser {
args.putIfAbsent('url', () => assetFilePath);
args.putIfAbsent('headers', () => headers);
args.putIfAbsent('options', () => optionsMap);
args.putIfAbsent('openWithSystemBrowser', () => false);
args.putIfAbsent('isLocalFile', () => true);
args.putIfAbsent('isData', () => false);
args.putIfAbsent('useChromeSafariBrowser', () => false);
await ChannelManager.channel.invokeMethod('open', args);
await _sharedChannel.invokeMethod('openFile', args);
}
///Opens a new [InAppBrowser] instance with [data] as a content, using [baseUrl] as the base URL for it.
......@@ -203,26 +198,16 @@ class InAppBrowser {
args.putIfAbsent('mimeType', () => mimeType);
args.putIfAbsent('encoding', () => encoding);
args.putIfAbsent('baseUrl', () => baseUrl);
args.putIfAbsent('openWithSystemBrowser', () => false);
args.putIfAbsent('isLocalFile', () => false);
args.putIfAbsent('isData', () => true);
args.putIfAbsent('useChromeSafariBrowser', () => false);
await ChannelManager.channel.invokeMethod('open', args);
args.putIfAbsent('historyUrl', () => androidHistoryUrl);
await _sharedChannel.invokeMethod('openData', args);
}
///This is a static method that opens an [url] in the system browser. You wont be able to use the [InAppBrowser] methods here!
static Future<void> openWithSystemBrowser({@required String url}) async {
assert(url != null && url.isNotEmpty);
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => "");
args.putIfAbsent('url', () => url);
args.putIfAbsent('headers', () => {});
args.putIfAbsent('isLocalFile', () => false);
args.putIfAbsent('isData', () => false);
args.putIfAbsent('openWithSystemBrowser', () => true);
args.putIfAbsent('useChromeSafariBrowser', () => false);
args.putIfAbsent('options', () => {});
return await ChannelManager.channel.invokeMethod('open', args);
return await _sharedChannel.invokeMethod('openWithSystemBrowser', args);
}
///Displays an [InAppBrowser] window that was opened hidden. Calling this has no effect if the [InAppBrowser] was already visible.
......@@ -230,31 +215,28 @@ class InAppBrowser {
this.throwIsNotOpened();
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
await ChannelManager.channel.invokeMethod('show', args);
await _channel.invokeMethod('show', args);
}
///Hides the [InAppBrowser] window. Calling this has no effect if the [InAppBrowser] was already hidden.
Future<void> hide() async {
this.throwIsNotOpened();
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
await ChannelManager.channel.invokeMethod('hide', args);
await _channel.invokeMethod('hide', args);
}
///Closes the [InAppBrowser] window.
Future<void> close() async {
this.throwIsNotOpened();
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
await ChannelManager.channel.invokeMethod('close', args);
await _channel.invokeMethod('close', args);
}
///Check if the Web View of the [InAppBrowser] instance is hidden.
Future<bool> isHidden() async {
this.throwIsNotOpened();
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
return await ChannelManager.channel.invokeMethod('isHidden', args);
return await _channel.invokeMethod('isHidden', args);
}
///Sets the [InAppBrowser] options with the new [options] and evaluates them.
......@@ -280,23 +262,19 @@ class InAppBrowser {
}
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('options', () => optionsMap);
args.putIfAbsent('optionsType', () => "InAppBrowserOptions");
await ChannelManager.channel.invokeMethod('setOptions', args);
await _channel.invokeMethod('setOptions', args);
}
///Gets the current [InAppBrowser] options as a `Map`. Returns `null` if the options are not setted yet.
Future<InAppBrowserClassOptions> getOptions() async {
this.throwIsNotOpened();
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('optionsType', () => "InAppBrowserOptions");
InAppBrowserClassOptions inAppBrowserClassOptions =
InAppBrowserClassOptions();
Map<dynamic, dynamic> options =
await ChannelManager.channel.invokeMethod('getOptions', args);
await _channel.invokeMethod('getOptions', args);
if (options != null) {
options = options.cast<String, dynamic>();
inAppBrowserClassOptions.crossPlatform =
......
......@@ -9,8 +9,6 @@ import 'webview_options.dart';
var uuidGenerator = new Uuid();
typedef Future<dynamic> ListenerCallback(MethodCall call);
///This type represents a callback, added with [addJavaScriptHandler], that listens to post messages sent from JavaScript.
///
///The Android implementation uses [addJavascriptInterface](https://developer.android.com/reference/android/webkit/WebView#addJavascriptInterface(java.lang.Object,%20java.lang.String)).
......
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