From 44c17d1efe7452661c8c667b72d63a2ef3d36507 Mon Sep 17 00:00:00 2001 From: Lorenzo Pichilli Date: Sun, 10 Nov 2019 14:11:30 +0100 Subject: [PATCH] updated code docs --- .idea/workspace.xml | 238 ++++++++---------- .../ContentBlocker/ContentBlockerHandler.java | 2 +- example/lib/chrome_safari_example.screen.dart | 4 +- example/lib/inline_example.screen.dart | 31 +-- example/lib/webview_example.screen.dart | 16 +- lib/src/chrome_safari_browser.dart | 35 +-- lib/src/content_blocker.dart | 69 ++++- lib/src/cookie_manager.dart | 13 +- lib/src/http_auth_credentials_database.dart | 31 ++- lib/src/in_app_browser.dart | 91 +++---- lib/src/in_app_webview.dart | 118 +++------ lib/src/types.dart | 27 +- 12 files changed, 310 insertions(+), 365 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 3c7217bd..43a20f12 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -15,11 +15,17 @@ - - + + + + + + + + @@ -39,11 +45,11 @@ - + - - + + @@ -51,11 +57,11 @@ - - + + - - + + @@ -64,52 +70,22 @@ - + - - - - - - - - - - - + + - + - - - - - - - - - - - - - - - - - - - - - - - + + @@ -120,8 +96,8 @@ - - + + @@ -141,8 +117,6 @@ - JsAlertResponse - JsConfirmResponse InAppWebViewUserPreferredContentMode onSag ServerTrustAuthResponse @@ -171,6 +145,8 @@ should resourceCustomSchemes shouldInterceptAjaxRequest + evaluateJavascript + WebHistory activity.getPreferences(0) @@ -223,8 +199,6 @@ @@ -503,7 +479,7 @@ - + @@ -515,7 +491,7 @@ - + @@ -655,26 +631,6 @@ - - - - - - - - - - - - - - - - - - - - @@ -712,16 +668,6 @@ - - - - - - - - - - @@ -729,37 +675,17 @@ - + - - - - - - - - - - - - - - - - - - - - - - + + - - + + @@ -768,51 +694,101 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - - - - - - - - - + + - + - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/ContentBlocker/ContentBlockerHandler.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/ContentBlocker/ContentBlockerHandler.java index 6c1d232a..341838db 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/ContentBlocker/ContentBlockerHandler.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/ContentBlocker/ContentBlockerHandler.java @@ -155,7 +155,7 @@ public class ContentBlockerHandler { break; case MAKE_HTTPS: - if (url.startsWith("http://")) { + if (scheme.equals("http") && (port == -1 || port == 80)) { String urlHttps = url.replace("http://", "https://"); Request mRequest = new Request.Builder().url(urlHttps).build(); diff --git a/example/lib/chrome_safari_example.screen.dart b/example/lib/chrome_safari_example.screen.dart index 9b07869a..ac6014e0 100644 --- a/example/lib/chrome_safari_example.screen.dart +++ b/example/lib/chrome_safari_example.screen.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_inappbrowser/flutter_inappbrowser.dart'; class MyChromeSafariBrowser extends ChromeSafariBrowser { - MyChromeSafariBrowser(browserFallback) : super(browserFallback); + MyChromeSafariBrowser(browserFallback) : super(bFallback: browserFallback); @override void onOpened() { print("ChromeSafari browser opened"); @@ -36,7 +36,7 @@ class _ChromeSafariExampleScreenState extends State { return new Center( child: new RaisedButton( onPressed: () async { - await widget.browser.open("https://flutter.dev/", + await widget.browser.open(url: "https://flutter.dev/", options: ChromeSafariBrowserClassOptions( androidChromeCustomTabsOptions: AndroidChromeCustomTabsOptions(addShareButton: false), iosSafariOptions: IosSafariOptions(barCollapsingEnabled: true) diff --git a/example/lib/inline_example.screen.dart b/example/lib/inline_example.screen.dart index b6a69baa..fa9f83b3 100755 --- a/example/lib/inline_example.screen.dart +++ b/example/lib/inline_example.screen.dart @@ -104,10 +104,11 @@ class _InlineExampleScreenState extends State { resourceCustomSchemes: ["my-special-custom-scheme"], contentBlockers: [ ContentBlocker( - ContentBlockerTrigger(".*", + trigger: ContentBlockerTrigger( + urlFilter: ".*", resourceType: [ContentBlockerTriggerResourceType.IMAGE, ContentBlockerTriggerResourceType.STYLE_SHEET], ifTopUrl: ["https://getbootstrap.com/"]), - ContentBlockerAction(ContentBlockerActionType.BLOCK) + action: ContentBlockerAction(type: ContentBlockerActionType.BLOCK) ) ] ), @@ -125,11 +126,11 @@ class _InlineExampleScreenState extends State { if (Platform.isAndroid) webView.startSafeBrowsing(); - webView.addJavaScriptHandler('handlerFoo', (args) { + webView.addJavaScriptHandler(handlerName:'handlerFoo', callback: (args) { return new Foo(bar: 'bar_value', baz: 'baz_value'); }); - webView.addJavaScriptHandler('handlerFooWithArgs', (args) { + webView.addJavaScriptHandler(handlerName: 'handlerFooWithArgs', callback: (args) { print(args); return [args[0] + 5, !args[1], args[2][0], args[3]['foo']]; }); @@ -155,20 +156,20 @@ class _InlineExampleScreenState extends State { var tRexHtml = await controller.getTRexRunnerHtml(); var tRexCss = await controller.getTRexRunnerCss(); - controller.loadData(""" + controller.loadData(data: """ - + - ${tRexHtml} + $tRexHtml

- URL ${url} failed to load. + URL $url failed to load.

- Error: ${code}, ${message} + Error: $code, $message

@@ -182,7 +183,7 @@ class _InlineExampleScreenState extends State { }, shouldOverrideUrlLoading: (InAppWebViewController controller, String url) { print("override $url"); - controller.loadUrl(url); + controller.loadUrl(url: url); }, onLoadResource: (InAppWebViewController controller, LoadedResource response) { print("Resource type: '"+response.initiatorType + "' started at: " + @@ -212,14 +213,14 @@ class _InlineExampleScreenState extends State { onLoadResourceCustomScheme: (InAppWebViewController controller, String scheme, String url) async { if (scheme == "my-special-custom-scheme") { var bytes = await rootBundle.load("assets/" + url.replaceFirst("my-special-custom-scheme://", "", 0)); - var response = new CustomSchemeResponse(bytes.buffer.asUint8List(), "image/svg+xml", contentEnconding: "utf-8"); + var response = new CustomSchemeResponse(data: bytes.buffer.asUint8List(), contentType: "image/svg+xml", contentEnconding: "utf-8"); return response; } return null; }, onTargetBlank: (InAppWebViewController controller, String url) { print("target _blank: " + url); - controller.loadUrl(url); + controller.loadUrl(url: url); }, onGeolocationPermissionsShowPrompt: (InAppWebViewController controller, String origin) async { GeolocationPermissionShowPromptResponse response; @@ -234,14 +235,14 @@ class _InlineExampleScreenState extends State { FlatButton( child: Text("Close"), onPressed: () { - response = new GeolocationPermissionShowPromptResponse(origin, false, false); + response = new GeolocationPermissionShowPromptResponse(origin: origin, allow: false, retain: false); Navigator.of(context).pop(); }, ), FlatButton( child: Text("Accept"), onPressed: () { - response = new GeolocationPermissionShowPromptResponse(origin, true, true); + response = new GeolocationPermissionShowPromptResponse(origin: origin, allow: true, retain: true); Navigator.of(context).pop(); }, ), @@ -312,7 +313,7 @@ class _InlineExampleScreenState extends State { return fetchRequest; }, onNavigationStateChange: (InAppWebViewController controller, String url) async { - print("NAVIGATION STATE CHANGE: ${url}"); + print("NAVIGATION STATE CHANGE: $url"); setState(() { this.url = url; }); diff --git a/example/lib/webview_example.screen.dart b/example/lib/webview_example.screen.dart index 091b3594..d3f61fa9 100644 --- a/example/lib/webview_example.screen.dart +++ b/example/lib/webview_example.screen.dart @@ -3,7 +3,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_inappbrowser/flutter_inappbrowser.dart'; -class MyInappBrowser extends InAppBrowser { +class MyInAppBrowser extends InAppBrowser { @override Future onBrowserCreated() async { @@ -43,7 +43,7 @@ class MyInappBrowser extends InAppBrowser { @override void shouldOverrideUrlLoading(String url) { print("\n\n override $url\n\n"); - this.webViewController.loadUrl(url); + this.webViewController.loadUrl(url: url); } @override @@ -75,11 +75,13 @@ class MyInappBrowser extends InAppBrowser { @override Future onLoadResourceCustomScheme(String scheme, String url) async { print("custom scheme: " + scheme); + return null; } @override Future onGeolocationPermissionsShowPrompt(String origin) async { print("request Geolocation permission API"); + return null; } @override @@ -89,18 +91,18 @@ class MyInappBrowser extends InAppBrowser { @override Future onJsConfirm(String message) { - + return null; } @override Future onJsPrompt(String message, String defaultValue) { - + return null; } } class WebviewExampleScreen extends StatefulWidget { - final MyInappBrowser browser = new MyInappBrowser(); - static BuildContext context = null; + final MyInAppBrowser browser = new MyInAppBrowser(); + static BuildContext context; @override _WebviewExampleScreenState createState() => new _WebviewExampleScreenState(); @@ -119,7 +121,7 @@ class _WebviewExampleScreenState extends State { child: new RaisedButton( onPressed: () { widget.browser.openFile( - "assets/index.html", + assetFilePath: "assets/index.html", //url: "https://www.google.com/", options: InAppBrowserClassOptions( inAppWebViewWidgetOptions: InAppWebViewWidgetOptions( diff --git a/lib/src/chrome_safari_browser.dart b/lib/src/chrome_safari_browser.dart index 8582ffef..9d031694 100644 --- a/lib/src/chrome_safari_browser.dart +++ b/lib/src/chrome_safari_browser.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:io'; +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'types.dart'; @@ -12,16 +13,16 @@ import 'in_app_browser.dart'; ///This class uses native [Chrome Custom Tabs](https://developer.android.com/reference/android/support/customtabs/package-summary) on Android ///and [SFSafariViewController](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller) on iOS. /// -///[browserFallback] represents the [InAppBrowser] instance fallback in case [Chrome Custom Tabs]/[SFSafariViewController] is not available. +///[browserFallback] represents the [InAppBrowser] instance fallback in case `Chrome Custom Tabs`/`SFSafariViewController` is not available. class ChromeSafariBrowser { String uuid; InAppBrowser browserFallback; bool _isOpened = false; ///Initialize the [ChromeSafariBrowser] instance with an [InAppBrowser] fallback instance or `null`. - ChromeSafariBrowser (bf) { + ChromeSafariBrowser ({bFallback}) { uuid = uuidGenerator.v4(); - browserFallback = bf; + browserFallback = bFallback; ChannelManager.addListener(uuid, handleMethod); _isOpened = false; } @@ -45,32 +46,14 @@ class ChromeSafariBrowser { ///Opens an [url] in a new [ChromeSafariBrowser] instance. /// - ///- [url]: The [url] to load. Call [encodeUriComponent()] on this if the [url] contains Unicode characters. + ///[url]: The [url] to load. Call [encodeUriComponent()] on this if the [url] contains Unicode characters. /// - ///- [options]: Options for the [ChromeSafariBrowser]. + ///[options]: Options for the [ChromeSafariBrowser]. /// - ///- [headersFallback]: The additional header of the [InAppBrowser] instance fallback to be used in the HTTP request for this URL, specified as a map from name to value. + ///[headersFallback]: The additional header of the [InAppBrowser] instance fallback to be used in the HTTP request for this URL, specified as a map from name to value. /// - ///- [optionsFallback]: Options used by the [InAppBrowser] instance fallback. - /// - ///**Android** supports these options: - /// - ///- __addShareButton__: Set to `false` if you don't want the default share button. The default value is `true`. - ///- __showTitle__: Set to `false` if the title shouldn't be shown in the custom tab. The default value is `true`. - ///- __toolbarBackgroundColor__: Set the custom background color of the toolbar. - ///- __enableUrlBarHiding__: Set to `true` to enable the url bar to hide as the user scrolls down on the page. The default value is `false`. - ///- __instantAppsEnabled__: Set to `true` to enable Instant Apps. The default value is `false`. - /// - ///**iOS** supports these options: - /// - ///- __entersReaderIfAvailable__: Set to `true` if Reader mode should be entered automatically when it is available for the webpage. The default value is `false`. - ///- __barCollapsingEnabled__: Set to `true` to enable bar collapsing. The default value is `false`. - ///- __dismissButtonStyle__: Set the custom style for the dismiss button. The default value is `0 //done`. See [SFSafariViewController.DismissButtonStyle](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller/dismissbuttonstyle) for all the available styles. - ///- __preferredBarTintColor__: Set the custom background color of the navigation bar and the toolbar. - ///- __preferredControlTintColor__: Set the custom color of the control buttons on the navigation bar and the toolbar. - ///- __presentationStyle__: Set the custom modal presentation style when presenting the WebView. The default value is `0 //fullscreen`. See [UIModalPresentationStyle](https://developer.apple.com/documentation/uikit/uimodalpresentationstyle) for all the available styles. - ///- __transitionStyle__: Set to the custom transition style when presenting the WebView. The default value is `0 //crossDissolve`. See [UIModalTransitionStyle](https://developer.apple.com/documentation/uikit/uimodaltransitionStyle) for all the available styles. - Future open(String url, {ChromeSafariBrowserClassOptions options, Map headersFallback = const {}, InAppBrowserClassOptions optionsFallback}) async { + ///[optionsFallback]: Options used by the [InAppBrowser] instance fallback. + Future open({@required String url, ChromeSafariBrowserClassOptions options, Map headersFallback = const {}, InAppBrowserClassOptions optionsFallback}) async { assert(url != null && url.isNotEmpty); this.throwIsAlreadyOpened(message: 'Cannot open $url!'); diff --git a/lib/src/content_blocker.dart b/lib/src/content_blocker.dart index 3075f320..2e775888 100644 --- a/lib/src/content_blocker.dart +++ b/lib/src/content_blocker.dart @@ -1,9 +1,19 @@ +import 'package:flutter/foundation.dart'; + +///ContentBlocker class represents a set of rules to use block content in the browser window. /// +///On iOS, it uses [WKContentRuleListStore](https://developer.apple.com/documentation/webkit/wkcontentruleliststore). +///On Android, it uses a custom implementation because such functionality doesn't exist. +/// +///In general, this [article](https://developer.apple.com/documentation/safariservices/creating_a_content_blocker) can be used to get an overview about this functionality +///but on Android there are two types of [action] that are unavailable: `block-cookies` and `ignore-previous-rules`. class ContentBlocker { + ///Trigger of the content blocker. The trigger tells to the WebView when to perform the corresponding action. ContentBlockerTrigger trigger; + ///Action associated to the trigger. The action tells to the WebView what to do when the trigger is matched. ContentBlockerAction action; - ContentBlocker(this.trigger, this.action); + ContentBlocker({@required this.trigger,@required this.action}); Map> toMap() { return { @@ -14,22 +24,22 @@ class ContentBlocker { static ContentBlocker fromMap(Map> map) { return ContentBlocker( - ContentBlockerTrigger.fromMap( + trigger: ContentBlockerTrigger.fromMap( Map.from(map["trigger"]) ), - ContentBlockerAction.fromMap( + action: ContentBlockerAction.fromMap( Map.from(map["action"]) ) ); } } -/// +///ContentBlockerTriggerResourceType class represents the possible resource type defined for a [ContentBlockerTrigger]. class ContentBlockerTriggerResourceType { final String _value; const ContentBlockerTriggerResourceType._internal(this._value); static ContentBlockerTriggerResourceType fromValue(String value) { - return (["document", "image", "LINK", "style-sheet", "script", "font", + return (["document", "image", "style-sheet", "script", "font", "media", "svg-document", "raw"].contains(value)) ? ContentBlockerTriggerResourceType._internal(value) : null; } toValue() => _value; @@ -41,10 +51,11 @@ class ContentBlockerTriggerResourceType { static const FONT = const ContentBlockerTriggerResourceType._internal('font'); static const MEDIA = const ContentBlockerTriggerResourceType._internal('media'); static const SVG_DOCUMENT = const ContentBlockerTriggerResourceType._internal('svg-document'); + ///Any untyped load static const RAW = const ContentBlockerTriggerResourceType._internal('raw'); } -/// +///ContentBlockerTriggerLoadType class represents the possible load type for a [ContentBlockerTrigger]. class ContentBlockerTriggerLoadType { final String _value; const ContentBlockerTriggerLoadType._internal(this._value); @@ -53,25 +64,44 @@ class ContentBlockerTriggerLoadType { } toValue() => _value; + ///FIRST_PARTY is triggered only if the resource has the same scheme, domain, and port as the main page resource. static const FIRST_PARTY = const ContentBlockerTriggerLoadType._internal('first-party'); + ///THIRD_PARTY is triggered if the resource is not from the same domain as the main page resource. static const THIRD_PARTY = const ContentBlockerTriggerLoadType._internal('third-party'); } -/// +///Trigger of the content blocker. The trigger tells to the WebView when to perform the corresponding action. +///A trigger dictionary must include an [ContentBlockerTrigger.urlFilter], which specifies a pattern to match the URL against. +///The remaining properties are optional and modify the behavior of the trigger. +///For example, you can limit the trigger to specific domains or have it not apply when a match is found on a specific domain. class ContentBlockerTrigger { + ///A regular expression pattern to match the URL against. String urlFilter; + ///Used only by iOS. A Boolean value. The default value is false. bool urlFilterIsCaseSensitive; + ///A list of [ContentBlockerTriggerResourceType] representing the resource types (how the browser intends to use the resource) that the rule should match. + ///If not specified, the rule matches all resource types. List resourceType; + ///A list of strings matched to a URL's domain; limits action to a list of specific domains. + ///Values must be lowercase ASCII, or punycode for non-ASCII. Add * in front to match domain and subdomains. Can't be used with [ContentBlockerTrigger.unlessDomain]. List ifDomain; + ///A list of strings matched to a URL's domain; acts on any site except domains in a provided list. + ///Values must be lowercase ASCII, or punycode for non-ASCII. Add * in front to match domain and subdomains. Can't be used with [ContentBlockerTrigger.ifDomain]. List unlessDomain; + ///A list of [ContentBlockerTriggerLoadType] that can include one of two mutually exclusive values. If not specified, the rule matches all load types. List loadType; + ///A list of strings matched to the entire main document URL; limits the action to a specific list of URL patterns. + ///Values must be lowercase ASCII, or punycode for non-ASCII. Can't be used with [ContentBlockerTrigger.unlessTopUrl]. List ifTopUrl; + ///An array of strings matched to the entire main document URL; acts on any site except URL patterns in provided list. + ///Values must be lowercase ASCII, or punycode for non-ASCII. Can't be used with [ContentBlockerTrigger.ifTopUrl]. List unlessTopUrl; - ContentBlockerTrigger(String urlFilter, {bool urlFilterIsCaseSensitive = false, List resourceType = const [], + ContentBlockerTrigger({@required String urlFilter, bool urlFilterIsCaseSensitive = false, List resourceType = const [], List ifDomain = const [], List unlessDomain = const [], List loadType = const [], List ifTopUrl = const [], List unlessTopUrl = const []}) { this.urlFilter = urlFilter; + assert(this.urlFilter != null); this.resourceType = resourceType; this.urlFilterIsCaseSensitive = urlFilterIsCaseSensitive; this.ifDomain = ifDomain; @@ -128,7 +158,7 @@ class ContentBlockerTrigger { }); return ContentBlockerTrigger( - map["url-filter"], + urlFilter: map["url-filter"], urlFilterIsCaseSensitive: map["url-filter-is-case-sensitive"], ifDomain: List.from(map["if-domain"] ?? []), unlessDomain: List.from(map["unless-domain"] ?? []), @@ -140,7 +170,7 @@ class ContentBlockerTrigger { } } -/// +///ContentBlockerActionType class represents the kind of action that can be used with a [ContentBlockerTrigger]. class ContentBlockerActionType { final String _value; const ContentBlockerActionType._internal(this._value); @@ -149,18 +179,31 @@ class ContentBlockerActionType { } toValue() => _value; + ///Stops loading of the resource. If the resource was cached, the cache is ignored. static const BLOCK = const ContentBlockerActionType._internal('block'); + ///Hides elements of the page based on a CSS selector. A selector field contains the selector list. Any matching element has its display property set to none, which hides it. + /// + ///**NOTE**: on Android, JavaScript must be enabled. static const CSS_DISPLAY_NONE = const ContentBlockerActionType._internal('css-display-none'); + ///Changes a URL from http to https. URLs with a specified (nondefault) port and links using other protocols are unaffected. static const MAKE_HTTPS = const ContentBlockerActionType._internal('make-https'); } -/// +///Action associated to the trigger. The action tells to the WebView what to do when the trigger is matched. +///When a trigger matches a resource, the browser queues the associated action for execution. +///The WebView evaluates all the triggers, it executes the actions in order. +///When a domain matches a trigger, all rules after the triggered rule that specify the same action are skipped. +///Group the rules with similar actions together to improve performance. class ContentBlockerAction { + ///Type of the action. ContentBlockerActionType type; + ///If the action type is [ContentBlockerActionType.CSS_DISPLAY_NONE], then also the [selector] property is required, otherwise it is ignored. + ///It specify a string that defines a selector list. Use CSS identifiers as the individual selector values, separated by commas. String selector; - ContentBlockerAction(ContentBlockerActionType type, {String selector}) { + ContentBlockerAction({@required ContentBlockerActionType type, String selector}) { this.type = type; + assert(this.type != null); if (this.type == ContentBlockerActionType.CSS_DISPLAY_NONE) { assert(selector != null); } @@ -183,7 +226,7 @@ class ContentBlockerAction { static ContentBlockerAction fromMap(Map map) { return ContentBlockerAction( - ContentBlockerActionType.fromValue(map["type"]), + type: ContentBlockerActionType.fromValue(map["type"]), selector: map["selector"] ); } diff --git a/lib/src/cookie_manager.dart b/lib/src/cookie_manager.dart index 9cb8c484..346edd96 100644 --- a/lib/src/cookie_manager.dart +++ b/lib/src/cookie_manager.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; ///Manages the cookies used by WebView instances. @@ -26,8 +27,8 @@ class CookieManager { /// ///The default value of [path] is `"/"`. ///If [domain] is `null`, its default value will be the domain name of [url]. - Future setCookie(String url, String name, String value, - { String domain, + Future setCookie({@required String url, @required String name, @required String value, + String domain, String path = "/", int expiresDate, int maxAge, @@ -55,7 +56,7 @@ class CookieManager { } ///Gets all the cookies for the given [url]. - Future>> getCookies(String url) async { + Future>> getCookies({@required String url}) async { assert(url != null && url.isNotEmpty); Map args = {}; @@ -70,7 +71,7 @@ class CookieManager { } ///Gets a cookie by its [name] for the given [url]. - Future> getCookie(String url, String name) async { + Future> getCookie({@required String url, @required String name}) async { assert(url != null && url.isNotEmpty); assert(name != null && name.isNotEmpty); @@ -90,7 +91,7 @@ class CookieManager { /// ///The default value of [path] is `"/"`. ///If [domain] is `null` or empty, its default value will be the domain name of [url]. - Future deleteCookie(String url, String name, {String domain = "", String path = "/"}) async { + Future deleteCookie({@required String url, @required String name, String domain = "", String path = "/"}) async { if (domain == null || domain.isEmpty) domain = _getDomainName(url); @@ -111,7 +112,7 @@ class CookieManager { /// ///The default value of [path] is `"/"`. ///If [domain] is `null` or empty, its default value will be the domain name of [url]. - Future deleteCookies(String url, {String domain = "", String path = "/"}) async { + Future deleteCookies({@required String url, String domain = "", String path = "/"}) async { if (domain == null || domain.isEmpty) domain = _getDomainName(url); diff --git a/lib/src/http_auth_credentials_database.dart b/lib/src/http_auth_credentials_database.dart index f0f460e5..331ef916 100644 --- a/lib/src/http_auth_credentials_database.dart +++ b/lib/src/http_auth_credentials_database.dart @@ -1,14 +1,19 @@ import 'dart:async'; +import 'package:flutter/foundation.dart'; + import 'types.dart'; import 'package:flutter/services.dart'; -/// +///HttpAuthCredentialDatabase class implements a singleton object (shared instance) which manages the shared HTTP auth credentials cache. +///On iOS, this class uses the [URLCredentialStorage](https://developer.apple.com/documentation/foundation/urlcredentialstorage) class. +///On Android, this class has a custom implementation using `android.database.sqlite.SQLiteDatabase` because [WebViewDatabase](https://developer.android.com/reference/android/webkit/WebViewDatabase) +///doesn't offer the same functionalities as iOS `URLCredentialStorage`. class HttpAuthCredentialDatabase { static HttpAuthCredentialDatabase _instance; static const MethodChannel _channel = const MethodChannel('com.pichillilorenzo/flutter_inappbrowser_credential_database'); - /// + ///Gets the database shared instance. static HttpAuthCredentialDatabase instance() { return (_instance != null) ? _instance : _init(); } @@ -22,7 +27,9 @@ class HttpAuthCredentialDatabase { static Future _handleMethod(MethodCall call) async { } - /// + ///Gets a map list of all HTTP auth credentials saved. + ///Each map contains the key `protectionSpace` of type [ProtectionSpace] + ///and the key `credentials` of type `List` that contains all the HTTP auth credentials saved for that `protectionSpace`. Future>> getAllAuthCredentials() async { Map args = {}; List allCredentials = await _channel.invokeMethod('getAllAuthCredentials', args); @@ -38,8 +45,8 @@ class HttpAuthCredentialDatabase { return result; } - /// - Future> getHttpAuthCredentials(ProtectionSpace protectionSpace) async { + ///Gets all the HTTP auth credentials saved for that [protectionSpace]. + Future> getHttpAuthCredentials({@required ProtectionSpace protectionSpace}) async { Map args = {}; args.putIfAbsent("host", () => protectionSpace.host); args.putIfAbsent("protocol", () => protectionSpace.protocol); @@ -53,8 +60,8 @@ class HttpAuthCredentialDatabase { return credentials; } - /// - Future setHttpAuthCredential(ProtectionSpace protectionSpace, HttpAuthCredential credential) async { + ///Saves an HTTP auth [credential] for that [protectionSpace]. + Future setHttpAuthCredential({@required ProtectionSpace protectionSpace, @required HttpAuthCredential credential}) async { Map args = {}; args.putIfAbsent("host", () => protectionSpace.host); args.putIfAbsent("protocol", () => protectionSpace.protocol); @@ -65,8 +72,8 @@ class HttpAuthCredentialDatabase { await _channel.invokeMethod('setHttpAuthCredential', args); } - /// - Future removeHttpAuthCredential(ProtectionSpace protectionSpace, HttpAuthCredential credential) async { + ///Removes an HTTP auth [credential] for that [protectionSpace]. + Future removeHttpAuthCredential({@required ProtectionSpace protectionSpace, @required HttpAuthCredential credential}) async { Map args = {}; args.putIfAbsent("host", () => protectionSpace.host); args.putIfAbsent("protocol", () => protectionSpace.protocol); @@ -77,8 +84,8 @@ class HttpAuthCredentialDatabase { await _channel.invokeMethod('removeHttpAuthCredential', args); } - /// - Future removeHttpAuthCredentials(ProtectionSpace protectionSpace) async { + ///Removes all the HTTP auth credentials saved for that [protectionSpace]. + Future removeHttpAuthCredentials({@required ProtectionSpace protectionSpace}) async { Map args = {}; args.putIfAbsent("host", () => protectionSpace.host); args.putIfAbsent("protocol", () => protectionSpace.protocol); @@ -87,7 +94,7 @@ class HttpAuthCredentialDatabase { await _channel.invokeMethod('removeHttpAuthCredentials', args); } - /// + ///Removes all the HTTP auth credentials saved in the database. Future clearAllAuthCredentials() async { Map args = {}; await _channel.invokeMethod('clearAllAuthCredentials', args); diff --git a/lib/src/in_app_browser.dart b/lib/src/in_app_browser.dart index 5650453c..5ffa6f08 100644 --- a/lib/src/in_app_browser.dart +++ b/lib/src/in_app_browser.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:collection'; import 'dart:io'; +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter_inappbrowser/src/webview_options.dart'; @@ -45,64 +46,11 @@ class InAppBrowser { ///Opens an [url] in a new [InAppBrowser] instance. /// - ///- [url]: The [url] to load. Call [encodeUriComponent()] on this if the [url] contains Unicode characters. The default value is `about:blank`. + ///[url]: The [url] to load. Call `encodeUriComponent()` on this if the [url] contains Unicode characters. The default value is `about:blank`. /// - ///- [headers]: The additional headers to be used in the HTTP request for this URL, specified as a map from name to value. + ///[headers]: The additional headers to be used in the HTTP request for this URL, specified as a map from name to value. /// - ///- [options]: Options for the [InAppBrowser]. - /// - /// - All platforms support: - /// - __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`. - /// - __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`. - /// - __userAgent__: Set the custom WebView's user-agent. - /// - __javaScriptEnabled__: Set to `true` to enable JavaScript. The default value is `true`. - /// - __javaScriptCanOpenWindowsAutomatically__: Set to `true` to allow JavaScript open windows without user interaction. The default value is `false`. - /// - __hidden__: Set to `true` to create the browser and load the page, but not show it. The `onLoadStop` event fires when loading is complete. Omit or set to `false` (default) to have the browser open and load normally. - /// - __toolbarTop__: Set to `false` to hide the toolbar at the top of the WebView. The default value is `true`. - /// - __toolbarTopBackgroundColor__: Set the custom background color of the toolbar at the top. - /// - __hideUrlBar__: Set to `true` to hide the url bar on the toolbar at the top. The default value is `false`. - /// - __mediaPlaybackRequiresUserGesture__: Set to `true` to prevent HTML5 audio or video from autoplaying. The default value is `true`. - /// - __transparentBackground__: Set to `true` to make the background of the WebView transparent. If your app has a dark theme, this can prevent a white flash on initialization. The default value is `false`. - /// - __resourceCustomSchemes__: List of custom schemes that [InAppBrowser] must handle. Use the [onLoadResourceCustomScheme()] event to intercept resource requests with custom scheme. - /// - /// - **Android** supports these additional options: - /// - /// - __hideTitleBar__: Set to `true` if you want the title should be displayed. The default value is `false`. - /// - __closeOnCannotGoBack__: Set to `false` to not close the InAppBrowser when the user click on the back button and the WebView cannot go back to the history. The default value is `true`. - /// - __clearSessionCache__: Set to `true` to have the session cookie cache cleared before the new window is opened. - /// - __builtInZoomControls__: Set to `true` if the WebView should use its 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`. - /// - __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`. - /// - __useWideViewPort__: Set to `true` if the WebView should enable support for the "viewport" HTML meta tag or should use a wide viewport. When the value of the setting is false, the layout width is always set to the width of the WebView control in device-independent (CSS) pixels. When the value is true and the page contains the viewport meta tag, the value of the width specified in the tag is used. If the page does not contain the tag or does not provide a width, then a wide viewport will be used. The default value is `true`. - /// - __safeBrowsingEnabled__: Set to `true` if you want the Safe Browsing is enabled. Safe Browsing allows WebView to protect against malware and phishing attacks by verifying the links. The default value is `true`. - /// - __progressBar__: Set to `false` to hide the progress bar at the bottom of the toolbar at the top. The default value is `true`. - /// - __textZoom__: Set text scaling of the WebView. The default value is `100`. - /// - __mixedContentMode__: Configures the WebView's behavior when a secure origin attempts to load a resource from an insecure origin. By default, apps that target `Build.VERSION_CODES.KITKAT` or below default to `MIXED_CONTENT_ALWAYS_ALLOW`. Apps targeting `Build.VERSION_CODES.LOLLIPOP` default to `MIXED_CONTENT_NEVER_ALLOW`. The preferred and most secure mode of operation for the WebView is `MIXED_CONTENT_NEVER_ALLOW` and use of `MIXED_CONTENT_ALWAYS_ALLOW` is strongly discouraged. - /// - /// - **iOS** supports these additional options: - /// - /// - __disallowOverScroll__: Set to `true` to disable the bouncing of the WebView when the scrolling has reached an edge of the content. The default value is `false`. - /// - __toolbarBottom__: Set to `false` to hide the toolbar at the bottom of the WebView. The default value is `true`. - /// - __toolbarBottomBackgroundColor__: Set the custom background color of the toolbar at the bottom. - /// - __toolbarBottomTranslucent__: Set to `true` to set the toolbar at the bottom translucent. The default value is `true`. - /// - __closeButtonCaption__: Set the custom text for the close button. - /// - __closeButtonColor__: Set the custom color for the close button. - /// - __presentationStyle__: Set the custom modal presentation style when presenting the WebView. The default value is `0 //fullscreen`. See [UIModalPresentationStyle](https://developer.apple.com/documentation/uikit/uimodalpresentationstyle) for all the available styles. - /// - __transitionStyle__: Set to the custom transition style when presenting the WebView. The default value is `0 //crossDissolve`. See [UIModalTransitionStyle](https://developer.apple.com/documentation/uikit/uimodaltransitionStyle) for all the available styles. - /// - __enableViewportScale__: Set to `true` to allow a viewport meta tag to either disable or restrict the range of user scaling. The default value is `false`. - /// - __suppressesIncrementalRendering__: Set to `true` if you want the WebView suppresses content rendering until it is fully loaded into memory.. The default value is `false`. - /// - __allowsAirPlayForMediaPlayback__: Set to `true` to allow AirPlay. The default value is `true`. - /// - __allowsBackForwardNavigationGestures__: Set to `true` to allow the horizontal swipe gestures trigger back-forward list navigations. The default value is `true`. - /// - __allowsLinkPreview__: Set to `true` to allow that pressing on a link displays a preview of the destination for the link. The default value is `true`. - /// - __ignoresViewportScaleLimits__: Set to `true` if you want that the WebView should always allow scaling of the webpage, regardless of the author's intent. The ignoresViewportScaleLimits property overrides the `user-scalable` HTML property in a webpage. The default value is `false`. - /// - __allowsInlineMediaPlayback__: Set to `true` to allow HTML5 media playback to appear inline within the screen layout, using browser-supplied controls rather than native controls. For this to work, add the `webkit-playsinline` attribute to any `