From 0c17e03256c748cfc21c1512ea9d8a1249e6c7a7 Mon Sep 17 00:00:00 2001 From: Lorenzo Pichilli Date: Sat, 9 Nov 2019 23:35:18 +0100 Subject: [PATCH] updated code docs, fixed javascript code for the ajax and fetch request event handlers --- .idea/workspace.xml | 198 +++++++----- .../InAppWebView/InAppWebView.java | 22 +- .../InAppWebView/InAppWebViewOptions.java | 45 +++ .../flutter_inappbrowser/Options.java | 24 +- ios/Classes/InAppWebView.swift | 4 +- lib/src/in_app_browser.dart | 2 +- lib/src/in_app_webview.dart | 4 +- lib/src/types.dart | 292 +++++++++++++++--- lib/src/webview_options.dart | 8 +- 9 files changed, 459 insertions(+), 140 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 284ae037..e1189688 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -15,7 +15,13 @@ - + + + + + + + @@ -40,8 +46,8 @@ - - + + @@ -52,8 +58,8 @@ - - + + @@ -62,10 +68,10 @@ - + - - + + @@ -74,10 +80,34 @@ - + + + + + + + + + + - + + + + + + + + + + + + + + + + @@ -94,36 +124,36 @@ - onNavigationStateChange - shouldInterceptFetchRequest - scheme - applicationNameForUserAgent - cacheMOde - inco - cacheEna - appCacheEnabled - appC - cache - customScheme - transparentBackground - ClientCertResponse - shouldO - useShouldOverrideUrlLoading - **NOTE**: In order to be able to li - XMLHttpRequest - nDownloadStart - ServerTrustAuthResponse - verticalScrollBarEnabled - mixedContentMode - eWideViewPort - initialScale mediaPlaybackRequiresUserGesture onDow toolbarTopFixedTitle resourceCustomSchemes JsAlertResponse - InAppWebViewUserPreferredContentMode JsConfirmResponse + InAppWebViewUserPreferredContentMode + onSag + ServerTrustAuthResponse + ClientCertResponse + weBVIEWCONTROL + getFa + supportZoom + layou + HttpAuthCredential + layoutA + AndroidInAppWebViewForceDark + AndroidInAppWebViewModeMenuItem + AndroidInAppWebViewMixedContentMode + IosInAppWebViewSelectionGranularity + preferredContent + IosWebViewOptionsPresentationStyle + AndroidInAppWebViewCacheMode + Action + IosSafariOptionsDismissButtonStyle + method + AjaxRequestEvent + withCredentials + FetchRequest + current activity.getPreferences(0) @@ -197,8 +227,8 @@ @@ -464,7 +494,7 @@ - + @@ -522,26 +552,6 @@ - - - - - - - - - - - - - - - - - - - - @@ -638,13 +648,6 @@ - - - - - - - @@ -699,37 +702,27 @@ - - - - - - - - - + + - + - - - - - + + - - + + @@ -746,10 +739,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + @@ -758,8 +788,8 @@ - - + + diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java index 576e363c..d9620dd4 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java @@ -162,6 +162,7 @@ final public class InAppWebView extends InputAwareWebView { " type: e.type," + " loaded: e.loaded," + " lengthComputable: e.lengthComputable" + + " total: e.total" + " }" + " };" + " window." + JavaScriptBridgeInterface.name + ".callHandler('onAjaxProgress', ajaxRequest).then(function(result) {" + @@ -233,6 +234,7 @@ final public class InAppWebView extends InputAwareWebView { " this.addEventListener('progress', handleEvent);" + " this.addEventListener('error', handleEvent);" + " this.addEventListener('abort', handleEvent);" + + " this.addEventListener('timeout', handleEvent);" + " var ajaxRequest = {" + " data: data," + " method: this._flutter_inappbrowser_method," + @@ -405,7 +407,7 @@ final public class InAppWebView extends InputAwareWebView { " controller.abort();" + " break;" + " }" + - " var resultResource = (result.resource != null) ? result.resource : resource;" + + " var resultResource = (result.url != null) ? result.url : resource;" + " var resultInit = init;" + " if (result.init != null) {" + " resultInit.method = result.method;" + @@ -555,8 +557,13 @@ final public class InAppWebView extends InputAwareWebView { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && options.forceDark != null) settings.setForceDark(options.forceDark); settings.setGeolocationEnabled(options.geolocationEnabled); - if (options.layoutAlgorithm != null) - settings.setLayoutAlgorithm(options.layoutAlgorithm); + if (options.layoutAlgorithm != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && options.layoutAlgorithm.equals(WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING)) { + settings.setLayoutAlgorithm(options.layoutAlgorithm); + } else { + settings.setLayoutAlgorithm(options.layoutAlgorithm); + } + } settings.setLoadsImagesAutomatically(options.loadsImagesAutomatically); settings.setMinimumFontSize(options.minimumFontSize); settings.setMinimumLogicalFontSize(options.minimumLogicalFontSize); @@ -948,8 +955,13 @@ final public class InAppWebView extends InputAwareWebView { if (newOptionsMap.get("geolocationEnabled") != null && options.geolocationEnabled != newOptions.geolocationEnabled) settings.setGeolocationEnabled(newOptions.geolocationEnabled); - if (newOptionsMap.get("layoutAlgorithm") != null && options.layoutAlgorithm != newOptions.layoutAlgorithm) - settings.setLayoutAlgorithm(newOptions.layoutAlgorithm); + if (newOptionsMap.get("layoutAlgorithm") != null && options.layoutAlgorithm != newOptions.layoutAlgorithm) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && newOptions.layoutAlgorithm.equals(WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING)) { + settings.setLayoutAlgorithm(newOptions.layoutAlgorithm); + } else { + settings.setLayoutAlgorithm(newOptions.layoutAlgorithm); + } + } if (newOptionsMap.get("loadWithOverviewMode") != null && options.loadWithOverviewMode != newOptions.loadWithOverviewMode) settings.setLoadWithOverviewMode(newOptions.loadWithOverviewMode); diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewOptions.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewOptions.java index a2e0259f..cf2942fb 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewOptions.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewOptions.java @@ -1,13 +1,18 @@ package com.pichillilorenzo.flutter_inappbrowser.InAppWebView; +import android.os.Build; +import android.util.Log; import android.webkit.WebSettings; import com.pichillilorenzo.flutter_inappbrowser.Options; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.Map; +import static android.webkit.WebSettings.LayoutAlgorithm.NORMAL; + public class InAppWebViewOptions extends Options { public static final String LOG_TAG = "InAppWebViewOptions"; @@ -75,4 +80,44 @@ public class InAppWebViewOptions extends Options { public Boolean saveFormData = true; public Boolean thirdPartyCookiesEnabled = true; public Boolean hardwareAcceleration = true; + + @Override + public Object onParse(Map.Entry pair) { + if (pair.getKey().equals("layoutAlgorithm")) { + switch ((String) pair.getValue()) { + case "NORMAL": + pair.setValue(NORMAL); + return pair; + case "TEXT_AUTOSIZING": + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + return pair.setValue(WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING); + } else { + pair.setValue(NORMAL); + } + return pair; + } + } + return super.onParse(pair); + } + + @Override + public Object onGetHashMap(Field field) { + if (field.getName().equals("layoutAlgorithm")) { + try { + WebSettings.LayoutAlgorithm value = (WebSettings.LayoutAlgorithm) field.get(this); + switch (value) { + case NORMAL: + return "NORMAL"; + default: + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && value.equals(WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING)) { + return "TEXT_AUTOSIZING"; + } + return "NORMAL"; + } + } catch (IllegalAccessException e) { + Log.d(LOG_TAG, e.getMessage()); + } + } + return super.onGetHashMap(field); + } } diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/Options.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/Options.java index ec492402..db925b94 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/Options.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/Options.java @@ -15,8 +15,9 @@ public class Options { Iterator it = options.entrySet().iterator(); while (it.hasNext()) { Map.Entry pair = (Map.Entry) it.next(); + Object value = this.onParse(pair); try { - this.getClass().getDeclaredField(pair.getKey()).set(this, pair.getValue()); + this.getClass().getDeclaredField(pair.getKey()).set(this, value); } catch (NoSuchFieldException e) { Log.d(LOG_TAG, e.getMessage()); } catch (IllegalAccessException e) { @@ -26,16 +27,25 @@ public class Options { return this; } + public Object onParse(Map.Entry pair) { + return pair.getValue(); + } + public HashMap getHashMap() { HashMap options = new HashMap<>(); - for (Field f : this.getClass().getDeclaredFields()) { - try { - options.put(f.getName(), f.get(this)); - } catch (IllegalAccessException e) { - Log.d(LOG_TAG, e.getMessage()); - } + for (Field field : this.getClass().getDeclaredFields()) { + options.put(field.getName(), onGetHashMap(field)); } return options; } + public Object onGetHashMap(Field field) { + try { + return field.get(this); + } catch (IllegalAccessException e) { + Log.d(LOG_TAG, e.getMessage()); + } + return null; + } + } diff --git a/ios/Classes/InAppWebView.swift b/ios/Classes/InAppWebView.swift index 7a3f9ca9..8c69a0f3 100755 --- a/ios/Classes/InAppWebView.swift +++ b/ios/Classes/InAppWebView.swift @@ -312,6 +312,7 @@ let interceptAjaxRequestsJS = """ type: e.type, loaded: e.loaded, lengthComputable: e.lengthComputable + total: e.total } }; window.\(JAVASCRIPT_BRIDGE_NAME).callHandler('onAjaxProgress', ajaxRequest).then(function(result) { @@ -383,6 +384,7 @@ let interceptAjaxRequestsJS = """ this.addEventListener('progress', handleEvent); this.addEventListener('error', handleEvent); this.addEventListener('abort', handleEvent); + this.addEventListener('timeout', handleEvent); var ajaxRequest = { data: data, method: this._flutter_inappbrowser_method, @@ -557,7 +559,7 @@ let interceptFetchRequestsJS = """ controller.abort(); break; } - var resultResource = (result.resource != null) ? result.resource : resource; + var resultResource = (result.url != null) ? result.url : resource; var resultInit = init; if (result.init != null) { resultInit.method = result.method; diff --git a/lib/src/in_app_browser.dart b/lib/src/in_app_browser.dart index 7f5d043d..5650453c 100644 --- a/lib/src/in_app_browser.dart +++ b/lib/src/in_app_browser.dart @@ -466,7 +466,7 @@ class InAppBrowser { } ///Event fires when the WebView need to perform server trust authentication (certificate validation). - ///The host application must return either [ServerTrustAuthResponse.CANCEL] or [ServerTrustAuthResponse.PROCEED]. + ///The host application must return either [ServerTrustAuthResponse] instance with [ServerTrustAuthResponseAction.CANCEL] or [ServerTrustAuthResponseAction.PROCEED]. /// ///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [ServerTrustChallenge]. Future onReceivedServerTrustAuthRequest(ServerTrustChallenge challenge) { diff --git a/lib/src/in_app_webview.dart b/lib/src/in_app_webview.dart index 72478228..eee2a274 100755 --- a/lib/src/in_app_webview.dart +++ b/lib/src/in_app_webview.dart @@ -162,7 +162,7 @@ class InAppWebView extends StatefulWidget { final Future Function(InAppWebViewController controller, HttpAuthChallenge challenge) onReceivedHttpAuthRequest; ///Event fires when the WebView need to perform server trust authentication (certificate validation). - ///The host application must return either [ServerTrustAuthResponse.CANCEL] or [ServerTrustAuthResponse.PROCEED]. + ///The host application must return either [ServerTrustAuthResponse] instance with [ServerTrustAuthResponseAction.CANCEL] or [ServerTrustAuthResponseAction.PROCEED]. /// ///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [ServerTrustChallenge]. final Future Function(InAppWebViewController controller, ServerTrustChallenge challenge) onReceivedServerTrustAuthRequest; @@ -668,7 +668,7 @@ class InAppWebViewController { Map responseHeaders = argMap["responseHeaders"]; Map eventMap = argMap["event"]; - AjaxRequestEvent event = AjaxRequestEvent(lengthComputable: eventMap["lengthComputable"], loaded: eventMap["loaded"], type: AjaxRequestEventType.fromValue(eventMap["type"])); + AjaxRequestEvent event = AjaxRequestEvent(lengthComputable: eventMap["lengthComputable"], loaded: eventMap["loaded"], total: eventMap["total"], type: AjaxRequestEventType.fromValue(eventMap["type"])); var request = new AjaxRequest(data: data, method: method, url: url, isAsync: isAsync, user: user, password: password, withCredentials: withCredentials, headers: headers, readyState: AjaxRequestReadyState.fromValue(readyState), status: status, responseURL: responseURL, diff --git a/lib/src/types.dart b/lib/src/types.dart index cde38456..72d51634 100644 --- a/lib/src/types.dart +++ b/lib/src/types.dart @@ -308,7 +308,7 @@ class JsPromptResponse { } } -/// +///SafeBrowsingThreat class represents the reason the resource was caught by Safe Browsing. class SafeBrowsingThreat { final int _value; const SafeBrowsingThreat._internal(this._value); @@ -332,14 +332,20 @@ class SafeBrowsingResponseAction { const SafeBrowsingResponseAction._internal(this._value); toValue() => _value; + ///Act as if the user clicked the "back to safety" button. static const BACK_TO_SAFETY = const SafeBrowsingResponseAction._internal(0); + ///Act as if the user clicked the "visit this unsafe site" button. static const PROCEED = const SafeBrowsingResponseAction._internal(1); + ///Display the default interstitial. static const SHOW_INTERSTITIAL = const SafeBrowsingResponseAction._internal(2); } -/// +///SafeBrowsingResponse class represents the response used by the [onSafeBrowsingHit] event. +///It is used to indicate an action to take when hitting a malicious URL. class SafeBrowsingResponse { + ///If reporting is enabled, all reports will be sent according to the privacy policy referenced by [InAppWebViewController.getSafeBrowsingPrivacyPolicyUrl]. bool report; + ///Indicate the [SafeBrowsingResponseAction] to take when hitting a malicious URL. SafeBrowsingResponseAction action; SafeBrowsingResponse({this.report = true, this.action = SafeBrowsingResponseAction.SHOW_INTERSTITIAL}); @@ -352,22 +358,29 @@ class SafeBrowsingResponse { } } -/// +///HttpAuthResponseAction class used by [HttpAuthResponse] class. class HttpAuthResponseAction { final int _value; const HttpAuthResponseAction._internal(this._value); toValue() => _value; + ///Instructs the WebView to cancel the authentication request. static const CANCEL = const HttpAuthResponseAction._internal(0); + ///Instructs the WebView to proceed with the authentication with the given credentials. static const PROCEED = const HttpAuthResponseAction._internal(1); + ///Uses the credentials stored for the current host. static const USE_SAVED_HTTP_AUTH_CREDENTIALS = const HttpAuthResponseAction._internal(2); } -/// +///HttpAuthResponse class represents the response used by the [onReceivedHttpAuthRequest] event. class HttpAuthResponse { + ///Represents the username used for the authentication if the [action] corresponds to [HttpAuthResponseAction.PROCEED] String username; + ///Represents the password used for the authentication if the [action] corresponds to [HttpAuthResponseAction.PROCEED] String password; + ///Indicate if the given credentials need to be saved permanently. bool permanentPersistence; + ///Indicate the [HttpAuthResponseAction] to take in response of the authentication challenge. HttpAuthResponseAction action; HttpAuthResponse({this.username = "", this.password = "", this.permanentPersistence = false, this.action = HttpAuthResponseAction.CANCEL}); @@ -382,44 +395,59 @@ class HttpAuthResponse { } } -/// +///HttpAuthChallenge class represents the challenge of the [onReceivedHttpAuthRequest] event. +///It provides all the information about the challenge. class HttpAuthChallenge { + ///A count of previous failed authentication attempts. int previousFailureCount; + ///The protection space requiring authentication. ProtectionSpace protectionSpace; HttpAuthChallenge({@required this.previousFailureCount, @required this.protectionSpace}): assert(previousFailureCount != null && protectionSpace != null); } -/// +///ProtectionSpace class represents a protection space requiring authentication. class ProtectionSpace { + ///The hostname of the server. String host; + ///The protocol of the server - e.g. "http", "ftp", "https". String protocol; + ///A string indicating a protocol-specific subdivision of a single host. + ///For http and https, this maps to the realm string in http authentication challenges. + ///For many other protocols it is unused. String realm; + ///The port of the server. int port; ProtectionSpace({@required this.host, @required this.protocol, this.realm, this.port}): assert(host != null && protocol != null); } -/// +///HttpAuthCredential represents the credentials of an http authentication. +///It is used by the [HttpAuthCredentialDatabase] class. class HttpAuthCredential { + ///Represents the username. String username; + ///Represents the password. String password; HttpAuthCredential({@required this.username, @required this.password}): assert(username != null && password != null); } -/// +///ServerTrustAuthResponseAction class used by [ServerTrustAuthResponse] class. class ServerTrustAuthResponseAction { final int _value; const ServerTrustAuthResponseAction._internal(this._value); toValue() => _value; + ///Instructs the WebView to cancel the authentication challenge. static const CANCEL = const ServerTrustAuthResponseAction._internal(0); + ///Instructs the WebView to proceed with the authentication challenge. static const PROCEED = const ServerTrustAuthResponseAction._internal(1); } -/// +///ServerTrustAuthResponse class represents the response used by the [onReceivedServerTrustAuthRequest] event. class ServerTrustAuthResponse { + ///Indicate the [ServerTrustAuthResponseAction] to take in response of the server trust authentication challenge. ServerTrustAuthResponseAction action; ServerTrustAuthResponse({this.action = ServerTrustAuthResponseAction.CANCEL}); @@ -431,32 +459,48 @@ class ServerTrustAuthResponse { } } -/// +///ServerTrustChallenge class represents the challenge of the [onReceivedServerTrustAuthRequest] event. +///It provides all the information about the challenge. class ServerTrustChallenge { + ///The protection space requiring authentication. ProtectionSpace protectionSpace; + ///The primary error associated to the server SSL certificate. + /// + ///**NOTE**: on iOS this value is always -1. int error; + ///The message associated to the [error]. + /// + ///**NOTE**: on iOS this value is always an empty string. String message; + ///The `X509Certificate` used to create the server SSL certificate. Uint8List serverCertificate; ServerTrustChallenge({@required this.protectionSpace, @required this.error, this.message, this.serverCertificate}): assert(protectionSpace != null && error != null); } -/// +///ClientCertResponseAction class used by [ClientCertResponse] class. class ClientCertResponseAction { final int _value; const ClientCertResponseAction._internal(this._value); toValue() => _value; + ///Cancel this request. static const CANCEL = const ClientCertResponseAction._internal(0); + ///Proceed with the specified certificate. static const PROCEED = const ClientCertResponseAction._internal(1); + ///Ignore the request for now. static const IGNORE = const ClientCertResponseAction._internal(2); } -/// +///ClientCertResponse class represents the response used by the [onReceivedClientCertRequest] event. class ClientCertResponse { + ///The file path of the certificate to use. String certificatePath; + ///The certificate password. String certificatePassword; + ///An Android-specific property used by Java [KeyStore](https://developer.android.com/reference/java/security/KeyStore) class to get the instance. String androidKeyStoreType; + ///Indicate the [ClientCertResponseAction] to take in response of the client certificate challenge. ClientCertResponseAction action; ClientCertResponse({this.certificatePath, this.certificatePassword = "", this.androidKeyStoreType = "PKCS12", this.action = ClientCertResponseAction.CANCEL}) { @@ -474,18 +518,24 @@ class ClientCertResponse { } } -/// +///ClientCertChallenge class represents the challenge of the [onReceivedClientCertRequest] event. +///It provides all the information about the challenge. class ClientCertChallenge { + ///The protection space requiring authentication. ProtectionSpace protectionSpace; ClientCertChallenge({@required this.protectionSpace}): assert(protectionSpace != null); } -/// +///Favicon class represents a favicon of a website. It is used by [InAppWebViewController.getFavicons] method. class Favicon { + ///The url of the favicon image. String url; + ///The relationship between the current web page and the favicon image. String rel; + ///The width of the favicon image. int width; + ///The height of the favicon image. int height; Favicon({@required this.url, this.rel, this.width, this.height}): assert(url != null); @@ -495,7 +545,7 @@ class Favicon { } } -/// +///AndroidInAppWebViewCacheMode class represents an Android-specific class used to override the way the cache is used. class AndroidInAppWebViewCacheMode { final int _value; const AndroidInAppWebViewCacheMode._internal(this._value); @@ -506,30 +556,43 @@ class AndroidInAppWebViewCacheMode { } toValue() => _value; + ///Default cache usage mode. If the navigation type doesn't impose any specific behavior, + ///use cached resources when they are available and not expired, otherwise load resources from the network. static const LOAD_DEFAULT = const AndroidInAppWebViewCacheMode._internal(-1); + ///Use cached resources when they are available, even if they have expired. Otherwise load resources from the network. static const LOAD_CACHE_ELSE_NETWORK = const AndroidInAppWebViewCacheMode._internal(1); + ///Don't use the cache, load from the network. static const LOAD_NO_CACHE = const AndroidInAppWebViewCacheMode._internal(2); + ///Don't use the network, load from the cache. static const LOAD_CACHE_ONLY = const AndroidInAppWebViewCacheMode._internal(3); } +///AndroidInAppWebViewModeMenuItem class represents an Android-specific class used to disable the action mode menu items. /// +///**NOTE**: available on Android 24+. class AndroidInAppWebViewModeMenuItem { final int _value; const AndroidInAppWebViewModeMenuItem._internal(this._value); static AndroidInAppWebViewModeMenuItem fromValue(int value) { - if (value != null && value >= 0 && value <= 4) + if (value != null && value != 3 && value >= 0 && value <= 4) return AndroidInAppWebViewModeMenuItem._internal(value); return null; } toValue() => _value; + ///No menu items should be disabled. static const MENU_ITEM_NONE = const AndroidInAppWebViewModeMenuItem._internal(0); + ///Disable menu item "Share". static const MENU_ITEM_SHARE = const AndroidInAppWebViewModeMenuItem._internal(1); + ///Disable menu item "Web Search". static const MENU_ITEM_WEB_SEARCH = const AndroidInAppWebViewModeMenuItem._internal(2); + ///Disable all the action mode menu items for text processing. static const MENU_ITEM_PROCESS_TEXT = const AndroidInAppWebViewModeMenuItem._internal(4); } +///AndroidInAppWebViewForceDark class represents an Android-specific class used to indicate the force dark mode. /// +///**NOTE**: available on Android 29+. class AndroidInAppWebViewForceDark { final int _value; const AndroidInAppWebViewForceDark._internal(this._value); @@ -540,12 +603,16 @@ class AndroidInAppWebViewForceDark { } toValue() => _value; + ///Disable force dark, irrespective of the force dark mode of the WebView parent. + ///In this mode, WebView content will always be rendered as-is, regardless of whether native views are being automatically darkened. static const FORCE_DARK_OFF = const AndroidInAppWebViewForceDark._internal(0); + ///Enable force dark dependent on the state of the WebView parent view. static const FORCE_DARK_AUTO = const AndroidInAppWebViewForceDark._internal(1); + ///Unconditionally enable force dark. In this mode WebView content will always be rendered so as to emulate a dark theme. static const FORCE_DARK_ON = const AndroidInAppWebViewForceDark._internal(2); } -/// +///AndroidInAppWebViewLayoutAlgorithm class represents an Android-specific class used to set the underlying layout algorithm. class AndroidInAppWebViewLayoutAlgorithm { final String _value; const AndroidInAppWebViewLayoutAlgorithm._internal(this._value); @@ -554,11 +621,18 @@ class AndroidInAppWebViewLayoutAlgorithm { } toValue() => _value; + ///NORMAL means no rendering changes. This is the recommended choice for maximum compatibility across different platforms and Android versions. static const NORMAL = const AndroidInAppWebViewLayoutAlgorithm._internal("NORMAL"); + ///TEXT_AUTOSIZING boosts font size of paragraphs based on heuristics to make the text readable when viewing a wide-viewport layout in the overview mode. + ///It is recommended to enable zoom support [AndroidInAppWebViewOptions.supportZoom] when using this mode. + /// + ///**NOTE**: available on Android 19+. static const TEXT_AUTOSIZING = const AndroidInAppWebViewLayoutAlgorithm._internal("TEXT_AUTOSIZING"); } +///AndroidInAppWebViewMixedContentMode class represents an Android-specific class used to configure the WebView's behavior when a secure origin attempts to load a resource from an insecure origin. /// +///**NOTE**: available on Android 21+. class AndroidInAppWebViewMixedContentMode { final int _value; const AndroidInAppWebViewMixedContentMode._internal(this._value); @@ -569,12 +643,21 @@ class AndroidInAppWebViewMixedContentMode { } toValue() => _value; + ///In this mode, the WebView will allow a secure origin to load content from any other origin, even if that origin is insecure. + ///This is the least secure mode of operation for the WebView, and where possible apps should not set this mode. static const MIXED_CONTENT_ALWAYS_ALLOW = const AndroidInAppWebViewMixedContentMode._internal(0); + ///In this mode, the WebView will not allow a secure origin to load content from an insecure origin. + ///This is the preferred and most secure mode of operation for the WebView and apps are strongly advised to use this mode. static const MIXED_CONTENT_NEVER_ALLOW = const AndroidInAppWebViewMixedContentMode._internal(1); + ///In this mode, the WebView will attempt to be compatible with the approach of a modern web browser with regard to mixed content. + ///Some insecure content may be allowed to be loaded by a secure origin and other types of content will be blocked. + ///The types of content are allowed or blocked may change release to release and are not explicitly defined. + ///This mode is intended to be used by apps that are not in control of the content that they render but desire to operate in a reasonably secure environment. + ///For highest security, apps are recommended to use [AndroidInAppWebViewMixedContentMode.MIXED_CONTENT_NEVER_ALLOW]. static const MIXED_CONTENT_COMPATIBILITY_MODE = const AndroidInAppWebViewMixedContentMode._internal(2); } -/// +///IosInAppWebViewSelectionGranularity class represents an iOS-specific class used to set the level of granularity with which the user can interactively select content in the web view. class IosInAppWebViewSelectionGranularity { final int _value; const IosInAppWebViewSelectionGranularity._internal(this._value); @@ -585,11 +668,15 @@ class IosInAppWebViewSelectionGranularity { } toValue() => _value; - static const CHARACTER = const IosInAppWebViewSelectionGranularity._internal(0); - static const DYNAMIC = const IosInAppWebViewSelectionGranularity._internal(1); + ///Selection granularity varies automatically based on the selection. + static const DYNAMIC = const IosInAppWebViewSelectionGranularity._internal(0); + ///Selection endpoints can be placed at any character boundary. + static const CHARACTER = const IosInAppWebViewSelectionGranularity._internal(1); } +///IosInAppWebViewDataDetectorTypes class represents an iOS-specific class used to specify a dataDetectoryTypes value that adds interactivity to web content that matches the value. /// +///**NOTE**: available on iOS 10.0+. class IosInAppWebViewDataDetectorTypes { final String _value; const IosInAppWebViewDataDetectorTypes._internal(this._value); @@ -599,19 +686,29 @@ class IosInAppWebViewDataDetectorTypes { } toValue() => _value; + ///No detection is performed. static const NONE = const IosInAppWebViewDataDetectorTypes._internal("NONE"); + ///Phone numbers are detected and turned into links. static const PHONE_NUMBER = const IosInAppWebViewDataDetectorTypes._internal("PHONE_NUMBER"); + ///URLs in text are detected and turned into links. static const LINK = const IosInAppWebViewDataDetectorTypes._internal("LINK"); + ///Addresses are detected and turned into links. static const ADDRESS = const IosInAppWebViewDataDetectorTypes._internal("ADDRESS"); + ///Dates and times that are in the future are detected and turned into links. static const CALENDAR_EVENT = const IosInAppWebViewDataDetectorTypes._internal("CALENDAR_EVENT"); + ///Tracking numbers are detected and turned into links. static const TRACKING_NUMBER = const IosInAppWebViewDataDetectorTypes._internal("TRACKING_NUMBER"); + ///Flight numbers are detected and turned into links. static const FLIGHT_NUMBER = const IosInAppWebViewDataDetectorTypes._internal("FLIGHT_NUMBER"); + ///Lookup suggestions are detected and turned into links. static const LOOKUP_SUGGESTION = const IosInAppWebViewDataDetectorTypes._internal("LOOKUP_SUGGESTION"); + ///Spotlight suggestions are detected and turned into links. static const SPOTLIGHT_SUGGESTION = const IosInAppWebViewDataDetectorTypes._internal("SPOTLIGHT_SUGGESTION"); + ///All of the above data types are turned into links when detected. Choosing this value will automatically include any new detection type that is added. static const ALL = const IosInAppWebViewDataDetectorTypes._internal("ALL"); } -/// +///InAppWebViewUserPreferredContentMode class represents the content mode to prefer when loading and rendering a webpage. class InAppWebViewUserPreferredContentMode { final int _value; const InAppWebViewUserPreferredContentMode._internal(this._value); @@ -622,12 +719,15 @@ class InAppWebViewUserPreferredContentMode { } toValue() => _value; + ///The recommended content mode for the current platform. static const RECOMMENDED = const InAppWebViewUserPreferredContentMode._internal(0); + ///Represents content targeting mobile browsers. static const MOBILE = const InAppWebViewUserPreferredContentMode._internal(1); + ///Represents content targeting desktop browsers. static const DESKTOP = const InAppWebViewUserPreferredContentMode._internal(2); } -/// +///IosWebViewOptionsPresentationStyle class represents an iOS-specific class used to specify the modal presentation style when presenting a view controller. class IosWebViewOptionsPresentationStyle { final int _value; const IosWebViewOptionsPresentationStyle._internal(this._value); @@ -638,19 +738,31 @@ class IosWebViewOptionsPresentationStyle { } toValue() => _value; + ///A presentation style in which the presented view covers the screen. static const FULL_SCREEN = const IosWebViewOptionsPresentationStyle._internal(0); + ///A presentation style that partially covers the underlying content. static const PAGE_SHEET = const IosWebViewOptionsPresentationStyle._internal(1); + ///A presentation style that displays the content centered in the screen. static const FORM_SHEET = const IosWebViewOptionsPresentationStyle._internal(2); + ///A presentation style where the content is displayed over another view controller’s content. static const CURRENT_CONTEXT = const IosWebViewOptionsPresentationStyle._internal(3); + ///A custom view presentation style that is managed by a custom presentation controller and one or more custom animator objects. static const CUSTOM = const IosWebViewOptionsPresentationStyle._internal(4); + ///A view presentation style in which the presented view covers the screen. static const OVER_FULL_SCREEN = const IosWebViewOptionsPresentationStyle._internal(5); + ///A presentation style where the content is displayed over another view controller’s content. static const OVER_CURRENT_CONTEXT = const IosWebViewOptionsPresentationStyle._internal(6); + ///A presentation style where the content is displayed in a popover view. static const POPOVER = const IosWebViewOptionsPresentationStyle._internal(7); + ///A presentation style that indicates no adaptations should be made. static const NONE = const IosWebViewOptionsPresentationStyle._internal(8); + ///The default presentation style chosen by the system. + /// + ///**NOTE**: available on iOS 13.0+. static const AUTOMATIC = const IosWebViewOptionsPresentationStyle._internal(9); } -/// +///IosWebViewOptionsTransitionStyle class represents an iOS-specific class used to specify the transition style when presenting a view controller. class IosWebViewOptionsTransitionStyle { final int _value; const IosWebViewOptionsTransitionStyle._internal(this._value); @@ -661,13 +773,25 @@ class IosWebViewOptionsTransitionStyle { } toValue() => _value; + ///When the view controller is presented, its view slides up from the bottom of the screen. + ///On dismissal, the view slides back down. This is the default transition style. static const COVER_VERTICAL = const IosWebViewOptionsTransitionStyle._internal(0); + ///When the view controller is presented, the current view initiates a horizontal 3D flip from right-to-left, + ///resulting in the revealing of the new view as if it were on the back of the previous view. + ///On dismissal, the flip occurs from left-to-right, returning to the original view. static const FLIP_HORIZONTAL = const IosWebViewOptionsTransitionStyle._internal(1); + ///When the view controller is presented, the current view fades out while the new view fades in at the same time. + ///On dismissal, a similar type of cross-fade is used to return to the original view. static const CROSS_DISSOLVE = const IosWebViewOptionsTransitionStyle._internal(2); + ///When the view controller is presented, one corner of the current view curls up to reveal the presented view underneath. + ///On dismissal, the curled up page unfurls itself back on top of the presented view. + ///A view controller presented using this transition is itself prevented from presenting any additional view controllers. static const PARTIAL_CURL = const IosWebViewOptionsTransitionStyle._internal(3); } +///IosWebViewOptionsTransitionStyle class represents an iOS-specific class used to set the custom style for the dismiss button. /// +///**NOTE**: available on iOS 11.0+. class IosSafariOptionsDismissButtonStyle { final int _value; const IosSafariOptionsDismissButtonStyle._internal(this._value); @@ -678,45 +802,59 @@ class IosSafariOptionsDismissButtonStyle { } toValue() => _value; + ///Makes the button title the localized string "Done". static const DONE = const IosSafariOptionsDismissButtonStyle._internal(0); + ///Makes the button title the localized string "Close". static const CLOSE = const IosSafariOptionsDismissButtonStyle._internal(1); + ///Makes the button title the localized string "Cancel". static const CANCEL = const IosSafariOptionsDismissButtonStyle._internal(2); } -/// +///InAppWebViewWidgetOptions class represents the options that can be used for an [InAppWebView]. class InAppWebViewWidgetOptions { + ///Cross-platform options. InAppWebViewOptions inAppWebViewOptions; + ///Android-specific options. AndroidInAppWebViewOptions androidInAppWebViewOptions; + ///iOS-specific options. IosInAppWebViewOptions iosInAppWebViewOptions; InAppWebViewWidgetOptions({this.inAppWebViewOptions, this.androidInAppWebViewOptions, this.iosInAppWebViewOptions}); } -/// +///InAppBrowserClassOptions class represents the options that can be used for an [InAppBrowser] WebView. class InAppBrowserClassOptions { + ///Cross-platform options. InAppBrowserOptions inAppBrowserOptions; + ///Android-specific options. AndroidInAppBrowserOptions androidInAppBrowserOptions; + ///iOS-specific options. IosInAppBrowserOptions iosInAppBrowserOptions; + ///WebView options. InAppWebViewWidgetOptions inAppWebViewWidgetOptions; InAppBrowserClassOptions({this.inAppBrowserOptions, this.androidInAppBrowserOptions, this.iosInAppBrowserOptions, this.inAppWebViewWidgetOptions}); } -/// +///ChromeSafariBrowserClassOptions class represents the options that can be used for an [ChromeSafariBrowser] window. class ChromeSafariBrowserClassOptions { + ///Android-specific options. AndroidChromeCustomTabsOptions androidChromeCustomTabsOptions; + ///iOS-specific options. IosSafariOptions iosSafariOptions; ChromeSafariBrowserClassOptions({this.androidChromeCustomTabsOptions, this.iosSafariOptions}); } -/// +///AjaxRequestAction class used by [AjaxRequest] class. class AjaxRequestAction { final int _value; const AjaxRequestAction._internal(this._value); toValue() => _value; + ///Aborts the current [AjaxRequest]. static const ABORT = const AjaxRequestAction._internal(0); + ///Proceeds with the current [AjaxRequest]. static const PROCEED = const AjaxRequestAction._internal(1); Map toMap() { @@ -730,7 +868,7 @@ class AjaxRequestAction { } } -/// +///AjaxRequestEventType class used by [AjaxRequestEvent] class. class AjaxRequestEventType { final String _value; const AjaxRequestEventType._internal(this._value); @@ -740,24 +878,42 @@ class AjaxRequestEventType { toValue() => _value; String toString() => _value; + ///The LOADSTART event is fired when a request has started to load data. static const LOADSTART = const AjaxRequestEventType._internal("loadstart"); + ///The LOAD event is fired when an `XMLHttpRequest` transaction completes successfully. static const LOAD = const AjaxRequestEventType._internal("load"); + ///The LOADEND event is fired when a request has completed, whether successfully (after [AjaxRequestEventType.LOAD]) or + ///unsuccessfully (after [AjaxRequestEventType.ABORT] or [AjaxRequestEventType.ERROR]). static const LOADEND = const AjaxRequestEventType._internal("loadend"); + ///The PROGRESS event is fired periodically when a request receives more data. static const PROGRESS = const AjaxRequestEventType._internal("progress"); + ///The ERROR event is fired when the request encountered an error. static const ERROR = const AjaxRequestEventType._internal("error"); + ///The ABORT event is fired when a request has been aborted. static const ABORT = const AjaxRequestEventType._internal("abort"); + ///The TIMEOUT event is fired when progression is terminated due to preset time expiring. + static const TIMEOUT = const AjaxRequestEventType._internal("timeout"); } -/// +///AjaxRequestEvent class used by [AjaxRequest] class. It represents events measuring progress of an [AjaxRequest]. class AjaxRequestEvent { + ///Event type. AjaxRequestEventType type; - int loaded; + ///Is a Boolean flag indicating if the total work to be done, and the amount of work already done, by the underlying process is calculable. + ///In other words, it tells if the progress is measurable or not. bool lengthComputable; + ///Is an integer representing the amount of work already performed by the underlying process. + ///The ratio of work done can be calculated with the property and [AjaxRequestEvent.total]. + ///When downloading a resource using HTTP, this only represent the part of the content itself, not headers and other overhead. + int loaded; + ///Is an integer representing the total amount of work that the underlying process is in the progress of performing. + ///When downloading a resource using HTTP, this only represent the content itself, not headers and other overhead. + int total; - AjaxRequestEvent({this.type, this.loaded, this.lengthComputable}); + AjaxRequestEvent({this.type, this.lengthComputable, this.loaded, this.total}); } -/// +///AjaxRequestReadyState class used by [AjaxRequest] class. It represents the state of an [AjaxRequest]. class AjaxRequestReadyState { final int _value; const AjaxRequestReadyState._internal(this._value); @@ -769,31 +925,63 @@ class AjaxRequestReadyState { toValue() => _value; String toString() => _value.toString(); + ///Client has been created. `XMLHttpRequest.open()` not called yet. static const UNSENT = const AjaxRequestReadyState._internal(0); + ///`XMLHttpRequest.open()` has been called. static const OPENED = const AjaxRequestReadyState._internal(1); + ///`XMLHttpRequest.send()` has been called, and [AjaxRequest.headers] and [AjaxRequest.status] are available. static const HEADERS_RECEIVED = const AjaxRequestReadyState._internal(2); + ///Downloading; [AjaxRequest.responseText] holds partial data. static const LOADING = const AjaxRequestReadyState._internal(3); + ///The operation is complete. static const DONE = const AjaxRequestReadyState._internal(4); } -/// +///AjaxRequest class represents a JavaScript [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) object. class AjaxRequest { + ///Data passed to as a parameter to the `XMLHttpRequest.send()` method. dynamic data; + ///The HTTP request method of the `XMLHttpRequest` request. String method; + ///The URL of the `XMLHttpRequest` request. String url; + ///An optional Boolean parameter, defaulting to true, indicating whether or not the request is performed asynchronously. bool isAsync; + ///The optional user name to use for authentication purposes; by default, this is the null value. String user; + ///The optional password to use for authentication purposes; by default, this is the null value. String password; + ///The XMLHttpRequest.withCredentials property is a Boolean that indicates whether or not cross-site Access-Control requests + ///should be made using credentials such as cookies, authorization headers or TLS client certificates. + ///Setting withCredentials has no effect on same-site requests. + ///In addition, this flag is also used to indicate when cookies are to be ignored in the response. The default is false. bool withCredentials; + ///The HTTP request headers. Map headers; + ///The state of the `XMLHttpRequest` request. AjaxRequestReadyState readyState; + ///The numerical HTTP [status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) of the `XMLHttpRequest`'s response. int status; + ///The serialized URL of the response or the empty string if the URL is null. + ///If the URL is returned, any URL fragment present in the URL will be stripped away. + ///The value of responseURL will be the final URL obtained after any redirects. String responseURL; + ///It is an enumerated string value specifying the type of data contained in the response. + ///It also lets the author change the [response type](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType). + ///If an empty string is set as the value of responseType, the default value of text is used. String responseType; + ///The text received from a server following a request being sent. String responseText; + ///A String containing the response's status message as returned by the HTTP server. + ///Unlike [AjaxRequest.status] which indicates a numerical status code, this property contains the text of the response status, such as "OK" or "Not Found". + ///If the request's readyState is in [AjaxRequestReadyState.UNSENT] or [AjaxRequestReadyState.OPENED] state, the value of statusText will be an empty string. + ///If the server response doesn't explicitly specify a status text, statusText will assume the default value "OK". String statusText; + ///All the response headers or returns null if no response has been received. If a network error happened, an empty string is returned. Map responseHeaders; + ///Event type of the `XMLHttpRequest` request. AjaxRequestEvent event; + ///Indicates the [AjaxRequestAction] that can be used to control the `XMLHttpRequest` request. AjaxRequestAction action; AjaxRequest({this.data, this.method, this.url, this.isAsync, this.user, this.password, @@ -826,18 +1014,21 @@ class AjaxRequest { } } -/// +///FetchRequestAction class used by [FetchRequest] class. class FetchRequestAction { final int _value; const FetchRequestAction._internal(this._value); toValue() => _value; + ///Aborts the fetch request. static const ABORT = const FetchRequestAction._internal(0); + ///Proceeds with the fetch request. static const PROCEED = const FetchRequestAction._internal(1); } -/// +///FetchRequestCredential class is an interface for [FetchRequestCredentialDefault], [FetchRequestFederatedCredential] and [FetchRequestPasswordCredential] classes. class FetchRequestCredential { + ///Type of credentials. String type; FetchRequestCredential({this.type}); @@ -849,8 +1040,9 @@ class FetchRequestCredential { } } -/// +///FetchRequestCredentialDefault class represents the default credentials used by an [FetchRequest]. class FetchRequestCredentialDefault extends FetchRequestCredential { + ///The value of the credentials. String value; FetchRequestCredentialDefault({type, this.value}): super(type: type); @@ -863,12 +1055,17 @@ class FetchRequestCredentialDefault extends FetchRequestCredential { } } -/// +///FetchRequestFederatedCredential class represents a [FederatedCredential](https://developer.mozilla.org/en-US/docs/Web/API/FederatedCredential) type of credentials. class FetchRequestFederatedCredential extends FetchRequestCredential { + ///Credential's identifier. dynamic id; + ///The name associated with a credential. It should be a human-readable, public name. String name; + ///Credential's federated identity protocol. String protocol; + ///Credential's federated identity provider. String provider; + ///URL pointing to an image for an icon. This image is intended for display in a credential chooser. The URL must be accessible without authentication. String iconURL; FetchRequestFederatedCredential({type, this.id, this.name, this.protocol, this.provider, this.iconURL}): super(type: type); @@ -885,11 +1082,15 @@ class FetchRequestFederatedCredential extends FetchRequestCredential { } } -/// +///FetchRequestPasswordCredential class represents a [PasswordCredential](https://developer.mozilla.org/en-US/docs/Web/API/PasswordCredential) type of credentials. class FetchRequestPasswordCredential extends FetchRequestCredential { + ///Credential's identifier. dynamic id; + ///The name associated with a credential. It should be a human-readable, public name. String name; + ///The password of the credential. String password; + ///URL pointing to an image for an icon. This image is intended for display in a credential chooser. The URL must be accessible without authentication. String iconURL; FetchRequestPasswordCredential({type, this.id, this.name, this.password, this.iconURL}): super(type: type); @@ -905,20 +1106,33 @@ class FetchRequestPasswordCredential extends FetchRequestCredential { } } -/// +///FetchRequest class represents a HTTP request created with JavaScript using the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch). class FetchRequest { + ///The URL of the request. String url; + ///The HTTP request method used of the request. String method; + ///The HTTP request headers. Map headers; + ///Body of the request. Uint8List body; + ///The mode used by the request. String mode; + ///The request credentials used by the request. FetchRequestCredential credentials; + ///The cache mode used by the request. String cache; + ///The redirect mode used by the request. String redirect; + ///A String specifying no-referrer, client, or a URL. String referrer; + ///The value of the referer HTTP header. String referrerPolicy; + ///Contains the subresource integrity value of the request. String integrity; + ///The keepalive option used to allow the request to outlive the page. bool keepalive; + ///Indicates the [FetchRequestAction] that can be used to control the request. FetchRequestAction action; FetchRequest({this.url, this.method, this.headers, this.body, this.mode, this.credentials, diff --git a/lib/src/webview_options.dart b/lib/src/webview_options.dart index 251fd32a..36708500 100644 --- a/lib/src/webview_options.dart +++ b/lib/src/webview_options.dart @@ -83,7 +83,7 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti /// ///**NOTE**: available on iOS 11.0+. List contentBlockers; - ///Sets the content mode that the WebView needs to use. The default value is [InAppWebViewUserPreferredContentMode.RECOMMENDED]. + ///Sets the content mode that the WebView needs to use when loading and rendering a webpage. The default value is [InAppWebViewUserPreferredContentMode.RECOMMENDED]. /// ///**NOTE**: available on iOS 13.0+. InAppWebViewUserPreferredContentMode preferredContentMode; @@ -676,10 +676,16 @@ class IosSafariOptions implements ChromeSafariBrowserOptions, IosOptions { ///Set to `true` to enable bar collapsing. The default value is `false`. bool barCollapsingEnabled; ///Set the custom style for the dismiss button. The default value is [IosSafariOptionsDismissButtonStyle.DONE]. + /// + ///**NOTE**: available on iOS 11.0+. IosSafariOptionsDismissButtonStyle dismissButtonStyle; ///Set the custom background color of the navigation bar and the toolbar. + /// + ///**NOTE**: available on iOS 10.0+. String preferredBarTintColor; ///Set the custom color of the control buttons on the navigation bar and the toolbar. + /// + ///**NOTE**: available on iOS 10.0+. String preferredControlTintColor; ///Set the custom modal presentation style when presenting the WebView. The default value is [IosWebViewOptionsPresentationStyle.FULL_SCREEN]. IosWebViewOptionsPresentationStyle presentationStyle;