Proposal: Allow extensions to access closed shadow root

1,230 views
Skip to first unread message

Chase Leslie

unread,
Aug 26, 2019, 5:18:51 PM8/26/19
to Chromium Extensions
As support for Web Components improves across browsers, developers of websites are likely to start taking advantage of the new useful features like the encapsulation offered by shadow DOM. Once there is widespread support for shadow DOM, I imagine it will get baked into libraries and frameworks as a matter of course. This poses a problem for extension developers, as currently closed shadow root is hidden for content scripts as it is for regular unprivileged page scripts.

I propose granting extensions the ability to traverse closed shadow roots. Perhaps there are practical concerns that could make this difficult to implement. Ultimately, I think end users install extensions because they want the additional functionality. Consider a simple extension that searches for words and highlights them in the document. If some of the text is contained in custom elements situated in a closed shadow root, the text is effectively invisible to the extension. Users likely don't care about the internals of the DOM. They will just assume the extension is poorly crafted or broken.

What does everyone think?

Simeon Vincent

unread,
Aug 26, 2019, 10:26:29 PM8/26/19
to Chromium Extensions
Hm… If you're looking for generic access to shadow roots, you could do something like inject a content script at document start that exposes the shadow root to your extension by doing something like…
{
 
// Proxy the default addShadow method in order to transparently intercept
 
// attachShadow calls and store a reference to the shadow root object for
 
// later use.
 
//
 
// We store shadow root references in a WeakMap in order to ensure that we're
 
// not leaking data to other scripts on the page. Additionally, this
 
// implementation uses a WeakMap to ensure that we don't keep references to
 
// shadow roots for nonexistent elements.

 
const shadowRootMap = new WeakMap();
 
const attachShadow = Element.prototype.attachShadow;

 
Element.prototype.attachShadow(function(options) {
   
const shadowRoot = attachShadow.call(this, options);
    shadowRootMap
.set(this, shadowRoot);
   
return shadowRoot;
 
});

 
// Use getShadowRoot to retrieve the shadow root of a custom element while
 
// iterating through DOM nodes or undefined.
 
function getShadowRoot(el) {
   
return shadowRootMap.get(el);
 
}
}

Please note that I did not test the above code, I just threw it together for demonstration purposes. While this may not be the most elegant solution, it should get the job done. Also, credit where it's due, this sample was inspired by Open vs. Closed Shadow DOM by Leon Revill.

If you're specifically interested in searching text on the page, I believe that standards orgs has been examining document search APIs in order to facilitate use cakes like making text in infinite scrolling pages. Previous efforts here include the FindText API and Find in Page API. I'm not sure if anyone is actively pursuing this use case, but if they are I'd recommend jumping in to those discussions. Point is this particular use case is more of a web platform issue.

If you've got something else in mind, I'd love to hear more :)

Simeon - @dotproto
Extensions Developer Advocate

Gildas

unread,
Aug 27, 2019, 6:20:32 AM8/27/19
to Chromium Extensions
There is a minor error, it should be:

...
Element.prototype.attachShadow = function(options) {

   
const shadowRoot = attachShadow.call(this, options);
    shadowRootMap
.set(this, shadowRoot);
   
return shadowRoot;
};
...

Chase Leslie

unread,
Aug 27, 2019, 7:36:20 PM8/27/19
to Chromium Extensions
Thanks for the reply Simeon. Note that I am not trying to solve a specific problem at the moment.

Proxying the Element.prototype.attachShadow implementation seems like it would work in the general case. Though a simple (hypothetical) extension like I mentioned would have to be transformed somewhat. Instead of the user activating the extension only when desired, the extension would have to proactively inject content scripts and proxy the prototype in every frame in anticipation of being needed. Alternatively, the extension could refresh the page when needed and inject content scripts. However, the user may have spent considerable time setting up or navigating in a dynamic page which would be undermined by a page reload.

What I was advocating for is giving extensions the ability to enumerate closed shadow roots as if they were open.

Scott Fortmann-Roe

unread,
Mar 22, 2020, 10:15:49 AM3/22/20
to Chase Leslie, Chromium Extensions, Simeon Vincent
I am running into an issue with this and wondering if anyone had a solution.

@Simeon Vincent's code works well, but in my tests it appears to need to be executed in the context of the page itself, not in the isolated world of the content script.

This can be done by injecting a script tag into the page itself with the code. However, I don't see any mechanism to get back a reference to the shadowRoot's within my content script.

I can pass some data back from the page to the content script by dispatching a custom event from the page and listening for it in the content script. However, when I do this with a new shadowRoot it gets replaced with null when it reaches the content script.

Any suggestions? Is there any way to pass a reference to a dom element from a page to a content script?

Also, it looks like Gecko is experimenting with providing direct access to closed shadow roots for extensions <https://developer.mozilla.org/en-US/docs/Web/API/Element/openOrClosedShadowRoot>. It might be nice to have that in Chrome.



--
You received this message because you are subscribed to the Google Groups "Chromium Extensions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extens...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-extensions/8d3a8391-6d86-460b-96ac-f940f37eaa95%40chromium.org.

Scott Fortmann-Roe

unread,
Mar 29, 2020, 11:22:44 AM3/29/20
to Chase Leslie, Chromium Extensions, Simeon Vincent
I've filed a feature request for this issue:

Stephen Beemsterboer

unread,
Jan 7, 2022, 4:44:00 PM1/7/22
to Chromium Extensions, sco...@gmail.com, Chromium Extensions, Simeon Vincent, Chase Leslie
For the benefit of future readers, this feature has now been implemented in Chromium: https://bugs.chromium.org/p/chromium/issues/detail?id=778816.

Jackie Han

unread,
Jan 8, 2022, 5:08:05 AM1/8/22
to Stephen Beemsterboer, Chromium Extensions, sco...@gmail.com, Simeon Vincent, Chase Leslie
The issue was fixed. But there is no document for "chrome.dom.openOrClosedShadowRoot" api!

Simeon Vincent

unread,
Jan 20, 2022, 8:33:01 PM1/20/22
to Jackie Han, Stephen Beemsterboer, Chromium Extensions, sco...@gmail.com, Chase Leslie
This should be fixed when PR 1987 on the docs repo lands.

Simeon - @dotproto
Chrome Extensions DevRel

Reply all
Reply to author
Forward
0 new messages