For Developers‎ > ‎Design Documents‎ > ‎

Design Plans for Out-of-Process iframes

This page provides high level information on our plans to support out-of-process iframes in Chromium, as part of the Site Isolation project.

Many parts of Chromium's architecture will need to change to support rendering and interacting with a frame in a different process from its parent page.  Our intended changes include keeping track of frames in multiple processes, routing certain script calls between processes, supporting cross-process navigations in frames, rendering and compositing frames in multiple processes, and sending input events to the correct processes.


Frame Representation

We expect much of Chromium's tab-level logic will need to become frame-level, since each frame may be rendered by different processes over its lifetime.

Background

In general, web pages that have script references to each other need to either live in the same process (if they are same-site) or have a way to route messages to each other (if they are cross-site).  Chromium manages these relationships by putting all pages that can reference each other in the same BrowsingInstance, and by grouping all of a BrowsingInstance's pages into SiteInstances based on site (as described on the Process Models page).  BrowsingInstances typically contain only a single tab, but they can include multiple tabs when a page uses window.open or targeted links.  Note that BrowsingInstances are not related to the number of tabs in a window, since tabs created manually are in their own BrowsingInstance.

To support cross-process interactions like postMessage, Chromium must keep a "swapped out" version of the page's DOMWindow in each of the other processes of its BrowsingInstance, as a placeholder.  As shown in the diagram at right, this allows a page from site A to find a swapped out DOMWindow in its own process for a tab that is currently active on site B.  The swapped out DOMWindow can then forward the postMessage call to the browser and then to the correct page in the process for site B.

With out-of-process iframes, Chromium needs to keep track of swapped out DOMWindows for subframes as well as tabs.

Browser Process

In the browser process, Chromium must keep track of the full frame tree for each tab.  WebContents will host a tree of FrameTreeNode objects, mirroring the frame tree of the current page.  Each FrameTreeNode will contain frame-specific information (e.g., the frame's name).  It will be responsible for cross-process navigations in the frame, and it will support routing messages from other processes to the active frame.

Renderer Process

In each renderer process, Chromium must keep track of swapped out DOMWindows for each frame in the BrowsingInstance, allowing JavaScript code to find frames and send messages to them.  We aim to minimize the overhead for each of the swapped out DOMWindows.

We plan to pull the frame-specific logic out of the content module's RenderView and RenderViewHost classes, into new RenderFrame and RenderFrameHost classes.  These new classes will allocate their own routing ids, so IPC messages can be targeted to specific frames. We will have a full RenderFrame for every active frame, regardless of process, and we will have a corresponding, slimmed down, "swapped out" RenderFrame as a placeholder in the other processes of the BrowsingInstance.  These "swapped out" placeholders are shown with dashed lines in the diagram below, which shows one BrowsingInstance with two tabs, containing two subframes each.



Inside Blink

Note: This section is semi-obsolete. See the FrameHandle design doc for more information about some of the Blink changes.

Within Blink, we want to distinguish between active Frames that have a full page and the swapped out Frames that are only placeholders.  Conceptually, an active Frame has a normal DOMWindow and a Document, while a swapped out Frame has a RemoteDOMWindow and no Document.  We plan to refactor Frame so that the Document is only accessible via the DOMWindow (removing the direct reference from Frame to Document), which could affect large portions of the code.

Using this approach will allow us to eliminate the current swapped out logic for navigating to a "swappedout://" URL and filtering IPC messages, because a RemoteDOMWindow will have no Document.

One major implication of this change is that code in Blink cannot assume that it is possible to walk the entire DOM tree in a single process.  This will likely require changes to components such as Editor and focus tracking, among others.

Note: We are investigating ways to reduce the memory requirements of these swapped out RenderFrames and DOMWindows, because there will be many more than in Chromium today.  Today, the space required is O(tabs * processes) within a BrowsingInstance, and most BrowsingInstances only contain 1 or 2 tabs.  This new model would require O(frames * processes) space.  This could be much higher, because the number of frames can be much larger than the number of tabs, and because the number of processes will increase based on cross-site frames.  Fortunately, there are many opportunities to reduce the overhead of these placeholder objects, relative to their active equivalents.

Navigation

Chromium will add support for cross-process navigations within subframes. Rather than letting the renderer process intercept the navigation and decide if the browser process should handle it, all navigations will be intercepted in the browser process's network stack. If the navigation crosses a site boundary, the browser process will be able to swap the frame's renderer process. This can be done because the browser process knows the full frame tree, as described above. Implementing this will require adapting TransferNavigationResourceThrottle and making sufficient information available on the IO thread to make process swap decisions.

A tab's session history also becomes more complicated when subframes may be rendered by different processes. Currently, Blink takes care of tracking the frame tree in each HistoryItem in the renderer process, and the browser process just tracks each back/forward entry using NavigationEntry. We will remove the frame tracking logic from Blink's HistoryController and keep track of each frame's navigations in the browser process directly.

We will also change the representation of a tab's session history to more closely match the HTML5 spec. Rather than cloning the frame tree for each HistoryItem, we will keep track of each frame's session history separately in the browser process, and we will use a separate "joint session history" list for back and forward navigations. Each entry in this list will have a tree of pointers to each frame's corresponding session history item. We expect this to require changes to the session restore logic as well.


Rendering

To render an iframe in a different process than its parent page, the browser process will pass information back and forth between the renderer processes and help the GPU process composite the images together in the correct sizes and locations. Some of this logic may be adapted or partly reused from BrowserPlugin, which is currently being used by Chrome Packaged Apps.

The design for rendering is encapsulated in a separate document.

Input Events

We are continuing to investigate the changes required to support hit testing and delivering input events to the correct iframe process. As with rendering, we are considering how to reuse modified versions of BrowserPlugin's input event handling logic.

Discussions/Questions

The mailing list for technical discussions on Site Isolations and Out-of-Process irfames is site-isolation-dev@chromium.org.