Commit aa20beaf authored by Lorenzo Pichilli's avatar Lorenzo Pichilli

updated shouldOverrideUrlLoading event for #146, added print method and event...

updated shouldOverrideUrlLoading event for #146, added print method and event #128, fix #123 javascript handler for Android API <= 22, renamed onTargetBlank to onCreateWindow event, deleted useOnTargetBlank option, added supportMultipleWindows android option, added getDefaultUserAgent static method, Updated default value for domStorageEnabled option to true
parent 3fd1f955
This diff is collapsed.
## 2.2.0
- Updated `clearCache` for Android
- Added `Promise` javascript [polyfill](https://github.com/taylorhakes/promise-polyfill/blob/master/src/index.js) for webviews that doesn't support it for `window.flutter_inappwebview.callHandler`
- Added `getDefaultUserAgent` static method to `InAppWebViewController`
- Added `printCurrentPage` method to `InAppWebViewController`
- Added `onPrint` event
- Added `supportMultipleWindows` webview option for Android
- Added `regexToCancelSubFramesLoading` webview option for Android to cancel subframe requests on `shouldOverrideUrlLoading` event based on a Regular Expression
- Updated default value for `domStorageEnabled` option to `true` for Android
- Fix for Android `InAppBrowser` for some controller methods not exposed.
### BREAKING CHANGES
- Updated `shouldOverrideUrlLoading` event:
- the `url` parameter has been moved inside an instance of `ShouldOverrideUrlLoadingRequest` class
- it has a return type `ShouldOverrideUrlLoadingAction` to allow or cancel navigation instead of cancel every time the request
- Renamed `onTargetBlank` to `onCreateWindow`
- Deleted `useOnTargetBlank` webview option
## 2.1.0+1 ## 2.1.0+1
- Fix docs - Fix docs
......
...@@ -76,6 +76,10 @@ Classes: ...@@ -76,6 +76,10 @@ Classes:
See the online [API Reference](https://pub.dartlang.org/documentation/flutter_inappwebview/latest/) to get the full documentation. See the online [API Reference](https://pub.dartlang.org/documentation/flutter_inappwebview/latest/) to get the full documentation.
The API showed in this `README.md` file shows only a part of the documentation that conforms to the master branch only.
So, here you could have methods, options, and events that aren't published yet.
If you need a specific version, change the **GitHub branch** to your version or use the **online API Reference** (recommended).
### Load a file inside `assets` folder ### Load a file inside `assets` folder
To be able to load your local files (assets, js, css, etc.), you need to add them in the `assets` section of the `pubspec.yaml` file, otherwise they cannot be found! To be able to load your local files (assets, js, css, etc.), you need to add them in the `assets` section of the `pubspec.yaml` file, otherwise they cannot be found!
...@@ -286,6 +290,8 @@ Screenshots: ...@@ -286,6 +290,8 @@ Screenshots:
* `getTRexRunnerCss`: Gets the css of the Chromium's t-rex runner game. Used in combination with `getTRexRunnerHtml()`. * `getTRexRunnerCss`: Gets the css of the Chromium's t-rex runner game. Used in combination with `getTRexRunnerHtml()`.
* `scrollTo({@required int x, @required int y})`: Scrolls the WebView to the position. * `scrollTo({@required int x, @required int y})`: Scrolls the WebView to the position.
* `scrollBy({@required int x, @required int y})`: Moves the scrolled position of the WebView. * `scrollBy({@required int x, @required int y})`: Moves the scrolled position of the WebView.
* `printCurrentPage`: Prints the current page.
* `static getDefaultUserAgent`: Gets the default user agent.
##### About the JavaScript handler ##### About the JavaScript handler
...@@ -339,7 +345,6 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly: ...@@ -339,7 +345,6 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly:
* `useShouldOverrideUrlLoading`: Set to `true` to be able to listen at the `shouldOverrideUrlLoading` event. The default value is `false`. * `useShouldOverrideUrlLoading`: Set to `true` to be able to listen at the `shouldOverrideUrlLoading` event. The default value is `false`.
* `useOnLoadResource`: Set to `true` to be able to listen at the `onLoadResource` event. The default value is `false`. * `useOnLoadResource`: Set to `true` to be able to listen at the `onLoadResource` event. The default value is `false`.
* `useOnDownloadStart`: Set to `true` to be able to listen at the `onDownloadStart` event. The default value is `false`. * `useOnDownloadStart`: Set to `true` to be able to listen at the `onDownloadStart` event. The default value is `false`.
* `useOnTargetBlank`: Set to `true` to be able to listen at the `onTargetBlank` event. The default value is `false`.
* `clearCache`: Set to `true` to have all the browser's cache cleared before the new window is opened. The default value is `false`. * `clearCache`: Set to `true` to have all the browser's cache cleared before the new window is opened. The default value is `false`.
* `userAgent`: Sets the user-agent for the WebView. * `userAgent`: Sets the user-agent for the WebView.
* `applicationNameForUserAgent`: Append to the existing user-agent. Setting userAgent will override this. * `applicationNameForUserAgent`: Append to the existing user-agent. Setting userAgent will override this.
...@@ -369,7 +374,7 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly: ...@@ -369,7 +374,7 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly:
* `displayZoomControls`: Set to `true` if the WebView should display on-screen zoom controls when using the built-in zoom mechanisms. The default value is `false`. * `displayZoomControls`: Set to `true` if the WebView should display on-screen zoom controls when using the built-in zoom mechanisms. The default value is `false`.
* `supportZoom`: Set to `false` if the WebView should not support zooming using its on-screen zoom controls and gestures. The default value is `true`. * `supportZoom`: Set to `false` if the WebView should not support zooming using its on-screen zoom controls and gestures. The default value is `true`.
* `databaseEnabled`: Set to `true` if you want the database storage API is enabled. The default value is `false`. * `databaseEnabled`: Set to `true` if you want the database storage API is enabled. The default value is `false`.
* `domStorageEnabled`: Set to `true` if you want the DOM storage API is enabled. The default value is `false`. * `domStorageEnabled`: Set to `true` if you want the DOM storage API is enabled. The default value is `true`.
* `useWideViewPort`: Set to `true` if the WebView should enable support for the "viewport" HTML meta tag or should use a wide viewport. * `useWideViewPort`: Set to `true` if the WebView should enable support for the "viewport" HTML meta tag or should use a wide viewport.
* `safeBrowsingEnabled`: Sets whether Safe Browsing is enabled. Safe Browsing allows WebView to protect against malware and phishing attacks by verifying the links. * `safeBrowsingEnabled`: Sets whether Safe Browsing is enabled. Safe Browsing allows WebView to protect against malware and phishing attacks by verifying the links.
* `mixedContentMode`: Configures the WebView's behavior when a secure origin attempts to load a resource from an insecure origin. * `mixedContentMode`: Configures the WebView's behavior when a secure origin attempts to load a resource from an insecure origin.
...@@ -403,6 +408,7 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly: ...@@ -403,6 +408,7 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly:
* `saveFormData`: Sets whether the WebView should save form data. In Android O, the platform has implemented a fully functional Autofill feature to store form data. * `saveFormData`: Sets whether the WebView should save form data. In Android O, the platform has implemented a fully functional Autofill feature to store form data.
* `thirdPartyCookiesEnabled`: Boolean value to enable third party cookies in the WebView. * `thirdPartyCookiesEnabled`: Boolean value to enable third party cookies in the WebView.
* `hardwareAcceleration`: Boolean value to enable Hardware Acceleration in the WebView. * `hardwareAcceleration`: Boolean value to enable Hardware Acceleration in the WebView.
* `supportMultipleWindows`: Sets whether the WebView whether supports multiple windows.
##### `InAppWebView` iOS-specific options ##### `InAppWebView` iOS-specific options
...@@ -429,12 +435,13 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly: ...@@ -429,12 +435,13 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly:
* `onLoadHttpError`: Event fired when the InAppWebView main page receives an HTTP error. * `onLoadHttpError`: Event fired when the InAppWebView main page receives an HTTP error.
* `onProgressChanged`: Event fired when the current progress of loading a page is changed. * `onProgressChanged`: Event fired when the current progress of loading a page is changed.
* `onConsoleMessage`: Event fired when the InAppWebView receives a ConsoleMessage. * `onConsoleMessage`: Event fired when the InAppWebView receives a ConsoleMessage.
* `shouldOverrideUrlLoading`: Give the host application a chance to take control when a URL is about to be loaded in the current WebView (to use this event, the `useShouldOverrideUrlLoading` option must be `true`). * `shouldOverrideUrlLoading`: Give the host application a chance to take control when a URL is about to be loaded in the current WebView (to use this event, the `useShouldOverrideUrlLoading` option must be `true`). This event is not called on the initial load of the WebView.
* `onNavigationStateChange`: Event fired when the navigation state of the InAppWebView changes, for example through the usage of the javascript **[History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API)** functions.
* `onLoadResource`: Event fired when the InAppWebView loads a resource (to use this event, the `useOnLoadResource` option must be `true`). * `onLoadResource`: Event fired when the InAppWebView loads a resource (to use this event, the `useOnLoadResource` option must be `true`).
* `onScrollChanged`: Event fired when the InAppWebView scrolls. * `onScrollChanged`: Event fired when the InAppWebView scrolls.
* `onDownloadStart`: Event fired when InAppWebView recognizes and starts a downloadable file (to use this event, the `useOnDownloadStart` option must be `true`). * `onDownloadStart`: Event fired when InAppWebView recognizes and starts a downloadable file (to use this event, the `useOnDownloadStart` option must be `true`).
* `onLoadResourceCustomScheme`: Event fired when the InAppWebView finds the `custom-scheme` while loading a resource. Here you can handle the url request and return a CustomSchemeResponse to load a specific resource encoded to `base64`. * `onLoadResourceCustomScheme`: Event fired when the InAppWebView finds the `custom-scheme` while loading a resource. Here you can handle the url request and return a CustomSchemeResponse to load a specific resource encoded to `base64`.
* `onTargetBlank`: Event fired when the InAppWebView tries to open a link with `target="_blank"` (to use this event, the `useOnTargetBlank` option must be `true`). * `onCreateWindow`: Event fired when the InAppWebView requests the host application to create a new window, for example when trying to open a link with `target="_blank"` or when `window.open()` is called by JavaScript side.
* `onGeolocationPermissionsShowPrompt`: Event that notifies the host application that web content from the specified origin is attempting to use the Geolocation API, but no permission state is currently set for that origin (available only on Android). * `onGeolocationPermissionsShowPrompt`: Event that notifies the host application that web content from the specified origin is attempting to use the Geolocation API, but no permission state is currently set for that origin (available only on Android).
* `onJsAlert`: Event fired when javascript calls the `alert()` method to display an alert dialog. * `onJsAlert`: Event fired when javascript calls the `alert()` method to display an alert dialog.
* `onJsConfirm`: Event fired when javascript calls the `confirm()` method to display a confirm dialog. * `onJsConfirm`: Event fired when javascript calls the `confirm()` method to display a confirm dialog.
...@@ -448,8 +455,8 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly: ...@@ -448,8 +455,8 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly:
* `onAjaxReadyStateChange`: Event fired whenever the `readyState` attribute of an `XMLHttpRequest` changes (to use this event, the `useShouldInterceptAjaxRequest` option must be `true`). * `onAjaxReadyStateChange`: Event fired whenever the `readyState` attribute of an `XMLHttpRequest` changes (to use this event, the `useShouldInterceptAjaxRequest` option must be `true`).
* `onAjaxProgress`: Event fired as an `XMLHttpRequest` progress (to use this event, the `useShouldInterceptAjaxRequest` option must be `true`). * `onAjaxProgress`: Event fired as an `XMLHttpRequest` progress (to use this event, the `useShouldInterceptAjaxRequest` option must be `true`).
* `shouldInterceptFetchRequest`: Event fired when a request is sent to a server through [Fetch API](https://developer.mozilla.org/it/docs/Web/API/Fetch_API) (to use this event, the `useShouldInterceptFetchRequest` option must be `true`). * `shouldInterceptFetchRequest`: Event fired when a request is sent to a server through [Fetch API](https://developer.mozilla.org/it/docs/Web/API/Fetch_API) (to use this event, the `useShouldInterceptFetchRequest` option must be `true`).
* `onNavigationStateChange`: Event fired when the navigation state of the InAppWebView changes.
* `onPermissionRequest`: Event fired when the webview is requesting permission to access the specified resources and the permission currently isn't granted or denied (available only on Android). * `onPermissionRequest`: Event fired when the webview is requesting permission to access the specified resources and the permission currently isn't granted or denied (available only on Android).
* `onPrint`: Event fired when `window.print()` is called from JavaScript side.
### `InAppBrowser` class ### `InAppBrowser` class
...@@ -495,9 +502,9 @@ class MyInAppBrowser extends InAppBrowser { ...@@ -495,9 +502,9 @@ class MyInAppBrowser extends InAppBrowser {
} }
@override @override
void shouldOverrideUrlLoading(String url) { void shouldOverrideUrlLoading(ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest) {
print("\n\n override $url\n\n"); print("\n\n override ${shouldOverrideUrlLoadingRequest.url}\n\n");
this.webViewController.loadUrl(url: url); this.webViewController.loadUrl(url: shouldOverrideUrlLoadingRequest.url);
} }
@override @override
......
...@@ -334,6 +334,14 @@ public class FlutterWebView implements PlatformView, MethodCallHandler { ...@@ -334,6 +334,14 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
result.success(false); result.success(false);
} }
break; break;
case "printCurrentPage":
if (webView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
webView.printCurrentPage();
result.success(true);
} else {
result.success(false);
}
break;
default: default:
result.notImplemented(); result.notImplemented();
} }
......
...@@ -25,6 +25,7 @@ import android.app.Activity; ...@@ -25,6 +25,7 @@ import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.Parcelable; import android.os.Parcelable;
import android.provider.Browser; import android.provider.Browser;
import android.net.Uri; import android.net.Uri;
...@@ -34,6 +35,8 @@ import android.webkit.WebView; ...@@ -34,6 +35,8 @@ import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import android.util.Log; import android.util.Log;
import androidx.annotation.RequiresApi;
import com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ChromeCustomTabsActivity; import com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ChromeCustomTabsActivity;
import com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.CustomTabActivityHelper; import com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.CustomTabActivityHelper;
...@@ -307,13 +310,51 @@ public class InAppBrowser implements MethodChannel.MethodCallHandler { ...@@ -307,13 +310,51 @@ public class InAppBrowser implements MethodChannel.MethodCallHandler {
case "clearMatches": case "clearMatches":
clearMatches(uuid, result); clearMatches(uuid, result);
break; break;
case "scrollTo":
{
Integer x = (Integer) call.argument("x");
Integer y = (Integer) call.argument("y");
scrollTo(uuid, x, y);
}
result.success(true);
break;
case "scrollBy":
{
Integer x = (Integer) call.argument("x");
Integer y = (Integer) call.argument("y");
scrollBy(uuid, x, y);
}
result.success(true);
break;
case "pause":
onPause(uuid);
result.success(true);
break;
case "resume":
onResume(uuid);
result.success(true);
break;
case "pauseTimers":
pauseTimers(uuid);
result.success(true);
break;
case "resumeTimers":
resumeTimers(uuid);
result.success(true);
break;
case "printCurrentPage":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
printCurrentPage(uuid);
}
result.success(true);
break;
default: default:
result.notImplemented(); result.notImplemented();
} }
} }
private void evaluateJavascript(String uuid, String source, final Result result) { public 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.evaluateJavascript(source, result); inAppBrowserActivity.evaluateJavascript(source, result);
...@@ -322,21 +363,21 @@ public class InAppBrowser implements MethodChannel.MethodCallHandler { ...@@ -322,21 +363,21 @@ public class InAppBrowser implements MethodChannel.MethodCallHandler {
} }
} }
private void injectJavascriptFileFromUrl(String uuid, String urlFile) { public 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.injectJavascriptFileFromUrl(urlFile); inAppBrowserActivity.injectJavascriptFileFromUrl(urlFile);
} }
} }
private void injectCSSCode(String uuid, String source) { public 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.injectCSSCode(source); inAppBrowserActivity.injectCSSCode(source);
} }
} }
private void injectCSSFileFromUrl(String uuid, String urlFile) { public 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.injectCSSFileFromUrl(urlFile); inAppBrowserActivity.injectCSSFileFromUrl(urlFile);
...@@ -386,7 +427,7 @@ public class InAppBrowser implements MethodChannel.MethodCallHandler { ...@@ -386,7 +427,7 @@ public class InAppBrowser implements MethodChannel.MethodCallHandler {
* Opens the intent, providing a chooser that excludes the current app to avoid * Opens the intent, providing a chooser that excludes the current app to avoid
* circular loops. * circular loops.
*/ */
private void openExternalExcludeCurrentApp(Activity activity, Intent intent) { public void openExternalExcludeCurrentApp(Activity activity, Intent intent) {
String currentPackage = activity.getPackageName(); String currentPackage = activity.getPackageName();
boolean hasCurrentPackage = false; boolean hasCurrentPackage = false;
PackageManager pm = activity.getPackageManager(); PackageManager pm = activity.getPackageManager();
...@@ -479,21 +520,21 @@ public class InAppBrowser implements MethodChannel.MethodCallHandler { ...@@ -479,21 +520,21 @@ public class InAppBrowser implements MethodChannel.MethodCallHandler {
activity.startActivity(intent); activity.startActivity(intent);
} }
private String getUrl(String uuid) { public String getUrl(String uuid) {
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid); InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null) if (inAppBrowserActivity != null)
return inAppBrowserActivity.getUrl(); return inAppBrowserActivity.getUrl();
return null; return null;
} }
private String getTitle(String uuid) { public String getTitle(String uuid) {
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid); InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null) if (inAppBrowserActivity != null)
return inAppBrowserActivity.getWebViewTitle(); return inAppBrowserActivity.getWebViewTitle();
return null; return null;
} }
private Integer getProgress(String uuid) { public Integer getProgress(String uuid) {
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid); InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null) if (inAppBrowserActivity != null)
return inAppBrowserActivity.getProgress(); return inAppBrowserActivity.getProgress();
...@@ -730,6 +771,49 @@ public class InAppBrowser implements MethodChannel.MethodCallHandler { ...@@ -730,6 +771,49 @@ public class InAppBrowser implements MethodChannel.MethodCallHandler {
result.success(false); result.success(false);
} }
public void scrollTo(String uuid, Integer x, Integer y) {
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null)
inAppBrowserActivity.scrollTo(x, y);
}
public void scrollBy(String uuid, Integer x, Integer y) {
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null)
inAppBrowserActivity.scrollBy(x, y);
}
public void onPause(String uuid) {
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null)
inAppBrowserActivity.onPauseWebView();
}
public void onResume(String uuid) {
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null)
inAppBrowserActivity.onResumeWebView();
}
public void pauseTimers(String uuid) {
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null)
inAppBrowserActivity.pauseTimers();
}
public void resumeTimers(String uuid) {
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null)
inAppBrowserActivity.resumeTimers();
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void printCurrentPage(String uuid) {
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null)
inAppBrowserActivity.printCurrentPage();
}
public void dispose() { public void dispose() {
channel.setMethodCallHandler(null); channel.setMethodCallHandler(null);
for ( InAppBrowserActivity activity : webViewActivities.values()) { for ( InAppBrowserActivity activity : webViewActivities.values()) {
......
...@@ -6,6 +6,8 @@ import android.graphics.Canvas; ...@@ -6,6 +6,8 @@ import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Picture; import android.graphics.Picture;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
...@@ -537,4 +539,41 @@ public class InAppBrowserActivity extends AppCompatActivity { ...@@ -537,4 +539,41 @@ public class InAppBrowserActivity extends AppCompatActivity {
webView.loadUrl("about:blank"); webView.loadUrl("about:blank");
} }
} }
public void scrollTo(Integer x, Integer y) {
if (webView != null)
webView.scrollTo(x, y);
}
public void scrollBy(Integer x, Integer y) {
if (webView != null)
webView.scrollBy(x, y);
}
public void onPauseWebView() {
if (webView != null)
webView.onPause();
}
public void onResumeWebView() {
if (webView != null)
webView.onResume();
}
public void pauseTimers() {
if (webView != null)
webView.pauseTimers();
}
public void resumeTimers() {
if (webView != null)
webView.resumeTimers();
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void printCurrentPage() {
if (webView != null)
webView.printCurrentPage();
}
} }
...@@ -6,6 +6,9 @@ import android.graphics.Bitmap; ...@@ -6,6 +6,9 @@ import android.graphics.Bitmap;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.os.Build; import android.os.Build;
import android.print.PrintAttributes;
import android.print.PrintDocumentAdapter;
import android.print.PrintManager;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log; import android.util.Log;
import android.view.MotionEvent; import android.view.MotionEvent;
...@@ -18,6 +21,8 @@ import android.webkit.WebHistoryItem; ...@@ -18,6 +21,8 @@ import android.webkit.WebHistoryItem;
import android.webkit.WebSettings; import android.webkit.WebSettings;
import android.webkit.WebStorage; import android.webkit.WebStorage;
import androidx.annotation.RequiresApi;
import com.pichillilorenzo.flutter_inappwebview.ContentBlocker.ContentBlocker; import com.pichillilorenzo.flutter_inappwebview.ContentBlocker.ContentBlocker;
import com.pichillilorenzo.flutter_inappwebview.ContentBlocker.ContentBlockerAction; import com.pichillilorenzo.flutter_inappwebview.ContentBlocker.ContentBlockerAction;
import com.pichillilorenzo.flutter_inappwebview.ContentBlocker.ContentBlockerHandler; import com.pichillilorenzo.flutter_inappwebview.ContentBlocker.ContentBlockerHandler;
...@@ -34,12 +39,13 @@ import java.util.ArrayList; ...@@ -34,12 +39,13 @@ import java.util.ArrayList;
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 java.util.regex.Pattern;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.PluginRegistry; import io.flutter.plugin.common.PluginRegistry;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import static com.pichillilorenzo.flutter_inappwebview.InAppWebView.PreferredContentModeOptionType.*; import static com.pichillilorenzo.flutter_inappwebview.InAppWebView.PreferredContentModeOptionType.fromValue;
final public class InAppWebView extends InputAwareWebView { final public class InAppWebView extends InputAwareWebView {
...@@ -57,6 +63,7 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -57,6 +63,7 @@ final public class InAppWebView extends InputAwareWebView {
public float scale = getResources().getDisplayMetrics().density; public float scale = getResources().getDisplayMetrics().density;
int okHttpClientCacheSize = 10 * 1024 * 1024; // 10MB int okHttpClientCacheSize = 10 * 1024 * 1024; // 10MB
public ContentBlockerHandler contentBlockerHandler = new ContentBlockerHandler(); public ContentBlockerHandler contentBlockerHandler = new ContentBlockerHandler();
public Pattern regexToCancelSubFramesLoadingCompiled;
static final String consoleLogJS = "(function(console) {" + static final String consoleLogJS = "(function(console) {" +
" var oldLogs = {" + " var oldLogs = {" +
...@@ -84,6 +91,10 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -84,6 +91,10 @@ final public class InAppWebView extends InputAwareWebView {
" }" + " }" +
"})(window.console);"; "})(window.console);";
static final String printJS = "window.print = function() {" +
" window." + JavaScriptBridgeInterface.name + ".callHandler('onPrint', window.location.href);" +
"}";
static final String platformReadyJS = "window.dispatchEvent(new Event('flutterInAppWebViewPlatformReady'));"; static final String platformReadyJS = "window.dispatchEvent(new Event('flutterInAppWebViewPlatformReady'));";
static final String variableForOnLoadResourceJS = "window._flutter_inappwebview_useOnLoadResource"; static final String variableForOnLoadResourceJS = "window._flutter_inappwebview_useOnLoadResource";
...@@ -554,7 +565,7 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -554,7 +565,7 @@ final public class InAppWebView extends InputAwareWebView {
settings.setJavaScriptCanOpenWindowsAutomatically(options.javaScriptCanOpenWindowsAutomatically); settings.setJavaScriptCanOpenWindowsAutomatically(options.javaScriptCanOpenWindowsAutomatically);
settings.setBuiltInZoomControls(options.builtInZoomControls); settings.setBuiltInZoomControls(options.builtInZoomControls);
settings.setDisplayZoomControls(options.displayZoomControls); settings.setDisplayZoomControls(options.displayZoomControls);
settings.setSupportMultipleWindows(options.useOnTargetBlank); settings.setSupportMultipleWindows(options.supportMultipleWindows);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
settings.setSafeBrowsingEnabled(options.safeBrowsingEnabled); settings.setSafeBrowsingEnabled(options.safeBrowsingEnabled);
...@@ -571,7 +582,7 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -571,7 +582,7 @@ final public class InAppWebView extends InputAwareWebView {
if (options.applicationNameForUserAgent != null && !options.applicationNameForUserAgent.isEmpty()) { if (options.applicationNameForUserAgent != null && !options.applicationNameForUserAgent.isEmpty()) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 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 userAgent = (options.userAgent != null && !options.userAgent.isEmpty()) ? options.userAgent : WebSettings.getDefaultUserAgent(getContext());
String userAgentWithApplicationName = userAgent + " " + options.applicationNameForUserAgent; String userAgentWithApplicationName = userAgent + " " + options.applicationNameForUserAgent;
settings.setUserAgentString(userAgentWithApplicationName); settings.setUserAgentString(userAgentWithApplicationName);
} }
...@@ -655,6 +666,9 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -655,6 +666,9 @@ final public class InAppWebView extends InputAwareWebView {
setLayerType(View.LAYER_TYPE_HARDWARE, null); setLayerType(View.LAYER_TYPE_HARDWARE, null);
else else
setLayerType(View.LAYER_TYPE_SOFTWARE, null); setLayerType(View.LAYER_TYPE_SOFTWARE, null);
if (options.regexToCancelSubFramesLoading != null) {
regexToCancelSubFramesLoadingCompiled = Pattern.compile(options.regexToCancelSubFramesLoading);
}
contentBlockerHandler.getRuleList().clear(); contentBlockerHandler.getRuleList().clear();
for (Map<String, Map<String, Object>> contentBlocker : options.contentBlockers) { for (Map<String, Map<String, Object>> contentBlocker : options.contentBlockers) {
...@@ -996,8 +1010,8 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -996,8 +1010,8 @@ final public class InAppWebView extends InputAwareWebView {
if (newOptionsMap.get("mixedContentMode") != null && !options.mixedContentMode.equals(newOptions.mixedContentMode)) if (newOptionsMap.get("mixedContentMode") != null && !options.mixedContentMode.equals(newOptions.mixedContentMode))
settings.setMixedContentMode(newOptions.mixedContentMode); settings.setMixedContentMode(newOptions.mixedContentMode);
if (newOptionsMap.get("useOnTargetBlank") != null && options.useOnTargetBlank != newOptions.useOnTargetBlank) if (newOptionsMap.get("supportMultipleWindows") != null && options.supportMultipleWindows != newOptions.supportMultipleWindows)
settings.setSupportMultipleWindows(newOptions.useOnTargetBlank); settings.setSupportMultipleWindows(newOptions.supportMultipleWindows);
if (newOptionsMap.get("useOnDownloadStart") != null && options.useOnDownloadStart != newOptions.useOnDownloadStart) { if (newOptionsMap.get("useOnDownloadStart") != null && options.useOnDownloadStart != newOptions.useOnDownloadStart) {
if (newOptions.useOnDownloadStart) { if (newOptions.useOnDownloadStart) {
...@@ -1127,6 +1141,13 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -1127,6 +1141,13 @@ final public class InAppWebView extends InputAwareWebView {
setLayerType(View.LAYER_TYPE_SOFTWARE, null); setLayerType(View.LAYER_TYPE_SOFTWARE, null);
} }
if (newOptionsMap.get("regexToCancelSubFramesLoading") != null && options.regexToCancelSubFramesLoading != newOptions.regexToCancelSubFramesLoading) {
if (newOptions.regexToCancelSubFramesLoading == null)
regexToCancelSubFramesLoadingCompiled = null;
else
regexToCancelSubFramesLoadingCompiled = Pattern.compile(options.regexToCancelSubFramesLoading);
}
if (newOptions.contentBlockers != null) { if (newOptions.contentBlockers != null) {
contentBlockerHandler.getRuleList().clear(); contentBlockerHandler.getRuleList().clear();
for (Map<String, Map<String, Object>> contentBlocker : newOptions.contentBlockers) { for (Map<String, Map<String, Object>> contentBlocker : newOptions.contentBlockers) {
...@@ -1304,6 +1325,22 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -1304,6 +1325,22 @@ final public class InAppWebView extends InputAwareWebView {
webSettings.setBuiltInZoomControls(enabled); webSettings.setBuiltInZoomControls(enabled);
} }
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void printCurrentPage() {
// Get a PrintManager instance
PrintManager printManager = (PrintManager) registrar.activity()
.getSystemService(Context.PRINT_SERVICE);
String jobName = getTitle() + " Document";
// Get a printCurrentPage adapter instance
PrintDocumentAdapter printAdapter = createPrintDocumentAdapter(jobName);
// Create a printCurrentPage job with name and adapter instance
printManager.print(jobName, printAdapter,
new PrintAttributes.Builder().build());
}
@Override @Override
public void dispose() { public void dispose() {
super.dispose(); super.dispose();
......
...@@ -418,16 +418,16 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR ...@@ -418,16 +418,16 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
if (data == null) { if (data == null) {
// to get the URL, create a temp weview // to get the URL, create a temp weview
final WebView newWebView = new WebView(view.getContext()); final WebView tempWebView = new WebView(view.getContext());
// disable javascript // disable javascript
newWebView.getSettings().setJavaScriptEnabled(false); tempWebView.getSettings().setJavaScriptEnabled(false);
newWebView.setWebViewClient(new WebViewClient(){ tempWebView.setWebViewClient(new WebViewClient(){
@Override @Override
public void onPageStarted(WebView v, String url, Bitmap favicon) { public void onPageStarted(WebView v, String url, Bitmap favicon) {
super.onPageStarted(v, url, favicon); super.onPageStarted(v, url, favicon);
obj.put("url", url); obj.put("url", url);
getChannel().invokeMethod("onTargetBlank", obj); getChannel().invokeMethod("onCreateWindow", obj);
// stop webview loading // stop webview loading
v.stopLoading(); v.stopLoading();
...@@ -437,13 +437,13 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR ...@@ -437,13 +437,13 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
v.destroy(); v.destroy();
} }
}); });
((WebView.WebViewTransport)resultMsg.obj).setWebView(newWebView); ((WebView.WebViewTransport) resultMsg.obj).setWebView(tempWebView);
resultMsg.sendToTarget(); resultMsg.sendToTarget();
return true; return true;
} }
obj.put("url", data); obj.put("url", data);
getChannel().invokeMethod("onTargetBlank", obj); getChannel().invokeMethod("onCreateWindow", obj);
return false; return false;
} }
......
package com.pichillilorenzo.flutter_inappwebview.InAppWebView; package com.pichillilorenzo.flutter_inappwebview.InAppWebView;
import android.content.Intent; import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.net.Uri;
import android.net.http.SslCertificate; 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.Log; import android.util.Log;
import android.view.KeyEvent;
import android.webkit.ClientCertRequest; import android.webkit.ClientCertRequest;
import android.webkit.CookieManager; import android.webkit.CookieManager;
import android.webkit.CookieSyncManager; import android.webkit.CookieSyncManager;
...@@ -43,6 +44,7 @@ import java.security.cert.X509Certificate; ...@@ -43,6 +44,7 @@ import java.security.cert.X509Certificate;
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 java.util.regex.Matcher;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
...@@ -51,7 +53,6 @@ public class InAppWebViewClient extends WebViewClient { ...@@ -51,7 +53,6 @@ public class InAppWebViewClient extends WebViewClient {
protected static final String LOG_TAG = "IABWebViewClient"; protected static final String LOG_TAG = "IABWebViewClient";
private FlutterWebView flutterWebView; private FlutterWebView flutterWebView;
private InAppBrowserActivity inAppBrowserActivity; private InAppBrowserActivity inAppBrowserActivity;
Map<Integer, String> statusCodeMapping = new HashMap<Integer, String>();
private static int previousAuthRequestFailureCount = 0; private static int previousAuthRequestFailureCount = 0;
private static List<Credential> credentialsProposed = null; private static List<Credential> credentialsProposed = null;
private String onPageStartedURL = ""; private String onPageStartedURL = "";
...@@ -63,72 +64,105 @@ public class InAppWebViewClient extends WebViewClient { ...@@ -63,72 +64,105 @@ public class InAppWebViewClient extends WebViewClient {
else if (obj instanceof FlutterWebView) else if (obj instanceof FlutterWebView)
this.flutterWebView = (FlutterWebView) obj; this.flutterWebView = (FlutterWebView) obj;
} }
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override @Override
public boolean shouldOverrideUrlLoading(WebView webView, String url) { public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
InAppWebView webView = (InAppWebView) view;
if (webView.options.useShouldOverrideUrlLoading) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
onShouldOverrideUrlLoading(
request.getUrl().toString(),
request.getMethod(),
request.getRequestHeaders(),
request.isForMainFrame(),
request.hasGesture(),
request.isRedirect());
} else {
onShouldOverrideUrlLoading(
request.getUrl().toString(),
request.getMethod(),
request.getRequestHeaders(),
request.isForMainFrame(),
request.hasGesture(),
false);
}
if (webView.regexToCancelSubFramesLoadingCompiled != null) {
if (request.isForMainFrame())
return true;
else {
Matcher m = webView.regexToCancelSubFramesLoadingCompiled.matcher(request.getUrl().toString());
if (m.matches())
return true;
else
return false;
}
} else {
// There isn't any way to load an URL for a frame that is not the main frame,
// so if the request is not for the main frame, the navigation is allowed.
return request.isForMainFrame();
}
}
return false;
}
@Override
public boolean shouldOverrideUrlLoading(WebView webView, String url) {
if (((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView).options.useShouldOverrideUrlLoading) { if (((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView).options.useShouldOverrideUrlLoading) {
Map<String, Object> obj = new HashMap<>(); onShouldOverrideUrlLoading(url, "GET", null,true, false, false);
if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("url", url);
getChannel().invokeMethod("shouldOverrideUrlLoading", obj);
return true; return true;
} }
return false;
}
if (url != null) { public void onShouldOverrideUrlLoading(final String url, final String method, final Map<String, String> headers, final boolean isForMainFrame, boolean hasGesture, boolean isRedirect) {
if (url.startsWith(WebView.SCHEME_TEL)) { Map<String, Object> obj = new HashMap<>();
try { if (inAppBrowserActivity != null)
Intent intent = new Intent(Intent.ACTION_DIAL); obj.put("uuid", inAppBrowserActivity.uuid);
intent.setData(Uri.parse(url)); obj.put("url", url);
((inAppBrowserActivity != null) ? inAppBrowserActivity : flutterWebView.activity).startActivity(intent); obj.put("method", method);
return true; obj.put("headers", headers);
} catch (android.content.ActivityNotFoundException e) { obj.put("isForMainFrame", isForMainFrame);
Log.e(LOG_TAG, "Error dialing " + url + ": " + e.toString()); obj.put("androidHasGesture", hasGesture);
} obj.put("androidIsRedirect", isRedirect);
} else if (url.startsWith("geo:") || url.startsWith(WebView.SCHEME_MAILTO) || url.startsWith("market:") || url.startsWith("intent:")) { obj.put("iosWKNavigationType", null);
try { getChannel().invokeMethod("shouldOverrideUrlLoading", obj, new MethodChannel.Result() {
Intent intent = new Intent(Intent.ACTION_VIEW); @Override
intent.setData(Uri.parse(url)); public void success(Object response) {
((inAppBrowserActivity != null) ? inAppBrowserActivity : flutterWebView.activity).startActivity(intent); if (response != null) {
return true; Map<String, Object> responseMap = (Map<String, Object>) response;
} catch (android.content.ActivityNotFoundException e) { Integer action = (Integer) responseMap.get("action");
Log.e(LOG_TAG, "Error with " + url + ": " + e.toString()); if (action != null) {
} switch (action) {
} case 1:
// If sms:5551212?body=This is the message if (isForMainFrame) {
else if (url.startsWith("sms:")) { // There isn't any way to load an URL for a frame that is not the main frame,
try { // so call this only on main frame.
Intent intent = new Intent(Intent.ACTION_VIEW); InAppWebView webView = ((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
// Get address webView.loadUrl(url, headers);
String address; else
int parmIndex = url.indexOf('?'); webView.loadUrl(url);
if (parmIndex == -1) { }
address = url.substring(4); return;
} else { case 0:
address = url.substring(4, parmIndex); default:
return;
// If body, then set sms body
Uri uri = Uri.parse(url);
String query = uri.getQuery();
if (query != null) {
if (query.startsWith("body=")) {
intent.putExtra("sms_body", query.substring(5));
}
} }
} }
intent.setData(Uri.parse("sms:" + address));
intent.putExtra("address", address);
intent.setType("vnd.android-dir/mms-sms");
((inAppBrowserActivity != null) ? inAppBrowserActivity : flutterWebView.activity).startActivity(intent);
return true;
} catch (android.content.ActivityNotFoundException e) {
Log.e(LOG_TAG, "Error sending sms " + url + ":" + e.toString());
} }
} }
}
return super.shouldOverrideUrlLoading(webView, url); @Override
public void error(String s, String s1, Object o) {
Log.d(LOG_TAG, "ERROR: " + s + " " + s1);
}
@Override
public void notImplemented() {
}
});
} }
@Override @Override
...@@ -138,7 +172,6 @@ public class InAppWebViewClient extends WebViewClient { ...@@ -138,7 +172,6 @@ public class InAppWebViewClient extends WebViewClient {
String js = InAppWebView.consoleLogJS.replaceAll("[\r\n]+", ""); String js = InAppWebView.consoleLogJS.replaceAll("[\r\n]+", "");
js += JavaScriptBridgeInterface.flutterInAppBroserJSClass.replaceAll("[\r\n]+", ""); js += JavaScriptBridgeInterface.flutterInAppBroserJSClass.replaceAll("[\r\n]+", "");
if (webView.options.useShouldInterceptAjaxRequest) { if (webView.options.useShouldInterceptAjaxRequest) {
js += InAppWebView.interceptAjaxRequestsJS.replaceAll("[\r\n]+", ""); js += InAppWebView.interceptAjaxRequestsJS.replaceAll("[\r\n]+", "");
} }
...@@ -148,6 +181,7 @@ public class InAppWebViewClient extends WebViewClient { ...@@ -148,6 +181,7 @@ public class InAppWebViewClient extends WebViewClient {
if (webView.options.useOnLoadResource) { if (webView.options.useOnLoadResource) {
js += InAppWebView.resourceObserverJS.replaceAll("[\r\n]+", ""); js += InAppWebView.resourceObserverJS.replaceAll("[\r\n]+", "");
} }
js += InAppWebView.printJS.replaceAll("[\r\n]+", "");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webView.evaluateJavascript(js, (ValueCallback<String>) null); webView.evaluateJavascript(js, (ValueCallback<String>) null);
...@@ -667,6 +701,11 @@ public class InAppWebViewClient extends WebViewClient { ...@@ -667,6 +701,11 @@ public class InAppWebViewClient extends WebViewClient {
return shouldInterceptRequest(view, url); return shouldInterceptRequest(view, url);
} }
@Override
public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
}
private MethodChannel getChannel() { private MethodChannel getChannel() {
return (inAppBrowserActivity != null) ? InAppWebViewFlutterPlugin.inAppBrowser.channel : flutterWebView.channel; return (inAppBrowserActivity != null) ? InAppWebViewFlutterPlugin.inAppBrowser.channel : flutterWebView.channel;
} }
......
...@@ -20,7 +20,6 @@ public class InAppWebViewOptions extends Options { ...@@ -20,7 +20,6 @@ public class InAppWebViewOptions extends Options {
public Boolean useShouldOverrideUrlLoading = false; public Boolean useShouldOverrideUrlLoading = false;
public Boolean useOnLoadResource = false; public Boolean useOnLoadResource = false;
public Boolean useOnDownloadStart = false; public Boolean useOnDownloadStart = false;
public Boolean useOnTargetBlank = false;
public Boolean clearCache = false; public Boolean clearCache = false;
public String userAgent = ""; public String userAgent = "";
public String applicationNameForUserAgent = ""; public String applicationNameForUserAgent = "";
...@@ -48,7 +47,7 @@ public class InAppWebViewOptions extends Options { ...@@ -48,7 +47,7 @@ public class InAppWebViewOptions extends Options {
public Boolean displayZoomControls = false; public Boolean displayZoomControls = false;
public Boolean supportZoom = true; public Boolean supportZoom = true;
public Boolean databaseEnabled = false; public Boolean databaseEnabled = false;
public Boolean domStorageEnabled = false; public Boolean domStorageEnabled = true;
public Boolean useWideViewPort = true; public Boolean useWideViewPort = true;
public Boolean safeBrowsingEnabled = true; public Boolean safeBrowsingEnabled = true;
public Integer mixedContentMode; public Integer mixedContentMode;
...@@ -82,6 +81,8 @@ public class InAppWebViewOptions extends Options { ...@@ -82,6 +81,8 @@ public class InAppWebViewOptions extends Options {
public Boolean saveFormData = true; public Boolean saveFormData = true;
public Boolean thirdPartyCookiesEnabled = true; public Boolean thirdPartyCookiesEnabled = true;
public Boolean hardwareAcceleration = true; public Boolean hardwareAcceleration = true;
public Boolean supportMultipleWindows = false;
public String regexToCancelSubFramesLoading;
@Override @Override
public Object onParse(Map.Entry<String, Object> pair) { public Object onParse(Map.Entry<String, Object> pair) {
......
...@@ -15,6 +15,7 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin { ...@@ -15,6 +15,7 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin {
protected static final String LOG_TAG = "InAppWebViewFlutterPlugin"; protected static final String LOG_TAG = "InAppWebViewFlutterPlugin";
public static InAppBrowser inAppBrowser; public static InAppBrowser inAppBrowser;
public static InAppWebViewStatic inAppWebViewStatic;
public static MyCookieManager myCookieManager; public static MyCookieManager myCookieManager;
public static CredentialDatabaseHandler credentialDatabaseHandler; public static CredentialDatabaseHandler credentialDatabaseHandler;
public static ValueCallback<Uri[]> uploadMessageArray; public static ValueCallback<Uri[]> uploadMessageArray;
...@@ -28,6 +29,7 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin { ...@@ -28,6 +29,7 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin {
.platformViewRegistry() .platformViewRegistry()
.registerViewFactory( .registerViewFactory(
"com.pichillilorenzo/flutter_inappwebview", new FlutterWebViewFactory(registrar, registrar.view())); "com.pichillilorenzo/flutter_inappwebview", new FlutterWebViewFactory(registrar, registrar.view()));
new InAppWebViewStatic(registrar);
new MyCookieManager(registrar); new MyCookieManager(registrar);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
new CredentialDatabaseHandler(registrar); new CredentialDatabaseHandler(registrar);
...@@ -44,6 +46,7 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin { ...@@ -44,6 +46,7 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin {
.getRegistry() .getRegistry()
.registerViewFactory( .registerViewFactory(
"com.pichillilorenzo/flutter_inappwebview", new FlutterWebViewFactory(registrar,null)); "com.pichillilorenzo/flutter_inappwebview", new FlutterWebViewFactory(registrar,null));
inAppWebViewStatic = new InAppWebViewStatic(registrar);
myCookieManager = new MyCookieManager(registrar); myCookieManager = new MyCookieManager(registrar);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
credentialDatabaseHandler = new CredentialDatabaseHandler(registrar); credentialDatabaseHandler = new CredentialDatabaseHandler(registrar);
...@@ -64,6 +67,10 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin { ...@@ -64,6 +67,10 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin {
credentialDatabaseHandler.dispose(); credentialDatabaseHandler.dispose();
credentialDatabaseHandler = null; credentialDatabaseHandler = null;
} }
if (inAppWebViewStatic != null) {
inAppWebViewStatic.dispose();
inAppWebViewStatic = null;
}
uploadMessageArray = null; uploadMessageArray = null;
} }
} }
package com.pichillilorenzo.flutter_inappwebview;
import android.util.Log;
import android.webkit.WebSettings;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.PluginRegistry;
public class InAppWebViewStatic implements MethodChannel.MethodCallHandler {
public PluginRegistry.Registrar registrar;
public MethodChannel channel;
protected static final String LOG_TAG = "InAppWebViewStatic";
public InAppWebViewStatic(PluginRegistry.Registrar r) {
registrar = r;
channel = new MethodChannel(registrar.messenger(), "com.pichillilorenzo/flutter_inappwebview_static");
channel.setMethodCallHandler(this);
}
@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
Log.d(LOG_TAG, call.method);
switch (call.method) {
case "getDefaultUserAgent":
result.success(WebSettings.getDefaultUserAgent(registrar.activeContext()));
break;
default:
result.notImplemented();
}
}
public void dispose() {
channel.setMethodCallHandler(null);
}
}
...@@ -2,10 +2,9 @@ ...@@ -2,10 +2,9 @@
# 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_inappwebview/example" export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example"
export "FLUTTER_TARGET=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/lib/main.dart" export "FLUTTER_TARGET=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"
...@@ -37,7 +37,7 @@ class MyInAppBrowser extends InAppBrowser { ...@@ -37,7 +37,7 @@ class MyInAppBrowser extends InAppBrowser {
} }
@override @override
void shouldOverrideUrlLoading(String url) { void shouldOverrideUrlLoading(String url, Map<String, String> headers, bool isForMainFrame) {
print("\n\n override $url\n\n"); print("\n\n override $url\n\n");
this.webViewController.loadUrl(url: url); this.webViewController.loadUrl(url: url);
} }
......
...@@ -31,7 +31,7 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> { ...@@ -31,7 +31,7 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
title: Text("InAppWebView") title: Text("InAppWebView")
), ),
drawer: myDrawer(context: context), drawer: myDrawer(context: context),
body: Container( body: SafeArea(
child: Column(children: <Widget>[ child: Column(children: <Widget>[
Container( Container(
padding: EdgeInsets.all(20.0), padding: EdgeInsets.all(20.0),
...@@ -69,6 +69,11 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> { ...@@ -69,6 +69,11 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
this.url = url; this.url = url;
}); });
}, },
onNavigationStateChange: (InAppWebViewController controller, String url) async {
setState(() {
this.url = url;
});
},
onProgressChanged: (InAppWebViewController controller, int progress) { onProgressChanged: (InAppWebViewController controller, int progress) {
setState(() { setState(() {
this.progress = progress / 100; this.progress = progress / 100;
......
This diff is collapsed.
...@@ -56,7 +56,7 @@ flutter: ...@@ -56,7 +56,7 @@ flutter:
- test_assets/in_app_webview_javascript_handler_test.html - test_assets/in_app_webview_javascript_handler_test.html
- test_assets/in_app_webview_on_load_resource_custom_scheme_test.html - test_assets/in_app_webview_on_load_resource_custom_scheme_test.html
- test_assets/in_app_webview_on_console_message_test.html - test_assets/in_app_webview_on_console_message_test.html
- test_assets/in_app_webview_on_target_blank_test.html - test_assets/in_app_webview_on_create_window_test.html
- test_assets/in_app_webview_on_js_dialog_test.html - test_assets/in_app_webview_on_js_dialog_test.html
- test_assets/css/ - test_assets/css/
- test_assets/images/ - test_assets/images/
......
...@@ -4,10 +4,10 @@ ...@@ -4,10 +4,10 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge"> <meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>InAppWebViewOnTargetBlankTest</title> <title>InAppWebViewOnCreateWindowTest</title>
</head> </head>
<body> <body>
<h1>InAppWebViewOnTargetBlankTest</h1> <h1>InAppWebViewOnCreateWindowTest</h1>
<a id="target-blank" href="https://flutter.dev/" target="_blank">target blank</a> <a id="target-blank" href="https://flutter.dev/" target="_blank">target blank</a>
<script> <script>
document.querySelector('#target-blank').click(); document.querySelector('#target-blank').click();
......
...@@ -5,15 +5,15 @@ import 'package:flutter_inappwebview/flutter_inappwebview.dart'; ...@@ -5,15 +5,15 @@ import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'main_test.dart'; import 'main_test.dart';
import 'custom_widget_test.dart'; import 'custom_widget_test.dart';
class InAppWebViewOnTargetBlankTest extends WidgetTest { class InAppWebViewOnCreateWindowTest extends WidgetTest {
final InAppWebViewOnTargetBlankTestState state = InAppWebViewOnTargetBlankTestState(); final InAppWebViewOnCreateWindowTestState state = InAppWebViewOnCreateWindowTestState();
@override @override
InAppWebViewOnTargetBlankTestState createState() => state; InAppWebViewOnCreateWindowTestState createState() => state;
} }
class InAppWebViewOnTargetBlankTestState extends WidgetTestState { class InAppWebViewOnCreateWindowTestState extends WidgetTestState {
String appBarTitle = "InAppWebViewOnTargetBlankTest"; String appBarTitle = "InAppWebViewOnCreateWindowTest";
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
...@@ -26,13 +26,12 @@ class InAppWebViewOnTargetBlankTestState extends WidgetTestState { ...@@ -26,13 +26,12 @@ class InAppWebViewOnTargetBlankTestState extends WidgetTestState {
Expanded( Expanded(
child: Container( child: Container(
child: InAppWebView( child: InAppWebView(
initialFile: "test_assets/in_app_webview_on_target_blank_test.html", initialFile: "test_assets/in_app_webview_on_create_window_test.html",
initialHeaders: {}, initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions( initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions( inAppWebViewOptions: InAppWebViewOptions(
clearCache: true, clearCache: true,
debuggingEnabled: true, debuggingEnabled: true,
useOnTargetBlank: true,
javaScriptCanOpenWindowsAutomatically: true, javaScriptCanOpenWindowsAutomatically: true,
) )
), ),
...@@ -49,7 +48,7 @@ class InAppWebViewOnTargetBlankTestState extends WidgetTestState { ...@@ -49,7 +48,7 @@ class InAppWebViewOnTargetBlankTestState extends WidgetTestState {
}); });
} }
}, },
onTargetBlank: (InAppWebViewController controller, String url) { onCreateWindow: (InAppWebViewController controller, String url) {
controller.loadUrl(url: url); controller.loadUrl(url: url);
}, },
), ),
......
...@@ -50,8 +50,9 @@ class InAppWebViewShouldOverrideUrlLoadingTestState extends WidgetTestState { ...@@ -50,8 +50,9 @@ class InAppWebViewShouldOverrideUrlLoadingTestState extends WidgetTestState {
controller.evaluateJavascript(source: "document.querySelector('#link').click();"); controller.evaluateJavascript(source: "document.querySelector('#link').click();");
} }
}, },
shouldOverrideUrlLoading: (InAppWebViewController controller, String url) { shouldOverrideUrlLoading: (InAppWebViewController controller, ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest) async {
controller.loadUrl(url: "https://flutter.dev/"); controller.loadUrl(url: "https://flutter.dev/");
return ShouldOverrideUrlLoadingAction.CANCEL;
}, },
), ),
), ),
......
...@@ -25,7 +25,7 @@ import 'in_app_webview_on_progress_changed_test.dart'; ...@@ -25,7 +25,7 @@ import 'in_app_webview_on_progress_changed_test.dart';
import 'in_app_webview_on_received_http_auth_request_test.dart'; import 'in_app_webview_on_received_http_auth_request_test.dart';
import 'in_app_webview_on_safe_browsing_hit_test.dart'; import 'in_app_webview_on_safe_browsing_hit_test.dart';
import 'in_app_webview_on_scroll_changed_test.dart'; import 'in_app_webview_on_scroll_changed_test.dart';
import 'in_app_webview_on_target_blank_test.dart'; import 'in_app_webview_on_create_window_test.dart';
import 'in_app_webview_should_override_url_loading_test.dart'; import 'in_app_webview_should_override_url_loading_test.dart';
import 'in_app_webview_ssl_request_test.dart'; import 'in_app_webview_ssl_request_test.dart';
...@@ -44,7 +44,7 @@ Map<String, WidgetBuilder> getTestRoutes({@required BuildContext context}) { ...@@ -44,7 +44,7 @@ Map<String, WidgetBuilder> getTestRoutes({@required BuildContext context}) {
'/InAppWebViewShouldOverrideUrlLoadingTest': (context) => InAppWebViewShouldOverrideUrlLoadingTest(), '/InAppWebViewShouldOverrideUrlLoadingTest': (context) => InAppWebViewShouldOverrideUrlLoadingTest(),
'/InAppWebViewOnConsoleMessageTest': (context) => InAppWebViewOnConsoleMessageTest(), '/InAppWebViewOnConsoleMessageTest': (context) => InAppWebViewOnConsoleMessageTest(),
'/InAppWebViewOnDownloadStartTest': (context) => InAppWebViewOnDownloadStartTest(), '/InAppWebViewOnDownloadStartTest': (context) => InAppWebViewOnDownloadStartTest(),
'/InAppWebViewOnTargetBlankTest': (context) => InAppWebViewOnTargetBlankTest(), '/InAppWebViewOnCreateWindowTest': (context) => InAppWebViewOnCreateWindowTest(),
'/InAppWebViewOnJsDialogTest': (context) => InAppWebViewOnJsDialogTest(), '/InAppWebViewOnJsDialogTest': (context) => InAppWebViewOnJsDialogTest(),
'/InAppWebViewOnSafeBrowsingHitTest': (context) => InAppWebViewOnSafeBrowsingHitTest(), '/InAppWebViewOnSafeBrowsingHitTest': (context) => InAppWebViewOnSafeBrowsingHitTest(),
'/InAppWebViewOnReceivedHttpAuthRequestTest': (context) => InAppWebViewOnReceivedHttpAuthRequestTest(), '/InAppWebViewOnReceivedHttpAuthRequestTest': (context) => InAppWebViewOnReceivedHttpAuthRequestTest(),
......
...@@ -20,7 +20,13 @@ ...@@ -20,7 +20,13 @@
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/.dart_tool" /> <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/.pub" /> <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/.pub" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/build" /> <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/build" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/ios/Flutter/App.framework/flutter_assets/packages" /> <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/.pub" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/build" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/.pub" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/build" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/ios/Flutter/App.framework/flutter_assets/packages" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/Flutter/App.framework/flutter_assets/packages" /> <excludeFolder url="file://$MODULE_DIR$/example/ios/Flutter/App.framework/flutter_assets/packages" />
<excludeFolder url="file://$MODULE_DIR$/flutter_inappbrowser_tests/.dart_tool" /> <excludeFolder url="file://$MODULE_DIR$/flutter_inappbrowser_tests/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/flutter_inappbrowser_tests/.pub" /> <excludeFolder url="file://$MODULE_DIR$/flutter_inappbrowser_tests/.pub" />
......
...@@ -330,6 +330,20 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView { ...@@ -330,6 +330,20 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView {
} }
result(true) result(true)
break break
case "printCurrentPage":
if webView != nil {
webView!.printCurrentPage(printCompletionHandler: {(completed, error) in
if !completed, let e = error {
result(false)
return
}
result(true)
})
} else {
result(false)
}
break
case "removeFromSuperview": case "removeFromSuperview":
webView!.removeFromSuperview() webView!.removeFromSuperview()
result(true) result(true)
......
This diff is collapsed.
...@@ -14,7 +14,6 @@ public class InAppWebViewOptions: Options { ...@@ -14,7 +14,6 @@ public class InAppWebViewOptions: Options {
var useShouldOverrideUrlLoading = false var useShouldOverrideUrlLoading = false
var useOnLoadResource = false var useOnLoadResource = false
var useOnDownloadStart = false var useOnDownloadStart = false
var useOnTargetBlank = false
var clearCache = false var clearCache = false
var userAgent = "" var userAgent = ""
var applicationNameForUserAgent = "" var applicationNameForUserAgent = ""
......
//
// InAppWebViewStatic.swift
// flutter_inappwebview
//
// Created by Lorenzo Pichilli on 08/12/2019.
//
import Foundation
import WebKit
class InAppWebViewStatic: NSObject, FlutterPlugin {
static var registrar: FlutterPluginRegistrar?
static var channel: FlutterMethodChannel?
static var webViewForUserAgent: WKWebView?
static var defaultUserAgent: String?
static func register(with registrar: FlutterPluginRegistrar) {
}
init(registrar: FlutterPluginRegistrar) {
super.init()
InAppWebViewStatic.registrar = registrar
InAppWebViewStatic.channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_inappwebview_static", binaryMessenger: registrar.messenger())
registrar.addMethodCallDelegate(self, channel: InAppWebViewStatic.channel!)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
//let arguments = call.arguments as? NSDictionary
switch call.method {
case "getDefaultUserAgent":
InAppWebViewStatic.getDefaultUserAgent(completionHandler: { (value) in
result(value)
})
break
default:
result(FlutterMethodNotImplemented)
break
}
}
static public func getDefaultUserAgent(completionHandler: @escaping (_ value: String?) -> Void) {
if defaultUserAgent == nil {
InAppWebViewStatic.webViewForUserAgent = WKWebView()
InAppWebViewStatic.webViewForUserAgent?.evaluateJavaScript("navigator.userAgent") { (value, error) in
if error != nil {
print("Error occured to get userAgent")
self.webViewForUserAgent = nil
completionHandler(nil)
return
}
if let unwrappedUserAgent = value as? String {
InAppWebViewStatic.defaultUserAgent = unwrappedUserAgent
completionHandler(defaultUserAgent)
} else {
print("Failed to get userAgent")
}
self.webViewForUserAgent = nil
}
} else {
completionHandler(defaultUserAgent)
}
}
}
...@@ -57,12 +57,10 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin { ...@@ -57,12 +57,10 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
SwiftFlutterPlugin.instance = SwiftFlutterPlugin(with: registrar) SwiftFlutterPlugin.instance = SwiftFlutterPlugin(with: registrar)
registrar.register(FlutterWebViewFactory(registrar: registrar) as FlutterPlatformViewFactory, withId: "com.pichillilorenzo/flutter_inappwebview") registrar.register(FlutterWebViewFactory(registrar: registrar) as FlutterPlatformViewFactory, withId: "com.pichillilorenzo/flutter_inappwebview")
InAppWebViewStatic(registrar: registrar)
if #available(iOS 11.0, *) { if #available(iOS 11.0, *) {
MyCookieManager(registrar: registrar) MyCookieManager(registrar: registrar)
} else {
// Fallback on earlier versions
} }
CredentialDatabase(registrar: registrar) CredentialDatabase(registrar: registrar)
} }
......
...@@ -357,10 +357,19 @@ class InAppBrowser { ...@@ -357,10 +357,19 @@ class InAppBrowser {
///Event fired when the [InAppBrowser] webview receives a [ConsoleMessage]. ///Event fired when the [InAppBrowser] webview receives a [ConsoleMessage].
void onConsoleMessage(ConsoleMessage consoleMessage) {} void onConsoleMessage(ConsoleMessage consoleMessage) {}
///Give the host application a chance to take control when a URL is about to be loaded in the current WebView. ///Give the host application a chance to take control when a URL is about to be loaded in the current WebView. This event is not called on the initial load of the WebView.
///
///Note that on Android there isn't any way to load an URL for a frame that is not the main frame, so if the request is not for the main frame, the navigation is allowed by default.
///However, if you want to cancel requests for subframes, you can use the [AndroidInAppWebViewOptions.regexToCancelSubFramesLoading] option
///to write a Regular Expression that, if the url request of a subframe matches, then the request of that subframe is canceled.
///
///Also, on Android, this method is not called for POST requests.
///
///[shouldOverrideUrlLoadingRequest] represents the navigation request.
/// ///
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldOverrideUrlLoading] option to `true`. ///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldOverrideUrlLoading] option to `true`.
void shouldOverrideUrlLoading(String url) {} // ignore: missing_return
Future<ShouldOverrideUrlLoadingAction> shouldOverrideUrlLoading(ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest) {}
///Event fired when the [InAppBrowser] webview loads a resource. ///Event fired when the [InAppBrowser] webview loads a resource.
/// ///
...@@ -390,12 +399,13 @@ class InAppBrowser { ...@@ -390,12 +399,13 @@ class InAppBrowser {
Future<CustomSchemeResponse> onLoadResourceCustomScheme( Future<CustomSchemeResponse> onLoadResourceCustomScheme(
String scheme, String url) {} String scheme, String url) {}
///Event fired when the [InAppBrowser] webview tries to open a link with `target="_blank"`. ///Event fired when the [InAppBrowser] webview requests the host application to create a new window,
///for example when trying to open a link with `target="_blank"` or when `window.open()` is called by JavaScript side.
/// ///
///[url] represents the url of the link. ///[url] represents the url of the request.
/// ///
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnTargetBlank] option to `true`. ///**NOTE**: on Android you need to set [AndroidInAppWebViewOptions.supportMultipleWindows] option to `true`.
void onTargetBlank(String url) {} void onCreateWindow(String url) {}
///Event that notifies the host application that web content from the specified origin is attempting to use the Geolocation API, but no permission state is currently set for that origin. ///Event that notifies the host application that web content from the specified origin is attempting to use the Geolocation API, but no permission state is currently set for that origin.
///Note that for applications targeting Android N and later SDKs (API level > `Build.VERSION_CODES.M`) this method is only called for requests originating from secure origins such as https. ///Note that for applications targeting Android N and later SDKs (API level > `Build.VERSION_CODES.M`) this method is only called for requests originating from secure origins such as https.
...@@ -533,6 +543,13 @@ class InAppBrowser { ...@@ -533,6 +543,13 @@ class InAppBrowser {
Future<PermissionRequestResponse> onPermissionRequest( Future<PermissionRequestResponse> onPermissionRequest(
String origin, List<String> resources) {} String origin, List<String> resources) {}
///Event fired when `window.print()` is called from JavaScript side.
///
///[url] represents the url on which is called.
///
///**NOTE**: available on Android 21+.
void onPrint(String url) {}
void throwIsAlreadyOpened({String message = ''}) { void throwIsAlreadyOpened({String message = ''}) {
if (this.isOpened()) { if (this.isOpened()) {
throw Exception([ throw Exception([
......
...@@ -16,12 +16,14 @@ import 'types.dart'; ...@@ -16,12 +16,14 @@ import 'types.dart';
import 'in_app_browser.dart'; import 'in_app_browser.dart';
import 'webview_options.dart'; import 'webview_options.dart';
///List of forbidden names for JavaScript handlers.
const javaScriptHandlerForbiddenNames = [ const javaScriptHandlerForbiddenNames = [
"onLoadResource", "onLoadResource",
"shouldInterceptAjaxRequest", "shouldInterceptAjaxRequest",
"onAjaxReadyStateChange", "onAjaxReadyStateChange",
"onAjaxProgress", "onAjaxProgress",
"shouldInterceptFetchRequest" "shouldInterceptFetchRequest",
"onPrint",
]; ];
///InAppWebView Widget class. ///InAppWebView Widget class.
...@@ -63,10 +65,18 @@ class InAppWebView extends StatefulWidget { ...@@ -63,10 +65,18 @@ class InAppWebView extends StatefulWidget {
InAppWebViewController controller, ConsoleMessage consoleMessage) InAppWebViewController controller, ConsoleMessage consoleMessage)
onConsoleMessage; onConsoleMessage;
///Give the host application a chance to take control when a URL is about to be loaded in the current WebView. ///Give the host application a chance to take control when a URL is about to be loaded in the current WebView. This event is not called on the initial load of the WebView.
///
///Note that on Android there isn't any way to load an URL for a frame that is not the main frame, so if the request is not for the main frame, the navigation is allowed by default.
///However, if you want to cancel requests for subframes, you can use the [AndroidInAppWebViewOptions.regexToCancelSubFramesLoading] option
///to write a Regular Expression that, if the url request of a subframe matches, then the request of that subframe is canceled.
///
///Also, on Android, this method is not called for POST requests.
///
///[shouldOverrideUrlLoadingRequest] represents the navigation request.
/// ///
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldOverrideUrlLoading] option to `true`. ///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldOverrideUrlLoading] option to `true`.
final void Function(InAppWebViewController controller, String url) final Future<ShouldOverrideUrlLoadingAction> Function(InAppWebViewController controller, ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest)
shouldOverrideUrlLoading; shouldOverrideUrlLoading;
///Event fired when the [InAppWebView] loads a resource. ///Event fired when the [InAppWebView] loads a resource.
...@@ -101,13 +111,14 @@ class InAppWebView extends StatefulWidget { ...@@ -101,13 +111,14 @@ class InAppWebView extends StatefulWidget {
InAppWebViewController controller, String scheme, String url) InAppWebViewController controller, String scheme, String url)
onLoadResourceCustomScheme; onLoadResourceCustomScheme;
///Event fired when the [InAppWebView] tries to open a link with `target="_blank"`. ///Event fired when the [InAppWebView] requests the host application to create a new window,
///for example when trying to open a link with `target="_blank"` or when `window.open()` is called by JavaScript side.
/// ///
///[url] represents the url of the link. ///[url] represents the url of the request.
/// ///
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnTargetBlank] option to `true`. ///**NOTE**: on Android you need to set [AndroidInAppWebViewOptions.supportMultipleWindows] option to `true`.
final void Function(InAppWebViewController controller, String url) final void Function(InAppWebViewController controller, String url)
onTargetBlank; onCreateWindow;
///Event that notifies the host application that web content from the specified origin is attempting to use the Geolocation API, but no permission state is currently set for that origin. ///Event that notifies the host application that web content from the specified origin is attempting to use the Geolocation API, but no permission state is currently set for that origin.
///Note that for applications targeting Android N and later SDKs (API level > `Build.VERSION_CODES.M`) this method is only called for requests originating from secure origins such as https. ///Note that for applications targeting Android N and later SDKs (API level > `Build.VERSION_CODES.M`) this method is only called for requests originating from secure origins such as https.
...@@ -246,7 +257,7 @@ class InAppWebView extends StatefulWidget { ...@@ -246,7 +257,7 @@ class InAppWebView extends StatefulWidget {
InAppWebViewController controller, FetchRequest fetchRequest) InAppWebViewController controller, FetchRequest fetchRequest)
shouldInterceptFetchRequest; shouldInterceptFetchRequest;
///Event fired when the navigation state of the [InAppWebView] changes throught the usage of ///Event fired when the navigation state of the [InAppWebView] changes through the usage of
///javascript **[History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API)** functions (`pushState()`, `replaceState()`) and `onpopstate` event. ///javascript **[History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API)** functions (`pushState()`, `replaceState()`) and `onpopstate` event.
/// ///
///Also, the event is fired when the javascript `window.location` changes without reloading the webview (for example appending or modifying an hash to the url). ///Also, the event is fired when the javascript `window.location` changes without reloading the webview (for example appending or modifying an hash to the url).
...@@ -267,6 +278,13 @@ class InAppWebView extends StatefulWidget { ...@@ -267,6 +278,13 @@ class InAppWebView extends StatefulWidget {
String origin, String origin,
List<String> resources) onPermissionRequest; List<String> resources) onPermissionRequest;
///Event fired when `window.print()` is called from JavaScript side.
///
///[url] represents the url on which is called.
///
///**NOTE**: available on Android 21+.
final void Function(InAppWebViewController controller, String url) onPrint;
///Initial url that will be loaded. ///Initial url that will be loaded.
final String initialUrl; final String initialUrl;
...@@ -310,7 +328,7 @@ class InAppWebView extends StatefulWidget { ...@@ -310,7 +328,7 @@ class InAppWebView extends StatefulWidget {
this.onScrollChanged, this.onScrollChanged,
this.onDownloadStart, this.onDownloadStart,
this.onLoadResourceCustomScheme, this.onLoadResourceCustomScheme,
this.onTargetBlank, this.onCreateWindow,
this.onGeolocationPermissionsShowPrompt, this.onGeolocationPermissionsShowPrompt,
this.onJsAlert, this.onJsAlert,
this.onJsConfirm, this.onJsConfirm,
...@@ -326,6 +344,7 @@ class InAppWebView extends StatefulWidget { ...@@ -326,6 +344,7 @@ class InAppWebView extends StatefulWidget {
this.shouldInterceptFetchRequest, this.shouldInterceptFetchRequest,
this.onNavigationStateChange, this.onNavigationStateChange,
this.onPermissionRequest, this.onPermissionRequest,
this.onPrint,
this.gestureRecognizers, this.gestureRecognizers,
}) : super(key: key); }) : super(key: key);
...@@ -426,6 +445,7 @@ class _InAppWebViewState extends State<InAppWebView> { ...@@ -426,6 +445,7 @@ class _InAppWebViewState extends State<InAppWebView> {
class InAppWebViewController { class InAppWebViewController {
InAppWebView _widget; InAppWebView _widget;
MethodChannel _channel; MethodChannel _channel;
static MethodChannel _staticChannel = MethodChannel('com.pichillilorenzo/flutter_inappwebview_static');
Map<String, JavaScriptHandlerCallback> javaScriptHandlersMap = Map<String, JavaScriptHandlerCallback> javaScriptHandlersMap =
HashMap<String, JavaScriptHandlerCallback>(); HashMap<String, JavaScriptHandlerCallback>();
// ignore: unused_field // ignore: unused_field
...@@ -491,10 +511,20 @@ class InAppWebViewController { ...@@ -491,10 +511,20 @@ class InAppWebViewController {
break; break;
case "shouldOverrideUrlLoading": case "shouldOverrideUrlLoading":
String url = call.arguments["url"]; String url = call.arguments["url"];
String method = call.arguments["method"];
Map<String, String> headers = call.arguments["headers"]?.cast<String, String>();
bool isForMainFrame = call.arguments["isForMainFrame"];
bool androidHasGesture = call.arguments["androidHasGesture"];
bool androidIsRedirect = call.arguments["androidIsRedirect"];
int iosWKNavigationType = call.arguments["iosWKNavigationType"];
ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest = ShouldOverrideUrlLoadingRequest(url: url, method: method, headers: headers, isForMainFrame: isForMainFrame,
androidHasGesture: androidHasGesture, androidIsRedirect: androidIsRedirect, iosWKNavigationType: IosWKNavigationType.fromValue(iosWKNavigationType));
if (_widget != null && _widget.shouldOverrideUrlLoading != null) if (_widget != null && _widget.shouldOverrideUrlLoading != null)
_widget.shouldOverrideUrlLoading(this, url); return (await _widget.shouldOverrideUrlLoading(this, shouldOverrideUrlLoadingRequest))?.toMap();
else if (_inAppBrowser != null) else if (_inAppBrowser != null)
_inAppBrowser.shouldOverrideUrlLoading(url); return (await _inAppBrowser.shouldOverrideUrlLoading(shouldOverrideUrlLoadingRequest))?.toMap();
break; break;
case "onConsoleMessage": case "onConsoleMessage":
String message = call.arguments["message"]; String message = call.arguments["message"];
...@@ -543,11 +573,11 @@ class InAppWebViewController { ...@@ -543,11 +573,11 @@ class InAppWebViewController {
} }
} }
break; break;
case "onTargetBlank": case "onCreateWindow":
String url = call.arguments["url"]; String url = call.arguments["url"];
if (_widget != null && _widget.onTargetBlank != null) if (_widget != null && _widget.onCreateWindow != null)
_widget.onTargetBlank(this, url); _widget.onCreateWindow(this, url);
else if (_inAppBrowser != null) _inAppBrowser.onTargetBlank(url); else if (_inAppBrowser != null) _inAppBrowser.onCreateWindow(url);
break; break;
case "onGeolocationPermissionsShowPrompt": case "onGeolocationPermissionsShowPrompt":
String origin = call.arguments["origin"]; String origin = call.arguments["origin"];
...@@ -875,6 +905,13 @@ class InAppWebViewController { ...@@ -875,6 +905,13 @@ class InAppWebViewController {
return jsonEncode( return jsonEncode(
await _inAppBrowser.shouldInterceptFetchRequest(request)); await _inAppBrowser.shouldInterceptFetchRequest(request));
return null; return null;
case "onPrint":
String url = args[0];
if (_widget != null && _widget.onPrint != null)
_widget.onPrint(this, url);
else if (_inAppBrowser != null)
_inAppBrowser.onPrint(url);
return null;
} }
if (javaScriptHandlersMap.containsKey(handlerName)) { if (javaScriptHandlersMap.containsKey(handlerName)) {
...@@ -1388,6 +1425,8 @@ class InAppWebViewController { ...@@ -1388,6 +1425,8 @@ class InAppWebViewController {
/// }); /// });
/// """); /// """);
///``` ///```
///
///Forbidden names for JavaScript handlers are defined in [javaScriptHandlerForbiddenNames].
void addJavaScriptHandler( void addJavaScriptHandler(
{@required String handlerName, {@required String handlerName,
@required JavaScriptHandlerCallback callback}) { @required JavaScriptHandlerCallback callback}) {
...@@ -1729,6 +1768,24 @@ class InAppWebViewController { ...@@ -1729,6 +1768,24 @@ class InAppWebViewController {
await _channel.invokeMethod('resumeTimers', args); await _channel.invokeMethod('resumeTimers', args);
} }
///Prints the current page.
///
///**NOTE**: available on Android 21+.
Future<void> printCurrentPage() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) {
_inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
}
await _channel.invokeMethod('printCurrentPage', args);
}
///Gets the default user agent.
static Future<String> getDefaultUserAgent() async {
Map<String, dynamic> args = <String, dynamic>{};
return await _staticChannel.invokeMethod('getDefaultUserAgent', args);
}
/*Future<void> dispose() async { /*Future<void> dispose() async {
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
if (Platform.isIOS) if (Platform.isIOS)
......
...@@ -1966,3 +1966,94 @@ class PermissionRequestResponse { ...@@ -1966,3 +1966,94 @@ class PermissionRequestResponse {
return {"resources": resources, "action": action?.toValue()}; return {"resources": resources, "action": action?.toValue()};
} }
} }
///ShouldOverrideUrlLoadingAction class is used by [shouldOverrideUrlLoading] event.
///It represents the policy to pass back to the decision handler.
class ShouldOverrideUrlLoadingAction {
final int _value;
const ShouldOverrideUrlLoadingAction._internal(this._value);
int toValue() => _value;
///Cancel the navigation.
static const CANCEL = const ShouldOverrideUrlLoadingAction._internal(0);
///Allow the navigation to continue.
static const ALLOW = const ShouldOverrideUrlLoadingAction._internal(1);
bool operator ==(value) => value == _value;
@override
int get hashCode => _value.hashCode;
Map<String, dynamic> toMap() {
return {
"action": _value,
};
}
}
///IosWKNavigationType class represents the type of action triggering a navigation on iOS for the [shouldOverrideUrlLoading] event.
class IosWKNavigationType {
final int _value;
const IosWKNavigationType._internal(this._value);
int toValue() => _value;
static IosWKNavigationType fromValue(int value) {
if (value != null && ((value >= 0 && value <= 4) || value == -1))
return IosWKNavigationType._internal(value);
return null;
}
///A link with an href attribute was activated by the user.
static const LINK_ACTIVATED = const IosWKNavigationType._internal(0);
///A form was submitted.
static const FORM_SUBMITTED = const IosWKNavigationType._internal(1);
///An item from the back-forward list was requested.
static const BACK_FORWARD = const IosWKNavigationType._internal(2);
///The webpage was reloaded.
static const RELOAD = const IosWKNavigationType._internal(3);
///A form was resubmitted (for example by going back, going forward, or reloading).
static const FORM_RESUBMITTED = const IosWKNavigationType._internal(4);
///Navigation is taking place for some other reason.
static const OTHER = const IosWKNavigationType._internal(-1);
bool operator ==(value) => value == _value;
@override
int get hashCode => _value.hashCode;
}
///ShouldOverrideUrlLoadingAction class represents the navigation request used by the [shouldOverrideUrlLoading] event.
class ShouldOverrideUrlLoadingRequest {
///Represents the url of the navigation request.
String url;
///Represents the method of the navigation request. On Android < 21, this value is always `GET`.
String method;
///Represents the headers of the navigation request. On Android < 21, this is always `null`.
Map<String, String> headers;
///Indicates whether the request was made for the main frame. On Android < 21, this is always `true`.
bool isForMainFrame;
///Gets whether the request was a result of a server-side redirect. Available only on Android. On Android < 21, this is always `false`.
bool androidHasGesture;
///Gets whether a gesture (such as a click) was associated with the request.
///For security reasons in certain situations this method may return `false` even though
///the sequence of events which caused the request to be created was initiated by a user
///gesture.
///
///Available only on Android. On Android < 24, this is always `false`.
bool androidIsRedirect;
///The type of action triggering the navigation. Available only on iOS.
IosWKNavigationType iosWKNavigationType;
ShouldOverrideUrlLoadingRequest({this.url, this.method, this.headers, this.isForMainFrame, this.androidHasGesture, this.androidIsRedirect, this.iosWKNavigationType});
}
\ No newline at end of file
...@@ -49,9 +49,6 @@ class InAppWebViewOptions ...@@ -49,9 +49,6 @@ class InAppWebViewOptions
///Set to `true` to be able to listen at the [onDownloadStart] event. The default value is `false`. ///Set to `true` to be able to listen at the [onDownloadStart] event. The default value is `false`.
bool useOnDownloadStart; bool useOnDownloadStart;
///Set to `true` to be able to listen at the [onTargetBlank] event. The default value is `false`.
bool useOnTargetBlank;
///Set to `true` to have all the browser's cache cleared before the new window is opened. The default value is `false`. ///Set to `true` to have all the browser's cache cleared before the new window is opened. The default value is `false`.
bool clearCache; bool clearCache;
...@@ -135,7 +132,6 @@ class InAppWebViewOptions ...@@ -135,7 +132,6 @@ class InAppWebViewOptions
{this.useShouldOverrideUrlLoading = false, {this.useShouldOverrideUrlLoading = false,
this.useOnLoadResource = false, this.useOnLoadResource = false,
this.useOnDownloadStart = false, this.useOnDownloadStart = false,
this.useOnTargetBlank = false,
this.clearCache = false, this.clearCache = false,
this.userAgent = "", this.userAgent = "",
this.applicationNameForUserAgent = "", this.applicationNameForUserAgent = "",
...@@ -174,7 +170,6 @@ class InAppWebViewOptions ...@@ -174,7 +170,6 @@ class InAppWebViewOptions
"useShouldOverrideUrlLoading": useShouldOverrideUrlLoading, "useShouldOverrideUrlLoading": useShouldOverrideUrlLoading,
"useOnLoadResource": useOnLoadResource, "useOnLoadResource": useOnLoadResource,
"useOnDownloadStart": useOnDownloadStart, "useOnDownloadStart": useOnDownloadStart,
"useOnTargetBlank": useOnTargetBlank,
"clearCache": clearCache, "clearCache": clearCache,
"userAgent": userAgent, "userAgent": userAgent,
"applicationNameForUserAgent": applicationNameForUserAgent, "applicationNameForUserAgent": applicationNameForUserAgent,
...@@ -213,7 +208,6 @@ class InAppWebViewOptions ...@@ -213,7 +208,6 @@ class InAppWebViewOptions
options.useShouldOverrideUrlLoading = map["useShouldOverrideUrlLoading"]; options.useShouldOverrideUrlLoading = map["useShouldOverrideUrlLoading"];
options.useOnLoadResource = map["useOnLoadResource"]; options.useOnLoadResource = map["useOnLoadResource"];
options.useOnDownloadStart = map["useOnDownloadStart"]; options.useOnDownloadStart = map["useOnDownloadStart"];
options.useOnTargetBlank = map["useOnTargetBlank"];
options.clearCache = map["clearCache"]; options.clearCache = map["clearCache"];
options.userAgent = map["userAgent"]; options.userAgent = map["userAgent"];
options.applicationNameForUserAgent = map["applicationNameForUserAgent"]; options.applicationNameForUserAgent = map["applicationNameForUserAgent"];
...@@ -265,7 +259,7 @@ class AndroidInAppWebViewOptions ...@@ -265,7 +259,7 @@ class AndroidInAppWebViewOptions
///Set to `true` if you want the database storage API is enabled. The default value is `false`. ///Set to `true` if you want the database storage API is enabled. The default value is `false`.
bool databaseEnabled; bool databaseEnabled;
///Set to `true` if you want the DOM storage API is enabled. The default value is `false`. ///Set to `true` if you want the DOM storage API is enabled. The default value is `true`.
bool domStorageEnabled; bool domStorageEnabled;
///Set to `true` if the WebView should enable support for the "viewport" HTML meta tag or should use a wide viewport. ///Set to `true` if the WebView should enable support for the "viewport" HTML meta tag or should use a wide viewport.
...@@ -392,6 +386,7 @@ class AndroidInAppWebViewOptions ...@@ -392,6 +386,7 @@ class AndroidInAppWebViewOptions
///Sets whether the WebView should save form data. In Android O, the platform has implemented a fully functional Autofill feature to store form data. ///Sets whether the WebView should save form data. In Android O, the platform has implemented a fully functional Autofill feature to store form data.
///Therefore, the Webview form data save feature is disabled. Note that the feature will continue to be supported on older versions of Android as before. ///Therefore, the Webview form data save feature is disabled. Note that the feature will continue to be supported on older versions of Android as before.
///The default value is `true`.
bool saveFormData; bool saveFormData;
///Boolean value to enable third party cookies in the WebView. ///Boolean value to enable third party cookies in the WebView.
...@@ -405,6 +400,13 @@ class AndroidInAppWebViewOptions ...@@ -405,6 +400,13 @@ class AndroidInAppWebViewOptions
///The default value is `true`. ///The default value is `true`.
bool hardwareAcceleration; bool hardwareAcceleration;
///Sets whether the WebView whether supports multiple windows.
///If set to `true`, [onCreateWindow] event must be implemented by the host application. The default value is `false`.
bool supportMultipleWindows;
///Regular expression used by [shouldOverrideUrlLoading] event to cancel navigation for frames that are not the main frame.
String regexToCancelSubFramesLoading;
AndroidInAppWebViewOptions( AndroidInAppWebViewOptions(
{this.textZoom = 100, {this.textZoom = 100,
this.clearSessionCache = false, this.clearSessionCache = false,
...@@ -412,7 +414,7 @@ class AndroidInAppWebViewOptions ...@@ -412,7 +414,7 @@ class AndroidInAppWebViewOptions
this.displayZoomControls = false, this.displayZoomControls = false,
this.supportZoom = true, this.supportZoom = true,
this.databaseEnabled = false, this.databaseEnabled = false,
this.domStorageEnabled = false, this.domStorageEnabled = true,
this.useWideViewPort = true, this.useWideViewPort = true,
this.safeBrowsingEnabled = true, this.safeBrowsingEnabled = true,
this.mixedContentMode, this.mixedContentMode,
...@@ -445,7 +447,9 @@ class AndroidInAppWebViewOptions ...@@ -445,7 +447,9 @@ class AndroidInAppWebViewOptions
this.saveFormData = true, this.saveFormData = true,
this.thirdPartyCookiesEnabled = true, this.thirdPartyCookiesEnabled = true,
this.hardwareAcceleration = true, this.hardwareAcceleration = true,
this.initialScale = 0}); this.initialScale = 0,
this.supportMultipleWindows = false,
this.regexToCancelSubFramesLoading});
@override @override
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
...@@ -489,7 +493,9 @@ class AndroidInAppWebViewOptions ...@@ -489,7 +493,9 @@ class AndroidInAppWebViewOptions
"standardFontFamily": standardFontFamily, "standardFontFamily": standardFontFamily,
"saveFormData": saveFormData, "saveFormData": saveFormData,
"thirdPartyCookiesEnabled": thirdPartyCookiesEnabled, "thirdPartyCookiesEnabled": thirdPartyCookiesEnabled,
"hardwareAcceleration": hardwareAcceleration "hardwareAcceleration": hardwareAcceleration,
"supportMultipleWindows": supportMultipleWindows,
"regexToCancelSubFramesLoading": regexToCancelSubFramesLoading
}; };
} }
...@@ -542,6 +548,8 @@ class AndroidInAppWebViewOptions ...@@ -542,6 +548,8 @@ class AndroidInAppWebViewOptions
options.saveFormData = map["saveFormData"]; options.saveFormData = map["saveFormData"];
options.thirdPartyCookiesEnabled = map["thirdPartyCookiesEnabled"]; options.thirdPartyCookiesEnabled = map["thirdPartyCookiesEnabled"];
options.hardwareAcceleration = map["hardwareAcceleration"]; options.hardwareAcceleration = map["hardwareAcceleration"];
options.supportMultipleWindows = map["supportMultipleWindows"];
options.regexToCancelSubFramesLoading = map["regexToCancelSubFramesLoading"];
return options; return options;
} }
} }
......
name: flutter_inappwebview name: flutter_inappwebview
description: A Flutter plugin that allows you to add an inline webview or open an in-app browser window. description: A Flutter plugin that allows you to add an inline webview or open an in-app browser window.
version: 2.1.0+1 version: 2.2.0
author: Lorenzo Pichilli <pichillilorenzo@gmail.com> author: Lorenzo Pichilli <pichillilorenzo@gmail.com>
homepage: https://github.com/pichillilorenzo/flutter_inappwebview homepage: https://github.com/pichillilorenzo/flutter_inappwebview
......
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