added ContentBlockerTrigger.ifFrameUrl and ContentBlockerTrigger.loadContext properties
This commit is contained in:
parent
d2e5c8dc87
commit
85ff4c1234
|
@ -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
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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');
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
Loading…
Reference in New Issue