diff --git a/.idea/runConfigurations/example_lib_main_dart.xml b/.idea/runConfigurations/example_lib_main_dart.xml
index 624f56a6..bac2c8a7 100644
--- a/.idea/runConfigurations/example_lib_main_dart.xml
+++ b/.idea/runConfigurations/example_lib_main_dart.xml
@@ -1,6 +1,5 @@
-
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index c3f13ef6..a5a9789e 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -15,35 +15,16 @@
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
@@ -66,8 +47,8 @@
-
-
+
+
@@ -76,10 +57,10 @@
-
+
-
-
+
+
@@ -88,10 +69,13 @@
-
+
-
-
+
+
+
+
+
@@ -99,8 +83,8 @@
-
-
+
+
@@ -108,6 +92,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -120,36 +143,36 @@
- toggleErrorInformationPopup
- error-information-popup-container
- offline-spri
- sprite
- icon-offline
- ICON
- loadImages
- RESOURCE_TEMPLATE_ID
- adjustDimensions
- outerContainerEl
- ontouch
- fromVa
- ContentBlockerActionType
- getOptions
- iOS
- Ios
- initialOptions
- initialOpti
- Platform
- Platform.i
- getOption
- .toValue
- fromValue(
- ?.toMap());
- fromMap
- setOptions
- fromValue
- List<
- debuggingEnabled
- initialOp
+ injectScriptUrlFile
+ [InAppWebView] window
+ javaScriptEnabled
+ onLoadRes
+ onLoadResource
+ onLoadResource"
+ javaScriptHandlersMap
+ javaScriptHandlers
+ onAjaxSend
+ Action
+ AjaxRequestEventType
+ onAjax
+ onAjaxReadyStateChange
+ onAjaxEvent
+ shouldInterceptAjaxRequest
+ onAjaxProgress
+ onAjaxReady
+ NAVIGATION
+ onNavigationStateChange
+ shouldInterceptFetchRequest
+ scheme
+ applicationNameForUserAgent
+ cacheMOde
+ inco
+ cacheEna
+ appCacheEnabled
+ appC
+ cache
+ customScheme
+ transparentBackground
activity.getPreferences(0)
@@ -160,6 +183,8 @@
ChannelManager
Function
?.toMap() ?? {});
+ javascriptEnabled
+ [InAppWebView]\
$PROJECT_DIR$/example/android
@@ -199,35 +224,35 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
@@ -238,6 +263,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -267,61 +341,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -341,13 +360,6 @@
-
-
-
-
-
-
-
@@ -355,6 +367,13 @@
+
+
+
+
+
+
+
-
+
@@ -486,7 +505,7 @@
-
+
@@ -494,10 +513,10 @@
-
-
-
-
+
+
+
+
@@ -524,25 +543,11 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -607,13 +612,6 @@
-
-
-
-
-
-
-
@@ -638,13 +636,6 @@
-
-
-
-
-
-
-
@@ -679,23 +670,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -740,40 +714,71 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -782,18 +787,28 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2ca29898..a2231f6d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,9 +13,9 @@
- Added `onLoadResourceCustomScheme` event and `resourceCustomSchemes` option to set custom schemes that WebView must handle to load resources
- Added `onTargetBlank` event and `useOnTargetBlank` option to manage links with `target="_blank"`
- Added `ContentBlocker`, `ContentBlockerTrigger` and `ContentBlockerAction` classes and the `contentBlockers` option that allows to define a set of rules to use to block content in the WebView
-- Added new WebView options: `minimumFontSize`, `debuggingEnabled`, `preferredContentMode`
-- Added new Android WebView options: `allowContentAccess`, `allowFileAccess`, `allowFileAccessFromFileURLs`, `allowUniversalAccessFromFileURLs`, `appCacheEnabled`, `appCachePath`, `blockNetworkImage`, `blockNetworkLoads`, `cacheMode`, `cursiveFontFamily`, `defaultFixedFontSize`, `defaultFontSize`, `defaultTextEncodingName`, `disabledActionModeMenuItems`, `fantasyFontFamily`, `fixedFontFamily`, `forceDark`, `geolocationEnabled`, `layoutAlgorithm`, `loadWithOverviewMode`, `loadsImagesAutomatically`, `minimumLogicalFontSize`, `needInitialFocus`, `offscreenPreRaster`, `sansSerifFontFamily`, `serifFontFamily`, `standardFontFamily`
-- Added new iOS WebView options: `applicationNameForUserAgent`, `isFraudulentWebsiteWarningEnabled`, `selectionGranularity`, `dataDetectorTypes`
+- Added new WebView options: `minimumFontSize`, `debuggingEnabled`, `preferredContentMode`, `applicationNameForUserAgent`, `incognito`, `cacheEnabled`
+- Added new Android WebView options: `allowContentAccess`, `allowFileAccess`, `allowFileAccessFromFileURLs`, `allowUniversalAccessFromFileURLs`, `appCachePath`, `blockNetworkImage`, `blockNetworkLoads`, `cacheMode`, `cursiveFontFamily`, `defaultFixedFontSize`, `defaultFontSize`, `defaultTextEncodingName`, `disabledActionModeMenuItems`, `fantasyFontFamily`, `fixedFontFamily`, `forceDark`, `geolocationEnabled`, `layoutAlgorithm`, `loadWithOverviewMode`, `loadsImagesAutomatically`, `minimumLogicalFontSize`, `needInitialFocus`, `offscreenPreRaster`, `sansSerifFontFamily`, `serifFontFamily`, `standardFontFamily`, `saveFormData`, `thirdPartyCookiesEnabled`, `hardwareAcceleration`
+- Added new iOS WebView options: `isFraudulentWebsiteWarningEnabled`, `selectionGranularity`, `dataDetectorTypes`, `sharedCookiesEnabled`
- Added `onGeolocationPermissionsShowPrompt` event and `GeolocationPermissionShowPromptResponse` class (available only for Android)
- Added `startSafeBrowsing`, `setSafeBrowsingWhitelist` and `getSafeBrowsingPrivacyPolicyUrl` methods (available only for Android)
- Added `clearSslPreferences` and `clearClientCertPreferences` methods (available only for Android)
@@ -26,7 +26,9 @@
- Added `HttpAuthCredentialDatabase` class
- Added `onReceivedServerTrustAuthRequest` and `onReceivedClientCertRequest` events to manage SSL requests
- Added `onFindResultReceived` event, `findAllAsync`, `findNext` and `clearMatches` methods
-- Added `getHtml` method
+- Added `getHtml`, `injectJavascriptFileFromAsset` and `injectCSSFileFromAsset` methods
+- Added `shouldInterceptAjaxRequest`, `onAjaxReadyStateChange`, `onAjaxProgress` and `shouldInterceptFetchRequest` events with `useShouldInterceptAjaxRequest` and `useShouldInterceptFetchRequest` webview options
+- Added `onNavigationStateChange` event
- Fun: added `getTRexRunnerHtml` and `getTRexRunnerCss` methods to get html (with javascript) and css to recreate the Chromium's t-rex runner game
### BREAKING CHANGES
@@ -37,6 +39,10 @@
- Updated `CookieManager` class
- 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`) found
+- Renamed `injectScriptFile` to `injectJavascriptFileFromUrl`
+- Renamed `injectScriptCode` to `evaluateJavascript`
+- Renamed `injectStyleCode` to `injectCSSCode`
+- Renamed `injectStyleFile` to `injectCSSFileFromUrl`
## 1.2.1
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/ContentBlocker/ContentBlockerHandler.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/ContentBlocker/ContentBlockerHandler.java
index 1863326a..6c1d232a 100644
--- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/ContentBlocker/ContentBlockerHandler.java
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/ContentBlocker/ContentBlockerHandler.java
@@ -21,6 +21,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.regex.Matcher;
+import io.flutter.plugin.common.MethodChannel;
import okhttp3.Request;
import okhttp3.Response;
@@ -145,7 +146,7 @@ public class ContentBlockerHandler {
@Override
public void run() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- webView.evaluateJavascript(jsScript, null);
+ webView.evaluateJavascript(jsScript, (MethodChannel.Result) null);
} else {
webView.loadUrl("javascript:" + jsScript);
}
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/FlutterWebView.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/FlutterWebView.java
index 03ce8346..bcf7cf70 100644
--- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/FlutterWebView.java
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/FlutterWebView.java
@@ -1,11 +1,9 @@
package com.pichillilorenzo.flutter_inappbrowser;
-import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.hardware.display.DisplayManager;
import android.os.Build;
-import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.webkit.WebChromeClient;
@@ -15,21 +13,20 @@ import android.webkit.WebViewClient;
import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.DisplayListenerProxy;
import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.InAppWebView;
import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.InAppWebViewOptions;
-import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.InputAwareWebView;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
-import 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.platform.PlatformView;
+import static io.flutter.plugin.common.MethodChannel.MethodCallHandler;
+import static io.flutter.plugin.common.MethodChannel.Result;
+
public class FlutterWebView implements PlatformView, MethodCallHandler {
static final String LOG_TAG = "FlutterWebView";
@@ -135,33 +132,33 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
else
result.success(false);
break;
- case "injectScriptCode":
+ case "evaluateJavascript":
if (webView != null) {
String source = (String) call.argument("source");
- webView.injectScriptCode(source, result);
+ webView.evaluateJavascript(source, result);
}
else {
result.success("");
}
break;
- case "injectScriptFile":
+ case "injectJavascriptFileFromUrl":
if (webView != null) {
String urlFile = (String) call.argument("urlFile");
- webView.injectScriptFile(urlFile);
+ webView.injectJavascriptFileFromUrl(urlFile);
}
result.success(true);
break;
- case "injectStyleCode":
+ case "injectCSSCode":
if (webView != null) {
String source = (String) call.argument("source");
- webView.injectStyleCode(source);
+ webView.injectCSSCode(source);
}
result.success(true);
break;
- case "injectStyleFile":
+ case "injectCSSFileFromUrl":
if (webView != null) {
String urlFile = (String) call.argument("urlFile");
- webView.injectStyleFile(urlFile);
+ webView.injectCSSFileFromUrl(urlFile);
}
result.success(true);
break;
@@ -312,13 +309,13 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
@Override
public void onInputConnectionLocked() {
- if (webView.inAppBrowserActivity == null)
+ if (webView != null && webView.inAppBrowserActivity == null)
webView.lockInputConnection();
}
@Override
public void onInputConnectionUnlocked() {
- if (webView.inAppBrowserActivity == null)
+ if (webView != null && webView.inAppBrowserActivity == null)
webView.unlockInputConnection();
}
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowser.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowser.java
index 27f3fa65..554b20ae 100644
--- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowser.java
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowser.java
@@ -192,23 +192,23 @@ public class InAppBrowser implements MethodChannel.MethodCallHandler {
case "close":
close(activity, uuid, result);
break;
- case "injectScriptCode":
+ case "evaluateJavascript":
source = (String) call.argument("source");
- injectScriptCode(uuid, source, result);
+ evaluateJavascript(uuid, source, result);
break;
- case "injectScriptFile":
+ case "injectJavascriptFileFromUrl":
urlFile = (String) call.argument("urlFile");
- injectScriptFile(uuid, urlFile);
+ injectJavascriptFileFromUrl(uuid, urlFile);
result.success(true);
break;
- case "injectStyleCode":
+ case "injectCSSCode":
source = (String) call.argument("source");
- injectStyleCode(uuid, source);
+ injectCSSCode(uuid, source);
result.success(true);
break;
- case "injectStyleFile":
+ case "injectCSSFileFromUrl":
urlFile = (String) call.argument("urlFile");
- injectStyleFile(uuid, urlFile);
+ injectCSSFileFromUrl(uuid, urlFile);
result.success(true);
break;
case "show":
@@ -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);
if (inAppBrowserActivity != null) {
- inAppBrowserActivity.injectScriptCode(source, result);
+ inAppBrowserActivity.evaluateJavascript(source, result);
} else {
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);
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);
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);
if (inAppBrowserActivity != null) {
- inAppBrowserActivity.injectStyleFile(urlFile);
+ inAppBrowserActivity.injectCSSFileFromUrl(urlFile);
}
}
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserActivity.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserActivity.java
index 1494aaf2..52e41ae7 100644
--- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserActivity.java
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserActivity.java
@@ -434,26 +434,26 @@ public class InAppBrowserActivity extends AppCompatActivity {
return optionsMap;
}
- public void injectScriptCode(String source, MethodChannel.Result result) {
+ public void evaluateJavascript(String source, MethodChannel.Result result) {
if (webView != null)
- webView.injectScriptCode(source, result);
+ webView.evaluateJavascript(source, result);
else
result.success("");
}
- public void injectScriptFile(String urlFile) {
+ public void injectJavascriptFileFromUrl(String urlFile) {
if (webView != null)
- webView.injectScriptFile(urlFile);
+ webView.injectJavascriptFileFromUrl(urlFile);
}
- public void injectStyleCode(String source) {
+ public void injectCSSCode(String source) {
if (webView != null)
- webView.injectStyleCode(source);
+ webView.injectCSSCode(source);
}
- public void injectStyleFile(String urlFile) {
+ public void injectCSSFileFromUrl(String urlFile) {
if (webView != null)
- webView.injectStyleFile(urlFile);
+ webView.injectCSSFileFromUrl(urlFile);
}
public HashMap getCopyBackForwardList() {
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java
index 8a471d83..298ea7c3 100644
--- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java
@@ -59,7 +59,7 @@ final public class InAppWebView extends InputAwareWebView {
int okHttpClientCacheSize = 10 * 1024 * 1024; // 10MB
public ContentBlockerHandler contentBlockerHandler = new ContentBlockerHandler();
- static final String consoleLogJS = "(function() {" +
+ static final String consoleLogJS = "(function(console) {" +
" var oldLogs = {" +
" 'log': console.log," +
" 'debug': console.debug," +
@@ -83,18 +83,354 @@ final public class InAppWebView extends InputAwareWebView {
" }" +
" })(k);" +
" }" +
- "})();";
+ "})(window.console);";
+
+ static final String platformReadyJS = "window.dispatchEvent(new Event('flutterInAppBrowserPlatformReady'));";
+
+ static final String variableForOnLoadResourceJS = "window._flutter_inappbrowser_useOnLoadResource";
+ static final String enableVariableForOnLoadResourceJS = variableForOnLoadResourceJS + " = $PLACEHOLDER_VALUE;";
static final String resourceObserverJS = "(function() {" +
" var observer = new PerformanceObserver(function(list) {" +
" list.getEntries().forEach(function(entry) {" +
- " window." + JavaScriptBridgeInterface.name + "._resourceLoaded(JSON.stringify(entry));" +
+ " if (window." + variableForOnLoadResourceJS + " == null || window." + variableForOnLoadResourceJS + " == true) {" +
+ " window." + JavaScriptBridgeInterface.name + ".callHandler('onLoadResource', entry);" +
+ " }" +
" });" +
" });" +
" observer.observe({entryTypes: ['resource']});" +
"})();";
- static final String platformReadyJS = "window.dispatchEvent(new Event('flutterInAppBrowserPlatformReady'));";
+ static final String variableForShouldInterceptAjaxRequestJS = "window._flutter_inappbrowser_useShouldInterceptAjaxRequest";
+ static final String enableVariableForShouldInterceptAjaxRequestJS = variableForShouldInterceptAjaxRequestJS + " = $PLACEHOLDER_VALUE;";
+
+ static final String interceptAjaxRequestsJS = "(function(ajax) {" +
+ " var send = ajax.prototype.send;" +
+ " var open = ajax.prototype.open;" +
+ " var setRequestHeader = ajax.prototype.setRequestHeader;" +
+ " ajax.prototype._flutter_inappbrowser_url = null;" +
+ " ajax.prototype._flutter_inappbrowser_method = null;" +
+ " ajax.prototype._flutter_inappbrowser_isAsync = null;" +
+ " ajax.prototype._flutter_inappbrowser_user = null;" +
+ " ajax.prototype._flutter_inappbrowser_password = null;" +
+ " ajax.prototype._flutter_inappbrowser_password = null;" +
+ " ajax.prototype._flutter_inappbrowser_already_onreadystatechange_wrapped = false;" +
+ " ajax.prototype._flutter_inappbrowser_request_headers = {};" +
+ " ajax.prototype.open = function(method, url, isAsync, user, password) {" +
+ " isAsync = (isAsync != null) ? isAsync : true;" +
+ " this._flutter_inappbrowser_url = url;" +
+ " this._flutter_inappbrowser_method = method;" +
+ " this._flutter_inappbrowser_isAsync = isAsync;" +
+ " this._flutter_inappbrowser_user = user;" +
+ " this._flutter_inappbrowser_password = password;" +
+ " open.call(this, method, url, isAsync, user, password);" +
+ " };" +
+ " ajax.prototype.setRequestHeader = function(header, value) {" +
+ " this._flutter_inappbrowser_request_headers[header] = value;" +
+ " setRequestHeader.call(this, header, value);" +
+ " };" +
+ " function handleEvent(e) {" +
+ " var self = this;" +
+ " if (window." + variableForShouldInterceptAjaxRequestJS + " == null || window." + variableForShouldInterceptAjaxRequestJS + " == true) {" +
+ " var headers = this.getAllResponseHeaders();" +
+ " var responseHeaders = {};" +
+ " if (headers != null) {" +
+ " var arr = headers.trim().split(/[\\r\\n]+/);" +
+ " arr.forEach(function (line) {" +
+ " var parts = line.split(': ');" +
+ " var header = parts.shift();" +
+ " var value = parts.join(': ');" +
+ " responseHeaders[header] = value;" +
+ " });" +
+ " }" +
+ " var ajaxRequest = {" +
+ " method: this._flutter_inappbrowser_method," +
+ " url: this._flutter_inappbrowser_url," +
+ " isAsync: this._flutter_inappbrowser_isAsync," +
+ " user: this._flutter_inappbrowser_user," +
+ " password: this._flutter_inappbrowser_password," +
+ " withCredentials: this.withCredentials," +
+ " headers: this._flutter_inappbrowser_request_headers," +
+ " readyState: this.readyState," +
+ " status: this.status," +
+ " responseURL: this.responseURL," +
+ " responseType: this.responseType," +
+ " responseText: this.responseText," +
+ " statusText: this.statusText," +
+ " responseHeaders, responseHeaders," +
+ " event: {" +
+ " type: e.type," +
+ " loaded: e.loaded," +
+ " lengthComputable: e.lengthComputable" +
+ " }" +
+ " };" +
+ " window." + JavaScriptBridgeInterface.name + ".callHandler('onAjaxProgress', ajaxRequest).then(function(result) {" +
+ " if (result != null) {" +
+ " switch (result) {" +
+ " case 0:" +
+ " self.abort();" +
+ " return;" +
+ " };" +
+ " }" +
+ " });" +
+ " }" +
+ " };" +
+ " ajax.prototype.send = function(data) {" +
+ " var self = this;" +
+ " if (window." + variableForShouldInterceptAjaxRequestJS + " == null || window." + variableForShouldInterceptAjaxRequestJS + " == true) {" +
+ " if (!this._flutter_inappbrowser_already_onreadystatechange_wrapped) {" +
+ " this._flutter_inappbrowser_already_onreadystatechange_wrapped = true;" +
+ " var onreadystatechange = this.onreadystatechange;" +
+ " this.onreadystatechange = function() {" +
+ " if (window." + variableForShouldInterceptAjaxRequestJS + " == null || window." + variableForShouldInterceptAjaxRequestJS + " == true) {" +
+ " var headers = this.getAllResponseHeaders();" +
+ " var responseHeaders = {};" +
+ " if (headers != null) {" +
+ " var arr = headers.trim().split(/[\\r\\n]+/);" +
+ " arr.forEach(function (line) {" +
+ " var parts = line.split(': ');" +
+ " var header = parts.shift();" +
+ " var value = parts.join(': ');" +
+ " responseHeaders[header] = value;" +
+ " });" +
+ " }" +
+ " var ajaxRequest = {" +
+ " method: this._flutter_inappbrowser_method," +
+ " url: this._flutter_inappbrowser_url," +
+ " isAsync: this._flutter_inappbrowser_isAsync," +
+ " user: this._flutter_inappbrowser_user," +
+ " password: this._flutter_inappbrowser_password," +
+ " withCredentials: this.withCredentials," +
+ " headers: this._flutter_inappbrowser_request_headers," +
+ " readyState: this.readyState," +
+ " status: this.status," +
+ " responseURL: this.responseURL," +
+ " responseType: this.responseType," +
+ " responseText: this.responseText," +
+ " statusText: this.statusText," +
+ " responseHeaders: responseHeaders" +
+ " };" +
+ " window." + JavaScriptBridgeInterface.name + ".callHandler('onAjaxReadyStateChange', ajaxRequest).then(function(result) {" +
+ " if (result != null) {" +
+ " switch (result) {" +
+ " case 0:" +
+ " self.abort();" +
+ " return;" +
+ " };" +
+ " }" +
+ " if (onreadystatechange != null) {" +
+ " onreadystatechange();" +
+ " }" +
+ " });" +
+ " } else if (onreadystatechange != null) {" +
+ " onreadystatechange();" +
+ " }" +
+ " };" +
+ " }" +
+ " this.addEventListener('loadstart', handleEvent);" +
+ " this.addEventListener('load', handleEvent);" +
+ " this.addEventListener('loadend', handleEvent);" +
+ " this.addEventListener('progress', handleEvent);" +
+ " this.addEventListener('error', handleEvent);" +
+ " this.addEventListener('abort', handleEvent);" +
+ " var ajaxRequest = {" +
+ " data: data," +
+ " method: this._flutter_inappbrowser_method," +
+ " url: this._flutter_inappbrowser_url," +
+ " isAsync: this._flutter_inappbrowser_isAsync," +
+ " user: this._flutter_inappbrowser_user," +
+ " password: this._flutter_inappbrowser_password," +
+ " withCredentials: this.withCredentials," +
+ " headers: this._flutter_inappbrowser_request_headers" +
+ " };" +
+ " window." + JavaScriptBridgeInterface.name + ".callHandler('shouldInterceptAjaxRequest', ajaxRequest).then(function(result) {" +
+ " if (result != null) {" +
+ " switch (result.action) {" +
+ " case 0:" +
+ " self.abort();" +
+ " return;" +
+ " };" +
+ " data = result.data;" +
+ " self.withCredentials = result.withCredentials;" +
+ " for (var header in result.headers) {" +
+ " var value = result.headers[header];" +
+ " self.setRequestHeader(header, value);" +
+ " };" +
+ " if ((self._flutter_inappbrowser_method != result.method && result.method != null) || (self._flutter_inappbrowser_url != result.url && result.url != null)) {" +
+ " self.abort();" +
+ " self.open(result.method, result.url, result.isAsync, result.user, result.password);" +
+ " return;" +
+ " }" +
+ " }" +
+ " send.call(self, data);" +
+ " });" +
+ " } else {" +
+ " send.call(this, data);" +
+ " }" +
+ " };" +
+ "})(window.XMLHttpRequest);";
+
+ static final String variableForShouldInterceptFetchRequestsJS = "window._flutter_inappbrowser_useShouldInterceptFetchRequest";
+ static final String enableVariableForShouldInterceptFetchRequestsJS = variableForShouldInterceptFetchRequestsJS + " = $PLACEHOLDER_VALUE;";
+
+ static final String interceptFetchRequestsJS = "(function(fetch) {" +
+ " if (fetch == null) {" +
+ " return;" +
+ " }" +
+ " function convertHeadersToJson(headers) {" +
+ " var headersObj = {};" +
+ " for (var header of headers.keys()) {" +
+ " var value = headers.get(header);" +
+ " headersObj[header] = value;" +
+ " }" +
+ " return headersObj;" +
+ " }" +
+ " function convertJsonToHeaders(headersJson) {" +
+ " return new Headers(headersJson);" +
+ " }" +
+ " function convertBodyToArray(body) {" +
+ " return new Response(body).arrayBuffer().then(function(arrayBuffer) {" +
+ " var arr = Array.from(new Uint8Array(arrayBuffer));" +
+ " return arr;" +
+ " })" +
+ " }" +
+ " function convertArrayIntBodyToUint8Array(arrayIntBody) {" +
+ " return new Uint8Array(arrayIntBody);" +
+ " }" +
+ " function convertCredentialsToJson(credentials) {" +
+ " var credentialsObj = {};" +
+ " if (window.FederatedCredential != null && credentials instanceof FederatedCredential) {" +
+ " credentialsObj.type = credentials.type;" +
+ " credentialsObj.id = credentials.id;" +
+ " credentialsObj.name = credentials.name;" +
+ " credentialsObj.protocol = credentials.protocol;" +
+ " credentialsObj.provider = credentials.provider;" +
+ " credentialsObj.iconURL = credentials.iconURL;" +
+ " } else if (window.PasswordCredential != null && credentials instanceof PasswordCredential) {" +
+ " credentialsObj.type = credentials.type;" +
+ " credentialsObj.id = credentials.id;" +
+ " credentialsObj.name = credentials.name;" +
+ " credentialsObj.password = credentials.password;" +
+ " credentialsObj.iconURL = credentials.iconURL;" +
+ " } else {" +
+ " credentialsObj.type = 'default';" +
+ " credentialsObj.value = credentials;" +
+ " }" +
+ " }" +
+ " function convertJsonToCredential(credentialsJson) {" +
+ " var credentials;" +
+ " if (window.FederatedCredential != null && credentialsJson.type === 'federated') {" +
+ " credentials = new FederatedCredential({" +
+ " id: credentialsJson.id," +
+ " name: credentialsJson.name," +
+ " protocol: credentialsJson.protocol," +
+ " provider: credentialsJson.provider," +
+ " iconURL: credentialsJson.iconURL" +
+ " });" +
+ " } else if (window.PasswordCredential != null && credentialsJson.type === 'password') {" +
+ " credentials = new PasswordCredential({" +
+ " id: credentialsJson.id," +
+ " name: credentialsJson.name," +
+ " password: credentialsJson.password," +
+ " iconURL: credentialsJson.iconURL" +
+ " });" +
+ " } else {" +
+ " credentials = credentialsJson;" +
+ " }" +
+ " return credentials;" +
+ " }" +
+ " window.fetch = async function(resource, init) {" +
+ " if (window." + variableForShouldInterceptFetchRequestsJS + " == null || window." + variableForShouldInterceptFetchRequestsJS + " == true) {" +
+ " var fetchRequest = {" +
+ " url: null," +
+ " method: null," +
+ " headers: null," +
+ " body: null," +
+ " mode: null," +
+ " credentials: null," +
+ " cache: null," +
+ " redirect: null," +
+ " referrer: null," +
+ " referrerPolicy: null," +
+ " integrity: null," +
+ " keepalive: null" +
+ " };" +
+ " if (resource instanceof Request) {" +
+ " fetchRequest.url = resource.url;" +
+ " fetchRequest.method = resource.method;" +
+ " fetchRequest.headers = resource.headers;" +
+ " fetchRequest.body = resource.body;" +
+ " fetchRequest.mode = resource.mode;" +
+ " fetchRequest.credentials = resource.credentials;" +
+ " fetchRequest.cache = resource.cache;" +
+ " fetchRequest.redirect = resource.redirect;" +
+ " fetchRequest.referrer = resource.referrer;" +
+ " fetchRequest.referrerPolicy = resource.referrerPolicy;" +
+ " fetchRequest.integrity = resource.integrity;" +
+ " fetchRequest.keepalive = resource.keepalive;" +
+ " } else {" +
+ " fetchRequest.url = resource;" +
+ " if (init != null) {" +
+ " fetchRequest.method = init.method;" +
+ " fetchRequest.headers = init.headers;" +
+ " fetchRequest.body = init.body;" +
+ " fetchRequest.mode = init.mode;" +
+ " fetchRequest.credentials = init.credentials;" +
+ " fetchRequest.cache = init.cache;" +
+ " fetchRequest.redirect = init.redirect;" +
+ " fetchRequest.referrer = init.referrer;" +
+ " fetchRequest.referrerPolicy = init.referrerPolicy;" +
+ " fetchRequest.integrity = init.integrity;" +
+ " fetchRequest.keepalive = init.keepalive;" +
+ " }" +
+ " }" +
+ " if (fetchRequest.headers instanceof Headers) {" +
+ " fetchRequest.headers = convertHeadersToJson(fetchRequest.headers);" +
+ " }" +
+ " fetchRequest.credentials = convertCredentialsToJson(fetchRequest.credentials);" +
+ " return convertBodyToArray(fetchRequest.body).then(function(body) {" +
+ " fetchRequest.body = body;" +
+ " return window." + JavaScriptBridgeInterface.name + ".callHandler('shouldInterceptFetchRequest', fetchRequest).then(function(result) {" +
+ " if (result != null) {" +
+ " switch (result.action) {" +
+ " case 0:" +
+ " var controller = new AbortController();" +
+ " if (init != null) {" +
+ " init.signal = controller.signal;" +
+ " } else {" +
+ " init = {" +
+ " signal: controller.signal" +
+ " };" +
+ " }" +
+ " controller.abort();" +
+ " break;" +
+ " }" +
+ " var resultResource = (result.resource != null) ? result.resource : resource;" +
+ " var resultInit = init;" +
+ " if (result.init != null) {" +
+ " resultInit.method = result.method;" +
+ " resultInit.headers = convertJsonToHeaders(result.headers);" +
+ " resultInit.body = convertArrayIntBodyToUint8Array(result.body);" +
+ " resultInit.mode = result.mode;" +
+ " resultInit.credentials = convertJsonToCredential(result.credentials);" +
+ " resultInit.cache = result.cache;" +
+ " resultInit.redirect = result.redirect;" +
+ " resultInit.referrer = result.referrer;" +
+ " resultInit.referrerPolicy = result.referrerPolicy;" +
+ " resultInit.integrity = result.integrity;" +
+ " resultInit.keepalive = result.keepalive;" +
+ " }" +
+ " return fetch(resultResource, resultInit);" +
+ " }" +
+ " return fetch(resource, init);" +
+ " });" +
+ " });" +
+ " } else {" +
+ " return fetch(resource, init);" +
+ " }" +
+ " };" +
+ "})(window.fetch);";
+
public InAppWebView(Context context) {
super(context);
@@ -163,19 +499,28 @@ final public class InAppWebView extends InputAwareWebView {
settings.setDatabaseEnabled(options.databaseEnabled);
settings.setDomStorageEnabled(options.domStorageEnabled);
- if (!options.userAgent.isEmpty())
+ if (options.userAgent != null && !options.userAgent.isEmpty())
settings.setUserAgentString(options.userAgent);
+ else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
+ settings.setUserAgentString(WebSettings.getDefaultUserAgent(getContext()));
+
+ if (options.applicationNameForUserAgent != null && !options.applicationNameForUserAgent.isEmpty()) {
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ String userAgent = (options.userAgent != null && !options.userAgent.isEmpty()) ? options.userAgent :WebSettings.getDefaultUserAgent(getContext());
+ String userAgentWithApplicationName = userAgent + " " + options.applicationNameForUserAgent;
+ settings.setUserAgentString(userAgentWithApplicationName);
+ }
+ }
if (options.clearCache)
clearAllCache();
else if (options.clearSessionCache)
CookieManager.getInstance().removeSessionCookie();
- // Enable Thirdparty Cookies on >=Android 5.0 device
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
- CookieManager.getInstance().setAcceptThirdPartyCookies(this, true);
+ CookieManager.getInstance().setAcceptThirdPartyCookies(this, options.thirdPartyCookiesEnabled);
- settings.setLoadWithOverviewMode(true);
+ settings.setLoadWithOverviewMode(options.loadWithOverviewMode);
settings.setUseWideViewPort(options.useWideViewPort);
settings.setSupportZoom(options.supportZoom);
settings.setTextZoom(options.textZoom);
@@ -192,8 +537,8 @@ final public class InAppWebView extends InputAwareWebView {
settings.setAllowFileAccess(options.allowFileAccess);
settings.setAllowFileAccessFromFileURLs(options.allowFileAccessFromFileURLs);
settings.setAllowUniversalAccessFromFileURLs(options.allowUniversalAccessFromFileURLs);
- settings.setAppCacheEnabled(options.appCacheEnabled);
- if (options.appCachePath != null && !options.appCachePath.isEmpty() && options.appCacheEnabled)
+ setCacheEnabled(options.cacheEnabled);
+ if (options.appCachePath != null && !options.appCachePath.isEmpty() && options.cacheEnabled)
settings.setAppCachePath(options.appCachePath);
settings.setBlockNetworkImage(options.blockNetworkImage);
settings.setBlockNetworkLoads(options.blockNetworkLoads);
@@ -212,7 +557,6 @@ final public class InAppWebView extends InputAwareWebView {
settings.setGeolocationEnabled(options.geolocationEnabled);
if (options.layoutAlgorithm != null)
settings.setLayoutAlgorithm(options.layoutAlgorithm);
- settings.setLoadWithOverviewMode(options.loadWithOverviewMode);
settings.setLoadsImagesAutomatically(options.loadsImagesAutomatically);
settings.setMinimumFontSize(options.minimumFontSize);
settings.setMinimumLogicalFontSize(options.minimumLogicalFontSize);
@@ -237,6 +581,13 @@ final public class InAppWebView extends InputAwareWebView {
break;
}
}
+ settings.setSaveFormData(options.saveFormData);
+ if (options.incognito)
+ setIncognito(true);
+ if (options.hardwareAcceleration)
+ setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ else
+ setLayerType(View.LAYER_TYPE_SOFTWARE, null);
contentBlockerHandler.getRuleList().clear();
for (Map> contentBlocker : options.contentBlockers) {
@@ -260,6 +611,49 @@ final public class InAppWebView extends InputAwareWebView {
});
}
+ public void setIncognito(boolean enabled) {
+ WebSettings settings = getSettings();
+ if (enabled) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ CookieManager.getInstance().removeAllCookies(null);
+ } else {
+ CookieManager.getInstance().removeAllCookie();
+ }
+
+ // Disable caching
+ settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
+ settings.setAppCacheEnabled(false);
+ clearHistory();
+ clearCache(true);
+
+ // No form data or autofill enabled
+ clearFormData();
+ settings.setSavePassword(false);
+ settings.setSaveFormData(false);
+ }
+ else {
+ settings.setCacheMode(WebSettings.LOAD_DEFAULT);
+ settings.setAppCacheEnabled(true);
+ settings.setSavePassword(true);
+ settings.setSaveFormData(true);
+ }
+ }
+
+ public void setCacheEnabled(boolean enabled) {
+ WebSettings settings = getSettings();
+ if (enabled) {
+ Context ctx = getContext();
+ if (ctx != null) {
+ settings.setAppCachePath(ctx.getCacheDir().getAbsolutePath());
+ settings.setCacheMode(WebSettings.LOAD_DEFAULT);
+ settings.setAppCacheEnabled(true);
+ }
+ } else {
+ settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
+ settings.setAppCacheEnabled(false);
+ }
+ }
+
public void loadUrl(String url, MethodChannel.Result result) {
if (!url.isEmpty()) {
loadUrl(url);
@@ -393,6 +787,36 @@ final public class InAppWebView extends InputAwareWebView {
if (newOptionsMap.get("debuggingEnabled") != null && options.debuggingEnabled != newOptions.debuggingEnabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
setWebContentsDebuggingEnabled(newOptions.debuggingEnabled);
+ if (newOptionsMap.get("useShouldInterceptAjaxRequest") != null && options.useShouldInterceptAjaxRequest != newOptions.useShouldInterceptAjaxRequest) {
+ 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) null);
+ } else {
+ loadUrl("javascript:" + sourceJs);
+ }
+ }
+
+ if (newOptionsMap.get("useShouldInterceptFetchRequest") != null && options.useShouldInterceptFetchRequest != newOptions.useShouldInterceptFetchRequest) {
+ 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) null);
+ } else {
+ loadUrl("javascript:" + sourceJs);
+ }
+ }
+
+ if (newOptionsMap.get("useOnLoadResource") != null && options.useOnLoadResource != newOptions.useOnLoadResource) {
+ String placeholderValue = newOptions.useOnLoadResource ? "true" : "false";
+ String sourceJs = InAppWebView.enableVariableForOnLoadResourceJS.replace("$PLACEHOLDER_VALUE", placeholderValue);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ evaluateJavascript(sourceJs, (ValueCallback) null);
+ } else {
+ loadUrl("javascript:" + sourceJs);
+ }
+ }
+
if (newOptionsMap.get("javaScriptCanOpenWindowsAutomatically") != null && options.javaScriptCanOpenWindowsAutomatically != newOptions.javaScriptCanOpenWindowsAutomatically)
settings.setJavaScriptCanOpenWindowsAutomatically(newOptions.javaScriptCanOpenWindowsAutomatically);
@@ -417,11 +841,22 @@ final public class InAppWebView extends InputAwareWebView {
if (newOptionsMap.get("userAgent") != null && !options.userAgent.equals(newOptions.userAgent) && !newOptions.userAgent.isEmpty())
settings.setUserAgentString(newOptions.userAgent);
+ if (newOptionsMap.get("applicationNameForUserAgent") != null && !options.applicationNameForUserAgent.equals(newOptions.applicationNameForUserAgent) && !newOptions.applicationNameForUserAgent.isEmpty()) {
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ String userAgent = (newOptions.userAgent != null && !newOptions.userAgent.isEmpty()) ? newOptions.userAgent : WebSettings.getDefaultUserAgent(getContext());
+ String userAgentWithApplicationName = userAgent + " " + options.applicationNameForUserAgent;
+ settings.setUserAgentString(userAgentWithApplicationName);
+ }
+ }
+
if (newOptionsMap.get("clearCache") != null && newOptions.clearCache)
clearAllCache();
else if (newOptionsMap.get("clearSessionCache") != null && newOptions.clearSessionCache)
CookieManager.getInstance().removeSessionCookie();
+ if (newOptionsMap.get("thirdPartyCookiesEnabled") != null && options.thirdPartyCookiesEnabled != newOptions.thirdPartyCookiesEnabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
+ CookieManager.getInstance().setAcceptThirdPartyCookies(this, newOptions.thirdPartyCookiesEnabled);
+
if (newOptionsMap.get("useWideViewPort") != null && options.useWideViewPort != newOptions.useWideViewPort)
settings.setUseWideViewPort(newOptions.useWideViewPort);
@@ -472,12 +907,11 @@ final public class InAppWebView extends InputAwareWebView {
if (newOptionsMap.get("allowUniversalAccessFromFileURLs") != null && options.allowUniversalAccessFromFileURLs != newOptions.allowUniversalAccessFromFileURLs)
settings.setAllowUniversalAccessFromFileURLs(newOptions.allowUniversalAccessFromFileURLs);
- if (newOptionsMap.get("appCacheEnabled") != null && options.appCacheEnabled != newOptions.appCacheEnabled)
- settings.setAppCacheEnabled(newOptions.appCacheEnabled);
+ if (newOptionsMap.get("cacheEnabled") != null && options.cacheEnabled != newOptions.cacheEnabled)
+ setCacheEnabled(newOptions.cacheEnabled);
if (newOptionsMap.get("appCachePath") != null && !options.appCachePath.equals(newOptions.appCachePath))
- if (newOptions.appCacheEnabled)
- settings.setAppCachePath(newOptions.appCachePath);
+ settings.setAppCachePath(newOptions.appCachePath);
if (newOptionsMap.get("blockNetworkImage") != null && options.blockNetworkImage != newOptions.blockNetworkImage)
settings.setBlockNetworkImage(newOptions.blockNetworkImage);
@@ -551,6 +985,19 @@ final public class InAppWebView extends InputAwareWebView {
if (newOptionsMap.get("standardFontFamily") != null && !options.standardFontFamily.equals(newOptions.standardFontFamily))
settings.setStandardFontFamily(newOptions.standardFontFamily);
+ if (newOptionsMap.get("saveFormData") != null && options.saveFormData != newOptions.saveFormData)
+ settings.setSaveFormData(newOptions.saveFormData);
+
+ if (newOptionsMap.get("incognito") != null && options.incognito != newOptions.incognito)
+ setIncognito(newOptions.incognito);
+
+ if (newOptionsMap.get("hardwareAcceleration") != null && options.hardwareAcceleration != newOptions.hardwareAcceleration) {
+ if (newOptions.hardwareAcceleration)
+ setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ else
+ setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+ }
+
if (newOptions.contentBlockers != null) {
contentBlockerHandler.getRuleList().clear();
for (Map> contentBlocker : newOptions.contentBlockers) {
@@ -630,22 +1077,22 @@ final public class InAppWebView extends InputAwareWebView {
});
}
- public void injectScriptCode(String source, MethodChannel.Result result) {
+ public void evaluateJavascript(String source, MethodChannel.Result result) {
String jsWrapper = "(function(){return JSON.stringify(eval(%s));})();";
injectDeferredObject(source, jsWrapper, result);
}
- public void injectScriptFile(String urlFile) {
+ 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);
}
- public void injectStyleCode(String source) {
+ 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);
}
- public void injectStyleFile(String urlFile) {
+ 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);
}
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewClient.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewClient.java
index dd761a67..067e7961 100644
--- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewClient.java
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewClient.java
@@ -7,7 +7,6 @@ import android.net.http.SslCertificate;
import android.net.http.SslError;
import android.os.Build;
import android.os.Bundle;
-import android.util.Base64;
import android.util.Log;
import android.webkit.ClientCertRequest;
import android.webkit.CookieManager;
@@ -51,9 +50,9 @@ public class InAppWebViewClient extends WebViewClient {
private FlutterWebView flutterWebView;
private InAppBrowserActivity inAppBrowserActivity;
Map statusCodeMapping = new HashMap();
- long startPageTime = 0;
private static int previousAuthRequestFailureCount = 0;
private static List credentialsProposed = null;
+ private String onPageStartedURL = "";
public InAppWebViewClient(Object obj) {
super();
@@ -61,60 +60,7 @@ public class InAppWebViewClient extends WebViewClient {
this.inAppBrowserActivity = (InAppBrowserActivity) obj;
else if (obj instanceof FlutterWebView)
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
public boolean shouldOverrideUrlLoading(WebView webView, String url) {
@@ -183,25 +129,26 @@ public class InAppWebViewClient extends WebViewClient {
return super.shouldOverrideUrlLoading(webView, url);
}
-
- /*
- * onPageStarted fires the LOAD_START_EVENT
- *
- * @param view
- * @param url
- * @param favicon
- */
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
InAppWebView webView = (InAppWebView) view;
- if (webView.options.useOnLoadResource)
- webView.loadUrl("javascript:" + webView.resourceObserverJS.replaceAll("[\r\n]+", ""));
+ webView.loadUrl("javascript:" + InAppWebView.consoleLogJS.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]+", ""));
+ }
+ onPageStartedURL = url;
super.onPageStarted(view, url, favicon);
- startPageTime = System.currentTimeMillis();
webView.isLoading = true;
if (inAppBrowserActivity != null && inAppBrowserActivity.searchView != null && !url.equals(inAppBrowserActivity.searchView.getQuery().toString())) {
inAppBrowserActivity.searchView.setQuery(url, false);
@@ -215,8 +162,8 @@ public class InAppWebViewClient extends WebViewClient {
}
- public void onPageFinished(final WebView view, String url) {
- InAppWebView webView = (InAppWebView) view;
+ public void onPageFinished(WebView view, String url) {
+ final InAppWebView webView = (InAppWebView) view;
super.onPageFinished(view, url);
@@ -236,18 +183,9 @@ public class InAppWebViewClient extends WebViewClient {
view.requestFocus();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- view.evaluateJavascript(InAppWebView.consoleLogJS, null);
- view.evaluateJavascript(JavaScriptBridgeInterface.flutterInAppBroserJSClass, new ValueCallback() {
- @Override
- public void onReceiveValue(String value) {
- view.evaluateJavascript(InAppWebView.platformReadyJS, null);
- }
- });
-
+ webView.evaluateJavascript(InAppWebView.platformReadyJS, (ValueCallback) null);
} else {
- view.loadUrl("javascript:" + InAppWebView.consoleLogJS);
- view.loadUrl("javascript:" + JavaScriptBridgeInterface.flutterInAppBroserJSClass);
- view.loadUrl("javascript:" + InAppWebView.platformReadyJS);
+ webView.loadUrl("javascript:" + InAppWebView.platformReadyJS.replaceAll("[\r\n]+", ""));
}
Map obj = new HashMap<>();
@@ -257,6 +195,21 @@ public class InAppWebViewClient extends WebViewClient {
getChannel().invokeMethod("onLoadStop", obj);
}
+ @Override
+ public void doUpdateVisitedHistory (WebView view, String url, boolean isReload) {
+ super.doUpdateVisitedHistory(view, url, isReload);
+
+ if (!isReload && !url.equals(onPageStartedURL)) {
+ onPageStartedURL = "";
+ Map obj = new HashMap<>();
+ if (inAppBrowserActivity != null)
+ obj.put("uuid", inAppBrowserActivity.uuid);
+ obj.put("url", url);
+ getChannel().invokeMethod("onNavigationStateChange", obj);
+ }
+ }
+
+ @Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewOptions.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewOptions.java
index 6b8254f3..5d547b87 100644
--- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewOptions.java
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewOptions.java
@@ -12,42 +12,46 @@ public class InAppWebViewOptions extends Options {
public static final String LOG_TAG = "InAppWebViewOptions";
- public boolean useShouldOverrideUrlLoading = false;
- public boolean useOnLoadResource = false;
- public boolean useOnDownloadStart = false;
- public boolean useOnTargetBlank = false;
- public boolean clearCache = false;
+ public Boolean useShouldOverrideUrlLoading = false;
+ public Boolean useOnLoadResource = false;
+ public Boolean useOnDownloadStart = false;
+ public Boolean useOnTargetBlank = false;
+ public Boolean clearCache = false;
public String userAgent = "";
- public boolean javaScriptEnabled = true;
- public boolean debuggingEnabled = false;
- public boolean javaScriptCanOpenWindowsAutomatically = false;
- public boolean mediaPlaybackRequiresUserGesture = true;
+ public String applicationNameForUserAgent = "";
+ public Boolean javaScriptEnabled = true;
+ public Boolean debuggingEnabled = false;
+ public Boolean javaScriptCanOpenWindowsAutomatically = false;
+ public Boolean mediaPlaybackRequiresUserGesture = true;
public Integer textZoom = 100;
public Integer minimumFontSize = 8;
- public boolean verticalScrollBarEnabled = true;
- public boolean horizontalScrollBarEnabled = true;
+ public Boolean verticalScrollBarEnabled = true;
+ public Boolean horizontalScrollBarEnabled = true;
public List resourceCustomSchemes = new ArrayList<>();
public List