diff --git a/.idea/workspace.xml b/.idea/workspace.xml index c7ce663e..fa9db498 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -5,21 +5,27 @@ + + - + - - - + + - - + - + + + + + + @@ -39,8 +45,8 @@ - - + + @@ -51,8 +57,8 @@ - - + + @@ -69,7 +75,6 @@ - Resource (0) closeDi hide() @@ -99,6 +104,7 @@ injectDeferredObject sourceFile hideUrlBar + InAppBrowser activity.getPreferences(0) @@ -122,13 +128,11 @@ - @@ -167,6 +173,9 @@ + + + @@ -177,29 +186,39 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -221,9 +240,6 @@ - - - @@ -239,6 +255,8 @@ + + @@ -412,41 +430,41 @@ - + - - - - - - - - - + + - - + - - + + + + + + + + + + + + - + - - @@ -492,20 +510,6 @@ - - - - - - - - - - - - - - @@ -542,7 +546,7 @@ - + @@ -550,7 +554,7 @@ - + @@ -630,13 +634,6 @@ - - - - - - - @@ -658,27 +655,6 @@ - - - - - - - - - - - - - - - - - - - - - @@ -693,13 +669,6 @@ - - - - - - - @@ -714,13 +683,6 @@ - - - - - - - @@ -738,20 +700,6 @@ - - - - - - - - - - - - - - @@ -771,20 +719,6 @@ - - - - - - - - - - - - - - @@ -799,7 +733,7 @@ - + @@ -815,10 +749,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + @@ -827,8 +857,8 @@ - - + + diff --git a/android/build.gradle b/android/build.gradle index 020a51c9..28a1e933 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -38,5 +38,4 @@ android { dependencies { implementation 'com.android.support:customtabs:27.1.1' implementation 'com.android.support:appcompat-v7:27.1.1' - implementation 'com.android.support.constraint:constraint-layout:1.1.3' } diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 6b644696..bf47aef8 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -3,7 +3,6 @@ package="com.pichillilorenzo.flutter_inappbrowser"> - diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowser.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserFlutterPlugin.java similarity index 81% rename from android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowser.java rename to android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserFlutterPlugin.java index ba869ea5..732cf54a 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowser.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserFlutterPlugin.java @@ -30,13 +30,16 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.support.annotation.RequiresApi; +import android.util.JsonReader; +import android.util.JsonToken; import android.webkit.MimeTypeMap; +import android.webkit.ValueCallback; import android.webkit.WebView; import android.webkit.WebViewClient; import android.util.Log; -import android.widget.Toast; -import java.time.Duration; +import java.io.IOException; +import java.io.StringReader; import java.util.HashMap; import java.util.Map; @@ -44,11 +47,10 @@ import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; -import io.flutter.plugin.common.PluginRegistry; import io.flutter.plugin.common.PluginRegistry.Registrar; -/** InAppBrowser */ -public class InAppBrowser implements MethodCallHandler { +/** InAppBrowserFlutterPlugin */ +public class InAppBrowserFlutterPlugin implements MethodCallHandler { public static Registrar registrar; public Activity activity; @@ -56,10 +58,10 @@ public class InAppBrowser implements MethodCallHandler { public static WebViewActivity webViewActivity; private static final String NULL = "null"; - protected static final String LOG_TAG = "InAppBrowser"; + protected static final String LOG_TAG = "InAppBrowserFlutterP"; - public InAppBrowser(Registrar r, Activity activity) { + public InAppBrowserFlutterPlugin(Registrar r, Activity activity) { registrar = r; this.activity = activity; channel = new MethodChannel(registrar.messenger(), "com.pichillilorenzo/flutter_inappbrowser"); @@ -68,7 +70,7 @@ public class InAppBrowser implements MethodCallHandler { /** Plugin registration. */ public static void registerWith(Registrar registrar) { final MethodChannel channel = new MethodChannel(registrar.messenger(), "com.pichillilorenzo/flutter_inappbrowser"); - channel.setMethodCallHandler(new InAppBrowser(registrar, registrar.activity())); + channel.setMethodCallHandler(new InAppBrowserFlutterPlugin(registrar, registrar.activity())); } @RequiresApi(api = Build.VERSION_CODES.KITKAT) @@ -111,9 +113,9 @@ public class InAppBrowser implements MethodCallHandler { Log.e(LOG_TAG, "Error dialing " + url + ": " + e.toString()); } } - // load in InAppBrowser + // load in InAppBrowserFlutterPlugin else { - Log.d(LOG_TAG, "loading in InAppBrowser"); + Log.d(LOG_TAG, "loading in InAppBrowserFlutterPlugin"); open(url, options); } } @@ -141,26 +143,25 @@ public class InAppBrowser implements MethodCallHandler { break; case "injectScriptCode": source = call.argument("source").toString(); - jsWrapper = "(function(){JSON.stringify([eval(%s)])})()"; - injectDeferredObject(source, jsWrapper); - result.success(true); + jsWrapper = "(function(){return JSON.stringify(eval(%s));})();"; + injectDeferredObject(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); + jsWrapper = "(function(d) { var c = d.createElement('script'); c.src = %s; d.body.appendChild(c); })(document);"; + injectDeferredObject(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); + jsWrapper = "(function(d) { var c = d.createElement('style'); c.innerHTML = %s; d.body.appendChild(c); })(document);"; + injectDeferredObject(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); + 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); result.success(true); break; case "show": @@ -203,7 +204,7 @@ public class InAppBrowser implements MethodCallHandler { } /** - * Inject an object (script or style) into the InAppBrowser WebView. + * Inject an object (script or style) into the InAppBrowserFlutterPlugin WebView. * * This is a helper method for the inject{Script|Style}{Code|File} API calls, which * provides a consistent method for injecting JavaScript code into the document. @@ -211,15 +212,14 @@ public class InAppBrowser 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 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 - * which should be executed directly. + * @param result */ - private void injectDeferredObject(String source, String jsWrapper) { - if (webViewActivity!=null) { + private void injectDeferredObject(String source, String jsWrapper, final Result result) { + if (webViewActivity != null) { String scriptToInject; if (jsWrapper != null) { org.json.JSONArray jsonEsc = new org.json.JSONArray(); @@ -232,14 +232,46 @@ public class InAppBrowser implements MethodCallHandler { } final String finalScriptToInject = scriptToInject; activity.runOnUiThread(new Runnable() { - @SuppressLint("NewApi") @Override public void run() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { // This action will have the side-effect of blurring the currently focused element webViewActivity.webView.loadUrl("javascript:" + finalScriptToInject); } else { - webViewActivity.webView.evaluateJavascript(finalScriptToInject, null); + webViewActivity.webView.evaluateJavascript(finalScriptToInject, new ValueCallback() { + @Override + public void onReceiveValue(String s) { + if (result == null) + return; + + JsonReader reader = new JsonReader(new StringReader(s)); + + // Must set lenient to parse single values + reader.setLenient(true); + + try { + String msg; + msg = reader.nextString(); + + JsonReader reader2 = new JsonReader(new StringReader(msg)); + reader2.setLenient(true); + + if (reader2.peek() == JsonToken.STRING) + msg = reader2.nextString(); + + result.success(msg); + + } catch (IOException e) { + Log.e(LOG_TAG, "IOException", e); + } finally { + try { + reader.close(); + } catch (IOException e) { + // NOOP + } + } + } + }); } } }); @@ -279,7 +311,7 @@ public class InAppBrowser implements MethodCallHandler { activity.startActivity(intent); // not catching FileUriExposedException explicitly because buildtools<24 doesn't know about it } catch (java.lang.RuntimeException e) { - Log.d(LOG_TAG, "InAppBrowser: Error loading url "+url+":"+ e.toString()); + Log.d(LOG_TAG, "InAppBrowserFlutterPlugin: Error loading url "+url+":"+ e.toString()); } } 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 2b731a49..0a0c4f94 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebViewClient.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebViewClient.java @@ -104,7 +104,7 @@ public class InAppBrowserWebViewClient extends WebViewClient { Map obj = new HashMap<>(); obj.put("url", url); - InAppBrowser.channel.invokeMethod("loadstart", obj); + InAppBrowserFlutterPlugin.channel.invokeMethod("loadstart", obj); } @@ -114,7 +114,7 @@ public class InAppBrowserWebViewClient extends WebViewClient { activity.isLoading = false; - // CB-10395 InAppBrowser's WebView not storing cookies reliable to local device storage + // CB-10395 InAppBrowserFlutterPlugin's WebView not storing cookies reliable to local device storage if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { CookieManager.getInstance().flush(); } else { @@ -127,7 +127,7 @@ public class InAppBrowserWebViewClient extends WebViewClient { Map obj = new HashMap<>(); obj.put("url", url); - InAppBrowser.channel.invokeMethod("loadstop", obj); + InAppBrowserFlutterPlugin.channel.invokeMethod("loadstop", obj); } public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { @@ -139,7 +139,7 @@ public class InAppBrowserWebViewClient extends WebViewClient { obj.put("url", failingUrl); obj.put("code", errorCode); obj.put("message", description); - InAppBrowser.channel.invokeMethod("loaderror", obj); + InAppBrowserFlutterPlugin.channel.invokeMethod("loaderror", obj); } /** diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/RequestPermissionHandler.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/RequestPermissionHandler.java index c8869638..76147c43 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/RequestPermissionHandler.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/RequestPermissionHandler.java @@ -13,8 +13,6 @@ import java.util.Map; public abstract class RequestPermissionHandler implements ActivityCompat.OnRequestPermissionsResultCallback { - public static int REQUEST_CODE_WRITE_EXTERNAL_STORAGE = 0; - private static Map> actionDictionary = new HashMap<>(); public static void checkAndRun(Activity activity, String permission, int requestCode, Runnable runnable) { 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 22a03159..07904515 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/WebViewActivity.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/WebViewActivity.java @@ -1,39 +1,23 @@ package com.pichillilorenzo.flutter_inappbrowser; -import android.Manifest; -import android.app.Activity; -import android.app.DownloadManager; -import android.content.Context; import android.content.Intent; -import android.content.pm.PackageManager; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; -import android.net.Uri; import android.os.Build; -import android.os.Environment; -import android.support.annotation.RequiresApi; -import android.support.v4.app.ActivityCompat; -import android.support.v4.content.ContextCompat; 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; import android.view.MenuItem; import android.view.View; import android.webkit.CookieManager; -import android.webkit.DownloadListener; -import android.webkit.URLUtil; import android.webkit.ValueCallback; import android.webkit.WebSettings; import android.webkit.WebView; -import android.widget.AutoCompleteTextView; -import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.SearchView; -import android.widget.Toast; import java.util.HashMap; import java.util.Map; @@ -64,7 +48,7 @@ public class WebViewActivity extends AppCompatActivity { options = new InAppBrowserOptions(); options.parse((HashMap) b.getSerializable("options")); - InAppBrowser.webViewActivity = this; + InAppBrowserFlutterPlugin.webViewActivity = this; actionBar = getSupportActionBar(); @@ -82,39 +66,39 @@ public class WebViewActivity extends AppCompatActivity { inAppBrowserWebViewClient = new InAppBrowserWebViewClient(this); webView.setWebViewClient(inAppBrowserWebViewClient); - final Activity activity = this; - - webView.setDownloadListener(new DownloadListener() { - @Override - public void onDownloadStart(final String url, final String userAgent, - final String contentDisposition, final String mimetype, - final long contentLength) { - - RequestPermissionHandler.checkAndRun(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE, RequestPermissionHandler.REQUEST_CODE_WRITE_EXTERNAL_STORAGE, new Runnable(){ - @Override - public void run(){ - DownloadManager.Request request = new DownloadManager.Request( - Uri.parse(url)); - - final String filename = URLUtil.guessFileName(url, contentDisposition, mimetype); - request.allowScanningByMediaScanner(); - request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); //Notify client once download is completed! - request.setVisibleInDownloadsUi(true); - request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename); - DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); - if (dm != null) { - dm.enqueue(request); - Toast.makeText(getApplicationContext(), "Downloading File: " + filename, //To notify the Client that the file is being downloaded - Toast.LENGTH_LONG).show(); - } - else { - Toast.makeText(getApplicationContext(), "Cannot Download File: " + filename, //To notify the Client that the file cannot be downloaded - Toast.LENGTH_LONG).show(); - } - } - }); - } - }); +// final Activity activity = this; +// +// webView.setDownloadListener(new DownloadListener() { +// @Override +// public void onDownloadStart(final String url, final String userAgent, +// final String contentDisposition, final String mimetype, +// final long contentLength) { +// +// RequestPermissionHandler.checkAndRun(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE, RequestPermissionHandler.REQUEST_CODE_WRITE_EXTERNAL_STORAGE, new Runnable(){ +// @Override +// public void run(){ +// DownloadManager.Request request = new DownloadManager.Request( +// Uri.parse(url)); +// +// final String filename = URLUtil.guessFileName(url, contentDisposition, mimetype); +// request.allowScanningByMediaScanner(); +// request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); //Notify client once download is completed! +// request.setVisibleInDownloadsUi(true); +// request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename); +// DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); +// if (dm != null) { +// dm.enqueue(request); +// Toast.makeText(getApplicationContext(), "Downloading File: " + filename, //To notify the Client that the file is being downloaded +// Toast.LENGTH_LONG).show(); +// } +// else { +// Toast.makeText(getApplicationContext(), "Cannot Download File: " + filename, //To notify the Client that the file cannot be downloaded +// Toast.LENGTH_LONG).show(); +// } +// } +// }); +// } +// }); WebSettings settings = webView.getSettings(); @@ -261,18 +245,6 @@ public class WebViewActivity extends AppCompatActivity { return super.onKeyDown(keyCode, event); } -// @TargetApi(Build.VERSION_CODES.KITKAT) -// void eval(MethodCall call, final MethodChannel.Result result) { -// String code = call.argument("code"); -// -// webView.evaluateJavascript(code, new ValueCallback() { -// @Override -// public void onReceiveValue(String value) { -// result.success(value); -// } -// }); -// } - public void close() { finish(); } diff --git a/example/ios/Podfile b/example/ios/Podfile index 3f8d0e6e..19e5027d 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -54,6 +54,7 @@ target 'Runner' do File.symlink(p[:path], symlink) pod p[:name], :path => File.join(symlink, 'ios') } + end post_install do |installer| diff --git a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..949b6789 --- /dev/null +++ b/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + BuildSystemType + Original + + diff --git a/example/lib/main.dart b/example/lib/main.dart index bed6360e..b151151e 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -11,9 +11,24 @@ class MyInAppBrowser extends InAppBrowser { } @override - void onLoadStop(String url) { + void onLoadStop(String url) async { super.onLoadStop(url); print("\n\nStopped $url\n\n"); + print(await this.injectScriptCode("document.body.innerHTML")); + print(await this.injectScriptCode("3")); + print(await this.injectScriptCode(""" + function asd (a,b) { + return a+b; + }; + asd(3,5); + """)); + print(await this.injectScriptCode(""" + ["3",56,"sdf"]; + """)); + print(await this.injectScriptCode(""" + var x = {"as":4, "dfdfg": 6}; + x; + """)); /*this.injectScriptFile("https://code.jquery.com/jquery-3.3.1.min.js"); this.injectScriptCode(""" \$( "body" ).html( "Next Step..." ) @@ -68,7 +83,7 @@ class _MyAppState extends State { child: new RaisedButton(onPressed: () { inAppBrowser.open("https://flutter.io/", options: { //"toolbarTopFixedTitle": "Fixed title", - "hideUrlBar": true, + //"hideUrlBar": true, //"toolbarTop": false, //"toolbarBottom": false }); diff --git a/flutter_inappbrowser.iml b/flutter_inappbrowser.iml index c5627b49..27accffb 100644 --- a/flutter_inappbrowser.iml +++ b/flutter_inappbrowser.iml @@ -14,6 +14,7 @@ + diff --git a/ios/Classes/InAppBrowser.h b/ios/Classes/InAppBrowserFlutterPlugin.h similarity index 93% rename from ios/Classes/InAppBrowser.h rename to ios/Classes/InAppBrowserFlutterPlugin.h index af48a52e..7bb0e655 100644 --- a/ios/Classes/InAppBrowser.h +++ b/ios/Classes/InAppBrowserFlutterPlugin.h @@ -17,7 +17,7 @@ #import -@interface InAppBrowser : NSObject +@interface InAppBrowserFlutterPlugin : NSObject + (void)registerWithRegistrar:(nonnull NSObject *)registrar; @end diff --git a/ios/Classes/InAppBrowser.m b/ios/Classes/InAppBrowserFlutterPlugin.m similarity index 91% rename from ios/Classes/InAppBrowser.m rename to ios/Classes/InAppBrowserFlutterPlugin.m index 49418973..1b11d037 100644 --- a/ios/Classes/InAppBrowser.m +++ b/ios/Classes/InAppBrowserFlutterPlugin.m @@ -15,10 +15,10 @@ under the License. */ -#import "InAppBrowser.h" +#import "InAppBrowserFlutterPlugin.h" #import -@implementation InAppBrowser : NSObject +@implementation InAppBrowserFlutterPlugin : NSObject + (void)registerWithRegistrar:(NSObject*)registrar { [SwiftFlutterPlugin registerWithRegistrar:registrar]; } diff --git a/ios/Classes/InAppBrowserWebViewController.swift b/ios/Classes/InAppBrowserWebViewController.swift index c33e4162..65448fd8 100644 --- a/ios/Classes/InAppBrowserWebViewController.swift +++ b/ios/Classes/InAppBrowserWebViewController.swift @@ -433,6 +433,40 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio decisionHandler(.allow) } +// func webView(_ webView: WKWebView, +// decidePolicyFor navigationResponse: WKNavigationResponse, +// decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) { +// let mimeType = navigationResponse.response.mimeType +// if mimeType != nil && !mimeType!.starts(with: "text/") { +// download(url: webView.url) +// decisionHandler(.cancel) +// return +// } +// decisionHandler(.allow) +// } +// +// func download (url: URL?) { +// let filename = url?.lastPathComponent +// +// let destination: DownloadRequest.DownloadFileDestination = { _, _ in +// let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] +// let fileURL = documentsURL.appendingPathComponent(filename!) +// +// return (fileURL, [.removePreviousFile, .createIntermediateDirectories]) +// } +// +// Alamofire.download((url?.absoluteString)!, to: destination).downloadProgress { progress in +// print("Download Progress: \(progress.fractionCompleted)") +// }.response { response in +// if response.error == nil, let path = response.destinationURL?.path { +// UIAlertView(title: nil, message: "File saved to " + path, delegate: nil, cancelButtonTitle: nil).show() +// } +// else { +// UIAlertView(title: nil, message: "Cannot save " + filename!, delegate: nil, cancelButtonTitle: nil).show() +// } +// } +// } + func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) { // loading url, start spinner, update back/forward backButton.isEnabled = webView.canGoBack diff --git a/ios/Classes/SwiftFlutterPlugin.swift b/ios/Classes/SwiftFlutterPlugin.swift index 7a4788b9..8dcab9c0 100644 --- a/ios/Classes/SwiftFlutterPlugin.swift +++ b/ios/Classes/SwiftFlutterPlugin.swift @@ -88,22 +88,22 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin { result(true) break case "injectScriptCode": - self.injectScriptCode(arguments: arguments!) - result(true) + self.injectScriptCode(arguments: arguments!, result: result) break case "injectScriptFile": - self.injectScriptFile(arguments: arguments!) + self.injectScriptFile(arguments: arguments!, result: nil) result(true) break case "injectStyleCode": - self.injectStyleCode(arguments: arguments!) + self.injectStyleCode(arguments: arguments!, result: nil) result(true) break case "injectStyleFile": - self.injectStyleFile(arguments: arguments!) + self.injectStyleFile(arguments: arguments!, result: nil) result(true) break default: + result(FlutterMethodNotImplemented) break } } @@ -151,7 +151,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin { } else { print("url is empty") - result(false) + result(FlutterError(code: "InAppBrowserFlutterPlugin", message: "url is empty", details: nil)) } result(true) } @@ -166,7 +166,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin { } else { print("url is empty") - result(false) + result(FlutterError(code: "InAppBrowserFlutterPlugin", message: "url is empty", details: nil)) } result(true) } @@ -265,39 +265,54 @@ 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) { - //if jsWrapper != nil { + 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) + + webViewController?.webView?.evaluateJavaScript(jsToInject, completionHandler: {(value, error) in + if result == nil { + return + } + + 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)) + } + + }) } - //} - //else { - // webViewController?.webView?.evaluateJavaScript(source) - //} } - public func injectScriptCode(arguments: NSDictionary) { - let jsWrapper = "(function(){JSON.stringify([eval(%@)])})()" - injectDeferredObject(arguments["source"] as! String, withWrapper: jsWrapper) + public func injectScriptCode(arguments: NSDictionary, result: FlutterResult?) { + let jsWrapper = "(function(){return JSON.stringify(eval(%@));})();" + injectDeferredObject(arguments["source"] as! String, withWrapper: jsWrapper, result: result) } - public func injectScriptFile(arguments: NSDictionary) { - let jsWrapper = "(function(d) { var c = d.createElement('script'); c.src = %@; d.body.appendChild(c); })(document)" - injectDeferredObject(arguments["urlFile"] as! String, withWrapper: jsWrapper) + public func injectScriptFile(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) } - public func injectStyleCode(arguments: NSDictionary) { - let jsWrapper = "(function(d) { var c = d.createElement('style'); c.innerHTML = %@; d.body.appendChild(c); })(document)" - injectDeferredObject(arguments["source"] as! String, withWrapper: jsWrapper) + public func injectStyleCode(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) } - public func injectStyleFile(arguments: NSDictionary) { - 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) + public func injectStyleFile(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) } func webViewDidStartLoad(_ webView: WKWebView) { diff --git a/lib/flutter_inappbrowser.dart b/lib/flutter_inappbrowser.dart index 2413c31f..bc79d5b3 100644 --- a/lib/flutter_inappbrowser.dart +++ b/lib/flutter_inappbrowser.dart @@ -174,7 +174,7 @@ class InAppBrowser { } ///Injects JavaScript code into the [InAppBrowser] window. (Only available when the target is set to `_blank` or to `_self`) - Future injectScriptCode(String source) async { + Future injectScriptCode(String source) async { Map args = {}; args.putIfAbsent('source', () => source); return await _channel.invokeMethod('injectScriptCode', args); @@ -221,9 +221,4 @@ class InAppBrowser { } - /// - void onCustomScheme(String url) { - - } - } diff --git a/pubspec.yaml b/pubspec.yaml index 7145251a..c355e54e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -18,7 +18,7 @@ dependencies: flutter: plugin: androidPackage: com.pichillilorenzo.flutter_inappbrowser - pluginClass: InAppBrowser + pluginClass: InAppBrowserFlutterPlugin # To add assets to your plugin package, add an assets section, like this: # assets: