diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index e955a1a4..f5bb0fce 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -10,20 +10,18 @@
-
-
-
+
-
+
-
-
+
+
@@ -40,11 +38,11 @@
-
+
-
-
+
+
@@ -52,11 +50,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -143,16 +154,16 @@
-
-
+
+
-
+
@@ -174,8 +185,9 @@
-
+
+
@@ -188,6 +200,12 @@
+
+
+
+
+
+
@@ -198,7 +216,6 @@
-
@@ -388,20 +405,21 @@
-
+
+
-
+
-
+
@@ -420,7 +438,6 @@
-
@@ -733,24 +750,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -758,54 +758,38 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -814,14 +798,25 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e6d4e571..954a188a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,10 @@
-## 0.1.0
+## 0.2.0
+
+- added support of Chrome CustomTabs for android
+- added support of SFSafariViewController for iOS
+- added the ability to create multiple instances of browsers
+
+## 0.1.1
- updated/added new methods
- updated UI of android/iOS in-app browser
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserFlutterPlugin.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserFlutterPlugin.java
index 1d43afbb..c8defd55 100644
--- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserFlutterPlugin.java
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserFlutterPlugin.java
@@ -61,8 +61,8 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
public static Registrar registrar;
public Activity activity;
public static MethodChannel channel;
- public static WebViewActivity webViewActivity;
- public static ChromeCustomTabsActivity chromeCustomTabsActivity;
+ public static Map webViewActivities = new HashMap<>();
+ public static Map chromeCustomTabsActivities = new HashMap<>();
private static final String NULL = "null";
protected static final String LOG_TAG = "InAppBrowserFlutterP";
@@ -85,6 +85,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
String source;
String jsWrapper;
String urlFile;
+ final String uuid = (String) call.argument("uuid");
switch (call.method) {
case "open":
@@ -110,13 +111,15 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
if (useChromeSafariBrowser) {
+ final String uuidFallback = (String) call.argument("uuidFallback");
+
final ChromeCustomTabsOptions options = new ChromeCustomTabsOptions();
options.parse((HashMap) call.argument("options"));
final InAppBrowserOptions optionsFallback = new InAppBrowserOptions();
optionsFallback.parse((HashMap) call.argument("optionsFallback"));
- open(url, options, headers,true, optionsFallback);
+ open(uuid, uuidFallback, url, options, headers,true, optionsFallback);
}
else {
@@ -141,89 +144,90 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
// load in InAppBrowserFlutterPlugin
else {
Log.d(LOG_TAG, "loading in InAppBrowserFlutterPlugin");
- open(url, options, headers, false, null);
+ open(uuid, null, url, options, headers, false, null);
}
}
// SYSTEM
else if ("_system".equals(target)) {
Log.d(LOG_TAG, "in system");
- openExternal(url, result);
+ openExternal(url);
}
// BLANK - or anything else
else {
Log.d(LOG_TAG, "in blank");
- open(url, options, headers, false, null);
+ open(uuid, null, url, options, headers, false, null);
}
}
+
result.success(true);
}
});
break;
case "loadUrl":
- loadUrl(call.argument("url").toString(), (Map) call.argument("headers"), result);
+ loadUrl(uuid, call.argument("url").toString(), (Map) call.argument("headers"), result);
break;
case "close":
- close();
+ close(uuid);
result.success(true);
break;
case "injectScriptCode":
source = call.argument("source").toString();
jsWrapper = "(function(){return JSON.stringify(eval(%s));})();";
- injectDeferredObject(source, jsWrapper, result);
+ injectDeferredObject(uuid, source, jsWrapper, result);
break;
case "injectScriptFile":
urlFile = call.argument("urlFile").toString();
jsWrapper = "(function(d) { var c = d.createElement('script'); c.src = %s; d.body.appendChild(c); })(document);";
- injectDeferredObject(urlFile, jsWrapper, null);
+ injectDeferredObject(uuid, urlFile, jsWrapper, null);
result.success(true);
break;
case "injectStyleCode":
source = call.argument("source").toString();
jsWrapper = "(function(d) { var c = d.createElement('style'); c.innerHTML = %s; d.body.appendChild(c); })(document);";
- injectDeferredObject(source, jsWrapper, null);
+ injectDeferredObject(uuid, source, jsWrapper, null);
result.success(true);
break;
case "injectStyleFile":
urlFile = call.argument("urlFile").toString();
jsWrapper = "(function(d) { var c = d.createElement('link'); c.rel='stylesheet'; c.type='text/css'; c.href = %s; d.head.appendChild(c); })(document);";
- injectDeferredObject(urlFile, jsWrapper, null);
+ injectDeferredObject(uuid, urlFile, jsWrapper, null);
result.success(true);
break;
case "show":
- show();
+ show(uuid);
result.success(true);
break;
case "hide":
- hide();
+ hide(uuid);
result.success(true);
break;
case "reload":
- reload();
+ reload(uuid);
result.success(true);
break;
case "goBack":
- goBack();
+ goBack(uuid);
result.success(true);
break;
case "canGoBack":
- result.success(canGoBack());
+ result.success(canGoBack(uuid));
break;
case "goForward":
- goForward();
+ goForward(uuid);
result.success(true);
break;
case "canGoForward":
- result.success(canGoForward());
+ result.success(canGoForward(uuid));
break;
case "stopLoading":
- stopLoading();
+ stopLoading(uuid);
result.success(true);
break;
case "isLoading":
- result.success(isLoading());
+ result.success(isLoading(uuid));
break;
case "isHidden":
- result.success(isHidden());
+ result.success(isHidden(uuid));
break;
default:
result.notImplemented();
@@ -240,13 +244,15 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
* If a wrapper string is supplied, then the source string will be JSON-encoded (adding
* quotes) and wrapped using string formatting. (The wrapper string should have a single
* '%s' marker)
- * @param source The source object (filename or script/style text) to inject into
+ * @param uuid
+ * @param source The source object (filename or script/style text) to inject into
* the document.
* @param jsWrapper A JavaScript string to wrap the source string in, so that the object
- * is properly injected, or null if the source string is JavaScript text
+ * is properly injected, or null if the source string is JavaScript text
* @param result
*/
- private void injectDeferredObject(String source, String jsWrapper, final Result result) {
+ private void injectDeferredObject(String uuid, String source, String jsWrapper, final Result result) {
+ final WebViewActivity webViewActivity = webViewActivities.get(uuid);
if (webViewActivity != null) {
String scriptToInject;
if (jsWrapper != null) {
@@ -323,7 +329,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
* @param url the url to load.
* @return "" if ok, or error message.
*/
- public void openExternal(String url, Result result) {
+ public void openExternal(String url) {
try {
Intent intent;
intent = new Intent(Intent.ACTION_VIEW);
@@ -381,24 +387,29 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
}
}
- public static void open(final String url, Options options, Map headers, boolean useChromeSafariBrowser, InAppBrowserOptions optionsFallback) {
+ public static void open(String uuid, String uuidFallback, final String url, Options options, Map headers, boolean useChromeSafariBrowser, InAppBrowserOptions optionsFallback) {
Intent intent = new Intent(registrar.activity(), (useChromeSafariBrowser) ? ChromeCustomTabsActivity.class : WebViewActivity.class);
Bundle extras = new Bundle();
+ extras.putString("uuid", uuid);
extras.putString("url", url);
extras.putSerializable("options", options.getHashMap());
extras.putSerializable("headers", (Serializable) headers);
- if (useChromeSafariBrowser && optionsFallback != null)
- extras.putSerializable("optionsFallback", optionsFallback.getHashMap());
- else
- extras.putSerializable("optionsFallback", (new InAppBrowserOptions()).getHashMap());
+ if (useChromeSafariBrowser) {
+ extras.putString("uuidFallback", uuidFallback);
+ if (optionsFallback != null)
+ extras.putSerializable("optionsFallback", optionsFallback.getHashMap());
+ else
+ extras.putSerializable("optionsFallback", (new InAppBrowserOptions()).getHashMap());
+ }
intent.putExtras(extras);
registrar.activity().startActivity(intent);
}
- public void loadUrl(String url, Map headers, Result result) {
+ public void loadUrl(String uuid, String url, Map headers, Result result) {
+ WebViewActivity webViewActivity = webViewActivities.get(uuid);
if (webViewActivity != null) {
if (headers != null)
webViewActivity.loadUrl(url, headers, result);
@@ -407,67 +418,79 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
}
}
- public void show() {
+ public void show(String uuid) {
+ WebViewActivity webViewActivity = webViewActivities.get(uuid);
if (webViewActivity != null)
webViewActivity.show();
}
- public void hide() {
+ public void hide(String uuid) {
+ WebViewActivity webViewActivity = webViewActivities.get(uuid);
if (webViewActivity != null)
webViewActivity.hide();
}
- public void reload() {
+ public void reload(String uuid) {
+ WebViewActivity webViewActivity = webViewActivities.get(uuid);
if (webViewActivity != null)
webViewActivity.reload();
}
- public boolean isLoading() {
+ public boolean isLoading(String uuid) {
+ WebViewActivity webViewActivity = webViewActivities.get(uuid);
if (webViewActivity != null)
return webViewActivity.isLoading();
return false;
}
- public boolean isHidden() {
+ public boolean isHidden(String uuid) {
+ WebViewActivity webViewActivity = webViewActivities.get(uuid);
if (webViewActivity != null)
return webViewActivity.isHidden;
return false;
}
- public void stopLoading() {
+ public void stopLoading(String uuid) {
+ WebViewActivity webViewActivity = webViewActivities.get(uuid);
if (webViewActivity != null)
webViewActivity.stopLoading();
}
- public void goBack() {
+ public void goBack(String uuid) {
+ WebViewActivity webViewActivity = webViewActivities.get(uuid);
if (webViewActivity != null)
webViewActivity.goBack();
}
- public boolean canGoBack() {
+ public boolean canGoBack(String uuid) {
+ WebViewActivity webViewActivity = webViewActivities.get(uuid);
if (webViewActivity != null)
return webViewActivity.canGoBack();
return false;
}
- public void goForward() {
+ public void goForward(String uuid) {
+ WebViewActivity webViewActivity = webViewActivities.get(uuid);
if (webViewActivity != null)
webViewActivity.goForward();
}
- public boolean canGoForward() {
+ public boolean canGoForward(String uuid) {
+ WebViewActivity webViewActivity = webViewActivities.get(uuid);
if (webViewActivity != null)
return webViewActivity.canGoForward();
return false;
}
- public static void close() {
+ public static void close(final String uuid) {
+ final WebViewActivity webViewActivity = webViewActivities.get(uuid);
registrar.activity().runOnUiThread(new Runnable() {
@Override
public void run() {
Map obj = new HashMap<>();
+ obj.put("uuid", uuid);
channel.invokeMethod("onExit", obj);
// The JS protects against multiple calls, so this should happen only when
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebViewClient.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebViewClient.java
index 0d336caa..b2e60e8d 100644
--- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebViewClient.java
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebViewClient.java
@@ -30,6 +30,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
if (activity.options.useShouldOverrideUrlLoading) {
Map obj = new HashMap<>();
+ obj.put("uuid", activity.uuid);
obj.put("url", url);
InAppBrowserFlutterPlugin.channel.invokeMethod("shouldOverrideUrlLoading", obj);
return true;
@@ -110,6 +111,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
}
Map obj = new HashMap<>();
+ obj.put("uuid", activity.uuid);
obj.put("url", url);
InAppBrowserFlutterPlugin.channel.invokeMethod("onLoadStart", obj);
}
@@ -133,6 +135,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
view.requestFocus();
Map obj = new HashMap<>();
+ obj.put("uuid", activity.uuid);
obj.put("url", url);
InAppBrowserFlutterPlugin.channel.invokeMethod("onLoadStop", obj);
}
@@ -143,6 +146,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
activity.isLoading = false;
Map obj = new HashMap<>();
+ obj.put("uuid", activity.uuid);
obj.put("url", failingUrl);
obj.put("code", errorCode);
obj.put("message", description);
@@ -153,6 +157,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
super.onReceivedSslError(view, handler, error);
Map obj = new HashMap<>();
+ obj.put("uuid", activity.uuid);
obj.put("url", error.getUrl());
obj.put("code", error.getPrimaryError());
String message;
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/WebViewActivity.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/WebViewActivity.java
index 31d884b3..47b92956 100644
--- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/WebViewActivity.java
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/WebViewActivity.java
@@ -7,7 +7,6 @@ import android.os.Build;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
-import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
@@ -27,6 +26,7 @@ import io.flutter.plugin.common.MethodChannel;
public class WebViewActivity extends AppCompatActivity {
+ String uuid;
WebView webView;
ActionBar actionBar;
InAppBrowserWebViewClient inAppBrowserWebViewClient;
@@ -47,6 +47,7 @@ public class WebViewActivity extends AppCompatActivity {
webView = findViewById(R.id.webView);
Bundle b = getIntent().getExtras();
+ uuid = b.getString("uuid");
String url = b.getString("url");
options = new InAppBrowserOptions();
@@ -54,7 +55,7 @@ public class WebViewActivity extends AppCompatActivity {
headers = (HashMap) b.getSerializable("headers");
- InAppBrowserFlutterPlugin.webViewActivity = this;
+ InAppBrowserFlutterPlugin.webViewActivities.put(uuid, this);
actionBar = getSupportActionBar();
@@ -243,7 +244,7 @@ public class WebViewActivity extends AppCompatActivity {
if (canGoBack())
goBack();
else if (options.closeOnCannotGoBack)
- InAppBrowserFlutterPlugin.close();
+ InAppBrowserFlutterPlugin.close(uuid);
return true;
}
return super.onKeyDown(keyCode, event);
@@ -340,7 +341,7 @@ public class WebViewActivity extends AppCompatActivity {
}
public void closeButtonClicked(MenuItem item) {
- InAppBrowserFlutterPlugin.close();
+ InAppBrowserFlutterPlugin.close(uuid);
}
}
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/chrome_custom_tabs/ChromeCustomTabsActivity.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/chrome_custom_tabs/ChromeCustomTabsActivity.java
index 1b1aebbb..aa15beeb 100644
--- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/chrome_custom_tabs/ChromeCustomTabsActivity.java
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/chrome_custom_tabs/ChromeCustomTabsActivity.java
@@ -6,6 +6,7 @@ import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.support.customtabs.CustomTabsIntent;
+import android.util.Log;
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserFlutterPlugin;
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserOptions;
@@ -16,6 +17,9 @@ import java.util.Map;
public class ChromeCustomTabsActivity extends Activity {
+ protected static final String LOG_TAG = "CustomTabsActivity";
+ String uuid;
+ String uuidFallback;
CustomTabsIntent.Builder builder;
ChromeCustomTabsOptions options;
Map headersFallback;
@@ -30,6 +34,8 @@ public class ChromeCustomTabsActivity extends Activity {
setContentView(R.layout.chrome_custom_tabs_layout);
Bundle b = getIntent().getExtras();
+ uuid = b.getString("uuid");
+ uuidFallback = b.getString("uuidFallback");
String url = b.getString("url");
options = new ChromeCustomTabsOptions();
@@ -40,8 +46,9 @@ public class ChromeCustomTabsActivity extends Activity {
optionsFallback = new InAppBrowserOptions();
optionsFallback.parse((HashMap) b.getSerializable("optionsFallback"));
- customTabActivityHelper = new CustomTabActivityHelper();
+ InAppBrowserFlutterPlugin.chromeCustomTabsActivities.put(uuid, this);
+ customTabActivityHelper = new CustomTabActivityHelper();
builder = new CustomTabsIntent.Builder();
prepareCustomTabs();
@@ -52,13 +59,20 @@ public class ChromeCustomTabsActivity extends Activity {
new CustomTabActivityHelper.CustomTabFallback() {
@Override
public void openUri(Activity activity, Uri uri) {
- InAppBrowserFlutterPlugin.open(uri.toString(), optionsFallback, headersFallback, false, null);
+ if (!uuidFallback.isEmpty())
+ InAppBrowserFlutterPlugin.open(uuidFallback, null, uri.toString(), optionsFallback, headersFallback, false, null);
+ else {
+ Log.d(LOG_TAG, "No WebView fallback declared.");
+ activity.finish();
+ }
}
});
if (chromeCustomTabsOpened) {
- InAppBrowserFlutterPlugin.channel.invokeMethod("onChromeSafariBrowserOpened", null);
- InAppBrowserFlutterPlugin.channel.invokeMethod("onChromeSafariBrowserLoaded", null);
+ Map obj = new HashMap<>();
+ obj.put("uuid", uuid);
+ InAppBrowserFlutterPlugin.channel.invokeMethod("onChromeSafariBrowserOpened", obj);
+ InAppBrowserFlutterPlugin.channel.invokeMethod("onChromeSafariBrowserLoaded", obj);
}
}
@@ -93,7 +107,9 @@ public class ChromeCustomTabsActivity extends Activity {
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CHROME_CUSTOM_TAB_REQUEST_CODE) {
finish();
- InAppBrowserFlutterPlugin.channel.invokeMethod("onChromeSafariBrowserClosed", null);
+ Map obj = new HashMap<>();
+ obj.put("uuid", uuid);
+ InAppBrowserFlutterPlugin.channel.invokeMethod("onChromeSafariBrowserClosed", obj);
}
}
}
diff --git a/example/lib/main.dart b/example/lib/main.dart
index 0f7efc6a..d312c75e 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -6,13 +6,17 @@ class MyInAppBrowser extends InAppBrowser {
@override
Future onLoadStart(String url) async {
- print("\n\nStarted $url\n\n");
+ print("\n\nStarted aaa $url\n\n");
+ inAppBrowserFallback2.open("https://www.google.com", options: {
+ "hidden": true
+ });
//print("\n\n ${await this.isHidden()} \n\n");
}
@override
Future onLoadStop(String url) async {
- print("\n\nStopped $url\n\n");
+ print("\n\nStopped aaa $url\n\n");
+ inAppBrowserFallback2.show();
// print(await this.injectScriptCode("document.body.innerHTML"));
// print(await this.injectScriptCode("3"));
// print(await this.injectScriptCode("""
@@ -61,7 +65,38 @@ class MyInAppBrowser extends InAppBrowser {
}
}
+class MyInAppBrowser2 extends InAppBrowser {
+
+ @override
+ Future onLoadStart(String url) async {
+ print("\n\nStarted $url\n\n");
+ //print("\n\n ${await this.isHidden()} \n\n");
+ }
+
+ @override
+ Future onLoadStop(String url) async {
+ print("\n\nStopped $url\n\n");
+ }
+
+ @override
+ void onLoadError(String url, int code, String message) {
+ print("\n\nCan't load $url.. Error: $message\n\n");
+ }
+
+ @override
+ void onExit() {
+ print("\n\nBrowser closed!\n\n");
+ }
+
+ @override
+ void shouldOverrideUrlLoading(String url) {
+ print("\n\n override $url\n\n");
+ this.loadUrl(url);
+ }
+}
+
MyInAppBrowser inAppBrowserFallback = new MyInAppBrowser();
+MyInAppBrowser2 inAppBrowserFallback2 = new MyInAppBrowser2();
class MyChromeSafariBrowser extends ChromeSafariBrowser {
MyChromeSafariBrowser(browserFallback) : super(browserFallback);
@@ -79,6 +114,7 @@ class MyChromeSafariBrowser extends ChromeSafariBrowser {
@override
void onClosed() {
print("ChromeSafari browser closed");
+ inAppBrowserFallback.open("https://flutter.io/");
}
}
diff --git a/ios/Classes/InAppBrowserWebViewController.swift b/ios/Classes/InAppBrowserWebViewController.swift
index 9fe57adc..dfd427bf 100644
--- a/ios/Classes/InAppBrowserWebViewController.swift
+++ b/ios/Classes/InAppBrowserWebViewController.swift
@@ -80,6 +80,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
var browserOptions: InAppBrowserOptions?
var initHeaders: [String: String]?
var isHidden = false
+ var uuid: String = ""
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
@@ -323,7 +324,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
currentURL = nil
if (navigationDelegate != nil) {
- navigationDelegate?.browserExit()
+ navigationDelegate?.browserExit(uuid: self.uuid)
}
weak var weakSelf = self
@@ -419,7 +420,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
let url = navigationAction.request.url
if (url != nil && navigationAction.navigationType == .linkActivated && (browserOptions?.useShouldOverrideUrlLoading)!) {
- navigationDelegate?.shouldOverrideUrlLoading(webView, url: url!)
+ navigationDelegate?.shouldOverrideUrlLoading(uuid: self.uuid, webView: webView, url: url!)
decisionHandler(.cancel)
return
}
@@ -475,7 +476,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
spinner.startAnimating()
}
- return (navigationDelegate?.onLoadStart(webView))!
+ return (navigationDelegate?.onLoadStart(uuid: self.uuid, webView: webView))!
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
@@ -485,7 +486,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
backButton.isEnabled = webView.canGoBack
forwardButton.isEnabled = webView.canGoForward
spinner.stopAnimating()
- navigationDelegate?.onLoadStop(webView)
+ navigationDelegate?.onLoadStop(uuid: self.uuid, webView: webView)
}
// func webView(_ webView: WKWebView,
@@ -495,7 +496,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
// backButton.isEnabled = webView.canGoBack
// forwardButton.isEnabled = webView.canGoForward
// spinner.stopAnimating()
-// navigationDelegate?.webView(webView, didFailLoadWithError: error)
+// navigationDelegate?.webView(uuid: self.uuid, webView: webView, didFailLoadWithError: error)
// }
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
@@ -503,6 +504,6 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
backButton.isEnabled = webView.canGoBack
forwardButton.isEnabled = webView.canGoForward
spinner.stopAnimating()
- navigationDelegate?.onLoadError(webView, error: error)
+ navigationDelegate?.onLoadError(uuid: self.uuid, webView: webView, error: error)
}
}
diff --git a/ios/Classes/SafariViewController.swift b/ios/Classes/SafariViewController.swift
index e5b411e4..bc35e4bb 100644
--- a/ios/Classes/SafariViewController.swift
+++ b/ios/Classes/SafariViewController.swift
@@ -14,6 +14,7 @@ class SafariViewController: SFSafariViewController, SFSafariViewControllerDelega
weak var statusDelegate: SwiftFlutterPlugin?
var tmpWindow: UIWindow?
var safariOptions: SafariBrowserOptions?
+ var uuid: String = ""
override func viewWillAppear(_ animated: Bool) {
prepareSafariBrowser()
@@ -37,7 +38,7 @@ class SafariViewController: SFSafariViewController, SFSafariViewControllerDelega
func close() {
if (statusDelegate != nil) {
- statusDelegate?.safariExit()
+ statusDelegate?.safariExit(uuid: self.uuid)
}
dismiss(animated: true)
@@ -55,7 +56,7 @@ class SafariViewController: SFSafariViewController, SFSafariViewControllerDelega
func safariViewController(_ controller: SFSafariViewController,
didCompleteInitialLoad didLoadSuccessfully: Bool) {
if didLoadSuccessfully {
- statusDelegate?.onChromeSafariBrowserLoaded()
+ statusDelegate?.onChromeSafariBrowserLoaded(uuid: self.uuid)
}
else {
print("Cant load successfully the 'SafariViewController'.")
diff --git a/ios/Classes/SwiftFlutterPlugin.swift b/ios/Classes/SwiftFlutterPlugin.swift
index 3c803d32..73893686 100644
--- a/ios/Classes/SwiftFlutterPlugin.swift
+++ b/ios/Classes/SwiftFlutterPlugin.swift
@@ -26,8 +26,8 @@ let WEBVIEW_STORYBOARD = "WebView"
let WEBVIEW_STORYBOARD_CONTROLLER_ID = "viewController"
public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
- var webViewController: InAppBrowserWebViewController?
- var safariViewController: Any?
+ var webViewControllers: [String: InAppBrowserWebViewController?] = [:]
+ var safariViewControllers: [String: Any?] = [:]
var tmpWindow: UIWindow?
var channel: FlutterMethodChannel
@@ -45,66 +45,96 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
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":
- self.open(arguments: arguments!, result: result)
+ self.open(uuid: uuid, arguments: arguments!, result: result)
break
case "loadUrl":
- self.loadUrl(arguments: arguments!, result: result)
+ self.loadUrl(uuid: uuid, arguments: arguments!, result: result)
break
case "close":
- self.close()
+ self.close(uuid: uuid)
result(true)
break
case "show":
- self.show()
+ self.show(uuid: uuid)
result(true)
break
case "hide":
- self.hide()
+ self.hide(uuid: uuid)
result(true)
break
case "reload":
- self.webViewController?.reload()
+ if let webViewController = self.webViewControllers[uuid] {
+ webViewController?.reload()
+ }
result(true)
break
case "goBack":
- self.webViewController?.goBack()
+ if let webViewController = self.webViewControllers[uuid] {
+ webViewController?.goBack()
+ }
result(true)
break
case "canGoBack":
- result(self.webViewController?.canGoBack() ?? false)
+ if let webViewController = self.webViewControllers[uuid] {
+ result(webViewController?.canGoBack() ?? false)
+ }
+ else {
+ result(false)
+ }
break
case "goForward":
- self.webViewController?.goForward()
+ if let webViewController = self.webViewControllers[uuid] {
+ webViewController?.goForward()
+ }
result(true)
break
case "canGoForward":
- result(self.webViewController?.canGoForward() ?? false)
+ if let webViewController = self.webViewControllers[uuid] {
+ result(webViewController?.canGoForward() ?? false)
+ }
+ else {
+ result(false)
+ }
break
case "isLoading":
- result((self.webViewController?.webView.isLoading ?? false) == true)
+ if let webViewController = self.webViewControllers[uuid] {
+ result((webViewController?.webView.isLoading ?? false) == true)
+ }
+ else {
+ result(false)
+ }
break
case "stopLoading":
- self.webViewController?.webView.stopLoading()
+ if let webViewController = self.webViewControllers[uuid] {
+ webViewController?.webView.stopLoading()
+ }
result(true)
break
case "isHidden":
- result((self.webViewController?.isHidden ?? false) == true)
+ if let webViewController = self.webViewControllers[uuid] {
+ result((webViewController?.isHidden ?? false) == true)
+ }
+ else {
+ result(false)
+ }
break
case "injectScriptCode":
- self.injectScriptCode(arguments: arguments!, result: result)
+ self.injectScriptCode(uuid: uuid, arguments: arguments!, result: result)
break
case "injectScriptFile":
- self.injectScriptFile(arguments: arguments!, result: nil)
+ self.injectScriptFile(uuid: uuid, arguments: arguments!, result: nil)
result(true)
break
case "injectStyleCode":
- self.injectStyleCode(arguments: arguments!, result: nil)
+ self.injectStyleCode(uuid: uuid, arguments: arguments!, result: nil)
result(true)
break
case "injectStyleFile":
- self.injectStyleFile(arguments: arguments!, result: nil)
+ self.injectStyleFile(uuid: uuid, arguments: arguments!, result: nil)
result(true)
break
default:
@@ -113,13 +143,15 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
}
}
- func close() {
- if webViewController == nil {
+ func close(uuid: String) {
+ if let webViewController = self.webViewControllers[uuid] {
+ // Things are cleaned up in browserExit.
+ webViewController?.close()
+ }
+ else {
print("IAB.close() called but it was already closed.")
return
}
- // Things are cleaned up in browserExit.
- webViewController?.close()
}
func isSystemUrl(_ url: URL) -> Bool {
@@ -129,7 +161,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
return false
}
- public func open(arguments: NSDictionary, result: @escaping FlutterResult) {
+ public func open(uuid: String, arguments: NSDictionary, result: @escaping FlutterResult) {
let url: String = (arguments["url"] as? String)!
let headers = (arguments["headers"] as? [String: String])!
@@ -140,56 +172,47 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
let useChromeSafariBrowser = (arguments["useChromeSafariBrowser"] as? Bool)
if useChromeSafariBrowser! {
+ let uuidFallback = (arguments["uuidFallback"] as? String)!
let options = (arguments["options"] as? [String: Any])!
let optionsFallback = (arguments["optionsFallback"] as? [String: Any])!
- open(inAppBrowser: absoluteUrl!, headers: headers, withOptions: options, useChromeSafariBrowser: true, withOptionsFallback: optionsFallback);
+ open(uuid: uuid, uuidFallback: uuidFallback, inAppBrowser: absoluteUrl!, headers: headers, withOptions: options, useChromeSafariBrowser: true, withOptionsFallback: optionsFallback);
}
else {
let options = (arguments["options"] as? [String: Any])!
+
if isSystemUrl(absoluteUrl!) {
target = "_system"
}
if (target == "_self" || target == "_target") {
- open(inAppBrowser: absoluteUrl!, headers: headers, withOptions: options, useChromeSafariBrowser: false, withOptionsFallback: nil)
+ open(uuid: uuid, uuidFallback: nil, inAppBrowser: absoluteUrl!, headers: headers, withOptions: options, useChromeSafariBrowser: false, withOptionsFallback: nil)
}
else if (target == "_system") {
open(inSystem: absoluteUrl!)
}
else {
// anything else
- open(inAppBrowser: absoluteUrl!, headers: headers,withOptions: options, useChromeSafariBrowser: false, withOptionsFallback: nil)
+ open(uuid: uuid, uuidFallback: nil, inAppBrowser: absoluteUrl!, headers: headers,withOptions: options, useChromeSafariBrowser: false, withOptionsFallback: nil)
}
}
result(true)
}
- public func loadUrl(arguments: NSDictionary, result: @escaping FlutterResult) {
- let url: String? = (arguments["url"] as? String)!
- let headers = (arguments["headers"] as? [String: String])!
+ func open(uuid: String, uuidFallback: String?, inAppBrowser url: URL, headers: [String: String], withOptions options: [String: Any], useChromeSafariBrowser: Bool, withOptionsFallback optionsFallback: [String: Any]?) {
- if url != nil {
- let absoluteUrl = URL(string: url!)!.absoluteURL
- webViewController?.loadUrl(url: absoluteUrl, headers: headers)
- }
- else {
- print("url is empty")
- result(FlutterError(code: "InAppBrowserFlutterPlugin", message: "url is empty", details: nil))
- }
- result(true)
- }
-
- func open(inAppBrowser url: URL, headers: [String: String], withOptions options: [String: Any], useChromeSafariBrowser: Bool, withOptionsFallback optionsFallback: [String: Any]?) {
+ var uuid = uuid
- if webViewController != nil {
- close()
+ if self.webViewControllers[uuid] != nil {
+ close(uuid: uuid)
}
+ let safariViewController = self.safariViewControllers[uuid]
+
if safariViewController != nil {
if #available(iOS 9.0, *) {
(safariViewController! as! SafariViewController).close()
- safariViewController = nil
+ self.safariViewControllers[uuid] = nil
} else {
// Fallback on earlier versions
}
@@ -230,19 +253,25 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
safari = SafariViewController(url: url)
}
+ safari.uuid = uuid
safari.delegate = safari
safari.statusDelegate = self
safari.tmpWindow = tmpWindow
safari.safariOptions = safariOptions
- safariViewController = safari
+ self.safariViewControllers[uuid] = safari
- tmpController.present(safariViewController! as! SFSafariViewController, animated: true)
- onChromeSafariBrowserOpened()
+ tmpController.present(self.safariViewControllers[uuid]! as! SFSafariViewController, animated: true)
+ onChromeSafariBrowserOpened(uuid: uuid)
return
}
else {
+ if uuidFallback == nil {
+ print("No WebView fallback declared.")
+ return
+ }
+ uuid = uuidFallback!
browserOptions = InAppBrowserOptions()
browserOptions.parse(options: optionsFallback!)
}
@@ -254,17 +283,19 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
let storyboard = UIStoryboard(name: WEBVIEW_STORYBOARD, bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: WEBVIEW_STORYBOARD_CONTROLLER_ID)
- webViewController = vc as? InAppBrowserWebViewController
- webViewController?.browserOptions = browserOptions
- webViewController?.isHidden = browserOptions.hidden
- webViewController?.tmpWindow = tmpWindow
- webViewController?.currentURL = url
- webViewController?.initHeaders = headers
- webViewController?.navigationDelegate = self
+ self.webViewControllers[uuid] = vc as? InAppBrowserWebViewController
+ let webViewController: InAppBrowserWebViewController = self.webViewControllers[uuid] as! InAppBrowserWebViewController
+ webViewController.uuid = uuid
+ webViewController.browserOptions = browserOptions
+ webViewController.isHidden = browserOptions.hidden
+ webViewController.tmpWindow = tmpWindow
+ webViewController.currentURL = url
+ webViewController.initHeaders = headers
+ webViewController.navigationDelegate = self
if browserOptions.hidden {
- webViewController!.view.isHidden = true
- tmpController.present(self.webViewController!, animated: false, completion: {() -> Void in
+ webViewController.view.isHidden = true
+ tmpController.present(webViewController, animated: false, completion: {() -> Void in
// if self.previousStatusBarStyle != -1 {
// UIApplication.shared.statusBarStyle = UIStatusBarStyle(rawValue: self.previousStatusBarStyle)!
// }
@@ -272,65 +303,89 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
// if self.previousStatusBarStyle != -1 {
// UIApplication.shared.statusBarStyle = UIStatusBarStyle(rawValue: self.previousStatusBarStyle)!
// }
- webViewController?.presentingViewController?.dismiss(animated: false, completion: {() -> Void in
+ webViewController.presentingViewController?.dismiss(animated: false, completion: {() -> Void in
self.tmpWindow?.windowLevel = 0.0
UIApplication.shared.delegate?.window??.makeKeyAndVisible()
})
}
else {
- tmpController.present(webViewController!, animated: true, completion: nil)
+ tmpController.present(webViewController, animated: true, completion: nil)
}
}
- public func show() {
+ public func loadUrl(uuid: String, arguments: NSDictionary, result: @escaping FlutterResult) {
+ let webViewController: InAppBrowserWebViewController = self.webViewControllers[uuid] as! InAppBrowserWebViewController
+ let url: String? = (arguments["url"] as? String)!
+ let headers = (arguments["headers"] as? [String: String])!
- if webViewController == nil {
- print("Tried to hide IAB after it was closed.")
- return
+ if url != nil {
+ let absoluteUrl = URL(string: url!)!.absoluteURL
+ webViewController.loadUrl(url: absoluteUrl, headers: headers)
}
-
- self.webViewController?.isHidden = false
- self.webViewController!.view.isHidden = false
-
- // Run later to avoid the "took a long time" log message.
- DispatchQueue.main.async(execute: {() -> Void in
- if self.webViewController != nil {
- let baseWindowLevel = UIApplication.shared.keyWindow?.windowLevel
- self.tmpWindow?.windowLevel = UIWindowLevel(baseWindowLevel! + 1)
- self.tmpWindow?.makeKeyAndVisible()
- UIApplication.shared.delegate?.window??.makeKeyAndVisible()
- self.tmpWindow?.rootViewController?.present(self.webViewController!, animated: true, completion: nil)
- }
- })
+ else {
+ print("url is empty")
+ result(FlutterError(code: "InAppBrowserFlutterPlugin", message: "url is empty", details: nil))
+ }
+ result(true)
}
-
- public func hide() {
- if webViewController == nil {
- print("Tried to hide IAB after it was closed.")
- return
- }
-
- if self.webViewController != nil {
- self.webViewController?.isHidden = true
- }
-
- // Run later to avoid the "took a long time" log message.
- DispatchQueue.main.async(execute: {() -> Void in
- if self.webViewController != nil {
- self.webViewController?.presentingViewController?.dismiss(animated: true, completion: {() -> Void in
- self.tmpWindow?.windowLevel = 0.0
- UIApplication.shared.delegate?.window??.makeKeyAndVisible()
- if self.previousStatusBarStyle != -1 {
- UIApplication.shared.statusBarStyle = UIStatusBarStyle(rawValue: self.previousStatusBarStyle)!
+
+ public func show(uuid: String) {
+ if let webViewController = self.webViewControllers[uuid] {
+ if webViewController != nil {
+ webViewController?.isHidden = false
+ webViewController?.view.isHidden = false
+
+ // Run later to avoid the "took a long time" log message.
+ DispatchQueue.main.async(execute: {() -> Void in
+ if webViewController != nil {
+ let baseWindowLevel = UIApplication.shared.keyWindow?.windowLevel
+ self.tmpWindow?.windowLevel = UIWindowLevel(baseWindowLevel! + 1)
+ self.tmpWindow?.makeKeyAndVisible()
+ UIApplication.shared.delegate?.window??.makeKeyAndVisible()
+ self.tmpWindow?.rootViewController?.present(webViewController!, animated: true, completion: nil)
}
})
}
- })
+ else {
+ print("Tried to hide IAB after it was closed.")
+ }
+ }
+ }
+
+ public func hide(uuid: String) {
+ if let webViewController = self.webViewControllers[uuid] {
+ if webViewController != nil {
+ webViewController?.isHidden = true
+
+ // Run later to avoid the "took a long time" log message.
+ DispatchQueue.main.async(execute: {() -> Void in
+ if webViewController != nil {
+ webViewController?.presentingViewController?.dismiss(animated: true, completion: {() -> Void in
+ self.tmpWindow?.windowLevel = 0.0
+ UIApplication.shared.delegate?.window??.makeKeyAndVisible()
+ if self.previousStatusBarStyle != -1 {
+ UIApplication.shared.statusBarStyle = UIStatusBarStyle(rawValue: self.previousStatusBarStyle)!
+ }
+ })
+ }
+ })
+ }
+ else {
+ print("Tried to hide IAB after it was closed.")
+ }
+ }
}
func open(inSystem url: URL) {
- if UIApplication.shared.openURL(url) == false {
- NotificationCenter.default.post(Notification(name: Notification.Name(rawValue: "CDVPluginHandleOpenURLNotification"), object: url))
+ if !UIApplication.shared.canOpenURL(url) {
+ NotificationCenter.default.post(Notification(name: Notification.Name(rawValue: "PluginHandleOpenURLNotification"), object: url))
+ return
+ }
+
+ if #available(iOS 10.0, *) {
+ UIApplication.shared.open(url, options: [:], completionHandler: nil)
+ } else {
+ UIApplication.shared.openURL(url)
}
}
@@ -342,113 +397,131 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
// '%@' marker).
//
// If no wrapper is supplied, then the source string is executed directly.
- func injectDeferredObject(_ source: String, withWrapper jsWrapper: String, result: FlutterResult?) {
- let jsonData: Data? = try? JSONSerialization.data(withJSONObject: [source], options: [])
- let sourceArrayString = String(data: jsonData!, encoding: String.Encoding.utf8)
- if sourceArrayString != nil {
- let sourceString: String? = (sourceArrayString! as NSString).substring(with: NSRange(location: 1, length: (sourceArrayString?.characters.count ?? 0) - 2))
- let jsToInject = String(format: jsWrapper, sourceString!)
-
- webViewController?.webView?.evaluateJavaScript(jsToInject, completionHandler: {(value, error) in
- if result == nil {
- return
- }
+ func injectDeferredObject(uuid: String, source: String, withWrapper jsWrapper: String, result: FlutterResult?) {
+ if let webViewController = self.webViewControllers[uuid] {
+ let jsonData: Data? = try? JSONSerialization.data(withJSONObject: [source], options: [])
+ let sourceArrayString = String(data: jsonData!, encoding: String.Encoding.utf8)
+ if sourceArrayString != nil {
+ let sourceString: String? = (sourceArrayString! as NSString).substring(with: NSRange(location: 1, length: (sourceArrayString?.characters.count ?? 0) - 2))
+ let jsToInject = String(format: jsWrapper, sourceString!)
- do {
- let data: Data = ("[" + String(describing: value!) + "]").data(using: String.Encoding.utf8, allowLossyConversion: false)!
- let json: Array = try JSONSerialization.jsonObject(with: data, options: []) as! Array
- if json[0] is String {
- result!(json[0])
+ webViewController?.webView?.evaluateJavaScript(jsToInject, completionHandler: {(value, error) in
+ if result == nil {
+ return
}
- else {
- result!(value)
+
+ do {
+ let data: Data = ("[" + String(describing: value!) + "]").data(using: String.Encoding.utf8, allowLossyConversion: false)!
+ let json: Array = try JSONSerialization.jsonObject(with: data, options: []) as! Array
+ if json[0] is String {
+ result!(json[0])
+ }
+ else {
+ result!(value)
+ }
+ } catch let error as NSError {
+ print("Failed to load: \(error.localizedDescription)")
+ result!(FlutterError(code: "InAppBrowserFlutterPlugin", message: "Failed to load: \(error.localizedDescription)", details: error))
}
- } catch let error as NSError {
- print("Failed to load: \(error.localizedDescription)")
- result!(FlutterError(code: "InAppBrowserFlutterPlugin", message: "Failed to load: \(error.localizedDescription)", details: error))
- }
-
- })
+
+ })
+ }
}
}
- public func injectScriptCode(arguments: NSDictionary, result: FlutterResult?) {
+ public func injectScriptCode(uuid: String, arguments: NSDictionary, result: FlutterResult?) {
let jsWrapper = "(function(){return JSON.stringify(eval(%@));})();"
- injectDeferredObject(arguments["source"] as! String, withWrapper: jsWrapper, result: result)
+ injectDeferredObject(uuid: uuid, source: arguments["source"] as! String, withWrapper: jsWrapper, result: result)
}
- public func injectScriptFile(arguments: NSDictionary, result: FlutterResult?) {
+ public func injectScriptFile(uuid: String, arguments: NSDictionary, result: FlutterResult?) {
let jsWrapper = "(function(d) { var c = d.createElement('script'); c.src = %@; d.body.appendChild(c); })(document);"
- injectDeferredObject(arguments["urlFile"] as! String, withWrapper: jsWrapper, result: result)
+ injectDeferredObject(uuid: uuid, source: arguments["urlFile"] as! String, withWrapper: jsWrapper, result: result)
}
- public func injectStyleCode(arguments: NSDictionary, result: FlutterResult?) {
+ public func injectStyleCode(uuid: String, arguments: NSDictionary, result: FlutterResult?) {
let jsWrapper = "(function(d) { var c = d.createElement('style'); c.innerHTML = %@; d.body.appendChild(c); })(document);"
- injectDeferredObject(arguments["source"] as! String, withWrapper: jsWrapper, result: result)
+ injectDeferredObject(uuid: uuid, source: arguments["source"] as! String, withWrapper: jsWrapper, result: result)
}
- public func injectStyleFile(arguments: NSDictionary, result: FlutterResult?) {
+ public func injectStyleFile(uuid: String, arguments: NSDictionary, result: FlutterResult?) {
let jsWrapper = "(function(d) { var c = d.createElement('link'); c.rel='stylesheet', c.type='text/css'; c.href = %@; d.body.appendChild(c); })(document);"
- injectDeferredObject(arguments["urlFile"] as! String, withWrapper: jsWrapper, result: result)
+ injectDeferredObject(uuid: uuid, source: arguments["urlFile"] as! String, withWrapper: jsWrapper, result: result)
}
- func onLoadStart(_ webView: WKWebView) {
- let url: String = webViewController!.currentURL!.absoluteString
- channel.invokeMethod("onLoadStart", arguments: ["url": url])
- }
-
- func onLoadStop(_ webView: WKWebView) {
- let url: String = webViewController!.currentURL!.absoluteString
- channel.invokeMethod("onLoadStop", arguments: ["url": url])
- }
-
- func onLoadError(_ webView: WKWebView, error: Error) {
- let url: String = webViewController!.currentURL!.absoluteString
- let arguments = ["url": url, "code": error._code, "message": error.localizedDescription] as [String : Any]
- channel.invokeMethod("onLoadError", arguments: arguments)
- }
-
- func onExit() {
- channel.invokeMethod("onExit", arguments: [])
- }
-
- func shouldOverrideUrlLoading(_ webView: WKWebView, url: URL) {
- channel.invokeMethod("shouldOverrideUrlLoading", arguments: ["url": url.absoluteString])
- }
-
- func onChromeSafariBrowserOpened() {
- channel.invokeMethod("onChromeSafariBrowserOpened", arguments: [])
- }
-
- func onChromeSafariBrowserLoaded() {
- channel.invokeMethod("onChromeSafariBrowserLoaded", arguments: [])
- }
-
- func onChromeSafariBrowserClosed() {
- channel.invokeMethod("onChromeSafariBrowserClosed", arguments: [])
- }
-
- func safariExit() {
- if #available(iOS 9.0, *) {
- (safariViewController as! SafariViewController).statusDelegate = nil
- (safariViewController as! SafariViewController).delegate = nil
+ func onLoadStart(uuid: String, webView: WKWebView) {
+ if let webViewController = self.webViewControllers[uuid] {
+ let url: String = webViewController!.currentURL!.absoluteString
+ channel.invokeMethod("onLoadStart", arguments: ["uuid": uuid, "url": url])
}
- safariViewController = nil
- onChromeSafariBrowserClosed()
}
- func browserExit() {
- // Set navigationDelegate to nil to ensure no callbacks are received from it.
- webViewController?.navigationDelegate = nil
- // Don't recycle the ViewController since it may be consuming a lot of memory.
- // Also - this is required for the PDF/User-Agent bug work-around.
- webViewController = nil
-
- if previousStatusBarStyle != -1 {
- UIApplication.shared.statusBarStyle = UIStatusBarStyle(rawValue: previousStatusBarStyle)!
+ func onLoadStop(uuid: String, webView: WKWebView) {
+ if let webViewController = self.webViewControllers[uuid] {
+ let url: String = webViewController!.currentURL!.absoluteString
+ channel.invokeMethod("onLoadStop", arguments: ["uuid": uuid, "url": url])
+ }
+ }
+
+ func onLoadError(uuid: String, webView: WKWebView, error: Error) {
+ if let webViewController = self.webViewControllers[uuid] {
+ let url: String = webViewController!.currentURL!.absoluteString
+ let arguments = ["uuid": uuid, "url": url, "code": error._code, "message": error.localizedDescription] as [String : Any]
+ channel.invokeMethod("onLoadError", arguments: arguments)
+ }
+ }
+
+ func onExit(uuid: String) {
+ channel.invokeMethod("onExit", arguments: ["uuid": uuid])
+ }
+
+ func shouldOverrideUrlLoading(uuid: String, webView: WKWebView, url: URL) {
+ if let webViewController = self.webViewControllers[uuid] {
+ channel.invokeMethod("shouldOverrideUrlLoading", arguments: ["uuid": uuid, "url": url.absoluteString])
+ }
+ }
+
+ func onChromeSafariBrowserOpened(uuid: String) {
+ if let safariViewController = self.safariViewControllers[uuid] {
+ channel.invokeMethod("onChromeSafariBrowserOpened", arguments: ["uuid": uuid])
+ }
+ }
+
+ func onChromeSafariBrowserLoaded(uuid: String) {
+ if let safariViewController = self.safariViewControllers[uuid] {
+ channel.invokeMethod("onChromeSafariBrowserLoaded", arguments: ["uuid": uuid])
+ }
+ }
+
+ func onChromeSafariBrowserClosed(uuid: String) {
+ channel.invokeMethod("onChromeSafariBrowserClosed", arguments: ["uuid": uuid])
+ }
+
+ func safariExit(uuid: String) {
+ if let safariViewController = self.safariViewControllers[uuid] {
+ if #available(iOS 9.0, *) {
+ (safariViewController as! SafariViewController).statusDelegate = nil
+ (safariViewController as! SafariViewController).delegate = nil
+ }
+ self.safariViewControllers[uuid] = nil
+ onChromeSafariBrowserClosed(uuid: uuid)
+ }
+ }
+
+ func browserExit(uuid: String) {
+ if let webViewController = self.webViewControllers[uuid] {
+ // Set navigationDelegate to nil to ensure no callbacks are received from it.
+ webViewController?.navigationDelegate = nil
+ // Don't recycle the ViewController since it may be consuming a lot of memory.
+ // Also - this is required for the PDF/User-Agent bug work-around.
+ self.webViewControllers[uuid] = nil
+
+ if previousStatusBarStyle != -1 {
+ UIApplication.shared.statusBarStyle = UIStatusBarStyle(rawValue: previousStatusBarStyle)!
+ }
+
+ onExit(uuid: uuid)
}
-
- onExit()
}
}
diff --git a/lib/flutter_inappbrowser.dart b/lib/flutter_inappbrowser.dart
index f1e86ac9..31727515 100644
--- a/lib/flutter_inappbrowser.dart
+++ b/lib/flutter_inappbrowser.dart
@@ -20,25 +20,30 @@
*/
import 'dart:async';
+import 'dart:collection';
import 'package:flutter/services.dart';
+import 'package:uuid/uuid.dart';
+
+typedef Future ListenerCallback(MethodCall call);
+
+var uuidGenerator = new Uuid();
class _ChannelManager {
static const MethodChannel channel = const MethodChannel('com.pichillilorenzo/flutter_inappbrowser');
static final initialized = false;
- static final listeners = [];
+ static final listeners = HashMap();
static Future _handleMethod(MethodCall call) async {
- for (var listener in listeners) {
- listener(call);
- }
+ String uuid = call.arguments["uuid"];
+ listeners[uuid](call);
return new Future.value("");
}
- static void addListener (Function callback) {
+ static void addListener (String key, ListenerCallback callback) {
if (!initialized)
init();
- listeners.add(callback);
+ listeners.putIfAbsent(key, () => callback);
}
static void init () {
@@ -51,9 +56,12 @@ class _ChannelManager {
/// This class uses the native WebView of the platform.
class InAppBrowser {
+ String uuid;
+
///
InAppBrowser () {
- _ChannelManager.addListener(_handleMethod);
+ uuid = uuidGenerator.v4();
+ _ChannelManager.addListener(uuid, _handleMethod);
}
Future _handleMethod(MethodCall call) async {
@@ -144,6 +152,7 @@ class InAppBrowser {
/// - __spinner__: Set to `false` to hide the spinner when the WebView is loading a page. The default value is `true`.
Future open(String url, {Map headers = const {}, String target = "_self", Map options = const {}}) async {
Map args = {};
+ args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('url', () => url);
args.putIfAbsent('headers', () => headers);
args.putIfAbsent('target', () => target);
@@ -155,6 +164,7 @@ class InAppBrowser {
///Loads the given [url] with optional [headers] specified as a map from name to value.
Future loadUrl(String url, {Map headers = const {}}) async {
Map args = {};
+ args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('url', () => url);
args.putIfAbsent('headers', () => headers);
return await _ChannelManager.channel.invokeMethod('loadUrl', args);
@@ -162,52 +172,71 @@ class InAppBrowser {
///Displays an [InAppBrowser] window that was opened hidden. Calling this has no effect if the [InAppBrowser] was already visible.
Future show() async {
- return await _ChannelManager.channel.invokeMethod('show');
+ Map args = {};
+ args.putIfAbsent('uuid', () => uuid);
+ return await _ChannelManager.channel.invokeMethod('show', args);
}
///Hides the [InAppBrowser] window. Calling this has no effect if the [InAppBrowser] was already hidden.
Future hide() async {
- return await _ChannelManager.channel.invokeMethod('hide');
+ Map args = {};
+ args.putIfAbsent('uuid', () => uuid);
+ return await _ChannelManager.channel.invokeMethod('hide', args);
}
///Closes the [InAppBrowser] window.
Future close() async {
- return await _ChannelManager.channel.invokeMethod('close');
+ Map args = {};
+ args.putIfAbsent('uuid', () => uuid);
+ return await _ChannelManager.channel.invokeMethod('close', args);
}
///Reloads the [InAppBrowser] window.
Future reload() async {
- return await _ChannelManager.channel.invokeMethod('reload');
+ Map args = {};
+ args.putIfAbsent('uuid', () => uuid);
+ return await _ChannelManager.channel.invokeMethod('reload', args);
}
///Goes back in the history of the [InAppBrowser] window.
Future goBack() async {
- return await _ChannelManager.channel.invokeMethod('goBack');
+ Map args = {};
+ args.putIfAbsent('uuid', () => uuid);
+ return await _ChannelManager.channel.invokeMethod('goBack', args);
}
///Goes forward in the history of the [InAppBrowser] window.
Future goForward() async {
- return await _ChannelManager.channel.invokeMethod('goForward');
+ Map args = {};
+ args.putIfAbsent('uuid', () => uuid);
+ return await _ChannelManager.channel.invokeMethod('goForward', args);
}
///Check if the Web View of the [InAppBrowser] instance is in a loading state.
Future isLoading() async {
- return await _ChannelManager.channel.invokeMethod('isLoading');
+ Map args = {};
+ args.putIfAbsent('uuid', () => uuid);
+ return await _ChannelManager.channel.invokeMethod('isLoading', args);
}
///Stops the Web View of the [InAppBrowser] instance from loading.
Future stopLoading() async {
- return await _ChannelManager.channel.invokeMethod('stopLoading');
+ Map args = {};
+ args.putIfAbsent('uuid', () => uuid);
+ return await _ChannelManager.channel.invokeMethod('stopLoading', args);
}
///Check if the Web View of the [InAppBrowser] instance is hidden.
Future isHidden() async {
- return await _ChannelManager.channel.invokeMethod('isHidden');
+ Map args = {};
+ args.putIfAbsent('uuid', () => uuid);
+ return await _ChannelManager.channel.invokeMethod('isHidden', args);
}
///Injects JavaScript code into the [InAppBrowser] window and returns the result of the evaluation. (Only available when the target is set to `_blank` or to `_self`)
Future injectScriptCode(String source) async {
Map args = {};
+ args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('source', () => source);
return await _ChannelManager.channel.invokeMethod('injectScriptCode', args);
}
@@ -215,6 +244,7 @@ class InAppBrowser {
///Injects a JavaScript file into the [InAppBrowser] window. (Only available when the target is set to `_blank` or to `_self`)
Future injectScriptFile(String urlFile) async {
Map args = {};
+ args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('urlFile', () => urlFile);
return await _ChannelManager.channel.invokeMethod('injectScriptFile', args);
}
@@ -222,6 +252,7 @@ class InAppBrowser {
///Injects CSS into the [InAppBrowser] window. (Only available when the target is set to `_blank` or to `_self`)
Future injectStyleCode(String source) async {
Map args = {};
+ args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('source', () => source);
return await _ChannelManager.channel.invokeMethod('injectStyleCode', args);
}
@@ -229,6 +260,7 @@ class InAppBrowser {
///Injects a CSS file into the [InAppBrowser] window. (Only available when the target is set to `_blank` or to `_self`)
Future injectStyleFile(String urlFile) async {
Map args = {};
+ args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('urlFile', () => urlFile);
return await _ChannelManager.channel.invokeMethod('injectStyleFile', args);
}
@@ -268,12 +300,14 @@ class InAppBrowser {
///
///[browserFallback] represents the [InAppBrowser] instance fallback in case [Chrome Custom Tabs]/[SFSafariViewController] is not available.
class ChromeSafariBrowser {
+ String uuid;
InAppBrowser browserFallback;
///
- ChromeSafariBrowser (browserFallback) {
- this.browserFallback = browserFallback;
- _ChannelManager.addListener(_handleMethod);
+ ChromeSafariBrowser (bf) {
+ uuid = uuidGenerator.v4();
+ browserFallback = bf;
+ _ChannelManager.addListener(uuid, _handleMethod);
}
Future _handleMethod(MethodCall call) async {
@@ -294,6 +328,9 @@ class ChromeSafariBrowser {
///
Future open(String url, {Map options = const {}, Map headersFallback = const {}, Map optionsFallback = const {}}) async {
Map args = {};
+ args.putIfAbsent('uuid', () => uuid);
+ print(browserFallback.uuid);
+ args.putIfAbsent('uuidFallback', () => (browserFallback != null) ? browserFallback.uuid : '');
args.putIfAbsent('url', () => url);
args.putIfAbsent('headers', () => headersFallback);
args.putIfAbsent('target', () => "");
diff --git a/pubspec.yaml b/pubspec.yaml
index 131f2fdb..64207085 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
name: flutter_inappbrowser
description: A Flutter plugin that allows you to open an in-app browser window. (inspired by the popular cordova-plugin-inappbrowser).
-version: 0.1.1
+version: 0.2.0
author: Lorenzo Pichilli
homepage: https://github.com/pichillilorenzo/flutter_inappbrowser
@@ -10,6 +10,7 @@ environment:
dependencies:
flutter:
sdk: flutter
+ uuid: ^1.0.3
# For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec