Inline scripts in manifest v3?

4,294 views
Skip to first unread message

Christopher Armstrong

unread,
Nov 15, 2021, 4:26:53 PM11/15/21
to Chromium Extensions
Hi there,

Our extension has a requirement of needing to inject and load javascript before the page's scripts load.

We are able to meet this requirement in manifest v2 by inlining a script like:
```
const script = document.createElement('script');
script.type = 'text/javascript';
script.setAttribute('async', 'false');
script.textContent = 'console.log("test")';
const container = document.head || document.documentElement;
container.insertBefore(script, container.children[0]);
```

This allows our script to be injected and load before the page's scripts, whereas setting src does not:
```
script.src = chrome.runtime.getURL('inject.js');
```

But manifest v3 does not allow inline scripting due to csp changes, it looks like. Is there a way to inline scripts in v3 or another approach to inject and load javascript before the page loads?

Error inlining in a manifest v3:

> Refused to execute inline script because it violates the following Content Security Policy directive: "default-src 'self' data: gap: ... 'unsafe-eval'". Either the 'unsafe-inline' keyword, a hash ('sha256-V+/U3qbjHKP0SaNQhMwYNm62gfWX4QHwPJ7We1PXokI='), or a nonce ('nonce-...') is required to enable inline execution. Note also that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.


Thank you,
Christopher

Shu

unread,
Nov 15, 2021, 4:40:07 PM11/15/21
to Chromium Extensions, christopher...@gmail.com
You can't use inline script, BUT, you can put that script in a separate file (so google can check it when you upload it to the store) and then inject it

_script = document.createElement('script');
_script.setAttribute('src', chrome.runtime.getURL('FILENAME.js'));
(document.head||document.documentElement).appendChild( _script  );
_script.parentNode.removeChild( _script);

Christopher Armstrong

unread,
Nov 15, 2021, 4:41:00 PM11/15/21
to Chromium Extensions, Christopher Armstrong
To clarify, we're not wanting to run arbitrary javascript.

We want to inline / set `textContent` equal to the content of a file that's listed in our `web_accessible_resources`.

Christopher Armstrong

unread,
Nov 15, 2021, 4:48:15 PM11/15/21
to Chromium Extensions, Christopher Armstrong
Another detail to add to this thread, this is only a problem on "warm" subsequent reloads when the page is cached. 

In the case when we visit a website for the first time and it is not cached, the extension's script loads before the page's script when we inject by doing:

```
script.src = chrome.runtime.getURL('inject.js');
```

On subsequent reloads when the page is cached, the page's scripts will load before the extension's script.

So our workaround that is v2-compatible but not v3-compatible is setting `script.textContent` to inline the javascript.

wOxxOm

unread,
Nov 16, 2021, 9:19:25 AM11/16/21
to Chromium Extensions, christopher...@gmail.com
Currently there's no way to run a script synchronously before the page scripts in MV3.

  1. https://crbug.com/1207006 is a feature request for an exact analog of MV2 approach.
  2. https://crbug.com/1054624 promised us a comparable solution via  chrome.scripting.registerContentScripts with the ability to specify world: 'MAIN'.
Reply all
Reply to author
Forward
0 new messages