Window objects and out-of-process iframes

55 views
Skip to first unread message

Ken Buchanan

unread,
Jun 9, 2014, 5:37:01 PM6/9/14
to Adam Klein, Nils Barth, Dan Carney, site-isol...@chromium.org, Daniel Cheng
Hi Adam, Nils, Dan,

Are any of you able to provide some advice on how v8 bindings are going to work with out-of-process iframes?

Specifically, Daniel Cheng and I have been looking at DOMWindow, with which different script contexts can interact (though in a very limited way, across origins). It seems we need 2 types of DOMWindows -- a local DOMWindow that is what exists now, and a RemoteDOMWindow that is an object representing a window that is rendered in a different process (and therefore has a different origin). It is not obvious to us how to structure this to be compatible with v8, since the DOMWindow object attached to the frame will be recreated when that frame goes out of process, but the v8 object will have to remain the same.

I haven't spent much time in bindings code, but Daniel has suggested we might create a new wrapper that can contain a regular DOMWindow or RemoteDOMWindow, and swap between the two as necessary. This might not be the most elegant solution, though; alternative suggestions are welcome if there.

Ken

Daniel Cheng

unread,
Jun 9, 2014, 6:30:42 PM6/9/14
to Ken Buchanan, Adam Klein, Nils Barth, Dan Carney, site-isol...@chromium.org
To elaborate, I think the problematic bit is that V8Window.cpp/V8Window.h is pretty tightly coupled with DOMWindow.cpp/DOMWindow.h (the generated binding includes it directly). I don't know of any other generated binding code that tries to bind with two different C++ classes (if there is precedent for this, we'd love to know).

To help things proceed, I think we can do something like this:
1. First, rename DOMWindow to LocalDOMWindow, and update Window.idl to point at that instead.
2. Make DOMWindow a virtual interface for things DOMWindow::screen(), DOMWindow::location(), etc.
3. Update Window.idl to point back at DOMWindow, and update V8WindowShell to tie the two bits together.
4. When we add RemoteDOMWindow, update V8WindowShell::installDOMWindow to handle that case as well.

We're a little fuzzy on the fine points of #2. Looking at what the IDL bindings generator outputs, I think it /should/ just work as long as we tie things together correctly in V8WindowShell. There's nothing fundamental that prevents generated bindings code from calling virtual methods right?

Finally, do we need to be concerned about the performance implications of using virtual dispatch?

Daniel

Nils Barth

unread,
Jun 11, 2014, 12:58:23 AM6/11/14
to Daniel Cheng, Kentaro Hara, kou...@chromium.org, Ken Buchanan, site-isol...@chromium.org, Adam Klein, Dan Carney
(Ken, Daniel: haraken and Kouhei are more knowledgeable about bindings internals, so asking them.)
haraken and Kouhei, question about V8 bindings with out-of-process iframes (details below).

Key point is that internally, DOMWindow is going to be replaced by LocalDOMWindow and RemoteDOMWindow.

Bindings-wise, we need a single class, right?
(As discussed before, the V8 wrapper needs to know the C++ class, so a single class per IDL interface.)

I think what Daniel suggests sounds sane, but agree that we might be worried about adding indirection (esp. virtual dispatch) onto DOMWindow.

WDYT?


Kentaro Hara

unread,
Jun 11, 2014, 1:15:00 AM6/11/14
to Nils Barth, Daniel Cheng, Kouhei Ueno, Ken Buchanan, site-isol...@chromium.org, Adam Klein, Dan Carney
From the perspective of whether it works or not, I think your approach will work.

However, I don't fully understand how the interaction between LocalDOMWindow, RemoteDOMWindow and DOMWindow's wrapper is going to be organized. Would you more elaborate on what happens on these objects in the out-of-process mode step by step (e.g., when RemoteDOMWindow is created, when V8WindowShell::installDOMWindow switches the C++ pointer from LocalDOMWindow to RemoteDOMWindow etc)?

 
To help things proceed, I think we can do something like this:
1. First, rename DOMWindow to LocalDOMWindow, and update Window.idl to point at that instead.
2. Make DOMWindow a virtual interface for things DOMWindow::screen(), DOMWindow::location(), etc.
3. Update Window.idl to point back at DOMWindow, and update V8WindowShell to tie the two bits together.
4. When we add RemoteDOMWindow, update V8WindowShell::installDOMWindow to handle that case as well. 
 
We're a little fuzzy on the fine points of #2. Looking at what the IDL bindings generator outputs, I think it /should/ just work as long as we tie things together correctly in V8WindowShell. There's nothing fundamental that prevents generated bindings code from calling virtual methods right? 

Right. The binding code just believes that a C++ pointer stored in a certain internal filed of V8's wrapper is a C++ pointer to the corresponding DOM object. Thus if you install a C++ pointer to LocalDOMWindow/RemoteDOMWindow into the internal field, you can make the binding code believe that it's a C++ pointer that the binding code should use. You can do that in V8WindowShell::installDOMWindow.
 
Finally, do we need to be concerned about the performance implications of using virtual dispatch?

Are you going to make all Window methods virtual? I guess most Window methods are not performance-sensitive.

--
Kentaro Hara, Tokyo, Japan

Daniel Cheng

unread,
Jun 11, 2014, 1:38:55 AM6/11/14
to Kentaro Hara, Nils Barth, Kouhei Ueno, Ken Buchanan, site-isol...@chromium.org, Adam Klein, Dan Carney
On Tue, Jun 10, 2014 at 10:14 PM, Kentaro Hara <har...@chromium.org> wrote:
From the perspective of whether it works or not, I think your approach will work.

However, I don't fully understand how the interaction between LocalDOMWindow, RemoteDOMWindow and DOMWindow's wrapper is going to be organized. Would you more elaborate on what happens on these objects in the out-of-process mode step by step (e.g., when RemoteDOMWindow is created, when V8WindowShell::installDOMWindow switches the C++ pointer from LocalDOMWindow to RemoteDOMWindow etc)?

​I don't think we've completely figured this out ourselves.​ There will be two ways to create a RemoteFrame, and in both of these cases, we will need a RemoteDOMWindow.

1. If the browser process decides that a frame navigation should result in a cross-process swap, then the browser will trigger Blink to swap that frame in the FrameTree from LocalFrame to RemoteFrame. Right now, we have a minimally implemented Blink API to allow the embedder to trigger this (WebFrame::swap). We envision that this will eventually call a new method on V8WindowShell to allow us to swap the C++ pointer to point to the RemoteDOMWindow.

2. Once the process swap has been triggered, we need to mirror the frame tree in the new process, so by definition, we will need to instantiate RemoteFrames. We may adapt the logic in installDOMWindow to handle this case, or maybe factor out the common bits so it doesn't get too complicated. Either case, we will install a RemoteDOMWindow as the C++ pointer directly.

Finally, we will need a way to swap a RemoteFrame back to a LocalFrame, but we might be able to use the same swap function from #1.

We also need to figure out how to help V8WindowShell live across this swap; right now, ScriptController owns it. I don't think RemoteFrame needs a ScriptController, since you shouldn't be able to evaluate script directly in a RemoteFrame context. I don't know if we should try to factor this out (I imagine this is hard) or have some method to hand off ownership to RemoteFrame for swapping.
 

 
To help things proceed, I think we can do something like this:
1. First, rename DOMWindow to LocalDOMWindow, and update Window.idl to point at that instead.
2. Make DOMWindow a virtual interface for things DOMWindow::screen(), DOMWindow::location(), etc.
3. Update Window.idl to point back at DOMWindow, and update V8WindowShell to tie the two bits together.
4. When we add RemoteDOMWindow, update V8WindowShell::installDOMWindow to handle that case as well. 
 
We're a little fuzzy on the fine points of #2. Looking at what the IDL bindings generator outputs, I think it /should/ just work as long as we tie things together correctly in V8WindowShell. There's nothing fundamental that prevents generated bindings code from calling virtual methods right? 

Right. The binding code just believes that a C++ pointer stored in a certain internal filed of V8's wrapper is a C++ pointer to the corresponding DOM object. Thus if you install a C++ pointer to LocalDOMWindow/RemoteDOMWindow into the internal field, you can make the binding code believe that it's a C++ pointer that the binding code should use. You can do that in V8WindowShell::installDOMWindow.
 
Finally, do we need to be concerned about the performance implications of using virtual dispatch?

Are you going to make all Window methods virtual? I guess most Window methods are not performance-sensitive.

​Yes I think we would probably make them virtual to facilitate the swapping.

Kentaro Hara

unread,
Jun 11, 2014, 3:06:28 AM6/11/14
to Daniel Cheng, Nils Barth, Kouhei Ueno, Ken Buchanan, site-isol...@chromium.org, Adam Klein, Dan Carney
​I don't think we've completely figured this out ourselves.​ There will be two ways to create a RemoteFrame, and in both of these cases, we will need a RemoteDOMWindow. 
 
1. If the browser process decides that a frame navigation should result in a cross-process swap, then the browser will trigger Blink to swap that frame in the FrameTree from LocalFrame to RemoteFrame. Right now, we have a minimally implemented Blink API to allow the embedder to trigger this (WebFrame::swap). We envision that this will eventually call a new method on V8WindowShell to allow us to swap the C++ pointer to point to the RemoteDOMWindow. 
 
2. Once the process swap has been triggered, we need to mirror the frame tree in the new process, so by definition, we will need to instantiate RemoteFrames. We may adapt the logic in installDOMWindow to handle this case, or maybe factor out the common bits so it doesn't get too complicated. Either case, we will install a RemoteDOMWindow as the C++ pointer directly. 
 
Finally, we will need a way to swap a RemoteFrame back to a LocalFrame, but we might be able to use the same swap function from #1.

Thanks for the details!

In that case, I think your approach will work; basically you just need to call V8WindowShell::installDOMWindow and switch the underlying C++ pointer from a LocalDOMWindow to a new RemoteDOMWindow.


We also need to figure out how to help V8WindowShell live across this swap; right now, ScriptController owns it. I don't think RemoteFrame needs a ScriptController, since you shouldn't be able to evaluate script directly in a RemoteFrame context. I don't know if we should try to factor this out (I imagine this is hard) or have some method to hand off ownership to RemoteFrame for swapping.

Currently, LocalFrame owns ScriptController, and the ScriptController owns V8WindowShell. So I guess the easiest way to hand off the ownership would be to:

- make RemoateFrame own the ScriptController, and the ScriptController own the V8WindowShell.
- but forbid the ScriptController to be used.
Reply all
Reply to author
Forward
0 new messages