0

I have a very simple Chrome Extension that defines a constant on the window object.

It works on online websites but fails on tabs that display local files with

Blocked script execution in 'file:...mht' because the document's frame is sandboxed and the 'allow-scripts' permission is not set.

I would somehow understand if it was the opposite way for security but this way it feels like I can do something in the extensions to fix this in a way that it also works for local offline files.

manifest.json

{
  "name": "Extension Expose",
  "description": "Extension.",
  "version": "1.0",
  "manifest_version": 3,
  "content_scripts": [
    {
      "matches": ["http://*/*", "https://*/*", "http://localhost/*", "https://localhost/*"],
      "js": ["content.js"]
    }
  ],
  "web_accessible_resources": [{ 
    "resources": ["write.js"],
    "matches": ["http://*/*", "https://*/*", "http://localhost/*", "https://localhost/*"]
  }]
}

content.js

console.log("content.js")

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

write.js

console.log("write.js")
window.ee = "abc"
console.log("successfully written to window")

On any live website it does its job perfectly

enter image description here

However if I open a local .mht I get the following

enter image description here

Adding to this, I have now set the matches to ["http://*/*", "https://*/*", "http://localhost/*", "https://localhost/*", "file://*", "file://*/*", "http://127.0.0.1/*", "https://127.0.0.1/*"] just to be extra safe, that didn't change anything.

In a pure html file the console throws

content.js:8 GET chrome-extension://abcdef/write.js net::ERR_BLOCKED_BY_CLIENT,

which has probably something to do with a cross-domain http request but I don't understand why the same error won't trigger on mht files

Alternatives

I found this answer https://stackoverflow.com/a/9517879 that lists a lot of different ways to do similar things. What I am doing primarily here is Method 1. What's interesting is that Method 3 (defining a script inline) does work for online html as well as offline html, but this still fails on .mht unfortunately. I suppose it's because of the way the .mht works internally.

user2875404
  • 3,048
  • 3
  • 25
  • 47

1 Answers1

2

There's a bug with web_accessible_resources on file:// pages, fixed only in Chrome 106.

A better solution is to use chrome.scripting instead anyway because it can set the variable before the page starts loading reliably and we don't make our extension detectable by web sites.

  1. Remove content_scripts and web_accessible_resources from manifest.json.
  2. Remove content.js
  3. Add to manifest.json:
  "background": {"service_worker": "bg.js"},
  "permissions": ["scripting"],
  "host_permissions": ["<all_urls>"]
  1. Add background.js:
chrome.runtime.onInstalled.addListener(async () => {
  const old = await chrome.scripting.getRegisteredContentScripts();
  if (old[0]) await chrome.scripting.unregisterContentScripts({ids: old.map(s => s.id)});
  await chrome.scripting.registerContentScripts([{
    id: 'write',
    js: ['write.js'],
    matches: ['<all_urls>'],
    runAt: 'document_start',
    world: 'MAIN',
  }]);
});
wOxxOm
  • 65,848
  • 11
  • 132
  • 136
  • Hey thank you so much for the response - I will try out on Chrome 106 right away. Your solution doesn't work for MHT pages tho :( It does work for online as well as offline HTML and is the cleanest solution so far but still seeing `Blocked script execution in 'file:///abc.mht' because the document's frame is sandboxed and the 'allow-scripts' permission is not set.` on MHT in Chrome 104 – user2875404 Sep 07 '22 at 08:52
  • Actually, MHT cannot run scripts by design so injecting a variable there is meaningless. Why are you doing it? – wOxxOm Sep 07 '22 at 10:04
  • Basically my use case is that I want to run a custom script on every page load. This custom script makes it easier for me to debug stuff (for example I can have immediate access to lodash since my custom script adds lodash to the window variable). I did save a lot of pages as MHT back then and instead of parsing lodash manually to each of them, I wanted my extension to take care of that. Works everywhere except for MHT. If you know another way to automatically inject JS on any chrome tab I'd be up for that – user2875404 Sep 07 '22 at 10:55
  • I tried to do it via a `devtools_page` now since it seems to be more fitting, unfortunately same result: Online and offline HTML works but no MHT, at this point I really doubt if there is a way at all – user2875404 Sep 07 '22 at 11:28
  • Yeah, MHT don't run script by design. As a workaround you can switch the `context selector` in console toolbar to your extension. There you will have access to the globals of your content script. – wOxxOm Sep 07 '22 at 14:46