diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 197fde9e..e655e257 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -15,17 +15,17 @@ - - + + + - + - - - + + @@ -48,8 +48,20 @@ - - + + + + + + + + + + + + + + @@ -57,8 +69,8 @@ - - + + @@ -78,8 +90,8 @@ - - + + @@ -90,8 +102,8 @@ - - + + @@ -102,8 +114,8 @@ - - + + @@ -123,8 +135,8 @@ - - + + @@ -132,27 +144,6 @@ - - - - - - - - - - - - - - - - - - - - - @@ -165,14 +156,6 @@ - NOTE - onGeolocationPermissionsShowPrompt - "onGeolocationPermissionsShowPrompt" - databaseEnabled - RequestPermission - geolocation - userInterfaceDirectionPolicy - WKSelectionGranularityDynamic minimumFontSize defaultWebpagePreferences contentBlockers @@ -195,6 +178,14 @@ onJsA toMap() .toMap() + onSafeBrowsingHitCallback + onSafeBrowsingHit" + ConsoleMessageLevel + ConsoleMessage + appCa + iOSInAppWebViewUserPreferredContentMode + SafeBrowsingResponse + onSafeBrowsingHit activity.getPreferences(0) @@ -254,17 +245,17 @@ @@ -328,6 +319,17 @@ + + + + + + + + + + + @@ -500,8 +502,8 @@ - - + + @@ -511,7 +513,7 @@ - + @@ -547,9 +549,6 @@ - - - @@ -793,70 +792,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -867,6 +802,13 @@ + + + + + + + @@ -881,10 +823,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c61d852..255120d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Added new iOS WebView options: `applicationNameForUserAgent`, `isFraudulentWebsiteWarningEnabled`, `selectionGranularity`, `dataDetectorTypes`, `preferredContentMode` - Added `onGeolocationPermissionsShowPrompt` event and `GeolocationPermissionShowPromptResponse` class (available only for Android) - Added `startSafeBrowsing`, `setSafeBrowsingWhitelist` and `getSafeBrowsingPrivacyPolicyUrl` methods (available only for Android) +- Added `onSafeBrowsingHit` event (available only for Android) - Added `onJsAlert`, `onJsConfirm` and `onJsPrompt` events to manage javascript popup dialogs ### BREAKING CHANGES 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 ea0b2071..71848cfd 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 @@ -10,8 +10,12 @@ import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.InAppWebView; import java.io.ByteArrayInputStream; import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -41,11 +45,19 @@ public class ContentBlockerHandler { this.ruleList = newRuleList; } - public WebResourceResponse checkUrl(final InAppWebView webView, String url, ContentBlockerTriggerResourceType responseResourceType) throws URISyntaxException, InterruptedException { + public WebResourceResponse checkUrl(final InAppWebView webView, String url, ContentBlockerTriggerResourceType responseResourceType) throws URISyntaxException, InterruptedException, MalformedURLException { if (webView.options.contentBlockers == null) return null; - URI u = new URI(url); + URI u; + try { + u = new URI(url); + } catch (URISyntaxException e) { + String[] urlSplitted = url.split(":"); + String scheme = urlSplitted[0]; + URL tempUrl = new URL(url.replace(scheme, "https")); + u = new URI(scheme, tempUrl.getUserInfo(), tempUrl.getHost(), tempUrl.getPort(), tempUrl.getPath(), tempUrl.getQuery(), tempUrl.getRef()); + } String host = u.getHost(); int port = u.getPort(); String scheme = u.getScheme(); @@ -182,12 +194,12 @@ public class ContentBlockerHandler { return null; } - public WebResourceResponse checkUrl(final InAppWebView webView, String url) throws URISyntaxException, InterruptedException { + public WebResourceResponse checkUrl(final InAppWebView webView, String url) throws URISyntaxException, InterruptedException, MalformedURLException { ContentBlockerTriggerResourceType responseResourceType = getResourceTypeFromUrl(webView, url); return checkUrl(webView, url, responseResourceType); } - public WebResourceResponse checkUrl(final InAppWebView webView, String url, String contentType) throws URISyntaxException, InterruptedException { + public WebResourceResponse checkUrl(final InAppWebView webView, String url, String contentType) throws URISyntaxException, InterruptedException, MalformedURLException { ContentBlockerTriggerResourceType responseResourceType = getResourceTypeFromContentType(contentType); return checkUrl(webView, url, responseResourceType); } diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/FlutterWebView.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/FlutterWebView.java index ab666854..8a3b7c0b 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/FlutterWebView.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/FlutterWebView.java @@ -3,6 +3,7 @@ package com.pichillilorenzo.flutter_inappbrowser; import android.Manifest; import android.app.Activity; import android.content.Context; +import android.os.Build; import android.util.Log; import android.view.View; import android.webkit.WebChromeClient; @@ -226,6 +227,12 @@ public class FlutterWebView implements PlatformView, MethodCallHandler { else result.success(false); break; + case "getSafeBrowsingPrivacyPolicyUrl": + if (webView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + result.success(webView.getSafeBrowsingPrivacyPolicyUrl().toString()); + } else + result.success(null); + break; case "dispose": dispose(); result.success(true); diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebChromeClient.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebChromeClient.java index b20461e8..f34feee3 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebChromeClient.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebChromeClient.java @@ -447,7 +447,7 @@ public class InAppWebChromeClient extends WebChromeClient { obj.put("sourceURL", consoleMessage.sourceId()); obj.put("lineNumber", consoleMessage.lineNumber()); obj.put("message", consoleMessage.message()); - obj.put("messageLevel", consoleMessage.messageLevel().toString()); + obj.put("messageLevel", consoleMessage.messageLevel().ordinal()); getChannel().invokeMethod("onConsoleMessage", obj); return true; } diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewClient.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewClient.java index c4d7c6a2..fc31fd3f 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewClient.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewClient.java @@ -10,6 +10,7 @@ import android.util.Log; import android.webkit.CookieManager; import android.webkit.CookieSyncManager; import android.webkit.HttpAuthHandler; +import android.webkit.SafeBrowsingResponse; import android.webkit.SslErrorHandler; import android.webkit.ValueCallback; import android.webkit.WebResourceRequest; @@ -306,6 +307,58 @@ public class InAppWebViewClient extends WebViewClient { webView.scale = newScale; } + @RequiresApi(api = Build.VERSION_CODES.O_MR1) + @Override + public void onSafeBrowsingHit(final WebView view, WebResourceRequest request, int threatType, final SafeBrowsingResponse callback) { + Map obj = new HashMap<>(); + if (inAppBrowserActivity != null) + obj.put("uuid", inAppBrowserActivity.uuid); + obj.put("url", request.getUrl().toString()); + obj.put("threatType", threatType); + + getChannel().invokeMethod("onSafeBrowsingHit", obj, new MethodChannel.Result() { + @Override + public void success(Object response) { + if (response != null) { + Map responseMap = (Map) response; + Boolean report = (Boolean) responseMap.get("report"); + Integer action = (Integer) responseMap.get("action"); + + Log.d(LOG_TAG, "\n\nreport: " + report); + Log.d(LOG_TAG, "\n\naction: " + action); + + report = report != null ? report : true; + + if (action != null) { + switch (action) { + case 0: + callback.backToSafety(report); + return; + case 1: + callback.proceed(report); + return; + case 2: + callback.showInterstitial(report); + return; + } + } + } + + callback.showInterstitial(true); + } + + @Override + public void error(String s, String s1, Object o) { + Log.e(LOG_TAG, s + ", " + s1); + } + + @Override + public void notImplemented() { + callback.showInterstitial(true); + } + }); + } + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { diff --git a/example/lib/inline_example.screen.dart b/example/lib/inline_example.screen.dart index 71a2188e..02b1d444 100644 --- a/example/lib/inline_example.screen.dart +++ b/example/lib/inline_example.screen.dart @@ -65,6 +65,7 @@ class _InlineExampleScreenState extends State { child: InAppWebView( //initialUrl: "https://www.youtube.com/embed/M7lc1UVf-VE?playsinline=1", //initialUrl: "https://flutter.dev/", + //initialUrl: "chrome://safe-browsing/match?type=malware", initialFile: "assets/index.html", initialHeaders: {}, initialOptions: [ @@ -88,6 +89,7 @@ class _InlineExampleScreenState extends State { appCacheEnabled: true, domStorageEnabled: true, geolocationEnabled: true, + safeBrowsingEnabled: true, //blockNetworkImage: true, ), iOSInAppWebViewOptions( @@ -97,6 +99,9 @@ class _InlineExampleScreenState extends State { onWebViewCreated: (InAppWebViewController controller) { webView = controller; + if (Platform.isAndroid) + webView.startSafeBrowsing(); + webView.addJavaScriptHandler('handlerFoo', (args) { return new Foo(bar: 'bar_value', baz: 'baz_value'); }); @@ -142,7 +147,7 @@ class _InlineExampleScreenState extends State { sourceURL: ${consoleMessage.sourceURL} lineNumber: ${consoleMessage.lineNumber} message: ${consoleMessage.message} - messageLevel: ${consoleMessage.messageLevel} + messageLevel: ${consoleMessage.messageLevel.toValue()} """); }, onDownloadStart: (InAppWebViewController controller, String url) async { @@ -210,6 +215,10 @@ class _InlineExampleScreenState extends State { JsPromptResponseAction action = await createPromptDialog(context, message); return new JsPromptResponse(handledByClient: true, action: action, value: _textFieldController.text); }, + onSafeBrowsingHit: (InAppWebViewController controller, String url, SafeBrowsingThreat threatType) async { + SafeBrowsingResponseAction action = SafeBrowsingResponseAction.BACK_TO_SAFETY; + return new SafeBrowsingResponse(report: true, action: action); + }, ), ), ), diff --git a/example/lib/webview_example.screen.dart b/example/lib/webview_example.screen.dart index 54cc3aba..945a366e 100644 --- a/example/lib/webview_example.screen.dart +++ b/example/lib/webview_example.screen.dart @@ -63,7 +63,7 @@ class MyInappBrowser extends InAppBrowser { sourceURL: ${consoleMessage.sourceURL} lineNumber: ${consoleMessage.lineNumber} message: ${consoleMessage.message} - messageLevel: ${consoleMessage.messageLevel} + messageLevel: ${consoleMessage.messageLevel.toValue()} """); } diff --git a/lib/src/in_app_browser.dart b/lib/src/in_app_browser.dart index 94d72da2..6118b062 100644 --- a/lib/src/in_app_browser.dart +++ b/lib/src/in_app_browser.dart @@ -394,6 +394,18 @@ class InAppBrowser { } + ///Event fires when the webview notifies that a loading URL has been flagged by Safe Browsing. + ///The default behavior is to show an interstitial to the user, with the reporting checkbox visible. + /// + ///[url] represents the url of the request. + /// + ///[threatType] represents the reason the resource was caught by Safe Browsing, corresponding to a [SafeBrowsingThreat]. + /// + ///**NOTE**: available only for Android. + Future onSafeBrowsingHit(String url, SafeBrowsingThreat threatType) { + + } + void throwIsAlreadyOpened({String message = ''}) { if (this.isOpened()) { throw Exception(['Error: ${ (message.isEmpty) ? '' : message + ' '}The browser is already opened.']); diff --git a/lib/src/in_app_webview.dart b/lib/src/in_app_webview.dart index 7d10465d..d9f47e4f 100644 --- a/lib/src/in_app_webview.dart +++ b/lib/src/in_app_webview.dart @@ -162,9 +162,20 @@ class InAppWebView extends StatefulWidget { ///If [JsPromptResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog. /// ///[message] represents the message to be displayed in the alert dialog. + /// ///[defaultValue] represents the default value displayed in the prompt dialog. final onJsPromptCallback onJsPrompt; + ///Event fires when the webview notifies that a loading URL has been flagged by Safe Browsing. + ///The default behavior is to show an interstitial to the user, with the reporting checkbox visible. + /// + ///[url] represents the url of the request. + /// + ///[threatType] represents the reason the resource was caught by Safe Browsing, corresponding to a [SafeBrowsingThreat]. + /// + ///**NOTE**: available only for Android. + final onSafeBrowsingHitCallback onSafeBrowsingHit; + ///Initial url that will be loaded. final String initialUrl; ///Initial asset file that will be loaded. See [InAppWebView.loadFile()] for explanation. @@ -207,6 +218,7 @@ class InAppWebView extends StatefulWidget { this.onJsAlert, this.onJsConfirm, this.onJsPrompt, + this.onSafeBrowsingHit, this.gestureRecognizers, }) : super(key: key); @@ -370,13 +382,7 @@ class InAppWebViewController { String sourceURL = call.arguments["sourceURL"]; int lineNumber = call.arguments["lineNumber"]; String message = call.arguments["message"]; - ConsoleMessageLevel messageLevel; - ConsoleMessageLevel.values.forEach((element) { - if ("ConsoleMessageLevel." + call.arguments["messageLevel"] == element.toString()) { - messageLevel = element; - return; - } - }); + ConsoleMessageLevel messageLevel = ConsoleMessageLevel.fromValue(call.arguments["messageLevel"]); if (_widget != null && _widget.onConsoleMessage != null) _widget.onConsoleMessage(this, ConsoleMessage(sourceURL, lineNumber, message, messageLevel)); else if (_inAppBrowser != null) @@ -454,6 +460,14 @@ class InAppWebViewController { else if (_inAppBrowser != null) return (await _inAppBrowser.onJsPrompt(message, defaultValue))?.toMap(); break; + case "onSafeBrowsingHit": + String url = call.arguments["url"]; + SafeBrowsingThreat threatType = SafeBrowsingThreat.fromValue(call.arguments["threatType"]); + if (_widget != null && _widget.onJsPrompt != null) + return (await _widget.onSafeBrowsingHit(this, url, threatType))?.toMap(); + else if (_inAppBrowser != null) + return (await _inAppBrowser.onSafeBrowsingHit(url, threatType))?.toMap(); + break; case "onCallJsHandler": String handlerName = call.arguments["handlerName"]; // decode args to json @@ -918,6 +932,17 @@ class InAppWebViewController { return await _channel.invokeMethod('setSafeBrowsingWhitelist', args); } + ///Returns a URL pointing to the privacy policy for Safe Browsing reporting. This value will never be `null`. + /// + ///**NOTE**: available only for Android. + Future getSafeBrowsingPrivacyPolicyUrl() async { + Map args = {}; + if (_inAppBrowserUuid != null && _inAppBrowser != null) { + _inAppBrowser.throwIsNotOpened(); + args.putIfAbsent('uuid', () => _inAppBrowserUuid); + } + return await _channel.invokeMethod('getSafeBrowsingPrivacyPolicyUrl', args); + } ///Dispose/Destroy the WebView. Future _dispose() async { diff --git a/lib/src/types.dart b/lib/src/types.dart index e482d8f8..707c9591 100644 --- a/lib/src/types.dart +++ b/lib/src/types.dart @@ -18,9 +18,22 @@ typedef Future ListenerCallback(MethodCall call); ///In this case, simply return data that you want to send and it will be automatically json encoded using [jsonEncode] from the `dart:convert` library. typedef dynamic JavaScriptHandlerCallback(List arguments); -///Enum representing the level of a console message. -enum ConsoleMessageLevel { - DEBUG, ERROR, LOG, TIP, WARNING +///Class representing the level of a console message. +class ConsoleMessageLevel { + final int _value; + const ConsoleMessageLevel._internal(this._value); + static ConsoleMessageLevel fromValue(int value) { + if (value >= 0 && value <= 4) + return ConsoleMessageLevel._internal(value); + return null; + } + toValue() => _value; + + static const TIP = const ConsoleMessageLevel._internal(0); + static const LOG = const ConsoleMessageLevel._internal(1); + static const WARNING = const ConsoleMessageLevel._internal(2); + static const ERROR = const ConsoleMessageLevel._internal(3); + static const DEBUG = const ConsoleMessageLevel._internal(4); } ///Public class representing a resource response of the [InAppBrowser] WebView. @@ -217,6 +230,46 @@ class JsPromptResponse { } } +class SafeBrowsingThreat { + final int _value; + const SafeBrowsingThreat._internal(this._value); + static SafeBrowsingThreat fromValue(int value) { + if (value >= 0 && value <= 4) + return SafeBrowsingThreat._internal(value); + return null; + } + toValue() => _value; + + static const SAFE_BROWSING_THREAT_UNKNOWN = const SafeBrowsingThreat._internal(0); + static const SAFE_BROWSING_THREAT_MALWARE = const SafeBrowsingThreat._internal(1); + static const SAFE_BROWSING_THREAT_PHISHING = const SafeBrowsingThreat._internal(2); + static const SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE = const SafeBrowsingThreat._internal(3); + static const SAFE_BROWSING_THREAT_BILLING = const SafeBrowsingThreat._internal(4); +} + +class SafeBrowsingResponseAction { + final int _value; + const SafeBrowsingResponseAction._internal(this._value); + toValue() => _value; + + static const BACK_TO_SAFETY = const SafeBrowsingResponseAction._internal(0); + static const PROCEED = const SafeBrowsingResponseAction._internal(1); + static const SHOW_INTERSTITIAL = const SafeBrowsingResponseAction._internal(2); +} +class SafeBrowsingResponse { + bool report; + SafeBrowsingResponseAction action; + + SafeBrowsingResponse({this.report = true, this.action = SafeBrowsingResponseAction.SHOW_INTERSTITIAL}); + + Map toMap() { + return { + "report": report, + "action": action?.toValue() + }; + } +} + typedef onWebViewCreatedCallback = void Function(InAppWebViewController controller); typedef onWebViewLoadStartCallback = void Function(InAppWebViewController controller, String url); typedef onWebViewLoadStopCallback = void Function(InAppWebViewController controller, String url); @@ -232,4 +285,5 @@ typedef onTargetBlankCallback = void Function(InAppWebViewController controller, typedef onGeolocationPermissionsShowPromptCallback = Future Function(InAppWebViewController controller, String origin); typedef onJsAlertCallback = Future Function(InAppWebViewController controller, String message); typedef onJsConfirmCallback = Future Function(InAppWebViewController controller, String message); -typedef onJsPromptCallback = Future Function(InAppWebViewController controller, String message, String defaultValue); \ No newline at end of file +typedef onJsPromptCallback = Future Function(InAppWebViewController controller, String message, String defaultValue); +typedef onSafeBrowsingHitCallback = Future Function(InAppWebViewController controller, String url, SafeBrowsingThreat threatType); \ No newline at end of file diff --git a/lib/src/webview_options.dart b/lib/src/webview_options.dart index 5809e084..e81cfebc 100644 --- a/lib/src/webview_options.dart +++ b/lib/src/webview_options.dart @@ -127,7 +127,6 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions { bool safeBrowsingEnabled; bool transparentBackground; AndroidInAppWebViewMixedContentMode mixedContentMode; - bool allowContentAccess; bool allowFileAccess; bool allowFileAccessFromFileURLs; @@ -258,7 +257,6 @@ class iOSInAppWebViewOptions implements WebViewOptions, BrowserOptions { bool allowsInlineMediaPlayback; bool allowsPictureInPictureMediaPlayback; bool transparentBackground; - String applicationNameForUserAgent; bool isFraudulentWebsiteWarningEnabled; iOSInAppWebViewSelectionGranularity selectionGranularity; @@ -337,18 +335,47 @@ class AndroidInAppBrowserOptions implements BrowserOptions { } } +class iOSInAppBrowserOptionsPresentationStyle { + final int _value; + const iOSInAppBrowserOptionsPresentationStyle._internal(this._value); + toValue() => _value; + + static const FULL_SCREEN = const iOSInAppBrowserOptionsPresentationStyle._internal(0); + static const PAGE_SHEET = const iOSInAppBrowserOptionsPresentationStyle._internal(1); + static const FORM_SHEET = const iOSInAppBrowserOptionsPresentationStyle._internal(2); + static const CURRENT_CONTEXT = const iOSInAppBrowserOptionsPresentationStyle._internal(3); + static const CUSTOM = const iOSInAppBrowserOptionsPresentationStyle._internal(4); + static const OVER_FULL_SCREEN = const iOSInAppBrowserOptionsPresentationStyle._internal(5); + static const OVER_CURRENT_CONTEXT = const iOSInAppBrowserOptionsPresentationStyle._internal(6); + static const POPOVER = const iOSInAppBrowserOptionsPresentationStyle._internal(7); + static const NONE = const iOSInAppBrowserOptionsPresentationStyle._internal(8); + static const AUTOMATIC = const iOSInAppBrowserOptionsPresentationStyle._internal(9); +} + +class iOSInAppBrowserOptionsTransitionStyle { + final int _value; + const iOSInAppBrowserOptionsTransitionStyle._internal(this._value); + toValue() => _value; + + static const COVER_VERTICAL = const iOSInAppBrowserOptionsTransitionStyle._internal(0); + static const FLIP_HORIZONTAL = const iOSInAppBrowserOptionsTransitionStyle._internal(1); + static const CROSS_DISSOLVE = const iOSInAppBrowserOptionsTransitionStyle._internal(2); + static const PARTIAL_CURL = const iOSInAppBrowserOptionsTransitionStyle._internal(3); +} + class iOSInAppBrowserOptions implements BrowserOptions { bool toolbarBottom; String toolbarBottomBackgroundColor; bool toolbarBottomTranslucent; String closeButtonCaption; String closeButtonColor; - int presentationStyle; //default fullscreen - int transitionStyle; //default crossDissolve + iOSInAppBrowserOptionsPresentationStyle presentationStyle; + iOSInAppBrowserOptionsTransitionStyle transitionStyle; bool spinner; iOSInAppBrowserOptions({this.toolbarBottom = true, this.toolbarBottomBackgroundColor = "", this.toolbarBottomTranslucent = true, this.closeButtonCaption = "", - this.closeButtonColor = "", this.presentationStyle = 0, this.transitionStyle = 0, this.spinner = true}); + this.closeButtonColor = "", this.presentationStyle = iOSInAppBrowserOptionsPresentationStyle.FULL_SCREEN, + this.transitionStyle = iOSInAppBrowserOptionsTransitionStyle.COVER_VERTICAL, this.spinner = true}); @override Map toMap() { @@ -358,8 +385,8 @@ class iOSInAppBrowserOptions implements BrowserOptions { "toolbarBottomTranslucent": toolbarBottomTranslucent, "closeButtonCaption": closeButtonCaption, "closeButtonColor": closeButtonColor, - "presentationStyle": presentationStyle, - "transitionStyle": transitionStyle, + "presentationStyle": presentationStyle.toValue(), + "transitionStyle": transitionStyle.toValue(), "spinner": spinner, }; } @@ -392,28 +419,39 @@ class AndroidChromeCustomTabsOptions implements ChromeCustomTabsOptions { } } +class iOSChromeCustomTabsOptionsDismissButtonStyle { + final int _value; + const iOSChromeCustomTabsOptionsDismissButtonStyle._internal(this._value); + toValue() => _value; + + static const DONE = const iOSChromeCustomTabsOptionsDismissButtonStyle._internal(0); + static const CLOSE = const iOSChromeCustomTabsOptionsDismissButtonStyle._internal(1); + static const CANCEL = const iOSChromeCustomTabsOptionsDismissButtonStyle._internal(2); +} + class iOSChromeCustomTabsOptions implements ChromeCustomTabsOptions { bool entersReaderIfAvailable; bool barCollapsingEnabled; - int dismissButtonStyle; //default done + iOSChromeCustomTabsOptionsDismissButtonStyle dismissButtonStyle; String preferredBarTintColor; String preferredControlTintColor; - int presentationStyle; //default fullscreen - int transitionStyle; //default crossDissolve + iOSInAppBrowserOptionsPresentationStyle presentationStyle; + iOSInAppBrowserOptionsTransitionStyle transitionStyle; - iOSChromeCustomTabsOptions({this.entersReaderIfAvailable = false, this.barCollapsingEnabled = false, this.dismissButtonStyle = 0, this.preferredBarTintColor = "", - this.preferredControlTintColor = "", this.presentationStyle = 0, this.transitionStyle = 0}); + iOSChromeCustomTabsOptions({this.entersReaderIfAvailable = false, this.barCollapsingEnabled = false, this.dismissButtonStyle = iOSChromeCustomTabsOptionsDismissButtonStyle.DONE, + this.preferredBarTintColor = "", this.preferredControlTintColor = "", this.presentationStyle = iOSInAppBrowserOptionsPresentationStyle.FULL_SCREEN, + this.transitionStyle = iOSInAppBrowserOptionsTransitionStyle.COVER_VERTICAL}); @override Map toMap() { return { "entersReaderIfAvailable": entersReaderIfAvailable, "barCollapsingEnabled": barCollapsingEnabled, - "dismissButtonStyle": dismissButtonStyle, + "dismissButtonStyle": dismissButtonStyle.toValue(), "preferredBarTintColor": preferredBarTintColor, "preferredControlTintColor": preferredControlTintColor, - "presentationStyle": presentationStyle, - "transitionStyle": transitionStyle, + "presentationStyle": presentationStyle.toValue(), + "transitionStyle": transitionStyle.toValue(), }; } } \ No newline at end of file