Manifest V3: Bookmark managers and bookmarklets

354 views
Skip to first unread message

Seth Freed

unread,
May 11, 2022, 10:32:17 PM5/11/22
to Chromium Extensions
Hi all.
We are currently assesing the issues we'll have to solve once we start porting our extension to the new Manifest V3 platform.
Our extension is a Bookmark Manager and it needs the ability to open bookmarks, evidently, as this is part of what a bookmark manager is supposed to do. However, the special case of bookmarklets (those with a javascript: URL) requires that the extension executes the javascript code into the desired tab. This is possible under Manifest V2 through the chrome.tabs.executeScript API, but there seems to be no way of doing the same under Manifest V3.
The new API chrome.scripting.executeScript accepts the code either as a function or as a file. So the only way we could run the bookmarklet code is by creating a function with the new Function() constructor which is not allowed in MV3 either.

We've looked around in the MV3 documentation, but we can't find any way of opening a bookmarklet. We'd appreciate any suggestions or advice regarding this issue. The ability to open a bookmark is fundamental in a Bookmark Manager extension and it would be a significant regression for our extension and our users that this functionality is lost under Manifest V3.

wOxxOm

unread,
May 12, 2022, 10:12:11 AM5/12/22
to Chromium Extensions, geth...@gmail.com
You can create a `script` element in page context so it runs in the same environment as it would when the user clicks the bookmark, meaning that a strict site CSP could prevent it from running. Compared to MV2 this is a functional regression as previously `script` elements created by the content script were ignoring the site CSP, but in this case it shouldn't matter.

async function execInPage(code) {
  const [tab] = await chrome.tabs.query({currentWindow: true, active: true});
  chrome.scripting.executeScript({
    target: {tabId: tab.id},
    func: code => {
      const el = document.createElement('script');
      el.textContent = code;
      document.documentElement.appendChild(el);
      el.remove();
    },
    args: [code],
    world: 'MAIN',
    //injectImmediately: true, // Chrome 102+
  });
}

Seth Freed

unread,
May 13, 2022, 1:13:35 AM5/13/22
to Chromium Extensions, wOxxOm, Seth Freed
Thanks for the detailed answer and code example.
I'd like to ask a few questions if you don't mind.

1. Is that approach not a violation of the Manifest V3 policy requirements mentioned in this link?
Specifically this one: "Using JavaScript's eval() method or other mechanisms to execute a string fetched from a remote source".

2. Does it make any difference to use world:"ISOLATED" versus world:"MAIN" in this case?
The new script element should be executed in the main world regardless of the value of the "world" parameter, correct?

3. When you say at the end "but in this case it shouldn't matter", do you mean that script elements created by a MAIN world script are not affected by the CSP?

Thanks in advance.

wOxxOm

unread,
May 13, 2022, 10:19:38 AM5/13/22
to Chromium Extensions, geth...@gmail.com, wOxxOm
  1. I don't know, but this is user-supplied code so I'd say it'll be allowed. It's kinda similar to userscripts that should be allowed although we still don't know if it'll actually happen given the amount of work it might take and the amount of work the extension authors will need for migration with the nonsensical deadline for MV2. Currently Tampermonkey can't even start migrating.

  2. The difference is that the MV3's default CSP (that forbids arbitrary code) won't apply to scripts created by a main-world code, which is by design as there's no reliable way to restrict it without crippling the ability of advanced extensions to extend the web.

  3. Since bookmarklets are already restricted by the site's CSP when executed explicitly by the user using the browser UI, the fact that the same restriction will apply to this code shouldn't matter. The regression is that in MV2 it was possible to circumvent the site's CSP by setting script.textContent inside the content script.

hrg...@gmail.com

unread,
May 13, 2022, 2:02:55 PM5/13/22
to Chromium Extensions, wOxxOm, geth...@gmail.com
The situation in your question 1 becomes complicated by the fact that a bookmark manager can create bookmarks as well. So now we can't assume that the code in a bookmarklet is user-provided.
Any extension with the "bookmarks" permission can create a bookmarklet and execute it.

This whole policy issue could be solved by the ability to execute user-provided code in the isolated world instead of the main world. As wOxxOm said, this functionality is a must for many, many extensions such as user-script managers and in general any extension that allows the user to provide their own logic.
Unfortunately, we are all entirely clueless about when (or if) this functionality will become part of MV3 before MV2 dies. Only 8 months remain for this deadline and MV3 is still full of bugs and missing features. At the current pace of improvement, it doesn't look like MV3 will be ready to replace MV2 by the end of this year.

Your safe bet for now is to submit your MV3 version as a beta version (while you keep your MV2 version as the main version) and to implement the approach given by wOxxOm. If your MV3 version is approved by the review staff, then your problem is solved.

Seth Freed

unread,
May 14, 2022, 2:51:03 PM5/14/22
to Chromium Extensions, hrg...@gmail.com, wOxxOm, Seth Freed
Thank you both for your comments. I understand now that Manifest V3 is still a work in progress.
In addition to our issue with bookmarklets, we are still waiting for the new favicon API  that is announced here:

A bookmark manager without favicons would look kind of dull and incomplete so we've got to wait some more till the APIs we need are added to MV3. Fingers crossed.

Reply all
Reply to author
Forward
0 new messages