Written by Lorenzo Pichilli
On this article, we’re going to discover ways to create a customized Content material Blocker for our WebView situations utilizing the flutter_inappwebview
plugin.
Content material Blockers are normally used for blocking advertisements, however you can too use them to dam some other content material. Blocking behaviors embody hiding parts, blocking masses, and, on iOS and macOS, stripping cookies from WebView requests.
Remember that, usually, Content material Blockers can not obtain the identical stage of performance as specialised extensions reminiscent of AdBlock or AdBlock Plus. Content material Blockers are a algorithm that by no means obtain any callbacks or notifications again from the WebView when it finds content material it wants to dam.
By way of the contentBlockers
property of the InAppWebViewSettings
class, we will outline an inventory of ContentBlocker
situations that the WebView will use.
The ContentBlocker class
We outline content-blocking conduct within the ContentBlocker
class. Each comprises an motion property and a set off property. The motion tells the WebView what to do when it encounters a match for the set off. The set off tells the WebView when to carry out the corresponding motion.
Here’s a primary instance:
initialSettings: InAppWebViewSettings(contentBlockers: [
ContentBlocker(
trigger: ContentBlockerTrigger(
urlFilter: ".*",
resourceType: [
ContentBlockerTriggerResourceType.IMAGE,
ContentBlockerTriggerResourceType.STYLE_SHEET
]
),
motion: ContentBlockerAction(
kind: ContentBlockerActionType.BLOCK
)
)
]),
On this instance, the ContentBlocker blocks the loading of each picture and stylesheet for each URL.
Add triggers to your Content material Blocker
A set off should outline the required urlFilter
property, which specifies a daily expression as a string to match the URL towards. The opposite properties are optionally available — they modify the conduct of the set off. For instance, you possibly can restrict the set off to particular domains or have it not apply when the WebView finds a match for a selected area.
Right here is an instance of a Content material Blocker with a set off for picture and elegance sheet sources that the WebView finds on any area besides these specified:
initialSettings: InAppWebViewSettings(contentBlockers: [
ContentBlocker(
trigger: ContentBlockerTrigger(
urlFilter: ".*",
resourceType: [
ContentBlockerTriggerResourceType.IMAGE,
ContentBlockerTriggerResourceType.STYLE_SHEET
],
unlessDomain: ["example.com", "github.com", "pub.dev"]
),
motion: ContentBlockerAction(
kind: ContentBlockerActionType.BLOCK
)
)
]),
For deeper set off customization, you should use the opposite properties of ContentBlockerTrigger
:
-
urlFilterIsCaseSensitive
: If the URL matching needs to be case-sensitive. By default, it’s case insensitive. -
resourceType
: A listing of “ContentBlockerTriggerResourceType” representing the useful resource sorts (how the browser intends to make use of the useful resource) that the rule ought to match. If it isn’t specified, the rule matches all useful resource sorts. -
ifDomain
: A listing of strings matched to a URL’s area; it limits motion to an inventory of particular domains. Values have to be lowercase ASCII or Punycode for non-ASCII characters. Add*
in entrance to match the area and subdomains. It will possibly’t be used withunlessDomain
. -
unlessDomain
: A listing of strings matched to a URL’s area; acts on any web site besides domains in a supplied listing. Values have to be lowercase ASCII or Punycode for non-ASCII. Add*
in entrance to match the area and subdomains. It will possibly’t be used withifDomain
. -
loadType
: A listing ofContentBlockerTriggerLoadType
that may embody certainly one of two mutually unique values. If not specified, the rule matches all load sorts.ContentBlockerTriggerLoadType.FIRST_PARTY
triggers provided that the useful resource has the identical scheme, area, and port as the principle web page useful resource.ContentBlockerTriggerLoadType.THIRD_PARTY
triggers if the useful resource isn’t from the identical area as the principle web page useful resource. -
ifTopUrl
: A listing of strings matched to all the essential doc URL; it limits the motion to a selected listing of URL patterns. Values have to be lowercase ASCII or Punycode for non-ASCII characters. It will possibly’t be used withunlessTopUrl
. -
unlessTopUrl
: An array of strings matched to all the essential doc URL; it acts on any web site besides URL patterns within the supplied listing. Values have to be lowercase ASCII or Punycode for non-ASCII characters. It will possibly’t be used withifTopUrl
. -
loadContext
: An array of strings that specify loading contexts. -
ifFrameUrl
: A listing of standard expressions to match iframes’ URL towards.
Test the code documentation for every particular property to search out out which platform helps that characteristic.
Add actions to your Content material Blocker
When a set off matches a useful resource, the WebView evaluates all of the triggers and executes the actions so as.
Group the foundations with comparable actions collectively to enhance efficiency. For instance, first specify guidelines that block content material loading adopted by guidelines that block cookies.
There are solely two legitimate properties for actions: kind
and selector
. An motion kind is required.
If the kind is ContentBlockerActionType.CSS_DISPLAY_NONE
, a selector
is required as properly; in any other case, the selector
is optionally available.
Right here is an easy instance:
initialSettings: InAppWebViewSettings(contentBlockers: [
ContentBlocker(
trigger: ContentBlockerTrigger(
urlFilter: "https://flutter.dev/.*",
),
action: ContentBlockerAction(
type: ContentBlockerActionType.CSS_DISPLAY_NONE,
selector: '.notification, .media, #developer-story'
)
)
]),
Legitimate sorts are:
-
BLOCK
: Stops the loading of the useful resource. If the useful resource was cached, the cache is ignored. -
BLOCK_COOKIES
: Strips cookies from the header earlier than sending it to the server. This solely blocks cookies which might be in any other case acceptable to WebView’s privateness coverage. CombiningBLOCK_COOKIES
withIGNORE_PREVIOUS_RULES
doesn’t override the browser’s privateness settings. -
CSS_DISPLAY_NONE
: Hides parts of the web page primarily based on a CSS selector. A selector discipline comprises the selector listing. Any matching factor has its show property set to none, which hides it. -
MAKE_HTTPS
: Modifications a URL fromhttp
tohttps
. URLs with a specified (nondefault) port and hyperlinks utilizing different protocols are unaffected. -
IGNORE_PREVIOUS_RULES
: Ignores beforehand triggered actions.
Test the code documentation for every particular kind to search out out which platform helps it.
Making a easy advert blocker
Let’s create a easy advert blocker utilizing what we’ve realized.
import 'package deal:flutter/basis.dart';
import 'package deal:flutter/materials.dart';
import 'package deal:flutter_inappwebview/flutter_inappwebview.dart';
Future essential() async {
WidgetsFlutterBinding.ensureInitialized();
if (!kIsWeb &&
kDebugMode &&
defaultTargetPlatform == TargetPlatform.android) {
await InAppWebViewController.setWebContentsDebuggingEnabled(kDebugMode);
}
runApp(const MaterialApp(residence: MyApp()));
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : tremendous(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
closing GlobalKey webViewKey = GlobalKey();
// listing of advert URL filters for use to dam advertisements from loading
closing adUrlFilters = [
".*.doubleclick.net/.*",
".*.ads.pubmatic.com/.*",
".*.googlesyndication.com/.*",
".*.google-analytics.com/.*",
".*.adservice.google.*/.*",
".*.adbrite.com/.*",
".*.exponential.com/.*",
".*.quantserve.com/.*",
".*.scorecardresearch.com/.*",
".*.zedo.com/.*",
".*.adsafeprotected.com/.*",
".*.teads.tv/.*",
".*.outbrain.com/.*"
];
closing Record<ContentBlocker> contentBlockers = [];
var contentBlockerEnabled = true;
InAppWebViewController? webViewController;
@override
void initState() {
tremendous.initState();
// for every advert URL filter, add a Content material Blocker to dam its loading
for (closing adUrlFilter in adUrlFilters) {
contentBlockers.add(ContentBlocker(
set off: ContentBlockerTrigger(
urlFilter: adUrlFilter,
),
motion: ContentBlockerAction(
kind: ContentBlockerActionType.BLOCK,
)));
}
// apply the "show: none" model to some HTML parts
contentBlockers.add(ContentBlocker(
set off: ContentBlockerTrigger(
urlFilter: ".*",
),
motion: ContentBlockerAction(
kind: ContentBlockerActionType.CSS_DISPLAY_NONE,
selector: ".banner, .banners, .advertisements, .advert, .advert")));
}
@override
Widget construct(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Textual content("Adverts Content material Blocker"),
actions: [
TextButton(
onPressed: () async {
contentBlockerEnabled = !contentBlockerEnabled;
if (contentBlockerEnabled) {
await webViewController?.setSettings(
settings: InAppWebViewSettings(
contentBlockers: contentBlockers));
} else {
await webViewController?.setSettings(
settings: InAppWebViewSettings(contentBlockers: []));
}
webViewController?.reload();
setState(() {});
},
model: TextButton.styleFrom(foregroundColor: Colours.white),
youngster: Textual content(contentBlockerEnabled ? 'Disable' : 'Allow'),
)
],
),
physique: SafeArea(
youngster: Column(kids: <Widget>[
Expanded(
child: Stack(
children: [
InAppWebView(
key: webViewKey,
initialUrlRequest:
URLRequest(url: WebUri('https://www.tomshardware.com/')),
initialSettings:
InAppWebViewSettings(contentBlockers: contentBlockers),
onWebViewCreated: (controller) {
webViewController = controller;
},
),
],
),
),
])));
}
}
Utilizing these guidelines will stop a bunch of advertisements from showing, reminiscent of Google Adverts.
Click on the Disable/Allow button to disable or allow the advert blocker characteristic.

Conclusion
Content material Blockers permit us to jot down performant guidelines for blocking content material within the WebView whereas respecting the person’s privateness.
Full challenge code is accessible on GitHub.
That’s all for in the present day!
Are you utilizing this plugin? Submit your app via the Submit Utility web page and comply with the directions.
Test the Showcase web page to see who’s already utilizing it!
This challenge follows the all-contributors specification (contributors). I need to thank all of the people who find themselves supporting the challenge in any method. Thanks so much to all of you! 💙
.
Lorenzo Pichilli is a Heroku structure designer and software program engineer who principally focuses on full-stack net and cell improvement. He’s a JavaScript, TypeScript, and Flutter fanatic who loves open supply. (You’ll be able to take a look at his initiatives on GitHub.) He additionally writes articles on Medium.