DEV Community

Cover image for The advertising filtering function of Web components
liu yang
liu yang

Posted on

The advertising filtering function of Web components

Ad Blocking with ArkWeb in HarmonyOS Next

Overview

ArkWeb provides an ad-blocking feature for applications, supporting both cloud-pushed default easylist rules and custom rule files set via interfaces. It intercepts ad resource downloads at the network layer or injects CSS rules into web pages to hide specific ad elements.

Easylist Syntax Rules

The current configuration file format follows easylist syntax rules. Here are some commonly used easylist syntax rules:

Rule Category Description Example
URL Interception Rule Blocks subresource requests where the URL matches "example.com/js/*_tv.js" across all websites. Used for defining domain filtering rules to match specific domains and all their subdomains. `
URL Interception Rule Blocks third-party resources where the URL matches "alimama.cn" on websites not belonging to alimama.com or taobao.com. {% raw %}$third_party is an options syntax indicating a match for third-party resources; using ~ before a domain name excludes that domain. `
Exception Rule Disables ad blocking on the example.com webpage. {% raw %}@@ is the syntax keyword for exception rules, indicating no filtering. `@@
Exception Rule On web pages with the domain litv.tv, does not filter subresources matching ".adserver.". {% raw %}@@.adserver.$domain=litv.tv
Element Hiding Rule Hides elements with class="i528" on domains myabandonware.com and myware.com. ## is used to indicate element hiding. myabandonware.com, myware.com##.i528
Element Hiding Exception Rule Does not hide elements with id="ad_1" on the sdf-event.sakura.ne.jp website. sdf-event.sakura.ne.jp#@##ad_1

Exception rules are typically used in conjunction with regular rules to disable regular rules in specific scenarios. Using exception rules alone does not make sense.

Constraints and Limitations

  • The WebviewController class includes the enableAdsBlock() interface to enable/disable the ad-blocking feature at the Web instance level.
  • A new AdsBlockManager global singleton class is introduced, providing capabilities for custom ad-blocking configurations and controlling site-level feature switches.
  • The Web instance offers the onAdsBlocked() callback notification method to inform the upper-layer application of interception information.
  • The AdsBlockManager interface's setAdsBlockRules() can only set one custom configuration, which will be persisted. There is no need to reconfigure on cold start, avoiding the recompilation and parsing of ad-blocking configurations on each cold start.
  • Data operated by AdsBlockManager interfaces such as addAdsBlockDisallowedList(), removeAdsBlockDisallowedList(), clearAdsBlockDisallowedList(), addAdsBlockAllowedList(), removeAdsBlockAllowedList(), and clearAdsBlockAllowedList() will not be persisted and need to be reset on cold start.
  • If a Web instance enables the ad-blocking feature but does not call AdsBlockManager interfaces to configure disallowlist and allowlist data, ad blocking will be enabled for all websites by default.
  • When allowlist and disallowlist data are used together, the allowlist has higher priority than the disallowlist. If a match is found in the allowlist, the disallowlist will not be used, and ad blocking will be enabled for that website.
  • If the application does not enable the ad-blocking feature, ensure that the Web component does not request the default built-in easylist configuration file from the server.
  • Disallowlist and allowlist data use suffix matching. For example, if the application sets the domain "xxyy.com", it can match the website with the URL "wwsstt.xxyy.com".

Use Cases

Enabling Ad Blocking

Applications can use the setAdsBlockRules() interface provided by AdsBlockManager to set custom easylist filtering rules and enable the ad-blocking feature via the enableAdsBlock() interface of the Web component.

In the following example, an application selects an easylist rule file using a file picker and enables the ad-blocking feature.

// xxx.ets
import { webview } from '@kit.ArkWeb';
import { picker, fileUri } from '@kit.CoreFileKit';

// Demonstrate clicking a button to open an easylist rule file via filepicker and set it in the Web component
@Entry
@Component
struct WebComponent {
  main_url: string = 'https://www.example.com';
  controller: webview.WebviewController = new webview.WebviewController();

  @State input_text: string = 'https://www.example.com';

  build() {
    Column() {
      Row() {
        Flex() {
          Button({type: ButtonType.Capsule}) {
            Text("setAdsBlockRules")
          }
          .onClick(() => {
            try {
              let documentSelectionOptions: ESObject = new picker.DocumentSelectOptions();
              let documentPicker: ESObject = new picker.DocumentViewPicker();
              documentPicker.select(documentSelectionOptions).then((documentSelectResult: ESObject) => {
                if (documentSelectResult && documentSelectResult.length > 0) {
                  let fileRealPath = new fileUri.FileUri(documentSelectResult[0]);
                  console.info('DocumentViewPicker.select successfully, uri: ' + fileRealPath);
                  webview.AdsBlockManager.setAdsBlockRules(fileRealPath.path, true);
                }
              })
            } catch (err) {
              console.error('DocumentViewPicker.select failed with err:' + err);
            }
          })
        }
      }
      Web({ src: this.main_url, controller: this.controller })
        .onControllerAttached(() => {
          this.controller.enableAdsBlock(true);
        })
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

If there is a built-in easylist rule file, the replace parameter of the setAdsBlockRules() interface can be used to set the rule file usage strategy. replace=true indicates not using the built-in easylist rule file, while replace=false means custom rules and built-in rules will work simultaneously. If there is a conflict between built-in and custom rules, use replace=true to disable the built-in rule effect.

The custom rule file set will take effect for all Web components within the application process, acting as a global application-level configuration file. It will be persisted and continue to work after application restarts.

Disabling Ad Blocking for Specific Domain Pages

After enabling the ad-blocking switch for the Web component, applications may sometimes want to disable ad blocking for specific pages. In addition to using custom easylist rules, AdsBlockManager also provides the addAdsBlockDisallowedList() interface to achieve this.

// xxx.ets
import { webview } from '@kit.ArkWeb';

// Demonstrate setting ad-blocking domain policy for the Web component via a button click
@Entry
@Component
struct WebComponent {
  main_url: string = 'https://www.example.com';
  text_input_controller: TextInputController = new TextInputController();
  controller: webview.WebviewController = new webview.WebviewController();

  @State input_text: string = 'https://www.example.com';

  build() {
    Column() {
      Row() {
        Flex() {
          TextInput({ text: this.input_text, placeholder: this.main_url, controller: this.text_input_controller })
            .id("input_url")
            .height(40)
            .margin(5)
            .borderColor(Color.Blue)
            .onChange((value: string) => {
              this.input_text = value;
            })

          Button({type: ButtonType.Capsule}) { Text("Go") }
          .onClick(() => {
            this.controller.loadUrl(this.input_text);
          })

          Button({type: ButtonType.Capsule}) { Text("addAdsBlockDisallowedList") }
          .onClick(() => {
            let arrDomainSuffixes = new Array<string>();
            arrDomainSuffixes.push('example.com');
            arrDomainSuffixes.push('abcdefg.cn');
            webview.AdsBlockManager.addAdsBlockDisallowedList(arrDomainSuffixes);
          })
        }
      }
      Web({ src: this.main_url, controller: this.controller })
        .onControllerAttached(() => {
          this.controller.enableAdsBlock(true);
        })
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)