Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correct way to inject ad blocker in React Native WebView #3039

Open
Alwinator opened this issue Feb 1, 2023 · 4 comments
Open

Correct way to inject ad blocker in React Native WebView #3039

Alwinator opened this issue Feb 1, 2023 · 4 comments

Comments

@Alwinator
Copy link

Alwinator commented Feb 1, 2023

I am working on a react native app with a web view that should block ads. The web view offers a way to inject javascript code. What is the correct way to inject your ad blocker?

I tried around but found no solution. It could look similar to the code below:

<WebView
  source={{
    uri: 'https://website-with-ads.example.com',
  }}
  javaScriptEnabled={true}
  injectedJavaScript={`
    var my_script = document.createElement('script');
    my_script.setAttribute('src','https://cdn.jsdelivr.net/npm/@cliqz/adblocker-webextension/dist/adblocker.umd.min.js');
    document.head.appendChild(my_script);
`}
/>

Thanks for your support!

@Alwinator
Copy link
Author

Alwinator commented Feb 17, 2023

Update:
I have built a webpack bundler that automatically injects the javascript in the react native webview. I was able to inject the following script without errors:

import {FiltersEngine} from '@cliqz/adblocker';

FiltersEngine.fromPrebuiltAdsAndTracking(fetch).then(engine => {
  console.log(engine);
});

However, what is the next step? Where can I do the matching? I need something like an onScriptLoading event.

@remusao Any ideas?

@remusao
Copy link
Collaborator

remusao commented Feb 18, 2023

Hi @Alwinator,

Unfortunately I am not very familiar with the APIs available in React Native WebView. What you will need is a way to intercept network requests for pages loaded in the WebView, and then ask the adblocker engine which action to take (e.g. block, allow, redirect). If you can figure out which APIs can be used I can help with the next steps.

Best,

@Alwinator
Copy link
Author

@remusao Does it also work by injecting JavaScript? I am able to manipulate the DOM. I need some way to intercept network requests. (Completely independent from the ReactNative WebView)

Idea 1

I thought of overwriting the XMLHttpRequest.prototype.send, but this does not work for HTML script and iframe elements.

Idea 2

Another approach would be to get all scripts and iframes and check them, which also does not work fine.

function processElement(element) {
 // process element.src with engine
 // and then element.remove()
}
const observer = new MutationObserver((mutations, observer) => {
  for (const mutation of mutations) {
    for (const addedNode of mutation.addedNodes) {
      if (addedNode.tagName === 'SCRIPT' || addedNode.tagName === 'IFRAME') {
        processElement(addedNode);
      }
    }
  }
});
observer.observe(document.body, {childList: true, subtree: true});

document.addEventListener('DOMContentLoaded', () => {
  Array.from(document.getElementsByTagName('script')).forEach(processElement);
  Array.from(document.getElementsByTagName('iframe')).forEach(processElement);
});

Idea 3

Maybe a better approach would be to achieve it with a service worker as described here. I will try this approach in the next few days when I have time.

Do you think it is in general possible without a web browser extension?

@remusao
Copy link
Collaborator

remusao commented Feb 26, 2023

@Alwinator i like your Service Worker idea. If you control the website and are able to inject a service worker it should be possible to load the adblocker there and perform the blocking or ads from there. You would likely need to write some amount of boiler plate since the library does not have a nice abstraction for that.

@remusao remusao mentioned this issue Apr 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants