Bug 1542791 - Part 1: Support enabling out-of-process iframes with per-frame granularity, r=mconley

This code builds on top of the E10S "remote tabs" configuration system to add a
system for specifying that remote subframes should be used. Fission can be
enabled for a window by including the "fission" flag in options when opening
the window.

Differential Revision: https://phabricator.services.mozilla.com/D26560

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Nika Layzell 2019-04-17 00:53:22 +00:00
Родитель cd6b56221a
Коммит 40f96bcf80
15 изменённых файлов: 162 добавлений и 10 удалений

Просмотреть файл

@ -4541,6 +4541,9 @@ function toOpenWindowByType(inType, uri, features) {
* remote: A boolean indicating if the window should run
* remote browser tabs or not. If omitted, the window
* will choose the profile default state.
* fission: A boolean indicating if the window should run
* with fission enabled or not. If omitted, the window
* will choose the profile default state.
* }
* @return a reference to the new window.
*/
@ -4570,6 +4573,12 @@ function OpenBrowserWindow(options) {
extraFeatures += ",non-remote";
}
if (options && options.fission) {
extraFeatures += ",fission";
} else if (options && options.fission === false) {
extraFeatures += ",non-fission";
}
// If the window is maximized, we want to skip the animation, since we're
// going to be taking up most of the screen anyways, and we want to optimize
// for showing the user a useful window as soon as possible.

Просмотреть файл

@ -23,6 +23,7 @@ LoadContext::LoadContext(nsIPrincipal* aPrincipal,
mNestedFrameId(0),
mIsContent(true),
mUseRemoteTabs(false),
mUseRemoteSubframes(false),
mUseTrackingProtection(false),
#ifdef DEBUG
mIsNotNull(true),
@ -34,6 +35,8 @@ LoadContext::LoadContext(nsIPrincipal* aPrincipal,
MOZ_ALWAYS_SUCCEEDS(aOptionalBase->GetIsContent(&mIsContent));
MOZ_ALWAYS_SUCCEEDS(aOptionalBase->GetUseRemoteTabs(&mUseRemoteTabs));
MOZ_ALWAYS_SUCCEEDS(
aOptionalBase->GetUseRemoteSubframes(&mUseRemoteSubframes));
MOZ_ALWAYS_SUCCEEDS(
aOptionalBase->GetUseTrackingProtection(&mUseTrackingProtection));
}
@ -126,6 +129,24 @@ LoadContext::SetRemoteTabs(bool aUseRemoteTabs) {
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
LoadContext::GetUseRemoteSubframes(bool* aUseRemoteSubframes) {
MOZ_ASSERT(mIsNotNull);
NS_ENSURE_ARG_POINTER(aUseRemoteSubframes);
*aUseRemoteSubframes = mUseRemoteSubframes;
return NS_OK;
}
NS_IMETHODIMP
LoadContext::SetRemoteSubframes(bool aUseRemoteSubframes) {
MOZ_ASSERT(mIsNotNull);
// We shouldn't need this on parent...
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
LoadContext::GetIsInIsolatedMozBrowserElement(
bool* aIsInIsolatedMozBrowserElement) {

Просмотреть файл

@ -41,6 +41,7 @@ class LoadContext final : public nsILoadContext, public nsIInterfaceRequestor {
mNestedFrameId(0),
mIsContent(aToCopy.mIsContent),
mUseRemoteTabs(aToCopy.mUseRemoteTabs),
mUseRemoteSubframes(aToCopy.mUseRemoteSubframes),
mUseTrackingProtection(aToCopy.mUseTrackingProtection),
#ifdef DEBUG
mIsNotNull(aToCopy.mIsNotNull),
@ -56,6 +57,7 @@ class LoadContext final : public nsILoadContext, public nsIInterfaceRequestor {
mNestedFrameId(aNestedFrameId),
mIsContent(aToCopy.mIsContent),
mUseRemoteTabs(aToCopy.mUseRemoteTabs),
mUseRemoteSubframes(aToCopy.mUseRemoteSubframes),
mUseTrackingProtection(aToCopy.mUseTrackingProtection),
#ifdef DEBUG
mIsNotNull(aToCopy.mIsNotNull),
@ -65,11 +67,13 @@ class LoadContext final : public nsILoadContext, public nsIInterfaceRequestor {
LoadContext(dom::Element* aTopFrameElement, bool aIsContent,
bool aUsePrivateBrowsing, bool aUseRemoteTabs,
bool aUseTrackingProtection, const OriginAttributes& aAttrs)
bool aUseRemoteSubframes, bool aUseTrackingProtection,
const OriginAttributes& aAttrs)
: mTopFrameElement(do_GetWeakReference(aTopFrameElement)),
mNestedFrameId(0),
mIsContent(aIsContent),
mUseRemoteTabs(aUseRemoteTabs),
mUseRemoteSubframes(aUseRemoteSubframes),
mUseTrackingProtection(aUseTrackingProtection),
#ifdef DEBUG
mIsNotNull(true),
@ -85,6 +89,7 @@ class LoadContext final : public nsILoadContext, public nsIInterfaceRequestor {
mNestedFrameId(0),
mIsContent(false),
mUseRemoteTabs(false),
mUseRemoteSubframes(false),
mUseTrackingProtection(false),
#ifdef DEBUG
mIsNotNull(true),
@ -104,6 +109,7 @@ class LoadContext final : public nsILoadContext, public nsIInterfaceRequestor {
uint64_t mNestedFrameId;
bool mIsContent;
bool mUseRemoteTabs;
bool mUseRemoteSubframes;
bool mUseTrackingProtection;
#ifdef DEBUG
bool mIsNotNull;

Просмотреть файл

@ -13,12 +13,18 @@
namespace IPC {
SerializedLoadContext::SerializedLoadContext(nsILoadContext* aLoadContext)
: mIsContent(false), mUseRemoteTabs(false), mUseTrackingProtection(false) {
: mIsContent(false),
mUseRemoteTabs(false),
mUseRemoteSubframes(false),
mUseTrackingProtection(false) {
Init(aLoadContext);
}
SerializedLoadContext::SerializedLoadContext(nsIChannel* aChannel)
: mIsContent(false), mUseRemoteTabs(false), mUseTrackingProtection(false) {
: mIsContent(false),
mUseRemoteTabs(false),
mUseRemoteSubframes(false),
mUseTrackingProtection(false) {
if (!aChannel) {
Init(nullptr);
return;
@ -45,7 +51,10 @@ SerializedLoadContext::SerializedLoadContext(nsIChannel* aChannel)
}
SerializedLoadContext::SerializedLoadContext(nsIWebSocketChannel* aChannel)
: mIsContent(false), mUseRemoteTabs(false), mUseTrackingProtection(false) {
: mIsContent(false),
mUseRemoteTabs(false),
mUseRemoteSubframes(false),
mUseTrackingProtection(false) {
nsCOMPtr<nsILoadContext> loadContext;
if (aChannel) {
NS_QueryNotificationCallbacks(aChannel, loadContext);
@ -59,6 +68,7 @@ void SerializedLoadContext::Init(nsILoadContext* aLoadContext) {
mIsPrivateBitValid = true;
aLoadContext->GetIsContent(&mIsContent);
aLoadContext->GetUseRemoteTabs(&mUseRemoteTabs);
aLoadContext->GetUseRemoteSubframes(&mUseRemoteSubframes);
aLoadContext->GetUseTrackingProtection(&mUseTrackingProtection);
aLoadContext->GetOriginAttributes(mOriginAttributes);
} else {
@ -68,6 +78,7 @@ void SerializedLoadContext::Init(nsILoadContext* aLoadContext) {
// we won't be GetInterfaced to nsILoadContext
mIsContent = true;
mUseRemoteTabs = false;
mUseRemoteSubframes = false;
mUseTrackingProtection = false;
}
}

Просмотреть файл

@ -31,6 +31,7 @@ class SerializedLoadContext {
mIsPrivateBitValid(false),
mIsContent(false),
mUseRemoteTabs(false),
mUseRemoteSubframes(false),
mUseTrackingProtection(false) {
Init(nullptr);
}
@ -51,6 +52,7 @@ class SerializedLoadContext {
bool mIsPrivateBitValid;
bool mIsContent;
bool mUseRemoteTabs;
bool mUseRemoteSubframes;
bool mUseTrackingProtection;
mozilla::OriginAttributes mOriginAttributes;
};
@ -68,6 +70,7 @@ struct ParamTraits<SerializedLoadContext> {
WriteParam(aMsg, aParam.mIsContent);
WriteParam(aMsg, aParam.mIsPrivateBitValid);
WriteParam(aMsg, aParam.mUseRemoteTabs);
WriteParam(aMsg, aParam.mUseRemoteSubframes);
WriteParam(aMsg, aParam.mUseTrackingProtection);
WriteParam(aMsg, suffix);
}
@ -79,6 +82,7 @@ struct ParamTraits<SerializedLoadContext> {
!ReadParam(aMsg, aIter, &aResult->mIsContent) ||
!ReadParam(aMsg, aIter, &aResult->mIsPrivateBitValid) ||
!ReadParam(aMsg, aIter, &aResult->mUseRemoteTabs) ||
!ReadParam(aMsg, aIter, &aResult->mUseRemoteSubframes) ||
!ReadParam(aMsg, aIter, &aResult->mUseTrackingProtection) ||
!ReadParam(aMsg, aIter, &suffix)) {
return false;

Просмотреть файл

@ -368,6 +368,7 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext)
mIsAppTab(false),
mUseGlobalHistory(false),
mUseRemoteTabs(false),
mUseRemoteSubframes(false),
mUseTrackingProtection(false),
mDeviceSizeIsPageSize(false),
mWindowDraggingAllowed(false),
@ -1526,10 +1527,36 @@ nsDocShell::SetRemoteTabs(bool aUseRemoteTabs) {
true);
}
// Don't allow non-remote tabs with remote subframes.
if (NS_WARN_IF(!aUseRemoteTabs && mUseRemoteSubframes)) {
return NS_ERROR_UNEXPECTED;
}
mUseRemoteTabs = aUseRemoteTabs;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetUseRemoteSubframes(bool* aUseRemoteSubframes) {
NS_ENSURE_ARG_POINTER(aUseRemoteSubframes);
*aUseRemoteSubframes = mUseRemoteSubframes;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetRemoteSubframes(bool aUseRemoteSubframes) {
// Should we annotate crash reports like in aUseRemoteTabs?
// Don't allow non-remote tabs with remote subframes.
if (NS_WARN_IF(aUseRemoteSubframes && !mUseRemoteTabs)) {
return NS_ERROR_UNEXPECTED;
}
mUseRemoteSubframes = aUseRemoteSubframes;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetAffectPrivateSessionLifetime(bool aAffectLifetime) {
MOZ_ASSERT(!mIsBeingDestroyed);

Просмотреть файл

@ -243,6 +243,8 @@ class nsDocShell final : public nsDocLoader,
NS_IMETHOD SetPrivateBrowsing(bool) override;
NS_IMETHOD GetUseRemoteTabs(bool*) override;
NS_IMETHOD SetRemoteTabs(bool) override;
NS_IMETHOD GetUseRemoteSubframes(bool*) override;
NS_IMETHOD SetRemoteSubframes(bool) override;
NS_IMETHOD GetScriptableOriginAttributes(
JSContext*, JS::MutableHandle<JS::Value>) override;
NS_IMETHOD_(void)
@ -1146,6 +1148,7 @@ class nsDocShell final : public nsDocLoader,
bool mIsAppTab : 1;
bool mUseGlobalHistory : 1;
bool mUseRemoteTabs : 1;
bool mUseRemoteSubframes : 1;
bool mUseTrackingProtection : 1;
bool mDeviceSizeIsPageSize : 1;
bool mWindowDraggingAllowed : 1;

Просмотреть файл

@ -81,6 +81,11 @@ interface nsILoadContext : nsISupports
*/
readonly attribute boolean useRemoteTabs;
/**
* Determines if out-of-process iframes should be used.
*/
readonly attribute boolean useRemoteSubframes;
/*
* Attribute that determines if tracking protection should be used. May not be
* changed after a document has been loaded in this context.
@ -105,6 +110,13 @@ interface nsILoadContext : nsISupports
return usingRT;
}
bool UseRemoteSubframes()
{
bool usingRSF = false;
GetUseRemoteSubframes(&usingRSF);
return usingRSF;
}
bool UseTrackingProtection()
{
bool usingTP = false;
@ -123,6 +135,11 @@ interface nsILoadContext : nsISupports
*/
[noscript] void SetRemoteTabs(in boolean aUseRemoteTabs);
/**
* Set the remote subframes bit of this load context. Exclusively meant to be used internally.
*/
[noscript] void SetRemoteSubframes(in boolean aUseRemoteSubframes);
/**
* Returns true iff the load is occurring inside an isolated mozbrowser
* element. <xul:browser> is not considered to be a mozbrowser element.

Просмотреть файл

@ -563,6 +563,8 @@ nsresult TabChild::Init(mozIDOMWindowProxy* aParent) {
loadContext->SetPrivateBrowsing(OriginAttributesRef().mPrivateBrowsingId > 0);
loadContext->SetRemoteTabs(mChromeFlags &
nsIWebBrowserChrome::CHROME_REMOTE_WINDOW);
loadContext->SetRemoteSubframes(mChromeFlags &
nsIWebBrowserChrome::CHROME_FISSION_WINDOW);
// Few lines before, baseWindow->Create() will end up creating a new
// window root in nsGlobalWindow::SetDocShell.

Просмотреть файл

@ -2911,6 +2911,7 @@ already_AddRefed<nsILoadContext> TabParent::GetLoadContext() {
loadContext = new LoadContext(
GetOwnerElement(), true /* aIsContent */, isPrivate,
mChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW,
mChromeFlags & nsIWebBrowserChrome::CHROME_FISSION_WINDOW,
useTrackingProtection, OriginAttributesRef());
mLoadContext = loadContext;
}
@ -3400,6 +3401,8 @@ class FakeChannel final : public nsIChannel,
GetOriginAttributes(mozilla::OriginAttributes& aAttrs) override {}
NS_IMETHOD GetUseRemoteTabs(bool*) NO_IMPL;
NS_IMETHOD SetRemoteTabs(bool) NO_IMPL;
NS_IMETHOD GetUseRemoteSubframes(bool*) NO_IMPL;
NS_IMETHOD SetRemoteSubframes(bool) NO_IMPL;
NS_IMETHOD GetUseTrackingProtection(bool*) NO_IMPL;
NS_IMETHOD SetUseTrackingProtection(bool) NO_IMPL;
#undef NO_IMPL

Просмотреть файл

@ -70,6 +70,9 @@ interface nsIWebBrowserChrome : nsISupports
// Whether this window should use remote (out-of-process) tabs.
const unsigned long CHROME_REMOTE_WINDOW = 0x00100000;
// Whether this window should use out-of-process cross-origin subframes.
const unsigned long CHROME_FISSION_WINDOW = 0x00200000;
// Prevents new window animations on MacOS and Windows. Currently
// ignored for Linux.
const unsigned long CHROME_SUPPRESS_ANIMATION = 0x01000000;

Просмотреть файл

@ -598,6 +598,13 @@ nsAppStartup::CreateChromeWindow2(nsIWebBrowserChrome *aParent,
(aChromeFlags & nsIWebBrowserChrome::CHROME_MODAL) == 0)
return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
// Fission windows must also be marked as remote
if ((aChromeFlags & nsIWebBrowserChrome::CHROME_FISSION_WINDOW) &&
!(aChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW)) {
NS_WARNING("Cannot create non-remote fission window!");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIXULWindow> newWindow;
if (aParent) {

Просмотреть файл

@ -468,6 +468,7 @@ nsWindowWatcher::OpenWindowWithTabParent(
return NS_ERROR_UNEXPECTED;
}
bool isFissionWindow = Preferences::GetBool("fission.autostart");
bool isPrivateBrowsingWindow =
Preferences::GetBool("browser.privatebrowsing.autostart");
@ -478,13 +479,13 @@ nsWindowWatcher::OpenWindowWithTabParent(
TabParent* openingTab = TabParent::GetFrom(aOpeningTabParent);
parentWindowOuter = openingTab->GetParentWindowOuter();
// Propagate the privacy status of the parent window, if
// Propagate the privacy & fission status of the parent window, if
// available, to the child.
if (!isPrivateBrowsingWindow) {
nsCOMPtr<nsILoadContext> parentContext = openingTab->GetLoadContext();
if (parentContext) {
isPrivateBrowsingWindow = parentContext->UsePrivateBrowsing();
}
nsCOMPtr<nsILoadContext> parentContext = openingTab->GetLoadContext();
if (parentContext) {
isFissionWindow = parentContext->UseRemoteSubframes();
isPrivateBrowsingWindow =
isPrivateBrowsingWindow || parentContext->UsePrivateBrowsing();
}
}
@ -517,6 +518,10 @@ nsWindowWatcher::OpenWindowWithTabParent(
// that the new window will need to be remote.
chromeFlags |= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;
if (isFissionWindow) {
chromeFlags |= nsIWebBrowserChrome::CHROME_FISSION_WINDOW;
}
nsCOMPtr<nsIWebBrowserChrome> parentChrome(do_GetInterface(parentTreeOwner));
nsCOMPtr<nsIWebBrowserChrome> newWindowChrome;
@ -546,6 +551,7 @@ nsWindowWatcher::OpenWindowWithTabParent(
}
chromeContext->SetPrivateBrowsing(isPrivateBrowsingWindow);
chromeContext->SetRemoteSubframes(isFissionWindow);
// Tabs opened from a content process can only open new windows
// that will also run with out-of-process tabs.
@ -1036,6 +1042,8 @@ nsresult nsWindowWatcher::OpenWindowInternal(
// tabs should be used.
bool isRemoteWindow =
!!(chromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW);
bool isFissionWindow =
!!(chromeFlags & nsIWebBrowserChrome::CHROME_FISSION_WINDOW);
if (isNewToplevelWindow) {
nsCOMPtr<nsIDocShellTreeItem> childRoot;
@ -1044,12 +1052,14 @@ nsresult nsWindowWatcher::OpenWindowInternal(
if (childContext) {
childContext->SetPrivateBrowsing(isPrivateBrowsingWindow);
childContext->SetRemoteTabs(isRemoteWindow);
childContext->SetRemoteSubframes(isFissionWindow);
}
} else if (windowIsNew) {
nsCOMPtr<nsILoadContext> childContext = do_QueryInterface(newDocShellItem);
if (childContext) {
childContext->SetPrivateBrowsing(isPrivateBrowsingWindow);
childContext->SetRemoteTabs(isRemoteWindow);
childContext->SetRemoteSubframes(isFissionWindow);
}
}
@ -1755,6 +1765,19 @@ uint32_t nsWindowWatcher::CalculateChromeFlagsForParent(
chromeFlags |= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;
}
// Determine whether the window should have remote subframes
bool fission = Preferences::GetBool("fission.autostart");
if (fission) {
fission = !WinHasOption(aFeatures, "non-fission", 0, &presenceFlag);
} else {
fission = WinHasOption(aFeatures, "fission", 0, &presenceFlag);
}
if (fission) {
chromeFlags |= nsIWebBrowserChrome::CHROME_FISSION_WINDOW;
}
chromeFlags |= WinHasOption(aFeatures, "popup", 0, &presenceFlag)
? nsIWebBrowserChrome::CHROME_WINDOW_POPUP
: 0;

Просмотреть файл

@ -230,6 +230,16 @@ OfflineCacheUpdateParent::SetRemoteTabs(bool aUseRemoteTabs) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::GetUseRemoteSubframes(bool* aUseRemoteSubframes) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::SetRemoteSubframes(bool aUseRemoteSubframes) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::GetIsInIsolatedMozBrowserElement(
bool* aIsInIsolatedMozBrowserElement) {

Просмотреть файл

@ -704,6 +704,7 @@ nsresult nsAppShellService::JustCreateTopWindow(
bool isPrivateBrowsingWindow =
Preferences::GetBool("browser.privatebrowsing.autostart");
bool isUsingRemoteTabs = mozilla::BrowserTabsRemoteAutostart();
bool isUsingRemoteSubframes = Preferences::GetBool("fission.autostart");
if (aChromeMask & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW) {
// Caller requested a private window
@ -712,6 +713,9 @@ nsresult nsAppShellService::JustCreateTopWindow(
if (aChromeMask & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW) {
isUsingRemoteTabs = true;
}
if (aChromeMask & nsIWebBrowserChrome::CHROME_FISSION_WINDOW) {
isUsingRemoteSubframes = true;
}
nsCOMPtr<mozIDOMWindowProxy> domWin = do_GetInterface(aParent);
nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(domWin);
@ -726,6 +730,7 @@ nsresult nsAppShellService::JustCreateTopWindow(
if (parentContext) {
isUsingRemoteTabs = parentContext->UseRemoteTabs();
isUsingRemoteSubframes = parentContext->UseRemoteSubframes();
}
nsCOMPtr<mozIDOMWindowProxy> newDomWin =
@ -735,6 +740,7 @@ nsresult nsAppShellService::JustCreateTopWindow(
if (thisContext) {
thisContext->SetPrivateBrowsing(isPrivateBrowsingWindow);
thisContext->SetRemoteTabs(isUsingRemoteTabs);
thisContext->SetRemoteSubframes(isUsingRemoteSubframes);
}
window.forget(aResult);