-
Notifications
You must be signed in to change notification settings - Fork 1
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
Rewrite bookmarklet execution to use userScripts
in Manifest V3.
#85
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
anthonyec
force-pushed
the
manifest-v3
branch
2 times, most recently
from
May 24, 2024 18:57
996c724
to
17b356c
Compare
anthonyec
force-pushed
the
manifest-v3
branch
2 times, most recently
from
May 26, 2024 22:33
adf3781
to
1cd491d
Compare
anthonyec
changed the title
Manifest V3
Rewrite bookmarklet execution to use May 28, 2024
userScripts
in Manifest V3.
This was referenced Jul 10, 2024
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
In Manifest V3 (MV3), it's no longer possible to execute arbitrary code in a webpage. This is how Powerlet worked, it took a bookmarklet's code and injected it into the page.
The only way to execute arbitrary code in MV3 is by registering code using the
userScripts
API. This API is designed around running code when a page loads. You tell Chrome what code file or string you want to run and on what site.You have no control with this new API to execute scripts "on demand". They always run on page load. This of course is an issue for Powerlet which is all about running code on demand.
To get around, code is generated from a user's bookmarklets. This generated code wraps the bookmarklet within a function. For example, the following bookmarklet:
Will become registered code that looks a bit like this:
These registered user scripts are executed in the "main" world on page load. This means they are located on the global
window
object!When you tell Powerlet to execute a script, it essentially calls the function on the page. The equivalent of doing:
Of course, it's not that easy. There is a lot of bridging of events (see
content_isolated.js
) so that an action in the extension popup can invoke a function on the globalwindow
object.Also, since scripts are registered once and only available after a page reload, when you change a bookmarklet's contents, it needs to reload the page before it can execute. This is done by comparing a hash of the current bookmarklet to the previous. Hash functions are also stored on the page like so:
There are downsides to this approach. One of which is Chrome's popup blocker will stop any calls to
window.open
. This is because scripts are executed in the "main" world, they don't appear any different to Chrome than naughty script trying to open windows without the user's intent.I tried a few ways to proxy the
window
object and invoke my ownopen
function in an isolated world. However, this caused problems when bookmarklets try to use the opened window in their script. For example, this would not work:Some bookmarklets do this to show UI in a popup window. I didn't use the proxy solution, and instead let Chrome notify the user a window has been blocked. The user will have to unblock the window for the current site they are viewing and rerun the bookmarklet.
It's not ideal, but I'll see if there's a better way. Like maybe an option to run bookmarklets in an isolated world? Or an option enable the experimental window proxy?
The big benefit to scripts running in the "main" world is that now they have access to global variables. This fixes issues where people wanted to the existing jQuery on a page (#63 #61)
Also if the website allows it, scripts can now make network requests (#81)!
Anyway, I'm gonna follow up with other PRs that fix a few things. But I wanted to get this out before the June 1st deadline!