ghostery / adblocker

Efficient embeddable adblocker library
https://www.ghostery.com
Mozilla Public License 2.0
803 stars 101 forks source link

error in production #2571

Closed colining closed 2 years ago

colining commented 2 years ago

when I start as production version,there is an error message

TypeError: Error processing argument at index 0, conversion failure from 
    at Gr.enable (F:\workspace\ficket\release\win-unpacked\resources\app.asar\main.prod.js:2:195822)
    at qr.enableBlockingInSession (F:\workspace\ficket\release\win-unpacked\resources\app.asar\main.prod.js:2:207158)
    at F:\workspace\ficket\release\win-unpacked\resources\app.asar\main.prod.js:2:214041
    at l (F:\workspace\ficket\release\win-unpacked\resources\app.asar\main.prod.js:8:496876)
    at Generator._invoke (F:\workspace\ficket\release\win-unpacked\resources\app.asar\main.prod.js:8:496664)
    at Generator.next (F:\workspace\ficket\release\win-unpacked\resources\app.asar\main.prod.js:8:497301)
    at Qr (F:\workspace\ficket\release\win-unpacked\resources\app.asar\main.prod.js:2:211080)
    at o (F:\workspace\ficket\release\win-unpacked\resources\app.asar\main.prod.js:2:211284)
(node:12520) electron: The default of contextIsolation is deprecated and will be changing from false to true in a future release of Electron.  See https://github.com/electron/electron/issues/23506 for more information

I try write code like this

const blocker = ElectronBlocker.parse(
  fs.readFileSync(
    path.join(__dirname, '../assets', 'easylist-china.txt'),
    'utf-8'
  )
);
  mainWindow
    .loadURL(`file://${__dirname}/index.html`)
    .then(() => {
      return blocker.enableBlockingInSession(mainWindow!.webContents.session);
    })
    .catch((e) => console.log(e));

It's will start normally with the error message

remusao commented 2 years ago

Hi @colining,

Is the ! in return blocker.enableBlockingInSession(mainWindow!.webContents.session); intended? (after mainWindow).

Best,

danline commented 2 years ago

Hi, I am also getting this error in production. It works great in dev build and the error happens only in production build. Here is the code I am using:

let adBlocker = await ElectronBlocker.fromPrebuiltAdsOnly(fetch)
adBlocker.enableBlockingInSession(session)
remusao commented 2 years ago

Can you please provide a minimal reproduction code with associated version of Electron where this happens?

danline commented 2 years ago

I am using Electron version 18.1.0. As for the reproducible code, I am not doing anything fancy. Just followed the sample code in the README for this project. I am using this in a BrowserView (which has the same webContents as BrowserWindow) so I get the session info like

session = [BrowserView instance].webContents.session
remusao commented 2 years ago

It might not be anything fancy but it is likely different enough from the example to highlight a new issue. I could not reproduce using the example contained in this repository (after fixing some small issues with the script: https://github.com/ghostery/adblocker/pull/2572). Could you maybe give it a shot and see what might be different in your project? It would likely be useful to understand the root of the issue.

danline commented 2 years ago

Thanks for the quick response @remusao! I was able to figure out the issue given that you said your example worked. I was actually using the code from the README and not the one from adblock-electron-example/index.ts. This made me initially use something like

let adBlocker = await ElectronBlocker.fromPrebuiltAdsOnly(fetch)
adBlocker.enableBlockingInSession(session)

The above code was causing the following error in production build:

TypeError: Error processing argument at index 0, conversion failure from
    at Lr.enable (/Applications/project.app/Contents/Resources/app.asar/background.js:2:1439108)
    at en.constructor.enableBlockingInSession (/Applications/project.app/Content

However, after digging deeper, I realized the above code was using the default config loadCosmeticFilters. This flag actually triggered a preload code when enabling the ad blocker within the library

    enable() {
        if (this.blocker.config.loadCosmeticFilters === true) {
            this.session.setPreloads(this.session.getPreloads().concat([PRELOAD_PATH]));
            ipcMain.on('get-cosmetic-filters', this.onGetCosmeticFilters);
            ipcMain.on('is-mutation-observer-enabled', this.onIsMutationObserverEnabled);
        }
        if (this.blocker.config.loadNetworkFilters === true) {
            this.session.webRequest.onHeadersReceived({ urls: ['<all_urls>'] }, this.onHeadersReceived);
            this.session.webRequest.onBeforeRequest({ urls: ['<all_urls>'] }, this.onBeforeRequest);
        }
    }

I figured the problem may be with the preload code because many projects may use different ways to implement Electron preloads in production. For example, the project I am working on uses Vue CLI Plugin Electron Builder which has its own way to do preloads.

So I tried using your code from the example which allows to set the config flags. Here is the code that works:

import { ElectronBlocker, adsAndTrackingLists } from '@cliqz/adblocker-electron';
import fetch from 'cross-fetch'; // required 'fetch'

const adBlocker = await ElectronBlocker.fromLists(
    fetch,
    adsAndTrackingLists,
    {
        loadCosmeticFilters: false
    }
);

adBlocker.enableBlockingInSession(session)
colining commented 2 years ago

Thanks for the quick response @remusao! I was able to figure out the issue given that you said your example worked. I was actually using the code from the README and not the one from adblock-electron-example/index.ts. This made me initially use something like

let adBlocker = await ElectronBlocker.fromPrebuiltAdsOnly(fetch)
adBlocker.enableBlockingInSession(session)

The above code was causing the following error in production build:

TypeError: Error processing argument at index 0, conversion failure from
    at Lr.enable (/Applications/project.app/Contents/Resources/app.asar/background.js:2:1439108)
    at en.constructor.enableBlockingInSession (/Applications/project.app/Content

However, after digging deeper, I realized the above code was using the default config loadCosmeticFilters. This flag actually triggered a preload code when enabling the ad blocker within the library

    enable() {
        if (this.blocker.config.loadCosmeticFilters === true) {
            this.session.setPreloads(this.session.getPreloads().concat([PRELOAD_PATH]));
            ipcMain.on('get-cosmetic-filters', this.onGetCosmeticFilters);
            ipcMain.on('is-mutation-observer-enabled', this.onIsMutationObserverEnabled);
        }
        if (this.blocker.config.loadNetworkFilters === true) {
            this.session.webRequest.onHeadersReceived({ urls: ['<all_urls>'] }, this.onHeadersReceived);
            this.session.webRequest.onBeforeRequest({ urls: ['<all_urls>'] }, this.onBeforeRequest);
        }
    }

I figured the problem may be with the preload code because many projects may use different ways to implement Electron preloads in production. For example, the project I am working on uses Vue CLI Plugin Electron Builder which has its own way to do preloads.

So I tried using your code from the example which allows to set the config flags. Here is the code that works:

import { ElectronBlocker, adsAndTrackingLists } from '@cliqz/adblocker-electron';
import fetch from 'cross-fetch'; // required 'fetch'

const adBlocker = await ElectronBlocker.fromLists(
    fetch,
    adsAndTrackingLists,
    {
        loadCosmeticFilters: false
    }
);

adBlocker.enableBlockingInSession(session)

super cool ,It's work!!!

maybe more exmple && explain for this lib @remusao

Thanks a lot

danline commented 2 years ago

@colining- just one caveat with the approach discussed here. The adblocker works for all other cases but youtube in-video ads don't work because it sets loadCosmeticFilters = false

See https://github.com/ghostery/adblocker/issues/2574