Manifest V3 Migration and Main World Script Injection

2,357 views
Skip to first unread message

tweak support

unread,
May 2, 2021, 5:56:11 AM5/2/21
to Chromium Extensions
Hello team,

We would like to clarify something around content scripts/script injection and migration to Manifest v3.

Our extension is highly dependent on the script injection timing. We want to inject a script into the page before anything else loads.

With Manifest V2 we were achieving this by:
1. Having a content script to load at "document_start".
2. In the content script we inject a script to run on the main world, as follows
```
const scriptString = 'function runAtStart () { console.log('our code...'); }';
const script = document.createElement('script'); script.appendChild(document.createTextNode(scriptString));
(document.body || document.head || document.documentElement).appendChild(script);
```

We are aware that this is no longer possible with Manifest V3 as it violates the new CSP.
(We get the following: Uncaught EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self'".)

We've noticed that with Manifest V3 however is possible to refactor into the following strategy:
1. Having a content script to load at "document_start" (as in Manifest V2, no change here)
2. Move our "string of javascript" to a separate file (let's call it runAtStart.js)
3. Declare the new script in the web_accessible_resources
```
"web_accessible_resources": [
  {
    "resources": ["runAtStart.js"],
    "matches": ["<all_urls>"],
    "use_dynamic_url": true
  }
]
```
4. In our content script we create a dynamic script to inject runAtStart.js
```
const s = document.createElement('script');
s.setAttribute('src', 'chrome-extension://<id_of_the_extension>/runAtStart.js');
document.documentElement.appendChild(s);
```

Is this a future proof implementation? Would this be rejected upon review? Or will this capability be restricted in further iterations of the Manifest V3? If this is the way to go now, should I advocate for this strategy?

Thank you!

Jackie Han

unread,
May 2, 2021, 6:26:49 AM5/2/21
to tweak support, Chromium Extensions
The point of your approach is to run the script in the "main world", not in "isolated worlds".
That is Ok. MV3 restricts dynamic script(string as js) and remote script, don't restrict this way(run static script in main world).
Generally, "isolated worlds" is a better way that can avoid conflicts, but it depends on your needs.

--
You received this message because you are subscribed to the Google Groups "Chromium Extensions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extens...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-extensions/60ff03bf-6884-4a23-a72e-aacf70fc3853n%40chromium.org.

Breeze

unread,
May 2, 2021, 6:37:13 PM5/2/21
to Chromium Extensions, Chromium Extensions, help....@gmail.com

Your new strategy is not equivalent with your first strategy: it is not truely `document_start`. It allows page's inline scripts to run earlier than your scripts. Inline scripts are parser-blocking, but scripts specified with a src attribute is not. AFAIK there is no such way to achive your extension's previous behavior on MV2 with MV3.

The extension which requires such a behavior and having the largest user base is Tampermonkey (#4 in Chrome web store), and its authors have expressed that their extension will continue to work on MV3. Once they move to MV3, we will see how this behavior can be achieved with MV3.
2021년 5월 2일 일요일 오후 7시 26분 49초 UTC+9에 Jackie Han님이 작성:

tweak support

unread,
May 3, 2021, 12:40:41 AM5/3/21
to Breeze, Chromium Extensions
Thanks for the confirmation, Jackie. And thanks for the Tampermonkey pointer, Breeze. I've noticed they use the same strategy as we do. Our automation is currently breaking; we do have automated tests to check for the behavior we want, which is to have our script execute before anything else. That's no longer the case anymore, as you've accurately pointed out.

 Inline scripts are parser-blocking, but scripts specified with a src attribute is not.

We've tried several different approaches to migrate our desired behavior to MV3, but so far, the only one that "kind of" working is mentioned above. Unfortunately, we can't really find a way to reliably run the script before the page loads, as we were doing in MV2.

We wonder how exactly will Tampermonkey achieve this. I guess we'll have to wait and see.

Follow-up question for Chrome advocates. Is there an alternative to inject scripts before page load rather than the mentioned? Maybe something undocumented? Or perhaps an item in your roadmap before deprecating MV2?

Cheers!

--
tweak team | website

wOxxOm

unread,
May 3, 2021, 7:44:18 AM5/3/21
to Chromium Extensions, help....@gmail.com, Chromium Extensions, Breeze
Despite the glorification ManifestV3 receives in the official communication, it's still in development, it's full of bugs, and it'll take probably another year for it to become comparable to MV2 in terms of possibilities it provides. The feature that will help you is not even in development yet: it's the ability to register scripts dynamically, both for the content scripts and for the "main world" scripts, see https://crbug.com/1054624.
Reply all
Reply to author
Forward
0 new messages