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 `WebViewFeature.DOCUMENT_START_SCRIPT` Android feature support
- Added `getRequestedWithHeaderMode`, `setRequestedWithHeaderMode` ServiceWorkerController methods
- Added `ContentBlockerTrigger.ifFrameUrl` and `ContentBlockerTrigger.loadContext` properties
- Updated `getMetaThemeColor` on iOS 15.0+
- Deprecated `onLoadError` for `onReceivedError`. `onReceivedError` 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(
key: webViewKey,
initialUrlRequest:
URLRequest(url: Uri.parse('https://developer.apple.com/videos/play/wwdc2022/10049/?time=264')),
URLRequest(url: Uri.parse('https://github.com/flutter')),
// initialUrlRequest:
// URLRequest(url: Uri.parse(Uri.base.toString().replaceFirst("/#/", "/") + 'page.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.
class ContentBlockerTrigger {
///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.
late bool urlFilterIsCaseSensitive;
///A list of regular expressions to match iframes URL against.
///
///*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.
///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.
///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.
///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.
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.
///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.
///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(
{required String urlFilter,
bool urlFilterIsCaseSensitive = false,
List<ContentBlockerTriggerResourceType> resourceType = const [],
List<String> ifDomain = const [],
List<String> unlessDomain = const [],
List<ContentBlockerTriggerLoadType> loadType = const [],
List<String> ifTopUrl = const [],
List<String> unlessTopUrl = const []}) {
this.urlFilter = urlFilter;
this.resourceType = resourceType;
this.urlFilterIsCaseSensitive = urlFilterIsCaseSensitive;
this.ifDomain = ifDomain;
this.unlessDomain = unlessDomain;
{required this.urlFilter,
this.ifFrameUrl = const <String>[],
this.urlFilterIsCaseSensitive = false,
this.resourceType = const <ContentBlockerTriggerResourceType>[],
this.ifDomain = const <String>[],
this.unlessDomain = const <String>[],
this.loadType = const <ContentBlockerTriggerLoadType>[],
this.ifTopUrl = const <String>[],
this.unlessTopUrl = const <String>[],
this.loadContext = const <ContentBlockerTriggerLoadContext>[]}) {
assert(!(this.ifDomain.isEmpty || this.unlessDomain.isEmpty) == false);
this.loadType = loadType;
assert(this.loadType.length <= 2);
this.ifTopUrl = ifTopUrl;
this.unlessTopUrl = unlessTopUrl;
assert(!(this.ifTopUrl.isEmpty || this.unlessTopUrl.isEmpty) == false);
}
@ -94,16 +100,22 @@ class ContentBlockerTrigger {
loadType.forEach((type) {
loadTypeStringList.add(type.toNativeValue());
});
List<String> loadContextStringList = [];
loadContext.forEach((type) {
loadContextStringList.add(type.toNativeValue());
});
Map<String, dynamic> map = {
"url-filter": urlFilter,
"if-frame-url": ifFrameUrl,
"url-filter-is-case-sensitive": urlFilterIsCaseSensitive,
"if-domain": ifDomain,
"unless-domain": unlessDomain,
"resource-type": resourceTypeStringList,
"load-type": loadTypeStringList,
"if-top-url": ifTopUrl,
"unless-top-url": unlessTopUrl
"unless-top-url": unlessTopUrl,
"load-context": loadContextStringList
};
map.keys
@ -119,6 +131,7 @@ class ContentBlockerTrigger {
static ContentBlockerTrigger fromMap(Map<String, dynamic> map) {
List<ContentBlockerTriggerResourceType> resourceType = [];
List<ContentBlockerTriggerLoadType> loadType = [];
List<ContentBlockerTriggerLoadContext> loadContext = [];
List<String> resourceTypeStringList =
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(
urlFilter: map["url-filter"],
ifFrameUrl: map["if-frame-url"],
urlFilterIsCaseSensitive: map["url-filter-is-case-sensitive"],
ifDomain: List<String>.from(map["if-domain"] ?? []),
unlessDomain: List<String>.from(map["unless-domain"] ?? []),
resourceType: resourceType,
loadType: loadType,
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.
class ContentBlockerAction {
///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.
///It specify a string that defines a selector list. Use CSS identifiers as the individual selector values, separated by commas.
String? selector;
ContentBlockerAction(
{required ContentBlockerActionType type, String? selector}) {
this.type = type;
{required this.type, this.selector}) {
if (this.type == ContentBlockerActionType.CSS_DISPLAY_NONE) {
assert(selector != null);
assert(this.selector != null);
}
this.selector = selector;
}
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 'requested_with_header_mode.dart' show RequestedWithHeaderMode;
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;