1

I'm migration my extension from V2 to V3. Now all is working fine except for one thing. In my V2 version I did

const actualCode = '(' + function () { 'console.log("demo");' } + `)();`;
const script = document.createElement('script');
script.textContent = actualCode;
(document.head || document.documentElement).appendChild(script);
script.remove();

Note that the console.log("demo") is a simplification of what I need to inject :)

I need to inject some javascript for my chrome-extension-magic to take place.

Now, in V3 this doesn't work anymore. I get the following error in my devtools-console

content.js:23114 
    
   Refused to execute inline script because it violates the following 
   ContentSecurity Policy directive: "script-src 'self'". Either the 
   'unsafe-inline' keyword, a hash ('sha256-tN52+5...6d2I/Szq8='), or a nonce
   ('nonce-...') is required to enable inline execution.

In the migration guide I noticed this section

"content_security_policy": {
   "extension_pages": "...",
   "sandbox": "..."
}

but there is not much description there, so this is magic to me. So I hope someone know can help me with this?

wOxxOm
  • 53,493
  • 8
  • 111
  • 119
Jeanluca Scaljeri
  • 22,579
  • 44
  • 171
  • 286
  • 2
    Use a separate file as shown in [method 1 here](https://stackoverflow.com/a/9517879). It runs asynchronously so it may run later than some scripts of the page. In the future chrome.scripting.registerContentScripts will allow specifying `world`. – wOxxOm Dec 24 '21 at 16:46
  • Thats it, thnx. I've tested it, but in my case this solution doesn't work unfortunately. In my case I need the injected script to run before the page's scripts runs. I've tested this solution and noticed that the injected script now runs too late :( – Jeanluca Scaljeri Dec 24 '21 at 20:50
  • You'll have to keep using MV2. – wOxxOm Dec 24 '21 at 20:55
  • Yes, I came to the exact same conclusion – Jeanluca Scaljeri Dec 24 '21 at 20:57
  • 1
    I see you use it to override XHR/fetch so here's an alternative (in case the site doesn't use the deprecated synchronous XHR): override XMLHttpRequest.prototype.response getter (also responseText) and Response.prototype.text getter (also json, blob, arrayBuffer, formData) via Object.getOwnPropertyDescriptor + Object.defineProperty. These getters are used after the remote server responds so your script should always run earlier. – wOxxOm Dec 24 '21 at 21:28
  • Thats a very interesting suggestion, and might be the solution to my probleem. I will investigate, because it should also work, for example, if the endpoint being called not yet even exists! Thnx for the suggestion! – Jeanluca Scaljeri Dec 25 '21 at 13:30
  • Do you think it would still be possible, if you consider the fact that I have to retrieve the response from `chrome.strorage` (async). It means that to be able to set a value for responseText I need to dispatch a message to the content script, asking for the data. – Jeanluca Scaljeri Dec 28 '21 at 12:09
  • Since chrome.storage is always queried locally (even for sync storage) it should be much faster than a remote request by the site so unless there's a bug in Chrome it should be fine. – wOxxOm Dec 28 '21 at 14:16
  • True, but if I replace `XMLHttpRequest.prototype.response` with my own getter, now as soon my getter is called, it means the server's response has already arrived and it will be to late for me to make that chrome.storage call – Jeanluca Scaljeri Dec 28 '21 at 14:24
  • This is where [MCVE](/help/mcve) is necessary. There may be a solution depending on what the actual workflow and the actual data are e.g. querying the [entire] storage when the content script starts. – wOxxOm Dec 28 '21 at 14:26
  • yes, all this is also way off topic :) Thanks for the help! – Jeanluca Scaljeri Dec 28 '21 at 14:42

1 Answers1

1

Refer to Use a content script to access the page context variables and functions

Since content scripts are executed in an "isolated world" environment, we can't do some special dom operations in content_script js.

This example will show you how to inject inject.js to web page before document start:

// document_start.js
var s = document.createElement('script');
s.src = chrome.runtime.getURL('inject.js');
s.onload = function() {
    this.remove();
};
(document.head || document.documentElement).appendChild(s);

manifest.json example for ManifestV3

"content_scripts": [
      {
            "matches": ["<all_urls>"],
            "js": ["document_start.js"],
            "run_at": "document_start" //default document end
      }
]
"web_accessible_resources": [{
  "resources": ["inject.js"],
  "matches": ["<all_urls>"]
}]
ahuigo
  • 2,343
  • 2
  • 22
  • 39