added ContentBlockerTrigger.ifFrameUrl and ContentBlockerTrigger.loadContext properties

This commit is contained in:
Lorenzo Pichilli 2022-10-08 17:48:16 +02:00
parent d2e5c8dc87
commit 85ff4c1234
6 changed files with 155 additions and 34 deletions

View File

@ -13,6 +13,7 @@
- Added `debugLoggingSettings` static property for WebView and ChromeSafariBrowser - Added `debugLoggingSettings` static property for WebView and ChromeSafariBrowser
- Added `WebViewFeature.DOCUMENT_START_SCRIPT` Android feature support - Added `WebViewFeature.DOCUMENT_START_SCRIPT` Android feature support
- Added `getRequestedWithHeaderMode`, `setRequestedWithHeaderMode` ServiceWorkerController methods - Added `getRequestedWithHeaderMode`, `setRequestedWithHeaderMode` ServiceWorkerController methods
- Added `ContentBlockerTrigger.ifFrameUrl` and `ContentBlockerTrigger.loadContext` properties
- Updated `getMetaThemeColor` on iOS 15.0+ - Updated `getMetaThemeColor` on iOS 15.0+
- Deprecated `onLoadError` for `onReceivedError`. `onReceivedError` will be called also for subframes - Deprecated `onLoadError` for `onReceivedError`. `onReceivedError` will be called also for subframes
- Deprecated `onLoadHttpError` for `onReceivedError`. `onReceivedHttpError` will be called also for subframes - Deprecated `onLoadHttpError` for `onReceivedError`. `onReceivedHttpError` will be called also for subframes

View File

@ -116,7 +116,7 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
InAppWebView( InAppWebView(
key: webViewKey, key: webViewKey,
initialUrlRequest: initialUrlRequest:
URLRequest(url: Uri.parse('https://developer.apple.com/videos/play/wwdc2022/10049/?time=264')), URLRequest(url: Uri.parse('https://github.com/flutter')),
// initialUrlRequest: // initialUrlRequest:
// URLRequest(url: Uri.parse(Uri.base.toString().replaceFirst("/#/", "/") + 'page.html')), // URLRequest(url: Uri.parse(Uri.base.toString().replaceFirst("/#/", "/") + 'page.html')),
// initialFile: "assets/index.html", // initialFile: "assets/index.html",

View File

@ -35,53 +35,59 @@ class ContentBlocker {
///For example, you can limit the trigger to specific domains or have it not apply when a match is found on a specific domain. ///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 { class ContentBlockerTrigger {
///A regular expression pattern to match the URL against. ///A regular expression pattern to match the URL against.
late String urlFilter; String urlFilter;
///Used only by iOS. A Boolean value. The default value is false. ///A list of regular expressions to match iframes URL against.
late bool urlFilterIsCaseSensitive; ///
///*NOTE*: available only on iOS.
List<String> ifFrameUrl;
///A Boolean value. The default value is `false`.
///
///*NOTE*: available only on iOS.
bool urlFilterIsCaseSensitive;
///A list of [ContentBlockerTriggerResourceType] representing the resource types (how the browser intends to use the resource) that the rule should match. ///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. ///If not specified, the rule matches all resource types.
late List<ContentBlockerTriggerResourceType> resourceType; List<ContentBlockerTriggerResourceType> resourceType;
///A list of strings matched to a URL's domain; limits action to a list of specific domains. ///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]. ///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].
late List<String> ifDomain; List<String> ifDomain;
///A list of strings matched to a URL's domain; acts on any site except domains in a provided list. ///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]. ///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].
late List<String> unlessDomain; List<String> unlessDomain;
///A list of [ContentBlockerTriggerLoadType] that can include one of two mutually exclusive values. If not specified, the rule matches all load types. ///A list of [ContentBlockerTriggerLoadType] that can include one of two mutually exclusive values. If not specified, the rule matches all load types.
late List<ContentBlockerTriggerLoadType> loadType; List<ContentBlockerTriggerLoadType> loadType;
///A list of strings matched to the entire main document URL; limits the action to a specific list of URL patterns. ///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]. ///Values must be lowercase ASCII, or punycode for non-ASCII. Can't be used with [ContentBlockerTrigger.unlessTopUrl].
late List<String> ifTopUrl; List<String> ifTopUrl;
///An array of strings matched to the entire main document URL; acts on any site except URL patterns in provided list. ///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]. ///Values must be lowercase ASCII, or punycode for non-ASCII. Can't be used with [ContentBlockerTrigger.ifTopUrl].
late List<String> unlessTopUrl; List<String> unlessTopUrl;
///An array of strings that specify loading contexts.
///
///*NOTE*: available only on iOS.
List<ContentBlockerTriggerLoadContext> loadContext;
ContentBlockerTrigger( ContentBlockerTrigger(
{required String urlFilter, {required this.urlFilter,
bool urlFilterIsCaseSensitive = false, this.ifFrameUrl = const <String>[],
List<ContentBlockerTriggerResourceType> resourceType = const [], this.urlFilterIsCaseSensitive = false,
List<String> ifDomain = const [], this.resourceType = const <ContentBlockerTriggerResourceType>[],
List<String> unlessDomain = const [], this.ifDomain = const <String>[],
List<ContentBlockerTriggerLoadType> loadType = const [], this.unlessDomain = const <String>[],
List<String> ifTopUrl = const [], this.loadType = const <ContentBlockerTriggerLoadType>[],
List<String> unlessTopUrl = const []}) { this.ifTopUrl = const <String>[],
this.urlFilter = urlFilter; this.unlessTopUrl = const <String>[],
this.resourceType = resourceType; this.loadContext = const <ContentBlockerTriggerLoadContext>[]}) {
this.urlFilterIsCaseSensitive = urlFilterIsCaseSensitive;
this.ifDomain = ifDomain;
this.unlessDomain = unlessDomain;
assert(!(this.ifDomain.isEmpty || this.unlessDomain.isEmpty) == false); assert(!(this.ifDomain.isEmpty || this.unlessDomain.isEmpty) == false);
this.loadType = loadType;
assert(this.loadType.length <= 2); assert(this.loadType.length <= 2);
this.ifTopUrl = ifTopUrl;
this.unlessTopUrl = unlessTopUrl;
assert(!(this.ifTopUrl.isEmpty || this.unlessTopUrl.isEmpty) == false); assert(!(this.ifTopUrl.isEmpty || this.unlessTopUrl.isEmpty) == false);
} }
@ -94,16 +100,22 @@ class ContentBlockerTrigger {
loadType.forEach((type) { loadType.forEach((type) {
loadTypeStringList.add(type.toNativeValue()); loadTypeStringList.add(type.toNativeValue());
}); });
List<String> loadContextStringList = [];
loadContext.forEach((type) {
loadContextStringList.add(type.toNativeValue());
});
Map<String, dynamic> map = { Map<String, dynamic> map = {
"url-filter": urlFilter, "url-filter": urlFilter,
"if-frame-url": ifFrameUrl,
"url-filter-is-case-sensitive": urlFilterIsCaseSensitive, "url-filter-is-case-sensitive": urlFilterIsCaseSensitive,
"if-domain": ifDomain, "if-domain": ifDomain,
"unless-domain": unlessDomain, "unless-domain": unlessDomain,
"resource-type": resourceTypeStringList, "resource-type": resourceTypeStringList,
"load-type": loadTypeStringList, "load-type": loadTypeStringList,
"if-top-url": ifTopUrl, "if-top-url": ifTopUrl,
"unless-top-url": unlessTopUrl "unless-top-url": unlessTopUrl,
"load-context": loadContextStringList
}; };
map.keys map.keys
@ -119,6 +131,7 @@ class ContentBlockerTrigger {
static ContentBlockerTrigger fromMap(Map<String, dynamic> map) { static ContentBlockerTrigger fromMap(Map<String, dynamic> map) {
List<ContentBlockerTriggerResourceType> resourceType = []; List<ContentBlockerTriggerResourceType> resourceType = [];
List<ContentBlockerTriggerLoadType> loadType = []; List<ContentBlockerTriggerLoadType> loadType = [];
List<ContentBlockerTriggerLoadContext> loadContext = [];
List<String> resourceTypeStringList = List<String> resourceTypeStringList =
List<String>.from(map["resource-type"] ?? []); List<String>.from(map["resource-type"] ?? []);
@ -137,15 +150,25 @@ class ContentBlockerTrigger {
} }
}); });
List<String> loadContextStringList = List<String>.from(map["load-context"] ?? []);
loadContextStringList.forEach((typeValue) {
var context = ContentBlockerTriggerLoadContext.fromNativeValue(typeValue);
if (context != null) {
loadContext.add(context);
}
});
return ContentBlockerTrigger( return ContentBlockerTrigger(
urlFilter: map["url-filter"], urlFilter: map["url-filter"],
ifFrameUrl: map["if-frame-url"],
urlFilterIsCaseSensitive: map["url-filter-is-case-sensitive"], urlFilterIsCaseSensitive: map["url-filter-is-case-sensitive"],
ifDomain: List<String>.from(map["if-domain"] ?? []), ifDomain: List<String>.from(map["if-domain"] ?? []),
unlessDomain: List<String>.from(map["unless-domain"] ?? []), unlessDomain: List<String>.from(map["unless-domain"] ?? []),
resourceType: resourceType, resourceType: resourceType,
loadType: loadType, loadType: loadType,
ifTopUrl: List<String>.from(map["if-top-url"] ?? []), ifTopUrl: List<String>.from(map["if-top-url"] ?? []),
unlessTopUrl: List<String>.from(map["unless-top-url"] ?? [])); unlessTopUrl: List<String>.from(map["unless-top-url"] ?? []),
loadContext: loadContext);
} }
} }
@ -156,19 +179,17 @@ class ContentBlockerTrigger {
///Group the rules with similar actions together to improve performance. ///Group the rules with similar actions together to improve performance.
class ContentBlockerAction { class ContentBlockerAction {
///Type of the action. ///Type of the action.
late ContentBlockerActionType type; ContentBlockerActionType type;
///If the action type is [ContentBlockerActionType.CSS_DISPLAY_NONE], then also the [selector] property is required, otherwise it is ignored. ///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. ///It specify a string that defines a selector list. Use CSS identifiers as the individual selector values, separated by commas.
String? selector; String? selector;
ContentBlockerAction( ContentBlockerAction(
{required ContentBlockerActionType type, String? selector}) { {required this.type, this.selector}) {
this.type = type;
if (this.type == ContentBlockerActionType.CSS_DISPLAY_NONE) { if (this.type == ContentBlockerActionType.CSS_DISPLAY_NONE) {
assert(selector != null); assert(this.selector != null);
} }
this.selector = selector;
} }
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {

View File

@ -0,0 +1,22 @@
import 'package:flutter_inappwebview_internal_annotations/flutter_inappwebview_internal_annotations.dart';
import '../content_blocker.dart';
part 'content_blocker_trigger_load_context.g.dart';
///Class that represents the kind of load context that can be used with a [ContentBlockerTrigger].
@ExchangeableEnum()
class ContentBlockerTriggerLoadContext_ {
// ignore: unused_field
final String _value;
const ContentBlockerTriggerLoadContext_._internal(this._value);
///Top frame load context
static const TOP_FRAME =
const ContentBlockerTriggerLoadContext_._internal('top-frame');
///Child frame load context
static const CHILD_FRAME =
const ContentBlockerTriggerLoadContext_._internal('child-frame');
}

View File

@ -0,0 +1,76 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'content_blocker_trigger_load_context.dart';
// **************************************************************************
// ExchangeableEnumGenerator
// **************************************************************************
///Class that represents the kind of load context that can be used with a [ContentBlockerTrigger].
class ContentBlockerTriggerLoadContext {
final String _value;
final String _nativeValue;
const ContentBlockerTriggerLoadContext._internal(
this._value, this._nativeValue);
// ignore: unused_element
factory ContentBlockerTriggerLoadContext._internalMultiPlatform(
String value, Function nativeValue) =>
ContentBlockerTriggerLoadContext._internal(value, nativeValue());
///Top frame load context
static const TOP_FRAME =
ContentBlockerTriggerLoadContext._internal('top-frame', 'top-frame');
///Child frame load context
static const CHILD_FRAME =
ContentBlockerTriggerLoadContext._internal('child-frame', 'child-frame');
///Set of all values of [ContentBlockerTriggerLoadContext].
static final Set<ContentBlockerTriggerLoadContext> values = [
ContentBlockerTriggerLoadContext.TOP_FRAME,
ContentBlockerTriggerLoadContext.CHILD_FRAME,
].toSet();
///Gets a possible [ContentBlockerTriggerLoadContext] instance from [String] value.
static ContentBlockerTriggerLoadContext? fromValue(String? value) {
if (value != null) {
try {
return ContentBlockerTriggerLoadContext.values
.firstWhere((element) => element.toValue() == value);
} catch (e) {
return null;
}
}
return null;
}
///Gets a possible [ContentBlockerTriggerLoadContext] instance from a native value.
static ContentBlockerTriggerLoadContext? fromNativeValue(String? value) {
if (value != null) {
try {
return ContentBlockerTriggerLoadContext.values
.firstWhere((element) => element.toNativeValue() == value);
} catch (e) {
return null;
}
}
return null;
}
///Gets [String] value.
String toValue() => _value;
///Gets [String] native value.
String toNativeValue() => _nativeValue;
@override
int get hashCode => _value.hashCode;
@override
bool operator ==(value) => value == _value;
@override
String toString() {
return _value;
}
}

View File

@ -162,4 +162,5 @@ export 'webview_render_process_action.dart' show WebViewRenderProcessAction;
export 'window_features.dart' show WindowFeatures, IOSWKWindowFeatures; export 'window_features.dart' show WindowFeatures, IOSWKWindowFeatures;
export 'requested_with_header_mode.dart' show RequestedWithHeaderMode; export 'requested_with_header_mode.dart' show RequestedWithHeaderMode;
export 'find_session.dart' show FindSession; export 'find_session.dart' show FindSession;
export 'search_result_display_style.dart' show SearchResultDisplayStyle; export 'search_result_display_style.dart' show SearchResultDisplayStyle;
export 'content_blocker_trigger_load_context.dart' show ContentBlockerTriggerLoadContext;