Commit 18919576 authored by Lorenzo Pichilli's avatar Lorenzo Pichilli

Added shouldInterceptAjaxRequest, onAjaxReadyStateChange, onAjaxProgressEvent...

Added shouldInterceptAjaxRequest, onAjaxReadyStateChange, onAjaxProgressEvent and shouldInterceptFetchRequest events, added useShouldInterceptAjaxRequest and useShouldInterceptFetchRequest webview options, updated node.js server test, added injectJavascriptFileFromAsset and injectCSSFileFromAsset methods, renamed some methods
parent 2811fce4
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="example/lib/main.dart" type="FlutterRunConfigurationType" factoryName="Flutter" singleton="false"> <configuration default="false" name="example/lib/main.dart" type="FlutterRunConfigurationType" factoryName="Flutter" singleton="false">
<option name="additionalArgs" value="--debug" />
<option name="filePath" value="$PROJECT_DIR$/example/lib/main.dart" /> <option name="filePath" value="$PROJECT_DIR$/example/lib/main.dart" />
<method v="2" /> <method v="2" />
</configuration> </configuration>
......
This diff is collapsed.
...@@ -26,7 +26,8 @@ ...@@ -26,7 +26,8 @@
- Added `HttpAuthCredentialDatabase` class - Added `HttpAuthCredentialDatabase` class
- Added `onReceivedServerTrustAuthRequest` and `onReceivedClientCertRequest` events to manage SSL requests - Added `onReceivedServerTrustAuthRequest` and `onReceivedClientCertRequest` events to manage SSL requests
- Added `onFindResultReceived` event, `findAllAsync`, `findNext` and `clearMatches` methods - Added `onFindResultReceived` event, `findAllAsync`, `findNext` and `clearMatches` methods
- Added `getHtml` method - Added `getHtml`, `injectJavascriptFileFromAsset` and `injectCSSFileFromAsset` methods
- Added `shouldInterceptAjaxRequest`, `onAjaxReadyStateChange`, `onAjaxProgressEvent` and `shouldInterceptFetchRequest` events with `useShouldInterceptAjaxRequest` and `useShouldInterceptFetchRequest` webview options
- Fun: added `getTRexRunnerHtml` and `getTRexRunnerCss` methods to get html (with javascript) and css to recreate the Chromium's t-rex runner game - Fun: added `getTRexRunnerHtml` and `getTRexRunnerCss` methods to get html (with javascript) and css to recreate the Chromium's t-rex runner game
### BREAKING CHANGES ### BREAKING CHANGES
...@@ -37,6 +38,10 @@ ...@@ -37,6 +38,10 @@
- Updated `CookieManager` class - Updated `CookieManager` class
- WebView options are now available with the new corresponding classes: `InAppWebViewOptions`, `AndroidInAppWebViewOptions`, `iOSInAppWebViewOptions`, `InAppBrowserOptions`, `AndroidInAppBrowserOptions`, `iOSInAppBrowserOptions`, `AndroidChromeCustomTabsOptions` and `iOSSafariOptions` - WebView options are now available with the new corresponding classes: `InAppWebViewOptions`, `AndroidInAppWebViewOptions`, `iOSInAppWebViewOptions`, `InAppBrowserOptions`, `AndroidInAppBrowserOptions`, `iOSInAppBrowserOptions`, `AndroidChromeCustomTabsOptions` and `iOSSafariOptions`
- Renamed `getFavicon` to `getFavicons`, now it returns a list of all favicons (`List<Favicon>`) found - Renamed `getFavicon` to `getFavicons`, now it returns a list of all favicons (`List<Favicon>`) found
- Renamed `injectScriptFile` to `injectJavascriptFileFromUrl`
- Renamed `injectScriptCode` to `evaluateJavascript`
- Renamed `injectStyleCode` to `injectCSSCode`
- Renamed `injectStyleFile` to `injectCSSFileFromUrl`
## 1.2.1 ## 1.2.1
......
...@@ -21,6 +21,7 @@ import java.util.concurrent.CopyOnWriteArrayList; ...@@ -21,6 +21,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import io.flutter.plugin.common.MethodChannel;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
...@@ -145,7 +146,7 @@ public class ContentBlockerHandler { ...@@ -145,7 +146,7 @@ public class ContentBlockerHandler {
@Override @Override
public void run() { public void run() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webView.evaluateJavascript(jsScript, null); webView.evaluateJavascript(jsScript, (MethodChannel.Result) null);
} else { } else {
webView.loadUrl("javascript:" + jsScript); webView.loadUrl("javascript:" + jsScript);
} }
......
package com.pichillilorenzo.flutter_inappbrowser; package com.pichillilorenzo.flutter_inappbrowser;
import android.Manifest;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager;
import android.os.Build; import android.os.Build;
import android.os.Handler;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.webkit.WebChromeClient; import android.webkit.WebChromeClient;
...@@ -15,21 +13,20 @@ import android.webkit.WebViewClient; ...@@ -15,21 +13,20 @@ import android.webkit.WebViewClient;
import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.DisplayListenerProxy; import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.DisplayListenerProxy;
import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.InAppWebView; import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.InAppWebView;
import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.InAppWebViewOptions; import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.InAppWebViewOptions;
import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.InputAwareWebView;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
import static io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import static io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar; import io.flutter.plugin.common.PluginRegistry.Registrar;
import io.flutter.plugin.platform.PlatformView; import io.flutter.plugin.platform.PlatformView;
import static io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import static io.flutter.plugin.common.MethodChannel.Result;
public class FlutterWebView implements PlatformView, MethodCallHandler { public class FlutterWebView implements PlatformView, MethodCallHandler {
static final String LOG_TAG = "FlutterWebView"; static final String LOG_TAG = "FlutterWebView";
...@@ -135,33 +132,33 @@ public class FlutterWebView implements PlatformView, MethodCallHandler { ...@@ -135,33 +132,33 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
else else
result.success(false); result.success(false);
break; break;
case "injectScriptCode": case "evaluateJavascript":
if (webView != null) { if (webView != null) {
String source = (String) call.argument("source"); String source = (String) call.argument("source");
webView.injectScriptCode(source, result); webView.evaluateJavascript(source, result);
} }
else { else {
result.success(""); result.success("");
} }
break; break;
case "injectScriptFile": case "injectJavascriptFileFromUrl":
if (webView != null) { if (webView != null) {
String urlFile = (String) call.argument("urlFile"); String urlFile = (String) call.argument("urlFile");
webView.injectScriptFile(urlFile); webView.injectJavascriptFileFromUrl(urlFile);
} }
result.success(true); result.success(true);
break; break;
case "injectStyleCode": case "injectCSSCode":
if (webView != null) { if (webView != null) {
String source = (String) call.argument("source"); String source = (String) call.argument("source");
webView.injectStyleCode(source); webView.injectCSSCode(source);
} }
result.success(true); result.success(true);
break; break;
case "injectStyleFile": case "injectCSSFileFromUrl":
if (webView != null) { if (webView != null) {
String urlFile = (String) call.argument("urlFile"); String urlFile = (String) call.argument("urlFile");
webView.injectStyleFile(urlFile); webView.injectCSSFileFromUrl(urlFile);
} }
result.success(true); result.success(true);
break; break;
...@@ -312,13 +309,13 @@ public class FlutterWebView implements PlatformView, MethodCallHandler { ...@@ -312,13 +309,13 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
@Override @Override
public void onInputConnectionLocked() { public void onInputConnectionLocked() {
if (webView.inAppBrowserActivity == null) if (webView != null && webView.inAppBrowserActivity == null)
webView.lockInputConnection(); webView.lockInputConnection();
} }
@Override @Override
public void onInputConnectionUnlocked() { public void onInputConnectionUnlocked() {
if (webView.inAppBrowserActivity == null) if (webView != null && webView.inAppBrowserActivity == null)
webView.unlockInputConnection(); webView.unlockInputConnection();
} }
......
...@@ -192,23 +192,23 @@ public class InAppBrowser implements MethodChannel.MethodCallHandler { ...@@ -192,23 +192,23 @@ public class InAppBrowser implements MethodChannel.MethodCallHandler {
case "close": case "close":
close(activity, uuid, result); close(activity, uuid, result);
break; break;
case "injectScriptCode": case "evaluateJavascript":
source = (String) call.argument("source"); source = (String) call.argument("source");
injectScriptCode(uuid, source, result); evaluateJavascript(uuid, source, result);
break; break;
case "injectScriptFile": case "injectJavascriptFileFromUrl":
urlFile = (String) call.argument("urlFile"); urlFile = (String) call.argument("urlFile");
injectScriptFile(uuid, urlFile); injectJavascriptFileFromUrl(uuid, urlFile);
result.success(true); result.success(true);
break; break;
case "injectStyleCode": case "injectCSSCode":
source = (String) call.argument("source"); source = (String) call.argument("source");
injectStyleCode(uuid, source); injectCSSCode(uuid, source);
result.success(true); result.success(true);
break; break;
case "injectStyleFile": case "injectCSSFileFromUrl":
urlFile = (String) call.argument("urlFile"); urlFile = (String) call.argument("urlFile");
injectStyleFile(uuid, urlFile); injectCSSFileFromUrl(uuid, urlFile);
result.success(true); result.success(true);
break; break;
case "show": case "show":
...@@ -314,33 +314,33 @@ public class InAppBrowser implements MethodChannel.MethodCallHandler { ...@@ -314,33 +314,33 @@ public class InAppBrowser implements MethodChannel.MethodCallHandler {
} }
private void injectScriptCode(String uuid, String source, final Result result) { private void evaluateJavascript(String uuid, String source, final Result result) {
final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid); final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null) { if (inAppBrowserActivity != null) {
inAppBrowserActivity.injectScriptCode(source, result); inAppBrowserActivity.evaluateJavascript(source, result);
} else { } else {
Log.d(LOG_TAG, "webView is null"); Log.d(LOG_TAG, "webView is null");
} }
} }
private void injectScriptFile(String uuid, String urlFile) { private void injectJavascriptFileFromUrl(String uuid, String urlFile) {
final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid); final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null) { if (inAppBrowserActivity != null) {
inAppBrowserActivity.injectScriptFile(urlFile); inAppBrowserActivity.injectJavascriptFileFromUrl(urlFile);
} }
} }
private void injectStyleCode(String uuid, String source) { private void injectCSSCode(String uuid, String source) {
final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid); final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null) { if (inAppBrowserActivity != null) {
inAppBrowserActivity.injectStyleCode(source); inAppBrowserActivity.injectCSSCode(source);
} }
} }
private void injectStyleFile(String uuid, String urlFile) { private void injectCSSFileFromUrl(String uuid, String urlFile) {
final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid); final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null) { if (inAppBrowserActivity != null) {
inAppBrowserActivity.injectStyleFile(urlFile); inAppBrowserActivity.injectCSSFileFromUrl(urlFile);
} }
} }
......
...@@ -434,26 +434,26 @@ public class InAppBrowserActivity extends AppCompatActivity { ...@@ -434,26 +434,26 @@ public class InAppBrowserActivity extends AppCompatActivity {
return optionsMap; return optionsMap;
} }
public void injectScriptCode(String source, MethodChannel.Result result) { public void evaluateJavascript(String source, MethodChannel.Result result) {
if (webView != null) if (webView != null)
webView.injectScriptCode(source, result); webView.evaluateJavascript(source, result);
else else
result.success(""); result.success("");
} }
public void injectScriptFile(String urlFile) { public void injectJavascriptFileFromUrl(String urlFile) {
if (webView != null) if (webView != null)
webView.injectScriptFile(urlFile); webView.injectJavascriptFileFromUrl(urlFile);
} }
public void injectStyleCode(String source) { public void injectCSSCode(String source) {
if (webView != null) if (webView != null)
webView.injectStyleCode(source); webView.injectCSSCode(source);
} }
public void injectStyleFile(String urlFile) { public void injectCSSFileFromUrl(String urlFile) {
if (webView != null) if (webView != null)
webView.injectStyleFile(urlFile); webView.injectCSSFileFromUrl(urlFile);
} }
public HashMap<String, Object> getCopyBackForwardList() { public HashMap<String, Object> getCopyBackForwardList() {
......
...@@ -7,7 +7,6 @@ import android.net.http.SslCertificate; ...@@ -7,7 +7,6 @@ import android.net.http.SslCertificate;
import android.net.http.SslError; import android.net.http.SslError;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.util.Base64;
import android.util.Log; import android.util.Log;
import android.webkit.ClientCertRequest; import android.webkit.ClientCertRequest;
import android.webkit.CookieManager; import android.webkit.CookieManager;
...@@ -15,7 +14,6 @@ import android.webkit.CookieSyncManager; ...@@ -15,7 +14,6 @@ import android.webkit.CookieSyncManager;
import android.webkit.HttpAuthHandler; import android.webkit.HttpAuthHandler;
import android.webkit.SafeBrowsingResponse; import android.webkit.SafeBrowsingResponse;
import android.webkit.SslErrorHandler; import android.webkit.SslErrorHandler;
import android.webkit.ValueCallback;
import android.webkit.WebResourceRequest; import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse; import android.webkit.WebResourceResponse;
import android.webkit.WebView; import android.webkit.WebView;
...@@ -61,60 +59,7 @@ public class InAppWebViewClient extends WebViewClient { ...@@ -61,60 +59,7 @@ public class InAppWebViewClient extends WebViewClient {
this.inAppBrowserActivity = (InAppBrowserActivity) obj; this.inAppBrowserActivity = (InAppBrowserActivity) obj;
else if (obj instanceof FlutterWebView) else if (obj instanceof FlutterWebView)
this.flutterWebView = (FlutterWebView) obj; this.flutterWebView = (FlutterWebView) obj;
prepareStatusCodeMapping();
} }
private void prepareStatusCodeMapping() {
statusCodeMapping.put(100, "Continue");
statusCodeMapping.put(101, "Switching Protocols");
statusCodeMapping.put(200, "OK");
statusCodeMapping.put(201, "Created");
statusCodeMapping.put(202, "Accepted");
statusCodeMapping.put(203, "Non-Authoritative Information");
statusCodeMapping.put(204, "No Content");
statusCodeMapping.put(205, "Reset Content");
statusCodeMapping.put(206, "Partial Content");
statusCodeMapping.put(300, "Multiple Choices");
statusCodeMapping.put(301, "Moved Permanently");
statusCodeMapping.put(302, "Found");
statusCodeMapping.put(303, "See Other");
statusCodeMapping.put(304, "Not Modified");
statusCodeMapping.put(307, "Temporary Redirect");
statusCodeMapping.put(308, "Permanent Redirect");
statusCodeMapping.put(400, "Bad Request");
statusCodeMapping.put(401, "Unauthorized");
statusCodeMapping.put(403, "Forbidden");
statusCodeMapping.put(404, "Not Found");
statusCodeMapping.put(405, "Method Not Allowed");
statusCodeMapping.put(406, "Not Acceptable");
statusCodeMapping.put(407, "Proxy Authentication Required");
statusCodeMapping.put(408, "Request Timeout");
statusCodeMapping.put(409, "Conflict");
statusCodeMapping.put(410, "Gone");
statusCodeMapping.put(411, "Length Required");
statusCodeMapping.put(412, "Precondition Failed");
statusCodeMapping.put(413, "Payload Too Large");
statusCodeMapping.put(414, "URI Too Long");
statusCodeMapping.put(415, "Unsupported Media Type");
statusCodeMapping.put(416, "Range Not Satisfiable");
statusCodeMapping.put(417, "Expectation Failed");
statusCodeMapping.put(418, "I'm a teapot");
statusCodeMapping.put(422, "Unprocessable Entity");
statusCodeMapping.put(425, "Too Early");
statusCodeMapping.put(426, "Upgrade Required");
statusCodeMapping.put(428, "Precondition Required");
statusCodeMapping.put(429, "Too Many Requests");
statusCodeMapping.put(431, "Request Header Fields Too Large");
statusCodeMapping.put(451, "Unavailable For Legal Reasons");
statusCodeMapping.put(500, "Internal Server Error");
statusCodeMapping.put(501, "Not Implemented");
statusCodeMapping.put(502, "Bad Gateway");
statusCodeMapping.put(503, "Service Unavailable");
statusCodeMapping.put(504, "Gateway Timeout");
statusCodeMapping.put(505, "HTTP Version Not Supported");
statusCodeMapping.put(511, "Network Authentication Required");
}
@Override @Override
public boolean shouldOverrideUrlLoading(WebView webView, String url) { public boolean shouldOverrideUrlLoading(WebView webView, String url) {
...@@ -183,21 +128,22 @@ public class InAppWebViewClient extends WebViewClient { ...@@ -183,21 +128,22 @@ public class InAppWebViewClient extends WebViewClient {
return super.shouldOverrideUrlLoading(webView, url); return super.shouldOverrideUrlLoading(webView, url);
} }
/*
* onPageStarted fires the LOAD_START_EVENT
*
* @param view
* @param url
* @param favicon
*/
@Override @Override
public void onPageStarted(WebView view, String url, Bitmap favicon) { public void onPageStarted(WebView view, String url, Bitmap favicon) {
InAppWebView webView = (InAppWebView) view; InAppWebView webView = (InAppWebView) view;
if (webView.options.useOnLoadResource) webView.loadUrl("javascript:" + InAppWebView.consoleLogJS.replaceAll("[\r\n]+", ""));
webView.loadUrl("javascript:" + webView.resourceObserverJS.replaceAll("[\r\n]+", "")); webView.loadUrl("javascript:" + JavaScriptBridgeInterface.flutterInAppBroserJSClass.replaceAll("[\r\n]+", ""));
if (webView.options.useShouldInterceptAjaxRequest) {
webView.loadUrl("javascript:" + InAppWebView.interceptAjaxRequestsJS.replaceAll("[\r\n]+", ""));
}
if (webView.options.useShouldInterceptFetchRequest) {
webView.loadUrl("javascript:" + InAppWebView.interceptFetchRequestsJS.replaceAll("[\r\n]+", ""));
}
if (webView.options.useOnLoadResource) {
webView.loadUrl("javascript:" + InAppWebView.resourceObserverJS.replaceAll("[\r\n]+", ""));
}
super.onPageStarted(view, url, favicon); super.onPageStarted(view, url, favicon);
...@@ -215,8 +161,8 @@ public class InAppWebViewClient extends WebViewClient { ...@@ -215,8 +161,8 @@ public class InAppWebViewClient extends WebViewClient {
} }
public void onPageFinished(final WebView view, String url) { public void onPageFinished(WebView view, String url) {
InAppWebView webView = (InAppWebView) view; final InAppWebView webView = (InAppWebView) view;
super.onPageFinished(view, url); super.onPageFinished(view, url);
...@@ -236,18 +182,9 @@ public class InAppWebViewClient extends WebViewClient { ...@@ -236,18 +182,9 @@ public class InAppWebViewClient extends WebViewClient {
view.requestFocus(); view.requestFocus();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
view.evaluateJavascript(InAppWebView.consoleLogJS, null); webView.evaluateJavascript(InAppWebView.platformReadyJS, (MethodChannel.Result) null);
view.evaluateJavascript(JavaScriptBridgeInterface.flutterInAppBroserJSClass, new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
view.evaluateJavascript(InAppWebView.platformReadyJS, null);
}
});
} else { } else {
view.loadUrl("javascript:" + InAppWebView.consoleLogJS); webView.loadUrl("javascript:" + InAppWebView.platformReadyJS.replaceAll("[\r\n]+", ""));
view.loadUrl("javascript:" + JavaScriptBridgeInterface.flutterInAppBroserJSClass);
view.loadUrl("javascript:" + InAppWebView.platformReadyJS);
} }
Map<String, Object> obj = new HashMap<>(); Map<String, Object> obj = new HashMap<>();
......
...@@ -29,6 +29,8 @@ public class InAppWebViewOptions extends Options { ...@@ -29,6 +29,8 @@ public class InAppWebViewOptions extends Options {
public List<String> resourceCustomSchemes = new ArrayList<>(); public List<String> resourceCustomSchemes = new ArrayList<>();
public List<Map<String, Map<String, Object>>> contentBlockers = new ArrayList<>(); public List<Map<String, Map<String, Object>>> contentBlockers = new ArrayList<>();
public Integer preferredContentMode = PreferredContentModeOptionType.RECOMMENDED.toValue(); public Integer preferredContentMode = PreferredContentModeOptionType.RECOMMENDED.toValue();
public Boolean useShouldInterceptAjaxRequest = false;
public Boolean useShouldInterceptFetchRequest = false;
public boolean clearSessionCache = false; public boolean clearSessionCache = false;
public boolean builtInZoomControls = false; public boolean builtInZoomControls = false;
......
...@@ -61,7 +61,7 @@ public class JavaScriptBridgeInterface { ...@@ -61,7 +61,7 @@ public class JavaScriptBridgeInterface {
return; return;
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webView.evaluateJavascript("window." + name + "[" + _callHandlerID + "](" + json + "); delete window." + name + "[" + _callHandlerID + "];", null); webView.evaluateJavascript("window." + name + "[" + _callHandlerID + "](" + json + "); delete window." + name + "[" + _callHandlerID + "];", (MethodChannel.Result) null);
} }
else { else {
webView.loadUrl("javascript:window." + name + "[" + _callHandlerID + "](" + json + "); delete window." + name + "[" + _callHandlerID + "];"); webView.loadUrl("javascript:window." + name + "[" + _callHandlerID + "](" + json + "); delete window." + name + "[" + _callHandlerID + "];");
...@@ -82,42 +82,6 @@ public class JavaScriptBridgeInterface { ...@@ -82,42 +82,6 @@ public class JavaScriptBridgeInterface {
}); });
} }
@JavascriptInterface
public void _resourceLoaded(String json) {
try {
JSONObject jsonObject = new JSONObject(json);
final Map<String, Object> obj = new HashMap<>();
if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
String initiatorType = jsonObject.getString("initiatorType");
String url = jsonObject.getString("name");
Double startTime = jsonObject.getDouble("startTime");
Double duration = jsonObject.getDouble("duration");
obj.put("initiatorType", initiatorType);
obj.put("url", url);
obj.put("startTime", startTime);
obj.put("duration", duration);
// java.lang.RuntimeException: Methods marked with @UiThread must be executed on the main thread.
// https://github.com/pichillilorenzo/flutter_inappbrowser/issues/98
final Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
getChannel().invokeMethod("onLoadResource", obj);
}
});
} catch (final JSONException e) {
Log.e(LOG_TAG, "Json parsing error: " + e.getMessage());
}
}
private MethodChannel getChannel() { private MethodChannel getChannel() {
return (inAppBrowserActivity != null) ? InAppBrowserFlutterPlugin.inAppBrowser.channel : flutterWebView.channel; return (inAppBrowserActivity != null) ? InAppBrowserFlutterPlugin.inAppBrowser.channel : flutterWebView.channel;
} }
......
...@@ -55,23 +55,43 @@ ...@@ -55,23 +55,43 @@
console.log("ready"); console.log("ready");
window.flutter_inappbrowser.callHandler('handlerFoo').then(function(result) { window.flutter_inappbrowser.callHandler('handlerFoo').then(function(result) {
console.log(result, typeof result); //console.log(result, typeof result);
console.log(JSON.stringify(result), result.bar); //console.log(JSON.stringify(result), result.bar);
}); });
window.flutter_inappbrowser.callHandler('handlerFooWithArgs', 1, true, ['bar', 5], {foo: 'baz'}).then(function(result) { window.flutter_inappbrowser.callHandler('handlerFooWithArgs', 1, true, ['bar', 5], {foo: 'baz'}).then(function(result) {
console.log(result, typeof result); //console.log(result, typeof result);
console.log(JSON.stringify(result)); //console.log(JSON.stringify(result));
}); });
}); });
$(document).ready(function() { $(document).ready(function() {
console.log("jQuery ready");
var xhttp = new XMLHttpRequest();
xhttp.addEventListener("load", function() {
console.log(this.responseText);
});
xhttp.open("POST", "http://192.168.1.20:8082/test-ajax-post");
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send("name=Lorenzo");
var xhttp2 = new XMLHttpRequest();
xhttp2.open("GET", "http://192.168.1.20:8082/test-download-file");
xhttp2.send();
fetch(new Request("http://192.168.1.20:8082/test-download-file")).then(function(response) {
console.log(response);
}).catch(function(error) {
console.error("ERROR: " + error);
});
/* /*
alert("Alert Popup"); alert("Alert Popup");
console.log(confirm("Press a button!")); console.log(confirm("Press a button!"));
console.log(prompt("Please enter your name", "Lorenzo")); console.log(prompt("Please enter your name", "Lorenzo"));
*/ */
console.log("jQuery ready");
/* /*
if ("geolocation" in navigator) { if ("geolocation" in navigator) {
console.log("Geolocation API enabled"); console.log("Geolocation API enabled");
......
...@@ -2,9 +2,10 @@ ...@@ -2,9 +2,10 @@
# This is a generated file; do not edit or check into version control. # This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/lorenzopichilli/flutter" export "FLUTTER_ROOT=/Users/lorenzopichilli/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappbrowser/example" export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappbrowser/example"
export "FLUTTER_TARGET=lib/main.dart" export "FLUTTER_TARGET=/Users/lorenzopichilli/Desktop/flutter_inappbrowser/example/lib/main.dart"
export "FLUTTER_BUILD_DIR=build" export "FLUTTER_BUILD_DIR=build"
export "SYMROOT=${SOURCE_ROOT}/../build/ios" export "SYMROOT=${SOURCE_ROOT}/../build/ios"
export "FLUTTER_FRAMEWORK_DIR=/Users/lorenzopichilli/flutter/bin/cache/artifacts/engine/ios" export "FLUTTER_FRAMEWORK_DIR=/Users/lorenzopichilli/flutter/bin/cache/artifacts/engine/ios"
export "FLUTTER_BUILD_NAME=1.0.0" export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1" export "FLUTTER_BUILD_NUMBER=1"
export "TRACK_WIDGET_CREATION=true"
...@@ -268,7 +268,6 @@ ...@@ -268,7 +268,6 @@
inputPaths = ( inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework", "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework",
"${BUILT_PRODUCTS_DIR}/WKWebViewWithURLProtocol/WKWebViewWithURLProtocol.framework",
"${BUILT_PRODUCTS_DIR}/flutter_downloader/flutter_downloader.framework", "${BUILT_PRODUCTS_DIR}/flutter_downloader/flutter_downloader.framework",
"${BUILT_PRODUCTS_DIR}/flutter_inappbrowser/flutter_inappbrowser.framework", "${BUILT_PRODUCTS_DIR}/flutter_inappbrowser/flutter_inappbrowser.framework",
"${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework", "${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework",
...@@ -276,7 +275,6 @@ ...@@ -276,7 +275,6 @@
name = "[CP] Embed Pods Frameworks"; name = "[CP] Embed Pods Frameworks";
outputPaths = ( outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WKWebViewWithURLProtocol.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_downloader.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_downloader.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_inappbrowser.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_inappbrowser.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework",
......
...@@ -93,11 +93,13 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> { ...@@ -93,11 +93,13 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
initialOptions: InAppWebViewWidgetOptions( initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions( inAppWebViewOptions: InAppWebViewOptions(
debuggingEnabled: true, debuggingEnabled: true,
//clearCache: true, clearCache: true,
useShouldOverrideUrlLoading: true, useShouldOverrideUrlLoading: true,
useOnTargetBlank: true, useOnTargetBlank: true,
//useOnLoadResource: true, useOnLoadResource: true,
useOnDownloadStart: true, useOnDownloadStart: true,
useShouldInterceptAjaxRequest: true,
useShouldInterceptFetchRequest: true,
//preferredContentMode: InAppWebViewUserPreferredContentMode.DESKTOP, //preferredContentMode: InAppWebViewUserPreferredContentMode.DESKTOP,
resourceCustomSchemes: ["my-special-custom-scheme"], resourceCustomSchemes: ["my-special-custom-scheme"],
contentBlockers: [ contentBlockers: [
...@@ -286,6 +288,29 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> { ...@@ -286,6 +288,29 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
onFindResultReceived: (InAppWebViewController controller, int activeMatchOrdinal, int numberOfMatches, bool isDoneCounting) async { onFindResultReceived: (InAppWebViewController controller, int activeMatchOrdinal, int numberOfMatches, bool isDoneCounting) async {
print("Current highlighted: $activeMatchOrdinal, Number of matches found: $numberOfMatches, find operation completed: $isDoneCounting"); print("Current highlighted: $activeMatchOrdinal, Number of matches found: $numberOfMatches, find operation completed: $isDoneCounting");
}, },
shouldInterceptAjaxRequest: (InAppWebViewController controller, AjaxRequest ajaxRequest) async {
print("AJAX REQUEST: ${ajaxRequest.method} - ${ajaxRequest.url}, DATA: ${ajaxRequest.data}");
// ajaxRequest.method = "GET";
// ajaxRequest.url = "http://192.168.1.20:8082/test-download-file";
// ajaxRequest.headers = {
// "Custom-Header": "Custom-Value"
// };
// return ajaxRequest;
return null;
},
onAjaxReadyStateChange: (InAppWebViewController controller, AjaxRequest ajaxRequest) async {
print("AJAX READY STATE CHANGE: ${ajaxRequest.method} - ${ajaxRequest.url}, ${ajaxRequest.status}, ${ajaxRequest.readyState}, ${ajaxRequest.responseType}, ${ajaxRequest.responseText}, ${ajaxRequest.responseHeaders}");
return null;
},
onAjaxProgressEvent: (InAppWebViewController controller, AjaxRequest ajaxRequest) async {
print("AJAX EVENT: ${ajaxRequest.method} - ${ajaxRequest.url}, ${ajaxRequest.event.type}, LOADED: ${ajaxRequest.event.loaded}, ${ajaxRequest.responseHeaders}");
return null;
},
shouldInterceptFetchRequest: (InAppWebViewController controller, FetchRequest fetchRequest) async {
print("FETCH REQUEST: ${fetchRequest.method} - ${fetchRequest.url}");
fetchRequest.action = FetchRequestAction.ABORT;
return fetchRequest;
},
), ),
), ),
), ),
......
...@@ -161,33 +161,33 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView { ...@@ -161,33 +161,33 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView {
result(false) result(false)
} }
break break
case "injectScriptCode": case "evaluateJavascript":
if webView != nil { if webView != nil {
let source = (arguments!["source"] as? String)! let source = (arguments!["source"] as? String)!
webView!.injectScriptCode(source: source, result: result) webView!.evaluateJavascript(source: source, result: result)
} }
else { else {
result("") result("")
} }
break break
case "injectScriptFile": case "injectJavascriptFileFromUrl":
if webView != nil { if webView != nil {
let urlFile = (arguments!["urlFile"] as? String)! let urlFile = (arguments!["urlFile"] as? String)!
webView!.injectScriptFile(urlFile: urlFile) webView!.injectJavascriptFileFromUrl(urlFile: urlFile)
} }
result(true) result(true)
break break
case "injectStyleCode": case "injectCSSCode":
if webView != nil { if webView != nil {
let source = (arguments!["source"] as? String)! let source = (arguments!["source"] as? String)!
webView!.injectStyleCode(source: source) webView!.injectCSSCode(source: source)
} }
result(true) result(true)
break break
case "injectStyleFile": case "injectCSSFileFromUrl":
if webView != nil { if webView != nil {
let urlFile = (arguments!["urlFile"] as? String)! let urlFile = (arguments!["urlFile"] as? String)!
webView!.injectStyleFile(urlFile: urlFile) webView!.injectCSSFileFromUrl(urlFile: urlFile)
} }
result(true) result(true)
break break
......
This diff is collapsed.
...@@ -26,6 +26,8 @@ public class InAppWebViewOptions: Options { ...@@ -26,6 +26,8 @@ public class InAppWebViewOptions: Options {
var resourceCustomSchemes: [String] = [] var resourceCustomSchemes: [String] = []
var contentBlockers: [[String: [String : Any]]] = [] var contentBlockers: [[String: [String : Any]]] = []
var minimumFontSize = 0; var minimumFontSize = 0;
var useShouldInterceptAjaxRequest = false
var useShouldInterceptFetchRequest = false
var disallowOverScroll = false var disallowOverScroll = false
var enableViewportScale = false var enableViewportScale = false
......
...@@ -195,19 +195,19 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin { ...@@ -195,19 +195,19 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
result(false) result(false)
} }
break break
case "injectScriptCode": case "evaluateJavascript":
self.injectScriptCode(uuid: uuid, arguments: arguments!, result: result) self.evaluateJavascript(uuid: uuid, arguments: arguments!, result: result)
break break
case "injectScriptFile": case "injectJavascriptFileFromUrl":
self.injectScriptFile(uuid: uuid, arguments: arguments!) self.injectJavascriptFileFromUrl(uuid: uuid, arguments: arguments!)
result(true) result(true)
break break
case "injectStyleCode": case "injectCSSCode":
self.injectStyleCode(uuid: uuid, arguments: arguments!) self.injectCSSCode(uuid: uuid, arguments: arguments!)
result(true) result(true)
break break
case "injectStyleFile": case "injectCSSFileFromUrl":
self.injectStyleFile(uuid: uuid, arguments: arguments!) self.injectCSSFileFromUrl(uuid: uuid, arguments: arguments!)
result(true) result(true)
break break
case "takeScreenshot": case "takeScreenshot":
...@@ -665,30 +665,30 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin { ...@@ -665,30 +665,30 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
} }
} }
public func injectScriptCode(uuid: String, arguments: NSDictionary, result: @escaping FlutterResult) { public func evaluateJavascript(uuid: String, arguments: NSDictionary, result: @escaping FlutterResult) {
if let webViewController = self.webViewControllers[uuid] { if let webViewController = self.webViewControllers[uuid] {
webViewController!.webView.injectScriptCode(source: arguments["source"] as! String, result: result) webViewController!.webView.evaluateJavascript(source: arguments["source"] as! String, result: result)
} }
else { else {
result(FlutterError(code: "InAppBrowserFlutterPlugin", message: "webView is null", details: nil)) result(FlutterError(code: "InAppBrowserFlutterPlugin", message: "webView is null", details: nil))
} }
} }
public func injectScriptFile(uuid: String, arguments: NSDictionary) { public func injectJavascriptFileFromUrl(uuid: String, arguments: NSDictionary) {
if let webViewController = self.webViewControllers[uuid] { if let webViewController = self.webViewControllers[uuid] {
webViewController!.webView.injectScriptFile(urlFile: arguments["urlFile"] as! String) webViewController!.webView.injectJavascriptFileFromUrl(urlFile: arguments["urlFile"] as! String)
} }
} }
public func injectStyleCode(uuid: String, arguments: NSDictionary) { public func injectCSSCode(uuid: String, arguments: NSDictionary) {
if let webViewController = self.webViewControllers[uuid] { if let webViewController = self.webViewControllers[uuid] {
webViewController!.webView.injectStyleCode(source: arguments["source"] as! String) webViewController!.webView.injectCSSCode(source: arguments["source"] as! String)
} }
} }
public func injectStyleFile(uuid: String, arguments: NSDictionary) { public func injectCSSFileFromUrl(uuid: String, arguments: NSDictionary) {
if let webViewController = self.webViewControllers[uuid] { if let webViewController = self.webViewControllers[uuid] {
webViewController!.webView.injectStyleFile(urlFile: arguments["urlFile"] as! String) webViewController!.webView.injectCSSFileFromUrl(urlFile: arguments["urlFile"] as! String)
} }
} }
......
...@@ -19,5 +19,4 @@ A new Flutter plugin. ...@@ -19,5 +19,4 @@ A new Flutter plugin.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' } s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }
s.swift_version = '5.0' s.swift_version = '5.0'
s.dependency "WKWebViewWithURLProtocol"
end end
This diff is collapsed.
...@@ -58,6 +58,27 @@ class LoadedResource { ...@@ -58,6 +58,27 @@ class LoadedResource {
} }
///Initial [data] as a content for an [InAppWebView] instance, using [baseUrl] as the base URL for it.
///The [mimeType] property specifies the format of the data.
///The [encoding] property specifies the encoding of the data.
class InAppWebViewInitialData {
String data;
String mimeType;
String encoding;
String baseUrl;
InAppWebViewInitialData(this.data, {this.mimeType = "text/html", this.encoding = "utf8", this.baseUrl = "about:blank"});
Map<String, String> toMap() {
return {
"data": data,
"mimeType": mimeType,
"encoding": encoding,
"baseUrl": baseUrl
};
}
}
/* /*
///Public class representing a resource request of the WebView. ///Public class representing a resource request of the WebView.
///It is used by the event [shouldInterceptRequest()]. ///It is used by the event [shouldInterceptRequest()].
...@@ -671,4 +692,163 @@ class ChromeSafariBrowserClassOptions { ...@@ -671,4 +692,163 @@ class ChromeSafariBrowserClassOptions {
IosSafariOptions iosSafariOptions; IosSafariOptions iosSafariOptions;
ChromeSafariBrowserClassOptions({this.androidChromeCustomTabsOptions, this.iosSafariOptions}); ChromeSafariBrowserClassOptions({this.androidChromeCustomTabsOptions, this.iosSafariOptions});
}
///
class AjaxRequestAction {
final int _value;
const AjaxRequestAction._internal(this._value);
toValue() => _value;
static const ABORT = const AjaxRequestAction._internal(0);
static const PROCEED = const AjaxRequestAction._internal(1);
}
///
class AjaxRequestEventType {
final String _value;
const AjaxRequestEventType._internal(this._value);
static AjaxRequestEventType fromValue(String value) {
return (["loadstart", "load", "loadend", "progress", "error", "abort"].contains(value)) ? AjaxRequestEventType._internal(value) : null;
}
toValue() => _value;
String toString() => _value;
static const LOADSTART = const AjaxRequestEventType._internal("loadstart");
static const LOAD = const AjaxRequestEventType._internal("load");
static const LOADEND = const AjaxRequestEventType._internal("loadend");
static const PROGRESS = const AjaxRequestEventType._internal("progress");
static const ERROR = const AjaxRequestEventType._internal("error");
static const ABORT = const AjaxRequestEventType._internal("abort");
}
///
class AjaxRequestEvent {
AjaxRequestEventType type;
int loaded;
bool lengthComputable;
AjaxRequestEvent({this.type, this.loaded, this.lengthComputable});
}
///
class AjaxRequestReadyState {
final int _value;
const AjaxRequestReadyState._internal(this._value);
static AjaxRequestReadyState fromValue(int value) {
if (value != null && value >= 0 && value <= 4)
return AjaxRequestReadyState._internal(value);
return null;
}
toValue() => _value;
String toString() => _value.toString();
static const UNSENT = const AjaxRequestReadyState._internal(0);
static const OPENED = const AjaxRequestReadyState._internal(1);
static const HEADERS_RECEIVED = const AjaxRequestReadyState._internal(2);
static const LOADING = const AjaxRequestReadyState._internal(3);
static const DONE = const AjaxRequestReadyState._internal(4);
}
///
class AjaxRequest {
dynamic data;
String method;
String url;
bool isAsync;
String user;
String password;
bool withCredentials;
Map<dynamic, dynamic> headers;
AjaxRequestReadyState readyState;
int status;
String responseURL;
String responseType;
String responseText;
String statusText;
Map<dynamic, dynamic> responseHeaders;
AjaxRequestEvent event;
AjaxRequestAction action;
AjaxRequest({this.data, this.method, this.url, this.isAsync, this.user, this.password,
this.withCredentials, this.headers, this.readyState, this.status, this.responseURL, this.responseType,
this.responseText, this.statusText, this.responseHeaders, this.event, this.action = AjaxRequestAction.PROCEED});
Map<String, dynamic> toMap() {
return {
"data": data,
"method": method,
"url": url,
"isAsync": isAsync,
"user": user,
"password": password,
"withCredentials": withCredentials,
"headers": headers,
"readyState": readyState?.toValue(),
"status": status,
"responseURL": responseURL,
"responseType": responseType,
"responseText": responseText,
"statusText": statusText,
"responseHeaders": responseHeaders,
"action": action?.toValue()
};
}
Map<String, dynamic> toJson() {
return this.toMap();
}
}
///
class FetchRequestAction {
final int _value;
const FetchRequestAction._internal(this._value);
toValue() => _value;
static const ABORT = const FetchRequestAction._internal(0);
static const PROCEED = const FetchRequestAction._internal(1);
}
///
class FetchRequest {
String url;
String method;
Map<dynamic, dynamic> headers;
dynamic body;
String mode;
String credentials;
String cache;
String redirect;
String referrer;
String referrerPolicy;
String integrity;
bool keepalive;
FetchRequestAction action;
FetchRequest({this.url, this.method, this.headers, this.body, this.mode, this.credentials,
this.cache, this.redirect, this.referrer, this.referrerPolicy, this.integrity, this.keepalive,
this.action = FetchRequestAction.PROCEED});
Map<String, dynamic> toMap() {
return {
"url": url,
"method": method,
"headers": headers,
"body": body,
"mode": mode,
"credentials": credentials,
"cache": cache,
"redirect": redirect,
"referrer": referrer,
"referrerPolicy": referrerPolicy,
"integrity": integrity,
"keepalive": keepalive,
"action": action?.toValue()
};
}
Map<String, dynamic> toJson() {
return this.toMap();
}
} }
\ No newline at end of file
...@@ -54,11 +54,14 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti ...@@ -54,11 +54,14 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti
List<String> resourceCustomSchemes; List<String> resourceCustomSchemes;
List<ContentBlocker> contentBlockers; List<ContentBlocker> contentBlockers;
InAppWebViewUserPreferredContentMode preferredContentMode; InAppWebViewUserPreferredContentMode preferredContentMode;
bool useShouldInterceptAjaxRequest;
bool useShouldInterceptFetchRequest;
InAppWebViewOptions({this.useShouldOverrideUrlLoading = false, this.useOnLoadResource = false, this.useOnDownloadStart = false, this.useOnTargetBlank = false, InAppWebViewOptions({this.useShouldOverrideUrlLoading = false, this.useOnLoadResource = false, this.useOnDownloadStart = false, this.useOnTargetBlank = false,
this.clearCache = false, this.userAgent = "", this.javaScriptEnabled = true, this.debuggingEnabled = false, this.javaScriptCanOpenWindowsAutomatically = false, this.clearCache = false, this.userAgent = "", this.javaScriptEnabled = true, this.debuggingEnabled = false, this.javaScriptCanOpenWindowsAutomatically = false,
this.mediaPlaybackRequiresUserGesture = true, this.textZoom = 100, this.minimumFontSize, this.verticalScrollBarEnabled = true, this.horizontalScrollBarEnabled = true, this.mediaPlaybackRequiresUserGesture = true, this.textZoom = 100, this.minimumFontSize, this.verticalScrollBarEnabled = true, this.horizontalScrollBarEnabled = true,
this.resourceCustomSchemes = const [], this.contentBlockers = const [], this.preferredContentMode = InAppWebViewUserPreferredContentMode.RECOMMENDED}) { this.resourceCustomSchemes = const [], this.contentBlockers = const [], this.preferredContentMode = InAppWebViewUserPreferredContentMode.RECOMMENDED,
this.useShouldInterceptAjaxRequest = false, this.useShouldInterceptFetchRequest = false}) {
if (this.minimumFontSize == null) if (this.minimumFontSize == null)
this.minimumFontSize = Platform.isAndroid ? 8 : 0; this.minimumFontSize = Platform.isAndroid ? 8 : 0;
assert(!this.resourceCustomSchemes.contains("http") && !this.resourceCustomSchemes.contains("https")); assert(!this.resourceCustomSchemes.contains("http") && !this.resourceCustomSchemes.contains("https"));
...@@ -87,7 +90,9 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti ...@@ -87,7 +90,9 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti
"horizontalScrollBarEnabled": horizontalScrollBarEnabled, "horizontalScrollBarEnabled": horizontalScrollBarEnabled,
"resourceCustomSchemes": resourceCustomSchemes, "resourceCustomSchemes": resourceCustomSchemes,
"contentBlockers": contentBlockersMapList, "contentBlockers": contentBlockersMapList,
"preferredContentMode": preferredContentMode?.toValue() "preferredContentMode": preferredContentMode?.toValue(),
"useShouldInterceptAjaxRequest": useShouldInterceptAjaxRequest,
"useShouldInterceptFetchRequest": useShouldInterceptFetchRequest
}; };
} }
......
This diff is collapsed.
// Example of the server https is taken from here: https://engineering.circle.com/https-authorized-certs-with-node-js-315e548354a2 // Example of the server https is taken from here: https://engineering.circle.com/https-authorized-certs-with-node-js-315e548354a2
// Conversion of client1-crt.pem to certificate.pfx: https://stackoverflow.com/a/38408666/4637638 // Conversion of client1-crt.pem to certificate.pfx: https://stackoverflow.com/a/38408666/4637638
const express = require('express') const express = require('express')
var https = require('https') const https = require('https')
const cors = require('cors')
const auth = require('basic-auth') const auth = require('basic-auth')
const app = express() const app = express()
const appHttps = express() const appHttps = express()
const appAuthBasic = express() const appAuthBasic = express()
const fs = require('fs') const fs = require('fs')
const path = require('path')
var options = { var options = {
key: fs.readFileSync('server-key.pem'), key: fs.readFileSync('server-key.pem'),
...@@ -17,6 +19,7 @@ var options = { ...@@ -17,6 +19,7 @@ var options = {
}; };
appHttps.get('/', (req, res) => { appHttps.get('/', (req, res) => {
console.log(JSON.stringify(req.headers))
const cert = req.connection.getPeerCertificate() const cert = req.connection.getPeerCertificate()
// The `req.client.authorized` flag will be true if the certificate is valid and was issued by a CA we white-listed // The `req.client.authorized` flag will be true if the certificate is valid and was issued by a CA we white-listed
...@@ -48,7 +51,8 @@ appHttps.get('/', (req, res) => { ...@@ -48,7 +51,8 @@ appHttps.get('/', (req, res) => {
}) })
appHttps.get('/fakeResource', (req, res) => { appHttps.get('/fakeResource', (req, res) => {
res.set("Content-Type", "text/javascript") console.log(JSON.stringify(req.headers))
res.set("Content-Type", "text/javascript")
res.send(`alert("HI");`) res.send(`alert("HI");`)
res.end() res.end()
}) })
...@@ -70,6 +74,7 @@ appAuthBasic.use((req, res, next) => { ...@@ -70,6 +74,7 @@ appAuthBasic.use((req, res, next) => {
}) })
appAuthBasic.get("/", (req, res) => { appAuthBasic.get("/", (req, res) => {
console.log(JSON.stringify(req.headers))
res.send(` res.send(`
<html> <html>
<head> <head>
...@@ -87,10 +92,13 @@ appAuthBasic.listen(8081) ...@@ -87,10 +92,13 @@ appAuthBasic.listen(8081)
// Parse URL-encoded bodies (as sent by HTML forms) // Parse URL-encoded bodies (as sent by HTML forms)
app.use(express.urlencoded()); app.use(express.urlencoded());
app.use(cors());
// Parse JSON bodies (as sent by API clients) // Parse JSON bodies (as sent by API clients)
app.use(express.json()); app.use(express.json());
app.get("/", (req, res) => { app.get("/", (req, res) => {
console.log(JSON.stringify(req.headers))
res.send(` res.send(`
<html> <html>
<head> <head>
...@@ -104,6 +112,7 @@ app.get("/", (req, res) => { ...@@ -104,6 +112,7 @@ app.get("/", (req, res) => {
}) })
app.post("/test-post", (req, res) => { app.post("/test-post", (req, res) => {
console.log(JSON.stringify(req.headers))
res.send(` res.send(`
<html> <html>
<head> <head>
...@@ -115,4 +124,27 @@ app.post("/test-post", (req, res) => { ...@@ -115,4 +124,27 @@ app.post("/test-post", (req, res) => {
`); `);
res.end() res.end()
}) })
app.post("/test-ajax-post", (req, res) => {
console.log(JSON.stringify(req.headers))
res.set("Content-Type", "application/json")
res.send(JSON.stringify({
"name": req.body.name,
"key2": "value2"
}))
res.end()
})
app.get("/test-download-file", (req, res) => {
console.log(JSON.stringify(req.headers))
const filePath = path.join(__dirname, 'assets', 'flutter_logo.png');
const stat = fs.statSync(filePath);
const file = fs.readFileSync(filePath, 'binary');
res.setHeader('Content-Length', stat.size);
res.setHeader('Content-Type', 'image/png');
res.setHeader('Content-Disposition', 'attachment; filename=flutter_logo.png');
res.write(file, 'binary');
res.end();
})
app.listen(8082) app.listen(8082)
\ No newline at end of file
...@@ -71,6 +71,15 @@ ...@@ -71,6 +71,15 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
}, },
"cors": {
"version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"requires": {
"object-assign": "^4",
"vary": "^1"
}
},
"debug": { "debug": {
"version": "2.6.9", "version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
...@@ -248,6 +257,11 @@ ...@@ -248,6 +257,11 @@
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
}, },
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
"on-finished": { "on-finished": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"basic-auth": "latest", "basic-auth": "latest",
"cors": "^2.8.5",
"express": "latest", "express": "latest",
"https": "latest" "https": "latest"
} }
......
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