Open Bug 1736575 Opened 3 years ago Updated 23 hours ago

Support execution world MAIN in `scripting.executeScript()` and content_scripts

Categories

(WebExtensions :: General, enhancement, P2)

enhancement
Points:
8

Tracking

(Not tracked)

ASSIGNED

People

(Reporter: willdurand, Assigned: robwu)

References

(Depends on 1 open bug, Blocks 3 open bugs)

Details

(Whiteboard: [mv3-m2][wecg])

Attachments

(5 files)

Severity: -- → N/A
Blocks: 1735474
No longer depends on: 1735474
Type: task → enhancement
Points: --- → 8

Unassigned myself because this is not a high priority bug for now.

Assignee: wdurand → nobody
Blocks: 1687764

"ISOLATED" was supported in bug 1759932.
This bug is currently about supporting execution in the "MAIN" world (i.e. the web page).

Whiteboard: [mv3-m2] → [mv3-m2][wecg]

When we commence work on this, we should also create new bugs or patches to introduce support for world to scripting.registerContentScripts and content_scripts in manifest.json. Chromium implemented that in https://crbug.com/1330986

The userScripts API proposal at https://github.com/w3c/webextensions/pull/331 includes the "USER_SCRIPT" world, after my feedback to the initial proposal. That is out of scope for this bug, we will file new bugs to implement the USER_SCRIPT world and new APIs when we get there (and these would be part of the userScripts namespace, not the scripting namespace anyway).

When this bug is fixed, we have to adjust the BCD that I added in https://github.com/mdn/browser-compat-data/pull/18878

Summary: Support execution world in `scripting.executeScript()` → Support execution world MAIN in `scripting.executeScript()`
Depends on: 1743790

I have worked on the Adobe Flash Player emulator Ruffle. There are a few things we've had to do differently between Firefox and Chromium to make sure it works on both browsers, and this is the cause of one of them.

On Chromium browsers, we are able to use scripting.registerContentScripts with the MAIN execution world to run a script (https://github.com/ruffle-rs/ruffle/blob/feacbdc118c92ff30f686c1203c6f08ccd92833d/web/packages/core/src/plugin-polyfill.ts#L203) to add "Shockwave Flash" to navigator.plugins to fool Flash detection scripts. The faster the script is run, the more likely it is to run before any Flash detection scripts. On Firefox, we instead have to add a raw script tag with the compiled form of that script as its source to do the same thing, which isn't as fast so is more likely to run after the detection already fails and is also a bit more roundabout.

On Firefox, we instead have to add a raw script tag with the compiled form of that script as its source to do the same thing

Hi Daniel, that shouldn't be necessary. See Sharing objects with page scripts.

(In reply to Gregory Pappas [:gregp] from comment #7)

On Firefox, we instead have to add a raw script tag with the compiled form of that script as its source to do the same thing

Hi Daniel, that shouldn't be necessary. See Sharing objects with page scripts.

That doesn't allow for running the script quickly enough that it can add "Shockwave Flash" to navigator.plugins before inline scripts on the page check for and don't see the presence of Shockwave Flash in navigator.plugins.

Summary: Support execution world MAIN in `scripting.executeScript()` → Support execution world MAIN in `scripting.executeScript()` and content_scripts
Blocks: 1875475

Hey! I have a dev-tool browser extension (https://github.com/tbrockman/opentelemetry-browser-extension) which relies on third-party libraries that wrap native page objects (fetch, XHR, etc.) that I'd hope to be able to use on Firefox at some point (both for my own use and others). Does it seem likely that Firefox will support scripting.executeScript() in the near future, or would it be wiser for me to try to create some sort of shim that leverages Xray vision in the meantime instead?

Flags: needinfo?(rob)

I intent to implement this feature soon (within a few releases).

Side note, a quick look at your extension shows that you are executing large chunks of code in the web page. The MAIN world context is untrusted, you cannot trust anything that comes out of it from the extension's point of view. Another observation is that your extension uses externally_connectable, which hasn't been implemented either (bug 1319168).

And another note: there is cross-browser interest in a new API to enable synchronous execution of (serialized) functions from the content script's "ISOLATED" world in the MAIN world's context. The shape of that API has been discussed during an in-person WECG meeting two weeks ago (and the meeting notes will be published soon). It would include a mechanism to enable scripts in the MAIN world and ISOLATED world to communicate securely with each other. A carefully crafted MAIN world script can then communicate with the extension without interference from the web page. I'll link the meeting notes and/or Bugzilla ticket when they are available.

Flags: needinfo?(rob)

(In reply to Rob Wu [:robwu] from comment #10)

I intent to implement this feature soon (within a few releases).

Cool to hear, best of luck on the implementation!

Side note, a quick look at your extension shows that you are executing large chunks of code in the web page. The MAIN world context is untrusted, you cannot trust anything that comes out of it from the extension's point of view. Another observation is that your extension uses externally_connectable, which hasn't been implemented either (bug 1319168).

Yeah, but I don't think there's really any alternative here given what APIs are currently available and what the extension aims to do (automatically inject Javascript code to instrument page requests/interactions/document loads), while also circumventing the potential CORS issues that would arise if the injected Javascript attempted to directly send the data to the users analytics backend within the MAIN world context. The background script will only relay valid OTLP trace/log data to the users specified backend, and the data isn't particularly critical or sensitive (would already be available to any other Javascript running in the same page/intended purpose is analytics so it's okay if data is modified/incorrect), but admittedly it does present a potential attack vector if chained together with a vulnerability in any downstream that processes the OTLP payload. I plan to limit this somewhat by allowing the user to specify which pages to inject/accept messages from, but I definitely understand it's not ideal.

Luckily I'm the only real user currently and I just use it for analytics to satisfy my own curiosity, but I think the ideal use-case would probably be for developers looking to track their own webpage performance (and not running it everywhere on the web at large).

Bummer about the lack of support for externally_connectable though 😔

It would include a mechanism to enable scripts in the MAIN world and ISOLATED world to communicate securely with each other. A carefully crafted MAIN world script can then communicate with the extension without interference from the web page. I'll link the meeting notes and/or Bugzilla ticket when they are available.

Sounds interesting! Would this then allow a secure MAIN -> ISOLATED -> background script communication channel to facilitate the above?

(this comment is off-topic for this bug, but I am responding to close the thread)

(In reply to iam from comment #11)

Bummer about the lack of support for externally_connectable though 😔

From the use case that you have described, it looks like CustomEvent + dispatchEvent from MAIN to ISOLATED is a better fit than externally_connectable. It enables the content script to do sanity checks (with more context than the background) before passing the data forward and back. Custom events can be intercepted or tampered with by the web page, but that is also the case with externally_connectable.

It would include a mechanism to enable scripts in the MAIN world and ISOLATED world to communicate securely with each other. A carefully crafted MAIN world script can then communicate with the extension without interference from the web page. I'll link the meeting notes and/or Bugzilla ticket when they are available.

Sounds interesting! Would this then allow a secure MAIN -> ISOLATED -> background script communication channel to facilitate the above?

It is the more secure version of dispatchEvent + CustomEvent.

In preparation for supporting world: "MAIN", this commit introduces
the "world" property to the scripting.RegisteredContentScript type, and
adjusts all tests that expect a default value.

Assignee: nobody → rob
Status: NEW → ASSIGNED

This adds support for the "world" option in the contentScripts.register
API. Although the API is MV2-only and superseded by MV3, we need to have
a consistent set of properties in content_scripts in manifest.json and
contentScripts.register(), to avoid regressions like bug 1896669.

For clarity, this also documents that the world property is not
supported in the (old) userScripts API.

This adds support for the world:"MAIN" option to the following parts of
the scripting API, including tests:

  • scripting.executeScript
  • scripting.getRegisteredContentScripts
  • scripting.registerContentScripts
  • scripting.updateContentScripts
  • scripting.ExecutionWorld.MAIN

This patch includes a minimal prototype for scripting.executeScript with
the func parameter, which does not work when the page has a CSP. This
functionality will be improved in the next patch.

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: