Commit 55242a35 authored by Lorenzo Pichilli's avatar Lorenzo Pichilli

updated management of Content Worlds, updated evaluateJavascript API

parent 54e027be
......@@ -166,7 +166,7 @@ public class ContentBlockerHandler {
@Override
public void run() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webView.evaluateJavascript(jsScript, (MethodChannel.Result) null);
webView.evaluateJavascript(jsScript, null);
} else {
webView.loadUrl("javascript:" + jsScript);
}
......
......@@ -16,6 +16,7 @@ import android.os.Message;
import android.print.PrintAttributes;
import android.print.PrintDocumentAdapter;
import android.print.PrintManager;
import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ActionMode;
......@@ -42,6 +43,7 @@ import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.webkit.WebViewCompat;
import androidx.webkit.WebViewFeature;
......@@ -56,14 +58,19 @@ import com.pichillilorenzo.flutter_inappwebview.R;
import com.pichillilorenzo.flutter_inappwebview.Shared;
import com.pichillilorenzo.flutter_inappwebview.Util;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import io.flutter.plugin.common.MethodChannel;
......@@ -106,8 +113,12 @@ final public class InAppWebView extends InputAwareWebView {
public Runnable checkContextMenuShouldBeClosedTask;
public int newCheckContextMenuShouldBeClosedTaskTask = 100; // ms
public Set<String> userScriptsContentWorlds = new HashSet<String>() {{
add("page");
}};
static final String pluginScriptsWrapperJS = "(function(){" +
" if (window." + JavaScriptBridgeInterface.name + "._pluginScriptsLoaded == null || !window." + JavaScriptBridgeInterface.name + "._pluginScriptsLoaded) {" +
" if (window." + JavaScriptBridgeInterface.name + " == null || window." + JavaScriptBridgeInterface.name + "._pluginScriptsLoaded == null || !window." + JavaScriptBridgeInterface.name + "._pluginScriptsLoaded) {" +
" $PLACEHOLDER_VALUE" +
" window." + JavaScriptBridgeInterface.name + "._pluginScriptsLoaded = true;" +
" }" +
......@@ -187,8 +198,8 @@ final public class InAppWebView extends InputAwareWebView {
" }" +
"})();";
static final String variableForOnLoadResourceJS = "window._flutter_inappwebview_useOnLoadResource";
static final String enableVariableForOnLoadResourceJS = variableForOnLoadResourceJS + " = $PLACEHOLDER_VALUE;";
static final String variableForOnLoadResourceJS = "_flutter_inappwebview_useOnLoadResource";
static final String enableVariableForOnLoadResourceJS = "window." + variableForOnLoadResourceJS + " = $PLACEHOLDER_VALUE;";
static final String resourceObserverJS = "(function() {" +
" var observer = new PerformanceObserver(function(list) {" +
......@@ -1169,7 +1180,9 @@ final public class InAppWebView extends InputAwareWebView {
String placeholderValue = newOptions.useShouldInterceptAjaxRequest ? "true" : "false";
String sourceJs = InAppWebView.enableVariableForShouldInterceptAjaxRequestJS.replace("$PLACEHOLDER_VALUE", placeholderValue);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
evaluateJavascript(sourceJs, (ValueCallback<String>) null);
for (String contentWorldName : userScriptsContentWorlds) {
evaluateJavascript(sourceJs, contentWorldName, null);
}
} else {
loadUrl("javascript:" + sourceJs);
}
......@@ -1179,7 +1192,9 @@ final public class InAppWebView extends InputAwareWebView {
String placeholderValue = newOptions.useShouldInterceptFetchRequest ? "true" : "false";
String sourceJs = InAppWebView.enableVariableForShouldInterceptFetchRequestsJS.replace("$PLACEHOLDER_VALUE", placeholderValue);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
evaluateJavascript(sourceJs, (ValueCallback<String>) null);
for (String contentWorldName : userScriptsContentWorlds) {
evaluateJavascript(sourceJs, contentWorldName, null);
}
} else {
loadUrl("javascript:" + sourceJs);
}
......@@ -1457,7 +1472,7 @@ final public class InAppWebView extends InputAwareWebView {
return (options != null) ? options.getRealOptions(this) : null;
}
public void injectDeferredObject(String source, String jsWrapper, final MethodChannel.Result result) {
public void injectDeferredObject(String source, @Nullable final String contentWorldName, String jsWrapper, final MethodChannel.Result result) {
String scriptToInject = source;
if (jsWrapper != null) {
org.json.JSONArray jsonEsc = new org.json.JSONArray();
......@@ -1472,8 +1487,26 @@ final public class InAppWebView extends InputAwareWebView {
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
loadUrl("javascript:" + finalScriptToInject);
loadUrl("javascript:" + finalScriptToInject.replaceAll("[\r\n]+", ""));
result.success("");
} else {
if (contentWorldName != null && !contentWorldName.equals("page")) {
String sourceToInject = finalScriptToInject;
if (!userScriptsContentWorlds.contains(contentWorldName)) {
userScriptsContentWorlds.add(contentWorldName);
// Add only the first time all the plugin scripts needed.
String jsPluginScripts = prepareAndWrapPluginUserScripts();
sourceToInject = jsPluginScripts + "\n" + sourceToInject;
}
sourceToInject = wrapSourceCodeInContentWorld(contentWorldName, sourceToInject);
evaluateJavascript(sourceToInject, new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
if (result == null)
return;
result.success(s);
}
});
} else {
evaluateJavascript(finalScriptToInject, new ValueCallback<String>() {
@Override
......@@ -1485,26 +1518,27 @@ final public class InAppWebView extends InputAwareWebView {
});
}
}
}
});
}
public void evaluateJavascript(String source, MethodChannel.Result result) {
injectDeferredObject(source, null, result);
public void evaluateJavascript(String source, String contentWorldName, MethodChannel.Result result) {
injectDeferredObject(source, contentWorldName, null, result);
}
public void injectJavascriptFileFromUrl(String urlFile) {
String jsWrapper = "(function(d) { var c = d.createElement('script'); c.src = %s; d.body.appendChild(c); })(document);";
injectDeferredObject(urlFile, jsWrapper, null);
injectDeferredObject(urlFile, null, jsWrapper, null);
}
public void injectCSSCode(String source) {
String jsWrapper = "(function(d) { var c = d.createElement('style'); c.innerHTML = %s; d.body.appendChild(c); })(document);";
injectDeferredObject(source, jsWrapper, null);
injectDeferredObject(source, null, jsWrapper, null);
}
public void injectCSSFileFromUrl(String urlFile) {
String 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(urlFile, null, jsWrapper, null);
}
public HashMap<String, Object> getCopyBackForwardList() {
......@@ -1999,6 +2033,10 @@ final public class InAppWebView extends InputAwareWebView {
}
public boolean addUserScript(Map<String, Object> userScript) {
String contentWorldName = (String) userScript.get("contentWorld");
if (contentWorldName != null && !userScriptsContentWorlds.contains(contentWorldName)) {
userScriptsContentWorlds.add(contentWorldName);
}
return userScripts.add(userScript);
}
......@@ -2010,6 +2048,52 @@ final public class InAppWebView extends InputAwareWebView {
userScripts.clear();
}
public void resetUserScriptsContentWorlds() {
userScriptsContentWorlds.clear();
userScriptsContentWorlds.add("page");
}
public String prepareAndWrapPluginUserScripts() {
String js = JavaScriptBridgeInterface.callHandlerScriptJS;
js += InAppWebView.consoleLogJS;
if (options.useShouldInterceptAjaxRequest) {
js += InAppWebView.interceptAjaxRequestsJS;
}
if (options.useShouldInterceptFetchRequest) {
js += InAppWebView.interceptFetchRequestsJS;
}
if (options.useOnLoadResource) {
js += InAppWebView.resourceObserverJS;
}
if (!options.useHybridComposition) {
js += InAppWebView.checkGlobalKeyDownEventToHideContextMenuJS;
}
js += InAppWebView.onWindowFocusEventJS;
js += InAppWebView.onWindowBlurEventJS;
js += InAppWebView.printJS;
String jsWrapped = InAppWebView.pluginScriptsWrapperJS
.replace("$PLACEHOLDER_VALUE", js);
return jsWrapped;
}
public String wrapSourceCodeInContentWorld(@Nullable String contentWorldName, String source) {
JSONObject sourceEncoded = new JSONObject();
try {
// encode the javascript source in order to escape special chars and quotes
sourceEncoded.put("source", source);
} catch (JSONException e) {
e.printStackTrace();
}
String sourceWrapped = contentWorldName == null || contentWorldName.equals("page") ? source :
InAppWebView.contentWorldWrapperJS.replace("$CONTENT_WORLD_NAME", contentWorldName)
.replace("$JSON_SOURCE_ENCODED", sourceEncoded.toString());
return sourceWrapped;
}
@Override
public void dispose() {
if (windowId != null && InAppWebViewChromeClient.windowWebViewMessages.containsKey(windowId)) {
......
......@@ -26,12 +26,8 @@ import androidx.annotation.RequiresApi;
import com.pichillilorenzo.flutter_inappwebview.CredentialDatabase.Credential;
import com.pichillilorenzo.flutter_inappwebview.CredentialDatabase.CredentialDatabase;
import com.pichillilorenzo.flutter_inappwebview.InAppBrowser.InAppBrowserActivity;
import com.pichillilorenzo.flutter_inappwebview.JavaScriptBridgeInterface;
import com.pichillilorenzo.flutter_inappwebview.Util;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayInputStream;
import java.net.MalformedURLException;
import java.net.URI;
......@@ -166,10 +162,10 @@ public class InAppWebViewClient extends WebViewClient {
private void loadCustomJavaScriptOnPageStarted(WebView view) {
InAppWebView webView = (InAppWebView) view;
String jsPluginScripts = preparePluginUserScripts(webView);
String jsPluginScriptsWrapped = webView.prepareAndWrapPluginUserScripts();
String jsUserScriptsAtDocumentStart = prepareUserScriptsAtDocumentStart(webView);
String js = wrapPluginAndUserScripts(jsPluginScripts, jsUserScriptsAtDocumentStart, null);
String js = wrapPluginAndUserScripts(jsPluginScriptsWrapped, jsUserScriptsAtDocumentStart, null);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webView.evaluateJavascript(js, (ValueCallback<String>) null);
......@@ -182,11 +178,11 @@ public class InAppWebViewClient extends WebViewClient {
InAppWebView webView = (InAppWebView) view;
// try to reload also custom scripts if they were not loaded during the onPageStarted event
String jsPluginScripts = preparePluginUserScripts(webView);
String jsPluginScriptsWrapped = webView.prepareAndWrapPluginUserScripts();
String jsUserScriptsAtDocumentStart = prepareUserScriptsAtDocumentStart(webView);
String jsUserScriptsAtDocumentEnd = prepareUserScriptsAtDocumentEnd(webView);
String js = wrapPluginAndUserScripts(jsPluginScripts, jsUserScriptsAtDocumentStart, jsUserScriptsAtDocumentEnd);
String js = wrapPluginAndUserScripts(jsPluginScriptsWrapped, jsUserScriptsAtDocumentStart, jsUserScriptsAtDocumentEnd);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webView.evaluateJavascript(js, (ValueCallback<String>) null);
......@@ -195,56 +191,24 @@ public class InAppWebViewClient extends WebViewClient {
}
}
private String preparePluginUserScripts(InAppWebView webView) {
String js = InAppWebView.consoleLogJS;
js += JavaScriptBridgeInterface.callHandlerScriptJS;
if (webView.options.useShouldInterceptAjaxRequest) {
js += InAppWebView.interceptAjaxRequestsJS;
}
if (webView.options.useShouldInterceptFetchRequest) {
js += InAppWebView.interceptFetchRequestsJS;
}
if (webView.options.useOnLoadResource) {
js += InAppWebView.resourceObserverJS;
}
if (!webView.options.useHybridComposition) {
js += InAppWebView.checkGlobalKeyDownEventToHideContextMenuJS;
}
js += InAppWebView.onWindowFocusEventJS;
js += InAppWebView.onWindowBlurEventJS;
js += InAppWebView.printJS;
return js;
}
private String prepareUserScriptsAtDocumentStart(InAppWebView webView) {
private String prepareUserScripts(InAppWebView webView, int atDocumentInjectionTime) {
StringBuilder js = new StringBuilder();
for (Map<String, Object> userScript : webView.userScripts) {
Integer injectionTime = (Integer) userScript.get("injectionTime");
if (injectionTime == null || injectionTime == 0) {
if ((injectionTime == null && atDocumentInjectionTime == 0) || (injectionTime != null && injectionTime == atDocumentInjectionTime)) {
String source = (String) userScript.get("source");
String contentWorldName = (String) userScript.get("contentWorld");
if (source != null) {
if (contentWorldName != null && !contentWorldName.equals("page")) {
String jsPluginScripts = preparePluginUserScripts(webView);
String jsPluginScripts = webView.prepareAndWrapPluginUserScripts();
source = jsPluginScripts + "\n" + source;
}
JSONObject sourceEncoded = new JSONObject();
try {
// encode the javascript source in order to escape special chars and quotes
sourceEncoded.put("source", source);
} catch (JSONException e) {
e.printStackTrace();
if (contentWorldName != null && !webView.userScriptsContentWorlds.contains(contentWorldName)) {
webView.userScriptsContentWorlds.add(contentWorldName);
}
String sourceWrapped = contentWorldName == null || contentWorldName.equals("page") ? source :
InAppWebView.contentWorldWrapperJS.replace("$CONTENT_WORLD_NAME", contentWorldName)
.replace("$CONTENT_WORLD_NAME", contentWorldName)
.replace("$JSON_SOURCE_ENCODED", sourceEncoded.toString());
if (contentWorldName != null && !contentWorldName.equals("page")) {
String sourceWrapped = webView.wrapSourceCodeInContentWorld(contentWorldName, source);
if (atDocumentInjectionTime == 0 && contentWorldName != null && !contentWorldName.equals("page")) {
// adds another wrapper because sometimes document.body is not ready and it is undefined, causing an error and not adding the iframe element.
sourceWrapped = InAppWebView.documentReadyWrapperJS.replace("$PLACEHOLDER_VALUE", sourceWrapped)
.replace("$PLACEHOLDER_VALUE", sourceWrapped);
......@@ -258,43 +222,15 @@ public class InAppWebViewClient extends WebViewClient {
return js.toString();
}
private String prepareUserScriptsAtDocumentEnd(InAppWebView webView) {
StringBuilder js = new StringBuilder();
for (Map<String, Object> userScript : webView.userScripts) {
Integer injectionTime = (Integer) userScript.get("injectionTime");
if (injectionTime != null && injectionTime == 1) {
String source = (String) userScript.get("source");
String contentWorldName = (String) userScript.get("contentWorld");
if (source != null) {
if (contentWorldName != null && !contentWorldName.equals("page")) {
String jsPluginScripts = preparePluginUserScripts(webView);
source = jsPluginScripts + "\n" + source;
}
JSONObject sourceEncoded = new JSONObject();
try {
// encode the javascript source in order to escape special chars and quotes
sourceEncoded.put("source", source);
} catch (JSONException e) {
e.printStackTrace();
}
String sourceWrapped = contentWorldName == null || contentWorldName.equals("page") ? source :
InAppWebView.contentWorldWrapperJS.replace("$CONTENT_WORLD_NAME", contentWorldName)
.replace("$CONTENT_WORLD_NAME", contentWorldName)
.replace("$JSON_SOURCE_ENCODED", sourceEncoded.toString());
js.append(sourceWrapped);
}
}
private String prepareUserScriptsAtDocumentStart(InAppWebView webView) {
return prepareUserScripts(webView, 0);
}
return js.toString();
private String prepareUserScriptsAtDocumentEnd(InAppWebView webView) {
return prepareUserScripts(webView, 1);
}
private String wrapPluginAndUserScripts(String jsPluginScripts, @Nullable String jsUserScriptsAtDocumentStart, @Nullable String jsUserScriptsAtDocumentEnd) {
String jsPluginScriptsWrapped = InAppWebView.pluginScriptsWrapperJS
.replace("$PLACEHOLDER_VALUE", jsPluginScripts);
private String wrapPluginAndUserScripts(String jsPluginScriptsWrapped, @Nullable String jsUserScriptsAtDocumentStart, @Nullable String jsUserScriptsAtDocumentEnd) {
String jsUserScriptsAtDocumentStartWrapped = jsUserScriptsAtDocumentStart == null || jsUserScriptsAtDocumentStart.isEmpty() ? "" :
InAppWebView.userScriptsAtDocumentStartWrapperJS.replace("$PLACEHOLDER_VALUE", jsUserScriptsAtDocumentStart);
String jsUserScriptsAtDocumentEndWrapped = jsUserScriptsAtDocumentEnd == null || jsUserScriptsAtDocumentEnd.isEmpty() ? "" :
......@@ -305,6 +241,7 @@ public class InAppWebViewClient extends WebViewClient {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
final InAppWebView webView = (InAppWebView) view;
webView.resetUserScriptsContentWorlds();
loadCustomJavaScriptOnPageStarted(webView);
......
......@@ -74,7 +74,8 @@ public class InAppWebViewMethodHandler implements MethodChannel.MethodCallHandle
case "evaluateJavascript":
if (webView != null) {
String source = (String) call.argument("source");
webView.evaluateJavascript(source, result);
String contentWorldName = (String) call.argument("contentWorld");
webView.evaluateJavascript(source, contentWorldName, result);
}
else {
result.success(null);
......
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"device_info","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":["device_info"]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/.pub-cache/git/plugins-16f3281b04b0db12e609352b1c9544901392e428/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.27/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1+1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.4/","dependencies":[]}],"android":[{"name":"device_info","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":["device_info"]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/.pub-cache/git/plugins-16f3281b04b0db12e609352b1c9544901392e428/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.27/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1+1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.4/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+8/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+2/","dependencies":[]},{"name":"url_launcher_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.0.4+3/","dependencies":[]},{"name":"url_launcher_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"device_info","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":["device_info"]},{"name":"integration_test","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2021-02-04 22:05:52.361400","version":"1.26.0-18.0.pre.90"}
\ No newline at end of file
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"device_info","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":["device_info"]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/.pub-cache/git/plugins-16f3281b04b0db12e609352b1c9544901392e428/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.27/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1+1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.4/","dependencies":[]}],"android":[{"name":"device_info","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":["device_info"]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/.pub-cache/git/plugins-16f3281b04b0db12e609352b1c9544901392e428/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.27/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1+1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.4/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+8/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+2/","dependencies":[]},{"name":"url_launcher_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.0.4+3/","dependencies":[]},{"name":"url_launcher_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"device_info","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":["device_info"]},{"name":"integration_test","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2021-02-06 02:03:14.260971","version":"1.26.0-18.0.pre.90"}
\ No newline at end of file
This diff is collapsed.
......@@ -30,15 +30,15 @@ class InAppWebViewMethodHandler: FlutterMethodCallDelegate {
result( (webView != nil) ? Int(webView!.estimatedProgress * 100) : nil )
break
case "loadUrl":
let url = (arguments!["url"] as? String)!
let headers = (arguments!["headers"] as? [String: String])!
let url = arguments!["url"] as! String
let headers = arguments!["headers"] as! [String: String]
webView?.loadUrl(url: URL(string: url)!, headers: headers)
result(true)
break
case "postUrl":
if webView != nil {
let url = (arguments!["url"] as? String)!
let postData = (arguments!["postData"] as? FlutterStandardTypedData)!
let url = arguments!["url"] as! String
let postData = arguments!["postData"] as! FlutterStandardTypedData
webView!.postUrl(url: URL(string: url)!, postData: postData.data, completionHandler: { () -> Void in
result(true)
})
......@@ -48,16 +48,16 @@ class InAppWebViewMethodHandler: FlutterMethodCallDelegate {
}
break
case "loadData":
let data = (arguments!["data"] as? String)!
let mimeType = (arguments!["mimeType"] as? String)!
let encoding = (arguments!["encoding"] as? String)!
let baseUrl = (arguments!["baseUrl"] as? String)!
let data = arguments!["data"] as! String
let mimeType = arguments!["mimeType"] as! String
let encoding = arguments!["encoding"] as! String
let baseUrl = arguments!["baseUrl"] as! String
webView?.loadData(data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl)
result(true)
break
case "loadFile":
let url = (arguments!["url"] as? String)!
let headers = (arguments!["headers"] as? [String: String])!
let url = arguments!["url"] as! String
let headers = arguments!["headers"] as! [String: String]
do {
try webView?.loadFile(url: url, headers: headers)
......@@ -70,25 +70,26 @@ class InAppWebViewMethodHandler: FlutterMethodCallDelegate {
break
case "evaluateJavascript":
if webView != nil {
let source = (arguments!["source"] as? String)!
webView!.evaluateJavascript(source: source, result: result)
let source = arguments!["source"] as! String
let contentWorldName = arguments!["contentWorld"] as? String
webView!.evaluateJavascript(source: source, contentWorldName: contentWorldName, result: result)
}
else {
result(nil)
}
break
case "injectJavascriptFileFromUrl":
let urlFile = (arguments!["urlFile"] as? String)!
let urlFile = arguments!["urlFile"] as! String
webView?.injectJavascriptFileFromUrl(urlFile: urlFile)
result(true)
break
case "injectCSSCode":
let source = (arguments!["source"] as? String)!
let source = arguments!["source"] as! String
webView?.injectCSSCode(source: source)
result(true)
break
case "injectCSSFileFromUrl":
let urlFile = (arguments!["urlFile"] as? String)!
let urlFile = arguments!["urlFile"] as! String
webView?.injectCSSFileFromUrl(urlFile: urlFile)
result(true)
break
......@@ -111,12 +112,12 @@ class InAppWebViewMethodHandler: FlutterMethodCallDelegate {
result(webView?.canGoForward ?? false)
break
case "goBackOrForward":
let steps = (arguments!["steps"] as? Int)!
let steps = arguments!["steps"] as! Int
webView?.goBackOrForward(steps: steps)
result(true)
break
case "canGoBackOrForward":
let steps = (arguments!["steps"] as? Int)!
let steps = arguments!["steps"] as! Int
result(webView?.canGoBackOrForward(steps: steps) ?? false)
break
case "stopLoading":
......
......@@ -1351,7 +1351,14 @@ class InAppWebViewController {
await _channel.invokeMethod('stopLoading', args);
}
///Evaluates JavaScript code into the WebView and returns the result of the evaluation.
///Evaluates JavaScript [source] code into the WebView and returns the result of the evaluation.
///
///[contentWorld], on iOS, it represents the namespace in which to evaluate the JavaScript [source] code.
///Instead, on Android, it will run the [source] code into an iframe.
///This parameter doesn’t apply to changes you make to the underlying web content, such as the document’s DOM structure.
///Those changes remain visible to all scripts, regardless of which content world you specify.
///For more information about content worlds, see [ContentWorld].
///Available on iOS 14.0+.
///
///**NOTE**: This method shouldn't be called in the [WebView.onWebViewCreated] or [WebView.onLoadStart] events,
///because, in these events, the [WebView] is not ready to handle it yet.
......@@ -1360,10 +1367,13 @@ class InAppWebViewController {
///
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#evaluateJavascript(java.lang.String,%20android.webkit.ValueCallback%3Cjava.lang.String%3E)
///
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1415017-evaluatejavascript
Future<dynamic> evaluateJavascript({required String source}) async {
///**Official iOS API**:
///- https://developer.apple.com/documentation/webkit/wkwebview/1415017-evaluatejavascript
///- https://developer.apple.com/documentation/webkit/wkwebview/3656442-evaluatejavascript
Future<dynamic> evaluateJavascript({required String source, ContentWorld? contentWorld}) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('source', () => source);
args.putIfAbsent('contentWorld', () => contentWorld?.name);
var data = await _channel.invokeMethod('evaluateJavascript', args);
if (data != null && defaultTargetPlatform == TargetPlatform.android) data = json.decode(data);
return data;
......
......@@ -4599,12 +4599,15 @@ class UserScript {
///Class that represents an object that defines a scope of execution for JavaScript code, and which you use to prevent conflicts between different scripts.
///
///**NOTE for iOS 14.0+**: this class represents the native [WKContentWorld](https://developer.apple.com/documentation/webkit/wkcontentworld) class.
///**NOTE for iOS**: available on iOS 14.0+. This class represents the native [WKContentWorld](https://developer.apple.com/documentation/webkit/wkcontentworld) class.
///
///**NOTE for Android**: it will create and append an `<iframe>` HTML element with `id` equals to `flutter_inappwebview_[name]` to the webpage's content that contains only the scripts
///in order to define a new scope of execution for JavaScript code. Unfortunately, there isn't any other way to do it.
///For any [ContentWorld], except [ContentWorld.page], if you need to access to the `window` or `document` global Object,
///you need to use `window.top` and `window.top.document` because the code runs inside an `<iframe>`.
///**NOTE for Android**: it will create and append an `<iframe>` HTML element with `id` equals to `flutter_inappwebview_[name]`
///to the webpage's content that contains only the inline `<script>` HTML elements in order to define a new scope of execution for JavaScript code.
///Unfortunately, there isn't any other way to do it.
///There are some limitations:
///- for any [ContentWorld], except [ContentWorld.page] (that is the webpage itself), if you need to access to the `window` or `document` global Object,
///you need to use `window.top` and `window.top.document` because the code runs inside an `<iframe>`;
///- also, the execution of the inline `<script>` could be blocked by the `Content-Security-Policy` header.
class ContentWorld {
///The name of a custom content world.
final String name;
......
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