Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shadow DOM and <iframe> #763

Open
annevk opened this issue Feb 29, 2016 · 23 comments
Open

Shadow DOM and <iframe> #763

annevk opened this issue Feb 29, 2016 · 23 comments
Labels
topic: shadow Relates to shadow trees (as defined in DOM)

Comments

@annevk
Copy link
Member

annevk commented Feb 29, 2016

<iframe> works if its "shadow-host-including inclusive ancestor" is a document that has a browsing context. I.e., including when it does not end up in the flattened tree.

<iframe> has a couple of major pain points when used in a shadow tree:

  • History API: <iframe> and the History API WICG/webcomponents#184 (Should probably simply not work, should the method calls simply be ignored or throw? If it does not work however this makes Shadow DOM less useful for composition.)
  • Named properties on the Window object: <iframe> and Window's named properties WICG/webcomponents#145 These should probably not dig into the shadow tree, but that will require adjustments to various definitions around browsing contexts.
  • Link targeting. Presumably <a href=test target=test> should not cross boundaries.
  • "allowfullscreen" should the shadow root also explicitly opt into this?
  • inertness: a browsing context container being inert causes all of the elements "in its Document" to be inert. It should instead be all elements connected to that document.

Paging @hayatoito @smaug---- @rniwa.

@annevk annevk added the topic: shadow Relates to shadow trees (as defined in DOM) label Mar 8, 2016
@TakayoshiKochi
Copy link
Member

For history API, let the discussion go in WICG/webcomponents#184.

For named properties, do we agree that anything in shadow tree should not show up?
I'd hope no one would object, but let us get a rough consensus.

Related, window.frames should not include <iframe>s in shadow trees.

For link targeting, I agree that target= should not cross boundaries.

For allowfullscreen, I'm not sure - is this discussed elsewhere for shadow root?

@annevk
Copy link
Member Author

annevk commented Apr 25, 2016

Yeah, the named properties and indexed properties should not point to anything in a shadow tree (note that window.frames === window, it's not really a collection). WICG/webcomponents#180 is about the Fullscreen API in general. I think it makes sense for shadow trees to have the same capabilities as the documents they are in, so no need for allowfullscreen on shadow root. They could do the same through script after all.

@TakayoshiKochi
Copy link
Member

Aha, okay, I have a bad memory - I commented in WICG/webcomponents#180.

I'd like to confirm <base>'s behavior.
As <base> is declared inert in shadow tree in the spec, <base> in shadow has no effect, but for one defined in document tree (in <head>),

  • <base href="..."> works for links in shadow trees
  • <base target="..."> works for links in shadow trees, if the target is one of pre-defined ones (_top etc.) or one in document tree, and even when the target happens to match one defined in the same shadow tree, it won't work.

@annevk
Copy link
Member Author

annevk commented Apr 25, 2016

I'm not quite sure what you mean by target.

@TakayoshiKochi
Copy link
Member

I was assuming the following HTML:

<base target="myframe">
<a href="http://foo">foo</a>
<div>
  #shadow-root
     <a href="http://bar">bar</a>
     <iframe name="myframe"></iframe>
</div>

Clicking on "foo" will navigate the whole document to foo, and clicking on "bar" will also navigate
the whole document to bar, both cases should not navigate inside the <iframe name="myframe"></iframe>.

@annevk
Copy link
Member Author

annevk commented Apr 25, 2016

That probably makes sense, yes.

@domenic
Copy link
Member

domenic commented Sep 6, 2017

Updated OP with an additional bullet about inertness. That one is easy to fix, at least.

@rniwa
Copy link

rniwa commented Oct 25, 2018

TPAC F2F note: target content attribute will be discussed along side with WICG/webcomponents#179.

@annevk
Copy link
Member Author

annevk commented Oct 25, 2018

Tentative model: shadow roots have their own name bucket and any popups they end up opening should probably be restricted to that shadow root (would only work for <a target>).

@mfreed7
Copy link
Contributor

mfreed7 commented Mar 2, 2021

Quick comment here, as it came up from an internal bug, on the question of named properties on the Window object. It seems that this issue was roughly resolved in WICG/webcomponents#145, to not leak frames that are located within (open or closed) shadow roots. And is how the implementations work for WebKit and Chromium, but not Gecko. In Gecko, even frames located in closed shadow trees are exposed on the Window object, thereby leaking the entire closed tree. This WPT shows this result.

It seems that #1625 attempted to codify WICG/webcomponents#145 this way, so the spec should (?) match the current behavior of WebKit/Chromium. I couldn't find a Mozilla bug, so I filed this one.

Let me know if I'm wrong about the above.

@mfreed7
Copy link
Contributor

mfreed7 commented Mar 12, 2021

Another followup comment on this issue. The fact that even open shadow roots hide any contained frames seems to preclude some natural use cases. Consider the example where sibling (cross-origin) iframes want to communicate with each other:

<div class="container">
  <iframe src="cross-origin1.html"></iframe>
  <iframe src="foo" name="frame2"></iframe>
</div>

with cross-origin1.html containing:

window.frames['frame2'].postMessage('bar');

This works great without Shadow DOM. But this completely breaks if anywhere in the ancestor chain, someone tries to use Shadow DOM:

<div id=host>
  <template shadowroot=open>
    <div class="container">
      <iframe src="cross-origin1.html"></iframe>
      <iframe src="foo" name="frame2"></iframe>
    </div>
  </template>
</div>

In this case, the two frames can no longer communicate with each other. Is there any other mechanism by which they can get window references to each other? They are contained within the same shadow tree here, so it would seem that they should be able to somehow communicate. This is a real use case from an internal group, so this isn't hypothetical. Is there any guidance on how to do this? @annevk @rniwa @domenic

Again, I can see why we probably don't want this to work for a closed shadow root, but even in that case it's a bit weird that iframes contained within the same shadow tree can't talk to each other.

P.S. I wasn't sure whether to post this here, or on WICG/webcomponents#145, but that one is closed so I went with this one.

@domenic
Copy link
Member

domenic commented Mar 12, 2021

In this case, the two frames can no longer communicate with each other. Is there any other mechanism by which they can get window references to each other?

For sure. They can do

document.querySelector("#host").shadowRoot.querySelector("iframe").contentWindow.postMessage('bar');

(I think I did my shadow-tree navigation right...)

@mfreed7
Copy link
Contributor

mfreed7 commented Mar 12, 2021

In this case, the two frames can no longer communicate with each other. Is there any other mechanism by which they can get window references to each other?

For sure. They can do

document.querySelector("#host").shadowRoot.querySelector("iframe").contentWindow.postMessage('bar');

(I think I did my shadow-tree navigation right...)

But the <iframe> is cross origin...

@domenic
Copy link
Member

domenic commented Mar 12, 2021

That doesn't impact things.

@mfreed7
Copy link
Contributor

mfreed7 commented Mar 12, 2021

Perhaps I don't understand. From cross-origin.html, document is just the iframe document, so querySelector("#host") returns null. In this example, frame1 is trying to talk to frame2.

@domenic
Copy link
Member

domenic commented Mar 12, 2021

Hmm, then the original example doesn't work. window.frames['x'] does not contain your parent's child frames. It contains your own child frames.

In general, window.frames['x'] is legacy syntax for document.querySelector("#x")?.contentWindow || document.querySelector("[name=x]")?.contentWindow.

@mfreed7
Copy link
Contributor

mfreed7 commented Mar 12, 2021

Sorry, that's a typo in my original post: cross-origin1.html should include .parent:

window.parent.frames['frame2'].postMessage('bar');

This example does work, and is broken by shadow dom.

@domenic
Copy link
Member

domenic commented Mar 12, 2021

I see. Yeah, I guess that is broken. I tend to think that's OK because named access in such a fashion is a legacy feature, so when designing new features like shadow DOM we try to restrict such legacy features so as to make the design space manageable. (The proper pattern would be to ask the parent to message the child by postMessage()ing the parent, or use BroadcastChannel or similar.) But I'll let others chime in.

@rniwa
Copy link

rniwa commented Mar 13, 2021

That is definitely intentional. We don't want iframe inside a shadow tree to be exposed on the global scope such that other scripts can stumble upon them.

@mfreed7
Copy link
Contributor

mfreed7 commented Mar 17, 2021

Thanks for the feedback here. I can see your points. The reason it (still?) feels a bit odd to me is that otherwise-working behavior is broken when the entire tree is placed into shadow dom. But I suppose the message is that this form of sibling-to-sibling direct frame communication, via the global window.frames, isn't great anyway, and there's a downside to exposing shadow-hidden frames just to fix this use case. I'm ok with that, and I'll feed that back to the requesting team.

@annevk
Copy link
Member Author

annevk commented Mar 18, 2021

Indeed, if we designed nested browsing contexts today they'd have far less side channels such as that one.

@itayadler
Copy link

In Firefox this isn't the behavior, window.frames include iframes inside ShadowDOM.

@mfreed7
Copy link
Contributor

mfreed7 commented Mar 26, 2022

In Firefox this isn't the behavior, window.frames include iframes inside ShadowDOM.

Right - that’s this bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1695969

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: shadow Relates to shadow trees (as defined in DOM)
Development

No branches or pull requests

6 participants