refactored remaining classes and properties

This commit is contained in:
Lorenzo Pichilli 2022-04-20 02:18:36 +02:00
parent 5371b77231
commit cdd2bdb09f
24 changed files with 869 additions and 139 deletions

View File

@ -34,7 +34,7 @@ public class ServiceWorkerManager implements MethodChannel.MethodCallHandler {
public ServiceWorkerManager(final InAppWebViewFlutterPlugin plugin) {
this.plugin = plugin;
channel = new MethodChannel(plugin.messenger, "com.pichillilorenzo/flutter_inappwebview_android_serviceworkercontroller");
channel = new MethodChannel(plugin.messenger, "com.pichillilorenzo/flutter_inappwebview_serviceworkercontroller");
channel.setMethodCallHandler(this);
if (WebViewFeature.isFeatureSupported(WebViewFeature.SERVICE_WORKER_BASIC_USAGE)) {
serviceWorkerController = ServiceWorkerControllerCompat.getInstance();

View File

@ -17,7 +17,7 @@ public class WebViewFeatureManager implements MethodChannel.MethodCallHandler {
public WebViewFeatureManager(final InAppWebViewFlutterPlugin plugin) {
this.plugin = plugin;
channel = new MethodChannel(plugin.messenger, "com.pichillilorenzo/flutter_inappwebview_android_webviewfeature");
channel = new MethodChannel(plugin.messenger, "com.pichillilorenzo/flutter_inappwebview_webviewfeature");
channel.setMethodCallHandler(this);
}

View File

@ -6,7 +6,6 @@ import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import androidx.browser.customtabs.CustomTabColorSchemeParams;
import androidx.browser.customtabs.CustomTabsCallback;
@ -29,7 +28,7 @@ public class ChromeCustomTabsActivity extends Activity implements MethodChannel.
public MethodChannel channel;
public String id;
public CustomTabsIntent.Builder builder;
public ChromeCustomTabsOptions options;
public ChromeCustomTabsSettings customSettings;
public CustomTabActivityHelper customTabActivityHelper;
public CustomTabsSession customTabsSession;
protected final int CHROME_CUSTOM_TAB_REQUEST_CODE = 100;
@ -56,8 +55,8 @@ public class ChromeCustomTabsActivity extends Activity implements MethodChannel.
final String url = b.getString("url");
options = new ChromeCustomTabsOptions();
options.parse((HashMap<String, Object>) b.getSerializable("options"));
customSettings = new ChromeCustomTabsSettings();
customSettings.parse((HashMap<String, Object>) b.getSerializable("settings"));
final List<HashMap<String, Object>> menuItemList = (List<HashMap<String, Object>>) b.getSerializable("menuItemList");
@ -154,23 +153,23 @@ public class ChromeCustomTabsActivity extends Activity implements MethodChannel.
}
private void prepareCustomTabs(List<HashMap<String, Object>> menuItemList) {
if (options.addDefaultShareMenuItem != null) {
builder.setShareState(options.addDefaultShareMenuItem ?
if (customSettings.addDefaultShareMenuItem != null) {
builder.setShareState(customSettings.addDefaultShareMenuItem ?
CustomTabsIntent.SHARE_STATE_ON : CustomTabsIntent.SHARE_STATE_OFF);
} else {
builder.setShareState(options.shareState);
builder.setShareState(customSettings.shareState);
}
if (options.toolbarBackgroundColor != null && !options.toolbarBackgroundColor.isEmpty()) {
if (customSettings.toolbarBackgroundColor != null && !customSettings.toolbarBackgroundColor.isEmpty()) {
CustomTabColorSchemeParams.Builder defaultColorSchemeBuilder = new CustomTabColorSchemeParams.Builder();
builder.setDefaultColorSchemeParams(defaultColorSchemeBuilder
.setToolbarColor(Color.parseColor(options.toolbarBackgroundColor))
.setToolbarColor(Color.parseColor(customSettings.toolbarBackgroundColor))
.build());
}
builder.setShowTitle(options.showTitle);
builder.setUrlBarHidingEnabled(options.enableUrlBarHiding);
builder.setInstantAppsEnabled(options.instantAppsEnabled);
builder.setShowTitle(customSettings.showTitle);
builder.setUrlBarHidingEnabled(customSettings.enableUrlBarHiding);
builder.setInstantAppsEnabled(customSettings.instantAppsEnabled);
for (HashMap<String, Object> menuItem : menuItemList) {
int id = (int) menuItem.get("id");
@ -180,12 +179,12 @@ public class ChromeCustomTabsActivity extends Activity implements MethodChannel.
}
private void prepareCustomTabsIntent(CustomTabsIntent customTabsIntent) {
if (options.packageName != null)
customTabsIntent.intent.setPackage(options.packageName);
if (customSettings.packageName != null)
customTabsIntent.intent.setPackage(customSettings.packageName);
else
customTabsIntent.intent.setPackage(CustomTabsHelper.getPackageNameToUse(this));
if (options.keepAliveEnabled)
if (customSettings.keepAliveEnabled)
CustomTabsHelper.addKeepAliveExtra(this, customTabsIntent.intent);
}

View File

@ -14,9 +14,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ChromeCustomTabsOptions implements IWebViewSettings<ChromeCustomTabsActivity> {
public class ChromeCustomTabsSettings implements IWebViewSettings<ChromeCustomTabsActivity> {
final static String LOG_TAG = "ChromeCustomTabsOptions";
final static String LOG_TAG = "ChromeCustomTabsSettings";
@Deprecated
public Boolean addDefaultShareMenuItem;
@ -36,7 +36,7 @@ public class ChromeCustomTabsOptions implements IWebViewSettings<ChromeCustomTab
public Integer screenOrientation = ScreenOrientation.DEFAULT;
@Override
public ChromeCustomTabsOptions parse(Map<String, Object> options) {
public ChromeCustomTabsSettings parse(Map<String, Object> options) {
for (Map.Entry<String, Object> pair : options.entrySet()) {
String key = pair.getKey();
Object value = pair.getValue();

View File

@ -43,9 +43,9 @@ public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandl
case "open":
{
String url = (String) call.argument("url");
HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options");
HashMap<String, Object> settings = (HashMap<String, Object>) call.argument("settings");
List<HashMap<String, Object>> menuItemList = (List<HashMap<String, Object>>) call.argument("menuItemList");
open(plugin.activity, id, url, options, menuItemList, result);
open(plugin.activity, id, url, settings, menuItemList, result);
}
break;
case "isAvailable":
@ -56,7 +56,7 @@ public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandl
}
}
public void open(Activity activity, String id, String url, HashMap<String, Object> options,
public void open(Activity activity, String id, String url, HashMap<String, Object> settings,
List<HashMap<String, Object>> menuItemList, MethodChannel.Result result) {
Intent intent = null;
@ -65,17 +65,17 @@ public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandl
extras.putBoolean("isData", false);
extras.putString("id", id);
extras.putString("managerId", this.id);
extras.putSerializable("options", options);
extras.putSerializable("settings", settings);
extras.putSerializable("menuItemList", (Serializable) menuItemList);
Boolean isSingleInstance = (Boolean) Util.getOrDefault(options, "isSingleInstance", false);
Boolean isTrustedWebActivity = (Boolean) Util.getOrDefault(options, "isTrustedWebActivity", false);
Boolean isSingleInstance = (Boolean) Util.getOrDefault(settings, "isSingleInstance", false);
Boolean isTrustedWebActivity = (Boolean) Util.getOrDefault(settings, "isTrustedWebActivity", false);
if (CustomTabActivityHelper.isAvailable(activity)) {
intent = new Intent(activity, !isSingleInstance ?
(!isTrustedWebActivity ? ChromeCustomTabsActivity.class : TrustedWebActivity.class) :
(!isTrustedWebActivity ? ChromeCustomTabsActivitySingleInstance.class : TrustedWebActivitySingleInstance.class));
intent.putExtras(extras);
Boolean noHistory = (Boolean) Util.getOrDefault(options, "noHistory", false);
Boolean noHistory = (Boolean) Util.getOrDefault(settings, "noHistory", false);
if (noHistory) {
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
}

View File

@ -33,32 +33,32 @@ public class TrustedWebActivity extends ChromeCustomTabsActivity {
}
private void prepareCustomTabs() {
if (options.toolbarBackgroundColor != null && !options.toolbarBackgroundColor.isEmpty()) {
if (customSettings.toolbarBackgroundColor != null && !customSettings.toolbarBackgroundColor.isEmpty()) {
CustomTabColorSchemeParams.Builder defaultColorSchemeBuilder = new CustomTabColorSchemeParams.Builder();
builder.setDefaultColorSchemeParams(defaultColorSchemeBuilder
.setToolbarColor(Color.parseColor(options.toolbarBackgroundColor))
.setToolbarColor(Color.parseColor(customSettings.toolbarBackgroundColor))
.build());
}
if (options.additionalTrustedOrigins != null && !options.additionalTrustedOrigins.isEmpty()) {
builder.setAdditionalTrustedOrigins(options.additionalTrustedOrigins);
if (customSettings.additionalTrustedOrigins != null && !customSettings.additionalTrustedOrigins.isEmpty()) {
builder.setAdditionalTrustedOrigins(customSettings.additionalTrustedOrigins);
}
if (options.displayMode != null) {
builder.setDisplayMode(options.displayMode);
if (customSettings.displayMode != null) {
builder.setDisplayMode(customSettings.displayMode);
}
builder.setScreenOrientation(options.screenOrientation);
builder.setScreenOrientation(customSettings.screenOrientation);
}
private void prepareCustomTabsIntent(TrustedWebActivityIntent trustedWebActivityIntent) {
Intent intent = trustedWebActivityIntent.getIntent();
if (options.packageName != null)
intent.setPackage(options.packageName);
if (customSettings.packageName != null)
intent.setPackage(customSettings.packageName);
else
intent.setPackage(CustomTabsHelper.getPackageNameToUse(this));
if (options.keepAliveEnabled)
if (customSettings.keepAliveEnabled)
CustomTabsHelper.addKeepAliveExtra(this, intent);
}
}

View File

@ -170,7 +170,7 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler {
String encoding = (String) arguments.get("encoding");
String baseUrl = (String) arguments.get("baseUrl");
String historyUrl = (String) arguments.get("historyUrl");
Map<String, Object> options = (Map<String, Object>) arguments.get("options");
Map<String, Object> settings = (Map<String, Object>) arguments.get("settings");
Map<String, Object> contextMenu = (Map<String, Object>) arguments.get("contextMenu");
Integer windowId = (Integer) arguments.get("windowId");
List<Map<String, Object>> initialUserScripts = (List<Map<String, Object>>) arguments.get("initialUserScripts");
@ -187,7 +187,7 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler {
extras.putString("initialHistoryUrl", historyUrl);
extras.putString("id", id);
extras.putString("managerId", this.id);
extras.putSerializable("options", (Serializable) options);
extras.putSerializable("settings", (Serializable) settings);
extras.putSerializable("contextMenu", (Serializable) contextMenu);
extras.putInt("windowId", windowId != null ? windowId : -1);
extras.putSerializable("initialUserScripts", (Serializable) initialUserScripts);

View File

@ -80,7 +80,7 @@ public class PullToRefreshControl : UIRefreshControl, FlutterPlugin {
backgroundColor = UIColor(hexString: color)
result(true)
break
case "setAttributedTitle":
case "setStyledTitle":
let attributedTitleMap = arguments!["attributedTitle"] as! [String: Any?]
attributedTitle = NSAttributedString.fromMap(map: attributedTitleMap)
result(true)

View File

@ -34,9 +34,9 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin {
case "open":
let id: String = arguments!["id"] as! String
let url = arguments!["url"] as! String
let options = arguments!["options"] as! [String: Any?]
let settings = arguments!["settings"] as! [String: Any?]
let menuItemList = arguments!["menuItemList"] as! [[String: Any]]
open(id: id, url: url, options: options, menuItemList: menuItemList, result: result)
open(id: id, url: url, settings: settings, menuItemList: menuItemList, result: result)
break
case "isAvailable":
if #available(iOS 9.0, *) {
@ -51,7 +51,7 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin {
}
}
public func open(id: String, url: String, options: [String: Any?], menuItemList: [[String: Any]], result: @escaping FlutterResult) {
public func open(id: String, url: String, settings: [String: Any?], menuItemList: [[String: Any]], result: @escaping FlutterResult) {
let absoluteUrl = URL(string: url)!.absoluteURL
if #available(iOS 9.0, *) {
@ -59,15 +59,15 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin {
if let flutterViewController = UIApplication.shared.delegate?.window.unsafelyUnwrapped?.rootViewController {
// flutterViewController could be casted to FlutterViewController if needed
let safariOptions = SafariBrowserOptions()
let _ = safariOptions.parse(options: options)
let safariSettings = SafariBrowserSettings()
let _ = safariSettings.parse(settings: settings)
let safari: SafariViewController
if #available(iOS 11.0, *) {
let config = SFSafariViewController.Configuration()
config.entersReaderIfAvailable = safariOptions.entersReaderIfAvailable
config.barCollapsingEnabled = safariOptions.barCollapsingEnabled
config.entersReaderIfAvailable = safariSettings.entersReaderIfAvailable
config.barCollapsingEnabled = safariSettings.barCollapsingEnabled
safari = SafariViewController(url: absoluteUrl, configuration: config)
} else {
@ -79,7 +79,7 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin {
safari.menuItemList = menuItemList
safari.prepareMethodChannel()
safari.delegate = safari
safari.safariOptions = safariOptions
safari.safariSettings = safariSettings
safari.prepareSafariBrowser()
flutterViewController.present(safari, animated: true) {

View File

@ -9,7 +9,7 @@ import Foundation
@available(iOS 9.0, *)
@objcMembers
public class SafariBrowserOptions: IWebViewSettings<SafariViewController> {
public class SafariBrowserSettings: IWebViewSettings<SafariViewController> {
var entersReaderIfAvailable = false
var barCollapsingEnabled = false

View File

@ -12,7 +12,7 @@ import SafariServices
public class SafariViewController: SFSafariViewController, FlutterPlugin, SFSafariViewControllerDelegate {
var channel: FlutterMethodChannel?
var safariOptions: SafariBrowserOptions?
var safariSettings: SafariBrowserSettings?
var id: String = ""
var menuItemList: [[String: Any]] = []
@ -55,25 +55,25 @@ public class SafariViewController: SFSafariViewController, FlutterPlugin, SFSafa
func prepareSafariBrowser() {
guard let safariOptions = safariOptions else {
guard let safariSettings = safariSettings else {
return
}
if #available(iOS 11.0, *) {
self.dismissButtonStyle = SFSafariViewController.DismissButtonStyle(rawValue: safariOptions.dismissButtonStyle)!
self.dismissButtonStyle = SFSafariViewController.DismissButtonStyle(rawValue: safariSettings.dismissButtonStyle)!
}
if #available(iOS 10.0, *) {
if let preferredBarTintColor = safariOptions.preferredBarTintColor, !preferredBarTintColor.isEmpty {
if let preferredBarTintColor = safariSettings.preferredBarTintColor, !preferredBarTintColor.isEmpty {
self.preferredBarTintColor = UIColor(hexString: preferredBarTintColor)
}
if let preferredControlTintColor = safariOptions.preferredControlTintColor, !preferredControlTintColor.isEmpty {
if let preferredControlTintColor = safariSettings.preferredControlTintColor, !preferredControlTintColor.isEmpty {
self.preferredControlTintColor = UIColor(hexString: preferredControlTintColor)
}
}
self.modalPresentationStyle = UIModalPresentationStyle(rawValue: safariOptions.presentationStyle)!
self.modalTransitionStyle = UIModalTransitionStyle(rawValue: safariOptions.transitionStyle)!
self.modalPresentationStyle = UIModalPresentationStyle(rawValue: safariSettings.presentationStyle)!
self.modalTransitionStyle = UIModalTransitionStyle(rawValue: safariSettings.transitionStyle)!
}
func close(result: FlutterResult?) {

View File

@ -3,15 +3,184 @@ import 'package:flutter/services.dart';
import 'webview_feature.dart';
import '../types.dart';
///Class that manages Service Workers used by [WebView].
///
///**NOTE**: available on Android 24+.
///
///**Supported Platforms/Implementations**:
///- Android native WebView ([Official API - ServiceWorkerControllerCompat](https://developer.android.com/reference/androidx/webkit/ServiceWorkerControllerCompat))
class ServiceWorkerController {
static ServiceWorkerController? _instance;
static const MethodChannel _channel = const MethodChannel(
'com.pichillilorenzo/flutter_inappwebview_serviceworkercontroller');
ServiceWorkerClient? serviceWorkerClient;
///Gets the [ServiceWorkerController] shared instance.
static ServiceWorkerController instance() {
return (_instance != null) ? _instance! : _init();
}
static ServiceWorkerController _init() {
_channel.setMethodCallHandler(_handleMethod);
_instance = ServiceWorkerController();
return _instance!;
}
static Future<dynamic> _handleMethod(MethodCall call) async {
ServiceWorkerController controller =
ServiceWorkerController.instance();
ServiceWorkerClient? serviceWorkerClient =
controller.serviceWorkerClient;
switch (call.method) {
case "shouldInterceptRequest":
if (serviceWorkerClient != null &&
serviceWorkerClient.shouldInterceptRequest != null) {
Map<String, dynamic> arguments =
call.arguments.cast<String, dynamic>();
WebResourceRequest request = WebResourceRequest.fromMap(arguments)!;
return (await serviceWorkerClient.shouldInterceptRequest!(request))
?.toMap();
}
break;
default:
throw UnimplementedError("Unimplemented ${call.method} method");
}
return null;
}
///Gets whether Service Workers support content URL access.
///This method should only be called if [WebViewFeature.isFeatureSupported] returns `true` for [WebViewFeature.SERVICE_WORKER_CONTENT_ACCESS].
///
///**NOTE**: available on Android 24+.
///
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/ServiceWorkerWebSettingsCompat#getAllowContentAccess()
static Future<bool> getAllowContentAccess() async {
Map<String, dynamic> args = <String, dynamic>{};
return await _channel.invokeMethod('getAllowContentAccess', args);
}
///Gets whether Service Workers support file access.
///This method should only be called if [WebViewFeature.isFeatureSupported] returns `true` for [WebViewFeature.SERVICE_WORKER_FILE_ACCESS].
///
///**NOTE**: available on Android 24+.
///
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/ServiceWorkerWebSettingsCompat#getAllowFileAccess()
static Future<bool> getAllowFileAccess() async {
Map<String, dynamic> args = <String, dynamic>{};
return await _channel.invokeMethod('getAllowFileAccess', args);
}
///Gets whether Service Workers are prohibited from loading any resources from the network.
///This method should only be called if [WebViewFeature.isFeatureSupported] returns `true` for [WebViewFeature.SERVICE_WORKER_BLOCK_NETWORK_LOADS].
///
///**NOTE**: available on Android 24+.
///
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/ServiceWorkerWebSettingsCompat#getBlockNetworkLoads()
static Future<bool> getBlockNetworkLoads() async {
Map<String, dynamic> args = <String, dynamic>{};
return await _channel.invokeMethod('getBlockNetworkLoads', args);
}
///Gets the current setting for overriding the cache mode.
///This method should only be called if [WebViewFeature.isFeatureSupported] returns `true` for [WebViewFeature.SERVICE_WORKER_CACHE_MODE].
///
///**NOTE**: available on Android 24+.
///
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/ServiceWorkerWebSettingsCompat#getCacheMode()
static Future<CacheMode?> getCacheMode() async {
Map<String, dynamic> args = <String, dynamic>{};
return CacheMode.fromValue(
await _channel.invokeMethod('getCacheMode', args));
}
///Enables or disables content URL access from Service Workers.
///This method should only be called if [WebViewFeature.isFeatureSupported] returns `true` for [WebViewFeature.SERVICE_WORKER_CONTENT_ACCESS].
///
///**NOTE**: available on Android 24+.
///
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/ServiceWorkerWebSettingsCompat#setAllowContentAccess(boolean)
static Future<void> setAllowContentAccess(bool allow) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("allow", () => allow);
await _channel.invokeMethod('setAllowContentAccess', args);
}
///Enables or disables file access within Service Workers.
///This method should only be called if [WebViewFeature.isFeatureSupported] returns `true` for [WebViewFeature.SERVICE_WORKER_FILE_ACCESS].
///
///**NOTE**: available on Android 24+.
///
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/ServiceWorkerWebSettingsCompat#setAllowFileAccess(boolean)
static Future<void> setAllowFileAccess(bool allow) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("allow", () => allow);
await _channel.invokeMethod('setAllowFileAccess', args);
}
///Sets whether Service Workers should not load resources from the network.
///This method should only be called if [WebViewFeature.isFeatureSupported] returns `true` for [WebViewFeature.SERVICE_WORKER_BLOCK_NETWORK_LOADS].
///
///**NOTE**: available on Android 24+.
///
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/ServiceWorkerWebSettingsCompat#setBlockNetworkLoads(boolean)
static Future<void> setBlockNetworkLoads(bool flag) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("flag", () => flag);
await _channel.invokeMethod('setBlockNetworkLoads', args);
}
///Overrides the way the cache is used.
///This method should only be called if [WebViewFeature.isFeatureSupported] returns `true` for [WebViewFeature.SERVICE_WORKER_CACHE_MODE].
///
///**NOTE**: available on Android 24+.
///
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/ServiceWorkerWebSettingsCompat#setCacheMode(int)
static Future<void> setCacheMode(CacheMode mode) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("mode", () => mode.toValue());
await _channel.invokeMethod('setCacheMode', args);
}
}
///Class used by clients to capture Service Worker related callbacks.
///
///**NOTE**: available on Android 24+.
///
///**Supported Platforms/Implementations**:
///- Android native WebView ([Official API - ServiceWorkerClientCompat](https://developer.android.com/reference/androidx/webkit/ServiceWorkerClientCompat))
class ServiceWorkerClient {
///Notify the host application of a resource request and allow the application to return the data.
///If the return value is `null`, the Service Worker will continue to load the resource as usual.
///Otherwise, the return response and data will be used.
///
///This method is called only if [WebViewFeature.SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST] is supported.
///You can check whether that flag is supported using [WebViewFeature.isFeatureSupported].
///
///[request] represents an object containing the details of the request.
///
///**NOTE**: available on Android 24+.
final Future<WebResourceResponse?> Function(WebResourceRequest request)?
shouldInterceptRequest;
ServiceWorkerClient({this.shouldInterceptRequest});
}
///Class that represents an Android-specific class that manages Service Workers used by [WebView].
///
///**NOTE**: available on Android 24+.
///
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/ServiceWorkerControllerCompat
///
///Use [ServiceWorkerController] instead.
@Deprecated("Use ServiceWorkerController instead")
class AndroidServiceWorkerController {
static AndroidServiceWorkerController? _instance;
static const MethodChannel _channel = const MethodChannel(
'com.pichillilorenzo/flutter_inappwebview_android_serviceworkercontroller');
'com.pichillilorenzo/flutter_inappwebview_serviceworkercontroller');
AndroidServiceWorkerClient? serviceWorkerClient;
@ -150,6 +319,8 @@ class AndroidServiceWorkerController {
///**NOTE**: available on Android 24+.
///
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/ServiceWorkerClientCompat
///Use [ServiceWorkerClient] instead.
@Deprecated("Use ServiceWorkerClient instead")
class AndroidServiceWorkerClient {
///Notify the host application of a resource request and allow the application to return the data.
///If the return value is `null`, the Service Worker will continue to load the resource as usual.

View File

@ -2,9 +2,269 @@ import 'dart:async';
import 'package:flutter/services.dart';
///Class that represents an Android-specific utility class for checking which WebView Support Library features are supported on the device.
class WebViewFeature {
static const MethodChannel _channel = const MethodChannel(
'com.pichillilorenzo/flutter_inappwebview_webviewfeature');
final String _value;
const WebViewFeature._internal(this._value);
static final Set<WebViewFeature> values = [
WebViewFeature.CREATE_WEB_MESSAGE_CHANNEL,
WebViewFeature.DISABLED_ACTION_MODE_MENU_ITEMS,
WebViewFeature.FORCE_DARK,
WebViewFeature.FORCE_DARK_STRATEGY,
WebViewFeature.GET_WEB_CHROME_CLIENT,
WebViewFeature.GET_WEB_VIEW_CLIENT,
WebViewFeature.GET_WEB_VIEW_RENDERER,
WebViewFeature.MULTI_PROCESS,
WebViewFeature.OFF_SCREEN_PRERASTER,
WebViewFeature.POST_WEB_MESSAGE,
WebViewFeature.PROXY_OVERRIDE,
WebViewFeature.RECEIVE_HTTP_ERROR,
WebViewFeature.RECEIVE_WEB_RESOURCE_ERROR,
WebViewFeature.SAFE_BROWSING_ALLOWLIST,
WebViewFeature.SAFE_BROWSING_ENABLE,
WebViewFeature.SAFE_BROWSING_HIT,
WebViewFeature.SAFE_BROWSING_PRIVACY_POLICY_URL,
WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY,
WebViewFeature.SAFE_BROWSING_RESPONSE_PROCEED,
WebViewFeature.SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL,
WebViewFeature.SERVICE_WORKER_BASIC_USAGE,
WebViewFeature.SERVICE_WORKER_BLOCK_NETWORK_LOADS,
WebViewFeature.SERVICE_WORKER_CACHE_MODE,
WebViewFeature.SERVICE_WORKER_CONTENT_ACCESS,
WebViewFeature.SERVICE_WORKER_FILE_ACCESS,
WebViewFeature.SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST,
WebViewFeature.SHOULD_OVERRIDE_WITH_REDIRECTS,
WebViewFeature.START_SAFE_BROWSING,
WebViewFeature.TRACING_CONTROLLER_BASIC_USAGE,
WebViewFeature.VISUAL_STATE_CALLBACK,
WebViewFeature.WEB_MESSAGE_CALLBACK_ON_MESSAGE,
WebViewFeature.WEB_MESSAGE_LISTENER,
WebViewFeature.WEB_MESSAGE_PORT_CLOSE,
WebViewFeature.WEB_MESSAGE_PORT_POST_MESSAGE,
WebViewFeature.WEB_MESSAGE_PORT_SET_MESSAGE_CALLBACK,
WebViewFeature.WEB_RESOURCE_ERROR_GET_CODE,
WebViewFeature.WEB_RESOURCE_ERROR_GET_DESCRIPTION,
WebViewFeature.WEB_RESOURCE_REQUEST_IS_REDIRECT,
WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE,
WebViewFeature.WEB_VIEW_RENDERER_TERMINATE,
].toSet();
static WebViewFeature? fromValue(String? value) {
if (value != null) {
try {
return WebViewFeature.values
.firstWhere((element) => element.toValue() == value);
} catch (e) {
return null;
}
}
return null;
}
String toValue() => _value;
@override
String toString() => _value;
///
static const CREATE_WEB_MESSAGE_CHANNEL =
const WebViewFeature._internal("CREATE_WEB_MESSAGE_CHANNEL");
///
static const DISABLED_ACTION_MODE_MENU_ITEMS =
const WebViewFeature._internal("DISABLED_ACTION_MODE_MENU_ITEMS");
///
static const FORCE_DARK = const WebViewFeature._internal("FORCE_DARK");
///
static const FORCE_DARK_STRATEGY =
const WebViewFeature._internal("FORCE_DARK_STRATEGY");
///
static const GET_WEB_CHROME_CLIENT =
const WebViewFeature._internal("GET_WEB_CHROME_CLIENT");
///
static const GET_WEB_VIEW_CLIENT =
const WebViewFeature._internal("GET_WEB_VIEW_CLIENT");
///
static const GET_WEB_VIEW_RENDERER =
const WebViewFeature._internal("GET_WEB_VIEW_RENDERER");
///
static const MULTI_PROCESS =
const WebViewFeature._internal("MULTI_PROCESS");
///
static const OFF_SCREEN_PRERASTER =
const WebViewFeature._internal("OFF_SCREEN_PRERASTER");
///
static const POST_WEB_MESSAGE =
const WebViewFeature._internal("POST_WEB_MESSAGE");
///
static const PROXY_OVERRIDE =
const WebViewFeature._internal("PROXY_OVERRIDE");
///
static const RECEIVE_HTTP_ERROR =
const WebViewFeature._internal("RECEIVE_HTTP_ERROR");
///
static const RECEIVE_WEB_RESOURCE_ERROR =
const WebViewFeature._internal("RECEIVE_WEB_RESOURCE_ERROR");
///
static const SAFE_BROWSING_ALLOWLIST =
const WebViewFeature._internal("SAFE_BROWSING_ALLOWLIST");
///
static const SAFE_BROWSING_ENABLE =
const WebViewFeature._internal("SAFE_BROWSING_ENABLE");
///
static const SAFE_BROWSING_HIT =
const WebViewFeature._internal("SAFE_BROWSING_HIT");
///
static const SAFE_BROWSING_PRIVACY_POLICY_URL =
const WebViewFeature._internal("SAFE_BROWSING_PRIVACY_POLICY_URL");
///
static const SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY =
const WebViewFeature._internal(
"SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY");
///
static const SAFE_BROWSING_RESPONSE_PROCEED =
const WebViewFeature._internal("SAFE_BROWSING_RESPONSE_PROCEED");
///
static const SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL =
const WebViewFeature._internal(
"SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL");
///Use [SAFE_BROWSING_ALLOWLIST] instead.
@Deprecated('Use SAFE_BROWSING_ALLOWLIST instead')
static const SAFE_BROWSING_WHITELIST =
const WebViewFeature._internal("SAFE_BROWSING_WHITELIST");
///
static const SERVICE_WORKER_BASIC_USAGE =
const WebViewFeature._internal("SERVICE_WORKER_BASIC_USAGE");
///
static const SERVICE_WORKER_BLOCK_NETWORK_LOADS =
const WebViewFeature._internal(
"SERVICE_WORKER_BLOCK_NETWORK_LOADS");
///
static const SERVICE_WORKER_CACHE_MODE =
const WebViewFeature._internal("SERVICE_WORKER_CACHE_MODE");
///
static const SERVICE_WORKER_CONTENT_ACCESS =
const WebViewFeature._internal("SERVICE_WORKER_CONTENT_ACCESS");
///
static const SERVICE_WORKER_FILE_ACCESS =
const WebViewFeature._internal("SERVICE_WORKER_FILE_ACCESS");
///
static const SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST =
const WebViewFeature._internal(
"SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST");
///
static const SHOULD_OVERRIDE_WITH_REDIRECTS =
const WebViewFeature._internal("SHOULD_OVERRIDE_WITH_REDIRECTS");
///
static const START_SAFE_BROWSING =
const WebViewFeature._internal("START_SAFE_BROWSING");
///
static const TRACING_CONTROLLER_BASIC_USAGE =
const WebViewFeature._internal("TRACING_CONTROLLER_BASIC_USAGE");
///
static const VISUAL_STATE_CALLBACK =
const WebViewFeature._internal("VISUAL_STATE_CALLBACK");
///
static const WEB_MESSAGE_CALLBACK_ON_MESSAGE =
const WebViewFeature._internal("WEB_MESSAGE_CALLBACK_ON_MESSAGE");
///
static const WEB_MESSAGE_LISTENER =
const WebViewFeature._internal("WEB_MESSAGE_LISTENER");
///
static const WEB_MESSAGE_PORT_CLOSE =
const WebViewFeature._internal("WEB_MESSAGE_PORT_CLOSE");
///
static const WEB_MESSAGE_PORT_POST_MESSAGE =
const WebViewFeature._internal("WEB_MESSAGE_PORT_POST_MESSAGE");
///
static const WEB_MESSAGE_PORT_SET_MESSAGE_CALLBACK =
const WebViewFeature._internal(
"WEB_MESSAGE_PORT_SET_MESSAGE_CALLBACK");
///
static const WEB_RESOURCE_ERROR_GET_CODE =
const WebViewFeature._internal("WEB_RESOURCE_ERROR_GET_CODE");
///
static const WEB_RESOURCE_ERROR_GET_DESCRIPTION =
const WebViewFeature._internal(
"WEB_RESOURCE_ERROR_GET_DESCRIPTION");
///
static const WEB_RESOURCE_REQUEST_IS_REDIRECT =
const WebViewFeature._internal("WEB_RESOURCE_REQUEST_IS_REDIRECT");
///
static const WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE =
const WebViewFeature._internal(
"WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE");
///
static const WEB_VIEW_RENDERER_TERMINATE =
const WebViewFeature._internal("WEB_VIEW_RENDERER_TERMINATE");
bool operator ==(value) => value == _value;
@override
int get hashCode => _value.hashCode;
///Return whether a feature is supported at run-time. On devices running Android version `Build.VERSION_CODES.LOLLIPOP` and higher,
///this will check whether a feature is supported, depending on the combination of the desired feature, the Android version of device,
///and the WebView APK on the device. If running on a device with a lower API level, this will always return `false`.
///
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/WebViewFeature#isFeatureSupported(java.lang.String)
static Future<bool> isFeatureSupported(WebViewFeature feature) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("feature", () => feature.toValue());
return await _channel.invokeMethod('isFeatureSupported', args);
}
}
///Class that represents an Android-specific utility class for checking which WebView Support Library features are supported on the device.
///Use [WebViewFeature] instead.
@Deprecated("Use WebViewFeature instead")
class AndroidWebViewFeature {
static const MethodChannel _channel = const MethodChannel(
'com.pichillilorenzo/flutter_inappwebview_android_webviewfeature');
'com.pichillilorenzo/flutter_inappwebview_webviewfeature');
final String _value;

View File

@ -3,12 +3,14 @@ import 'dart:ui';
import '../../util.dart';
import '../../types.dart';
import '../chrome_safari_browser_options.dart';
import '../chrome_safari_browser_settings.dart';
import '../chrome_safari_browser.dart';
import '../../in_app_webview/android/in_app_webview_options.dart';
///This class represents all the Android-only [ChromeSafariBrowser] options available.
///Use [ChromeSafariBrowserSettings] instead.
@Deprecated('Use ChromeSafariBrowserSettings instead')
class AndroidChromeCustomTabsOptions
implements ChromeSafariBrowserOptions, AndroidOptions {
///Use [shareState] instead.

View File

@ -4,7 +4,7 @@ import 'dart:collection';
import 'package:flutter/services.dart';
import 'package:flutter_inappwebview/src/util.dart';
import 'chrome_safari_browser_options.dart';
import 'chrome_safari_browser_settings.dart';
class ChromeSafariBrowserAlreadyOpenedException implements Exception {
final dynamic message;
@ -84,8 +84,13 @@ class ChromeSafariBrowser {
///[url]: The [url] to load.
///
///[options]: Options for the [ChromeSafariBrowser].
///
///[settings]: Settings for the [ChromeSafariBrowser].
Future<void> open(
{required Uri url, ChromeSafariBrowserClassOptions? options}) async {
{required Uri url,
// ignore: deprecated_member_use_from_same_package
@Deprecated('Use settings instead') ChromeSafariBrowserClassOptions? options,
ChromeSafariBrowserSettings? settings}) async {
assert(url.toString().isNotEmpty);
this.throwIsAlreadyOpened(message: 'Cannot open $url!');
@ -94,10 +99,13 @@ class ChromeSafariBrowser {
menuItemList.add({"id": value.id, "label": value.label});
});
var initialSettings = settings?.toMap() ?? options?.toMap() ??
ChromeSafariBrowserSettings().toMap();
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('id', () => id);
args.putIfAbsent('url', () => url.toString());
args.putIfAbsent('options', () => options?.toMap() ?? {});
args.putIfAbsent('settings', () => initialSettings);
args.putIfAbsent('menuItemList', () => menuItemList);
await _sharedChannel.invokeMethod('open', args);
this._isOpened = true;

View File

@ -1,60 +0,0 @@
import 'package:flutter/foundation.dart';
import 'android/chrome_custom_tabs_options.dart';
import 'ios/safari_options.dart';
class ChromeSafariBrowserOptions {
Map<String, dynamic> toMap() {
return {};
}
static ChromeSafariBrowserOptions fromMap(Map<String, dynamic> map) {
return new ChromeSafariBrowserOptions();
}
ChromeSafariBrowserOptions copy() {
return ChromeSafariBrowserOptions.fromMap(this.toMap());
}
Map<String, dynamic> toJson() {
return this.toMap();
}
@override
String toString() {
return toMap().toString();
}
}
///Class that represents the options that can be used for an [ChromeSafariBrowser] window.
class ChromeSafariBrowserClassOptions {
///Android-specific options.
AndroidChromeCustomTabsOptions? android;
///iOS-specific options.
IOSSafariOptions? ios;
ChromeSafariBrowserClassOptions({this.android, this.ios}) {
this.android = this.android ?? AndroidChromeCustomTabsOptions();
this.ios = this.ios ?? IOSSafariOptions();
}
Map<String, dynamic> toMap() {
Map<String, dynamic> options = {};
if (defaultTargetPlatform == TargetPlatform.android)
options.addAll(this.android?.toMap() ?? {});
else if (defaultTargetPlatform == TargetPlatform.iOS)
options.addAll(this.ios?.toMap() ?? {});
return options;
}
Map<String, dynamic> toJson() {
return this.toMap();
}
@override
String toString() {
return toMap().toString();
}
}

View File

@ -0,0 +1,306 @@
import 'dart:ui';
import 'package:flutter/foundation.dart';
import '../util.dart';
import 'android/chrome_custom_tabs_options.dart';
import 'ios/safari_options.dart';
import '../types.dart';
class ChromeSafariBrowserOptions {
Map<String, dynamic> toMap() {
return {};
}
static ChromeSafariBrowserOptions fromMap(Map<String, dynamic> map) {
return new ChromeSafariBrowserOptions();
}
ChromeSafariBrowserOptions copy() {
return ChromeSafariBrowserOptions.fromMap(this.toMap());
}
Map<String, dynamic> toJson() {
return this.toMap();
}
@override
String toString() {
return toMap().toString();
}
}
///Class that represents the settings that can be used for an [ChromeSafariBrowser] window.
class ChromeSafariBrowserSettings implements ChromeSafariBrowserOptions {
///The share state that should be applied to the custom tab. The default value is [CustomTabsShareState.SHARE_STATE_DEFAULT].
///
///**NOTE**: Not available in a Trusted Web Activity.
///
///**Supported Platforms/Implementations**:
///- Android native WebView
CustomTabsShareState shareState;
///Set to `false` if the title shouldn't be shown in the custom tab. The default value is `true`.
///
///**NOTE**: Not available in a Trusted Web Activity.
///
///**Supported Platforms/Implementations**:
///- Android native WebView
bool showTitle;
///Set the custom background color of the toolbar.
///
///**Supported Platforms/Implementations**:
///- Android native WebView
Color? toolbarBackgroundColor;
///Set to `true` to enable the url bar to hide as the user scrolls down on the page. The default value is `false`.
///
///**NOTE**: Not available in a Trusted Web Activity.
///
///**Supported Platforms/Implementations**:
///- Android native WebView
bool enableUrlBarHiding;
///Set to `true` to enable Instant Apps. The default value is `false`.
///
///**NOTE**: Not available in a Trusted Web Activity.
///
///**Supported Platforms/Implementations**:
///- Android native WebView
bool instantAppsEnabled;
///Set an explicit application package name that limits
///the components this Intent will resolve to. If left to the default
///value of null, all components in all applications will considered.
///If non-null, the Intent can only match the components in the given
///application package.
///
///**Supported Platforms/Implementations**:
///- Android native WebView
String? packageName;
///Set to `true` to enable Keep Alive. The default value is `false`.
///
///**Supported Platforms/Implementations**:
///- Android native WebView
bool keepAliveEnabled;
///Set to `true` to launch the Android activity in `singleInstance` mode. The default value is `false`.
///
///**Supported Platforms/Implementations**:
///- Android native WebView
bool isSingleInstance;
///Set to `true` to launch the Android intent with the flag `FLAG_ACTIVITY_NO_HISTORY`. The default value is `false`.
///
///**Supported Platforms/Implementations**:
///- Android native WebView
bool noHistory;
///Set to `true` to launch the Custom Tab as a Trusted Web Activity. The default value is `false`.
///
///**Supported Platforms/Implementations**:
///- Android native WebView
bool isTrustedWebActivity;
///Sets a list of additional trusted origins that the user may navigate or be redirected to from the starting uri.
///
///**NOTE**: Available only in a Trusted Web Activity.
///
///**Supported Platforms/Implementations**:
///- Android native WebView
List<String> additionalTrustedOrigins;
///Sets a display mode of a Trusted Web Activity.
///
///**NOTE**: Available only in a Trusted Web Activity.
///
///**Supported Platforms/Implementations**:
///- Android native WebView
TrustedWebActivityDisplayMode? displayMode;
///Sets a screen orientation. This can be used e.g. to enable the locking of an orientation lock type.
///
///**NOTE**: Available only in a Trusted Web Activity.
///
///**Supported Platforms/Implementations**:
///- Android native WebView
TrustedWebActivityScreenOrientation screenOrientation;
///Set to `true` if Reader mode should be entered automatically when it is available for the webpage. The default value is `false`.
///
///**Supported Platforms/Implementations**:
///- iOS
bool entersReaderIfAvailable;
///Set to `true` to enable bar collapsing. The default value is `false`.
///
///**Supported Platforms/Implementations**:
///- iOS
bool barCollapsingEnabled;
///Set the custom style for the dismiss button. The default value is [DismissButtonStyle.DONE].
///
///**NOTE**: available on iOS 11.0+.
///
///**Supported Platforms/Implementations**:
///- iOS
DismissButtonStyle dismissButtonStyle;
///Set the custom background color of the navigation bar and the toolbar.
///
///**NOTE**: available on iOS 10.0+.
///
///**Supported Platforms/Implementations**:
///- iOS
Color? preferredBarTintColor;
///Set the custom color of the control buttons on the navigation bar and the toolbar.
///
///**NOTE**: available on iOS 10.0+.
///
///**Supported Platforms/Implementations**:
///- iOS
Color? preferredControlTintColor;
///Set the custom modal presentation style when presenting the WebView. The default value is [ModalPresentationStyle.FULL_SCREEN].
///
///**Supported Platforms/Implementations**:
///- iOS
ModalPresentationStyle presentationStyle;
///Set to the custom transition style when presenting the WebView. The default value is [ModalTransitionStyle.COVER_VERTICAL].
///
///**Supported Platforms/Implementations**:
///- iOS
ModalTransitionStyle transitionStyle;
ChromeSafariBrowserSettings(
{this.shareState = CustomTabsShareState.SHARE_STATE_DEFAULT,
this.showTitle = true,
this.toolbarBackgroundColor,
this.enableUrlBarHiding = false,
this.instantAppsEnabled = false,
this.packageName,
this.keepAliveEnabled = false,
this.isSingleInstance = false,
this.noHistory = false,
this.isTrustedWebActivity = false,
this.additionalTrustedOrigins = const [],
this.displayMode,
this.screenOrientation = TrustedWebActivityScreenOrientation.DEFAULT,
this.entersReaderIfAvailable = false,
this.barCollapsingEnabled = false,
this.dismissButtonStyle = DismissButtonStyle.DONE,
this.preferredBarTintColor,
this.preferredControlTintColor,
this.presentationStyle = ModalPresentationStyle.FULL_SCREEN,
this.transitionStyle = ModalTransitionStyle.COVER_VERTICAL});
@override
Map<String, dynamic> toMap() {
return {
"shareState": shareState.toValue(),
"showTitle": showTitle,
"toolbarBackgroundColor": toolbarBackgroundColor?.toHex(),
"enableUrlBarHiding": enableUrlBarHiding,
"instantAppsEnabled": instantAppsEnabled,
"packageName": packageName,
"keepAliveEnabled": keepAliveEnabled,
"isSingleInstance": isSingleInstance,
"noHistory": noHistory,
"isTrustedWebActivity": isTrustedWebActivity,
"additionalTrustedOrigins": additionalTrustedOrigins,
"displayMode": displayMode?.toMap(),
"screenOrientation": screenOrientation.toValue(),
"entersReaderIfAvailable": entersReaderIfAvailable,
"barCollapsingEnabled": barCollapsingEnabled,
"dismissButtonStyle": dismissButtonStyle.toValue(),
"preferredBarTintColor": preferredBarTintColor?.toHex(),
"preferredControlTintColor": preferredControlTintColor?.toHex(),
"presentationStyle": presentationStyle.toValue(),
"transitionStyle": transitionStyle.toValue()
};
}
static ChromeSafariBrowserSettings fromMap(Map<String, dynamic> map) {
ChromeSafariBrowserSettings options =
new ChromeSafariBrowserSettings();
options.shareState = map["shareState"];
options.showTitle = map["showTitle"];
options.toolbarBackgroundColor =
UtilColor.fromHex(map["toolbarBackgroundColor"]);
options.enableUrlBarHiding = map["enableUrlBarHiding"];
options.instantAppsEnabled = map["instantAppsEnabled"];
options.packageName = map["packageName"];
options.keepAliveEnabled = map["keepAliveEnabled"];
options.isSingleInstance = map["isSingleInstance"];
options.noHistory = map["noHistory"];
options.isTrustedWebActivity = map["isTrustedWebActivity"];
options.additionalTrustedOrigins = map["additionalTrustedOrigins"];
switch (map["displayMode"]["type"]) {
case "IMMERSIVE_MODE":
options.displayMode =
TrustedWebActivityImmersiveDisplayMode.fromMap(map["displayMode"]);
break;
case "DEFAULT_MODE":
default:
options.displayMode = TrustedWebActivityDefaultDisplayMode();
break;
}
options.screenOrientation = map["screenOrientation"];
return options;
}
@override
Map<String, dynamic> toJson() {
return this.toMap();
}
@override
String toString() {
return toMap().toString();
}
@override
ChromeSafariBrowserSettings copy() {
return ChromeSafariBrowserSettings.fromMap(this.toMap());
}
}
///Class that represents the options that can be used for an [ChromeSafariBrowser] window.
///Use [ChromeSafariBrowserSettings] instead.
@Deprecated('Use ChromeSafariBrowserSettings instead')
class ChromeSafariBrowserClassOptions {
///Android-specific options.
AndroidChromeCustomTabsOptions? android;
///iOS-specific options.
IOSSafariOptions? ios;
ChromeSafariBrowserClassOptions({this.android, this.ios}) {
this.android = this.android ?? AndroidChromeCustomTabsOptions();
this.ios = this.ios ?? IOSSafariOptions();
}
Map<String, dynamic> toMap() {
Map<String, dynamic> options = {};
if (defaultTargetPlatform == TargetPlatform.android)
options.addAll(this.android?.toMap() ?? {});
else if (defaultTargetPlatform == TargetPlatform.iOS)
options.addAll(this.ios?.toMap() ?? {});
return options;
}
Map<String, dynamic> toJson() {
return this.toMap();
}
@override
String toString() {
return toMap().toString();
}
}

View File

@ -3,12 +3,14 @@ import 'dart:ui';
import '../../util.dart';
import '../../types.dart';
import '../chrome_safari_browser_options.dart';
import '../chrome_safari_browser_settings.dart';
import '../chrome_safari_browser.dart';
import '../../in_app_webview/ios/in_app_webview_options.dart';
///This class represents all the iOS-only [ChromeSafariBrowser] options available.
///Use [ChromeSafariBrowserSettings] instead.
@Deprecated('Use ChromeSafariBrowserSettings instead')
class IOSSafariOptions implements ChromeSafariBrowserOptions, IosOptions {
///Set to `true` if Reader mode should be entered automatically when it is available for the webpage. The default value is `false`.
bool entersReaderIfAvailable;

View File

@ -1,4 +1,4 @@
export 'chrome_safari_browser.dart';
export 'chrome_safari_browser_options.dart';
export 'chrome_safari_browser_settings.dart';
export 'android/main.dart';
export 'ios/main.dart';

View File

@ -28,7 +28,11 @@ class HttpAuthCredentialDatabase {
///Gets a map list of all HTTP auth credentials saved.
///Each map contains the key `protectionSpace` of type [URLProtectionSpace]
///and the key `credentials` of type `List<URLCredential>` that contains all the HTTP auth credentials saved for that `protectionSpace`.
///and the key `credentials` of type List<[URLCredential]> that contains all the HTTP auth credentials saved for that `protectionSpace`.
///
///**Supported Platforms/Implementations**:
///- Android native WebView
///- iOS ([Official API - URLCredentialStorage.allCredentials](https://developer.apple.com/documentation/foundation/urlcredentialstorage/1413859-allcredentials))
Future<List<URLProtectionSpaceHttpAuthCredentials>>
getAllAuthCredentials() async {
Map<String, dynamic> args = <String, dynamic>{};
@ -48,6 +52,10 @@ class HttpAuthCredentialDatabase {
}
///Gets all the HTTP auth credentials saved for that [protectionSpace].
///
///**Supported Platforms/Implementations**:
///- Android native WebView
///- iOS
Future<List<URLCredential>> getHttpAuthCredentials(
{required URLProtectionSpace protectionSpace}) async {
Map<String, dynamic> args = <String, dynamic>{};
@ -68,6 +76,10 @@ class HttpAuthCredentialDatabase {
}
///Saves an HTTP auth [credential] for that [protectionSpace].
///
///**Supported Platforms/Implementations**:
///- Android native WebView
///- iOS ([Official API - URLCredentialStorage.set](https://developer.apple.com/documentation/foundation/urlcredentialstorage/1407227-set))
Future<void> setHttpAuthCredential(
{required URLProtectionSpace protectionSpace,
required URLCredential credential}) async {
@ -82,6 +94,10 @@ class HttpAuthCredentialDatabase {
}
///Removes an HTTP auth [credential] for that [protectionSpace].
///
///**Supported Platforms/Implementations**:
///- Android native WebView
///- iOS ([Official API - URLCredentialStorage.remove](https://developer.apple.com/documentation/foundation/urlcredentialstorage/1408664-remove))
Future<void> removeHttpAuthCredential(
{required URLProtectionSpace protectionSpace,
required URLCredential credential}) async {
@ -96,6 +112,10 @@ class HttpAuthCredentialDatabase {
}
///Removes all the HTTP auth credentials saved for that [protectionSpace].
///
///**Supported Platforms/Implementations**:
///- Android native WebView
///- iOS
Future<void> removeHttpAuthCredentials(
{required URLProtectionSpace protectionSpace}) async {
Map<String, dynamic> args = <String, dynamic>{};
@ -107,6 +127,10 @@ class HttpAuthCredentialDatabase {
}
///Removes all the HTTP auth credentials saved in the database.
///
///**Supported Platforms/Implementations**:
///- Android native WebView
///- iOS
Future<void> clearAllAuthCredentials() async {
Map<String, dynamic> args = <String, dynamic>{};
await _channel.invokeMethod('clearAllAuthCredentials', args);

View File

@ -103,6 +103,8 @@ class InAppBrowser {
///[urlRequest]: The [urlRequest] to load.
///
///[options]: Options for the [InAppBrowser].
///
///[settings]: Settings for the [InAppBrowser].
Future<void> openUrlRequest(
{required URLRequest urlRequest,
// ignore: deprecated_member_use_from_same_package
@ -166,6 +168,8 @@ class InAppBrowser {
///[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].
///
///[settings]: Settings for the [InAppBrowser].
Future<void> openFile(
{required String assetFilePath,
// ignore: deprecated_member_use_from_same_package
@ -203,18 +207,20 @@ class InAppBrowser {
///The [androidHistoryUrl] parameter is the URL to use as the history entry. The default value is `about:blank`. If non-null, this must be a valid URL. This parameter is used only on Android.
///
///The [options] parameter specifies the options for the [InAppBrowser].
///
///[settings]: Settings for the [InAppBrowser].
Future<void> openData(
{required String data,
String mimeType = "text/html",
String encoding = "utf8",
Uri? baseUrl,
Uri? androidHistoryUrl,
@Deprecated("Use historyUrl instead") Uri? androidHistoryUrl,
Uri? historyUrl,
// ignore: deprecated_member_use_from_same_package
@Deprecated('Use settings instead') InAppBrowserClassOptions? options,
InAppBrowserClassSettings? settings}) async {
this.throwIfAlreadyOpened(message: 'Cannot open data!');
var initialSettings = settings?.toMap() ?? options?.toMap() ??
InAppBrowserClassSettings().toMap();
@ -226,7 +232,7 @@ class InAppBrowser {
args.putIfAbsent('encoding', () => encoding);
args.putIfAbsent('baseUrl', () => baseUrl?.toString() ?? "about:blank");
args.putIfAbsent(
'historyUrl', () => androidHistoryUrl?.toString() ?? "about:blank");
'historyUrl', () => (historyUrl ?? androidHistoryUrl)?.toString() ?? "about:blank");
args.putIfAbsent('contextMenu', () => contextMenu?.toMap() ?? {});
args.putIfAbsent('windowId', () => windowId);
args.putIfAbsent('implementation', () => implementation.toValue());

View File

@ -18,7 +18,7 @@ abstract class AndroidInAppWebViewControllerMixin {
///This should not be called if Safe Browsing has been disabled by manifest tag or [AndroidInAppWebViewOptions.safeBrowsingEnabled].
///This prepares resources used for Safe Browsing.
///
///This method should only be called if [AndroidWebViewFeature.isFeatureSupported] returns `true` for [AndroidWebViewFeature.START_SAFE_BROWSING].
///This method should only be called if [WebViewFeature.isFeatureSupported] returns `true` for [WebViewFeature.START_SAFE_BROWSING].
///
///**Supported Platforms/Implementations**:
///- Android native WebView ([Official API - WebView.startSafeBrowsing](https://developer.android.com/reference/android/webkit/WebView#startSafeBrowsing(android.content.Context,%20android.webkit.ValueCallback%3Cjava.lang.Boolean%3E)))

View File

@ -1327,6 +1327,8 @@ class InAppWebViewController with AndroidInAppWebViewControllerMixin, IOSInAppWe
Uri? iosAllowingReadAccessTo,
Uri? allowingReadAccessTo}) async {
assert(urlRequest.url != null && urlRequest.url.toString().isNotEmpty);
assert(allowingReadAccessTo == null ||
allowingReadAccessTo.isScheme("file"));
assert(iosAllowingReadAccessTo == null ||
iosAllowingReadAccessTo.isScheme("file"));
@ -1385,6 +1387,8 @@ class InAppWebViewController with AndroidInAppWebViewControllerMixin, IOSInAppWe
@Deprecated('Use allowingReadAccessTo instead')
Uri? iosAllowingReadAccessTo,
Uri? allowingReadAccessTo}) async {
assert(allowingReadAccessTo == null ||
allowingReadAccessTo.isScheme("file"));
assert(iosAllowingReadAccessTo == null ||
iosAllowingReadAccessTo.isScheme("file"));
@ -2514,7 +2518,7 @@ class InAppWebViewController with AndroidInAppWebViewControllerMixin, IOSInAppWe
///
///This method should be called when the page is loaded, for example, when the [WebView.onLoadStop] is fired, otherwise the [WebMessageChannel] won't work.
///
///**NOTE for Android native WebView**: This method should only be called if [AndroidWebViewFeature.isFeatureSupported] returns `true` for [AndroidWebViewFeature.CREATE_WEB_MESSAGE_CHANNEL].
///**NOTE for Android native WebView**: This method should only be called if [WebViewFeature.isFeatureSupported] returns `true` for [WebViewFeature.CREATE_WEB_MESSAGE_CHANNEL].
///
///**NOTE**: On iOS, it is implemented using JavaScript.
///
@ -2534,7 +2538,7 @@ class InAppWebViewController with AndroidInAppWebViewControllerMixin, IOSInAppWe
///
///A target origin can be set as a wildcard ("*"). However this is not recommended.
///
///**NOTE for Android native WebView**: This method should only be called if [AndroidWebViewFeature.isFeatureSupported] returns `true` for [AndroidWebViewFeature.POST_WEB_MESSAGE].
///**NOTE for Android native WebView**: This method should only be called if [WebViewFeature.isFeatureSupported] returns `true` for [WebViewFeature.POST_WEB_MESSAGE].
///
///**NOTE**: On iOS, it is implemented using JavaScript.
///
@ -2692,7 +2696,7 @@ class InAppWebViewController with AndroidInAppWebViewControllerMixin, IOSInAppWe
/// // Flutter App
/// child: InAppWebView(
/// onWebViewCreated: (controller) async {
/// if (!Platform.isAndroid || await AndroidWebViewFeature.isFeatureSupported(AndroidWebViewFeature.WEB_MESSAGE_LISTENER)) {
/// if (!Platform.isAndroid || await WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) {
/// await controller.addWebMessageListener(WebMessageListener(
/// jsObjectName: "myObject",
/// onPostMessage: (message, sourceOrigin, isMainFrame, replyProxy) {
@ -2706,7 +2710,7 @@ class InAppWebViewController with AndroidInAppWebViewControllerMixin, IOSInAppWe
/// ),
///```
///
///**NOTE for Android**: This method should only be called if [AndroidWebViewFeature.isFeatureSupported] returns `true` for [AndroidWebViewFeature.WEB_MESSAGE_LISTENER].
///**NOTE for Android**: This method should only be called if [WebViewFeature.isFeatureSupported] returns `true` for [WebViewFeature.WEB_MESSAGE_LISTENER].
///
///**NOTE for iOS**: This is implemented using Javascript.
///
@ -2764,7 +2768,7 @@ class InAppWebViewController with AndroidInAppWebViewControllerMixin, IOSInAppWe
///Returns a URL pointing to the privacy policy for Safe Browsing reporting.
///
///This method should only be called if [AndroidWebViewFeature.isFeatureSupported] returns `true` for [AndroidWebViewFeature.SAFE_BROWSING_PRIVACY_POLICY_URL].
///This method should only be called if [WebViewFeature.isFeatureSupported] returns `true` for [WebViewFeature.SAFE_BROWSING_PRIVACY_POLICY_URL].
///
///**Supported Platforms/Implementations**:
///- Android native WebView ([Official API - WebViewCompat.getSafeBrowsingPrivacyPolicyUrl](https://developer.android.com/reference/androidx/webkit/WebViewCompat#getSafeBrowsingPrivacyPolicyUrl()))
@ -2787,7 +2791,7 @@ class InAppWebViewController with AndroidInAppWebViewControllerMixin, IOSInAppWe
///
///All other rules, including wildcards, are invalid. The correct syntax for hosts is defined by [RFC 3986](https://tools.ietf.org/html/rfc3986#section-3.2.2).
///
///This method should only be called if [AndroidWebViewFeature.isFeatureSupported] returns `true` for [AndroidWebViewFeature.SAFE_BROWSING_ALLOWLIST].
///This method should only be called if [WebViewFeature.isFeatureSupported] returns `true` for [WebViewFeature.SAFE_BROWSING_ALLOWLIST].
///
///[hosts] represents the list of hosts. This value must never be `null`.
///

View File

@ -132,13 +132,21 @@ class PullToRefreshController {
await _channel?.invokeMethod('setSize', args);
}
///Sets the styled title text to display in the refresh control.
///
///**NOTE**: Available only on iOS.
///Use [setStyledTitle] instead.
@Deprecated("Use setStyledTitle instead")
Future<void> setAttributedTitle(IOSNSAttributedString attributedTitle) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('attributedTitle', () => attributedTitle.toMap());
await _channel?.invokeMethod('setAttributedTitle', args);
await _channel?.invokeMethod('setStyledTitle', args);
}
///Sets the styled title text to display in the refresh control.
///
///**NOTE**: Available only on iOS.
Future<void> setStyledTitle(AttributedString attributedTitle) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('attributedTitle', () => attributedTitle.toMap());
await _channel?.invokeMethod('setStyledTitle', args);
}
void initMethodChannel(dynamic id) {