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

feat(plugin-adblocker): Add cooperative intercept mode support #592

Merged

Conversation

FdezRomero
Copy link
Contributor

@FdezRomero FdezRomero commented Nov 23, 2021

Adds support for the new Cooperative Intercept Mode available in Puppeteer v11+ and defining a custom interceptResolutionPriority for the following plugins:

  • puppeteer-extra-plugin-block-resources
  • puppeteer-extra-plugin-block-adblocker

This change checks that the required interception functions are available, so it's backwards compatible with the Legacy Mode and previous Puppeteer versions.

The @cliqz/adblocker-puppeteer dependency already included support for Cooperative Mode in v1.23.0.

Fixes #364, #156

@github-actions github-actions bot added the plugin: puppeteer-extra PuppeteerExtra Plugin related label Nov 23, 2021
@FdezRomero
Copy link
Contributor Author

@benallfree I implemented your suggestions and fixes. I also included a TypeScript definition that I was using on my client app 😉 Let me know if you find something else.

currentPriority
})

if (alreadyHandled) return

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I missed this the first time. Can you walk me through the intent? In cooperative mode, the Puppeteer core will run all handlers and resolve the intercept to the one with the highest priority. Unless you have a special case, your handler should simply do its computation and respond at whatever priority it is set to. If a different response at a higher priority takes place, it will prevail and yours will “lose”. If yours is the highest priority response, it will “win”

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@benallfree The problem is that if you use a plugin (or any other interceptor) that hasn't been migrated to Cooperative Mode and still uses Legacy Mode, the request is handled right away.

So if we call to continue/abort/respond etc. then we get the Request is already handled! error again (I just tried it again to verify). That's why we need this condition here, because we can't asume all plugins are opting-in to the new mode.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh that’s very smart, I think I’ll suggest this pattern in the official docs! Well done.

currentPriority
})

if (alreadyHandled) return

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh that’s very smart, I think I’ll suggest this pattern in the official docs! Well done.

@FdezRomero
Copy link
Contributor Author

@benallfree Glad to hear that! It seems that this PR needs a second approval. Do you know who can help with that? Thanks!

@benallfree
Copy link

benallfree commented Nov 24, 2021

@FdezRomero I'm not a maintainer of this package so I'm not sure how to help with a 2nd approval.

By the way, I just submitted puppeteer/puppeteer#7796 based on your work here. It fixes that spelling mistake and officially exposes isInterceptResolutionHandled() logic. You might consider waiting on this merge until we know whether the Puppeteer team will accept my PR.

@benallfree
Copy link

@FdezRomero Small note, cooperative support came in 10.2 https://github.com/puppeteer/puppeteer/blob/v11.0.0/CHANGELOG.md#1020-2021-08-04

@FdezRomero
Copy link
Contributor Author

@benallfree Ah nice! I changed the comment, and will wait for the API improvements in Puppeteer 👍🏻

We will have to update the API in @cliqz/adblocker-puppeteer as well so it doesn't break.

@FdezRomero FdezRomero marked this pull request as draft November 25, 2021 15:00
@benallfree
Copy link

@FdezRomero What will break? #7796 does not introduce breaking changes, or it’s not supposed to :)

@FdezRomero
Copy link
Contributor Author

FdezRomero commented Nov 26, 2021

You're right @benallfree, @cliqz/adblocker-puppeteer isn't using the interceptResolution() method to check if the request has been already handled or not, so it won't be affected by the rename to interceptResolutionState() 👍🏻

I moved this PR back to draft and will apply the changes once puppeteer/puppeteer#7796 ships. Hopefully it gets reviewed soon!.

@benallfree
Copy link

@FdezRomero puppeteer/puppeteer#7796 has been accepted by the Puppeteer team 👍

@FdezRomero
Copy link
Contributor Author

@benallfree Great! I'll update the PR with the new API 👍🏻
Any idea when a new version might be released?

@benallfree
Copy link

@FdezRomero No idea 😅

@github-actions github-actions bot added the package: core Affecting a core package label Dec 10, 2021
@FdezRomero FdezRomero marked this pull request as ready for review December 10, 2021 19:45
@FdezRomero
Copy link
Contributor Author

Hi @benallfree, I have updated adblocker-puppeteer to the latest version with the fixes and upgraded the code to your newer Puppeteer API, which also made the code easier to read. Would you mind giving it another look? Thanks! 🙏🏻

Copy link

@benallfree benallfree left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm w optional suggestions 👍

puppeteer.use(AdblockerPlugin())
puppeteer.use(AdblockerPlugin({
// Optionally enable Cooperative Mode for several request interceptors
interceptResolutionPriority: 0

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Safer as DEFAULT_INTERCEPT_RESOLUTION_PRIORITY , but I'm not sure if they export it. If not, that's a fix for me :D

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's exported. I changed it in all examples 👍🏻

const blockResourcesPlugin = require('puppeteer-extra-plugin-block-resources')()
const blockResourcesPlugin = require('puppeteer-extra-plugin-block-resources')({
// Optionally enable Cooperative Mode for several request interceptors
interceptResolutionPriority: 0

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same note

if (alreadyHandled) return

if (shouldBlock) {
const abortArgs = request.continueRequestOverrides

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you using continueRequestOverrides purely for version detection? If so, it might make more sense to use abortErrorReason since this is an abort() call.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know about this method, thanks! I changed it for the feature detection 👍🏻

* Sets the request interception priority on the `PuppeteerBlocker` instance.
*/
private setRequestInterceptionPriority(): void {
this.blocker?.setRequestInterceptionPriority(this.opts.interceptResolutionPriority)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not familiar enough with the lib to know if this is correct, it seems to be passing it down a layer?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@benallfree Yes exactly, it references the instance of adblocker-puppeteer that is used internally, which is the one that really intercepts and handles the requests, and this pupeteer-extra plugin acts as a wrapper: https://github.com/ghostery/adblocker/blob/master/packages/adblocker-puppeteer/adblocker.ts#L282-L283

@FdezRomero
Copy link
Contributor Author

I think it's good to go! Let's see if it can get a bit of love from the maintainers 🤞🏻😄 @berstend

@FdezRomero
Copy link
Contributor Author

Happy new year @berstend! 🎉

How can we get a second review to get this merged? We already made the necessary changes upstream in Puppeteer and Adblocker to support Cooperative Intercept mode in puppeteer-extra 😉

Thanks!

@deldrid1
Copy link

@berstend - Any chance this can be reviewed? This is a critical feature I need!

@benallfree
Copy link

@deldrid1 @berstend You both might consider running your own fork for a while, it seems the maintainer is busy on other things.

@berstend
Copy link
Owner

Thanks! LGTM

@berstend berstend changed the title feat: add cooperative intercept mode support feat(plugin-adblocker): Add cooperative intercept mode support Jun 20, 2022
@berstend berstend merged commit c0daeda into berstend:master Jun 20, 2022
@berstend
Copy link
Owner

Successfully published:
 - puppeteer-extra-plugin-adblocker@2.13.0
 - puppeteer-extra-plugin-block-resources@2.4.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
package: core Affecting a core package plugin: puppeteer-extra PuppeteerExtra Plugin related
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Solving request interception chain
4 participants