Reputation: 5663
Is it possible to inject JS before page load, or is it necessary to use content scripts and way for the document to finish?
For example, is there a faster way to execute JS that turns the page red as soon as it's opened?
Upvotes: 54
Views: 39662
Reputation: 3647
For Manifest V3 there was a new field added to content scripts in 102.0.5005.58 Stable: world
And there are also a lot of chrome bugs related to that topic: #634381, #1054624, #1207006
You have to use "world": "main"
at the content script together with "run_at": "document_start"
and a CSP to allow the injection from the Extension. Otherwise the injected script gets rejected with:
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' 'wasm-unsafe-eval'". Either the 'unsafe-inline' keyword, a hash ('sha256-*'), or a nonce ('nonce-...') is required to enable inline execution.
"world": "MAIN":
[Extensions] Add main world injections for dynamic content scripts
This CL adds a new field "world" for dynamic content scripts which allows the extension to specify if the script will run in the isolated or main world. By default, scripts which do not specify this field will run in the isolated world.
Valid attributes are "ISOLATED"
(default) or "MAIN"
.
Example files i used:
manifest.json
{
"name": "script injection",
"version": "0",
"manifest_version": 3,
"minimum_chrome_version": "103.0",
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["inject.js"],
"run_at": "document_start",
"world": "MAIN"
}
],
"web_accessible_resources": [{
"resources": ["injected.js"],
"matches": ["<all_urls>"]
}],
"content_security_policy": {
"extension_pages": "default-src 'self' 'wasm-unsafe-eval';"
}
}
inject.js
let el = document.createElement("script");
el.src = chrome.runtime.getURL("injected.js");
document.documentElement.appendChild(el);
console.log("injected");
injected.js
console.log(typeof alert); // "function"
console.log("injected file");
delete window.alert;
console.log(typeof alert); // "undefined"
[]
Upvotes: 12
Reputation: 348972
Declare a content script in the manifest file with "run_at": "document_start"
to get it to run as soon as possible, i.e. right after constructing the document root (when <head>
does not exist yet).
For your very specific example, it might be better to declare a content style instead, similar to content scripts, but using the "css"
key instead of "js"
.
If you want to dynamically run a script as soon as possible, then call chrome.tabs.executeScript
when the chrome.webNavigation.onCommitted
event is triggered.
Upvotes: 71