Bug 1500257 part 4 - Modify nsFrameLoader to create PRemoteFrame when enabled via pref and attribute. r=qdot

This commit hooks up nsFrameLoader in the child process to use the
PRemoteFrame protocol to support remote iframes. This is only activated
when a special pref is set, and the iframe has a marker attribute on it.

For example:
<iframe fission/>

In the future, we should unify nsFrameLoader to operate on a common
interface between the parent process top-level browser, and child
process subframe case. This commit just adds a new member that can
be used instead of mRemoteBrowser, when appropriate. IsRemoteFrame()
will return true for both cases.

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

--HG--
extra : source : e33b9de7283e5fb6441e118b25af8d4ac3411bf2
extra : intermediate-source : 697a9159e0d260118ee6ebd34948d187a8c5359f
This commit is contained in:
Ryan Hunt 2019-01-23 10:56:27 -06:00
parent deb91798a8
commit 0d69472e8b
3 changed files with 58 additions and 17 deletions

View File

@ -101,6 +101,8 @@
#include "mozilla/dom/ParentSHistory.h"
#include "mozilla/dom/ChildSHistory.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/RemoteFrameChild.h"
#include "mozilla/dom/HTMLBodyElement.h"
@ -349,7 +351,7 @@ nsresult nsFrameLoader::ReallyStartLoadingInternal() {
AUTO_PROFILER_LABEL("nsFrameLoader::ReallyStartLoadingInternal", OTHER);
if (IsRemoteFrame()) {
if (!mRemoteBrowser && !TryRemoteBrowser()) {
if (!mRemoteBrowser && !mRemoteFrameChild && !TryRemoteBrowser()) {
NS_WARNING("Couldn't create child process for iframe.");
return NS_ERROR_FAILURE;
}
@ -790,7 +792,7 @@ bool nsFrameLoader::ShowRemoteFrame(const ScreenIntSize& size,
NS_ASSERTION(IsRemoteFrame(),
"ShowRemote only makes sense on remote frames.");
if (!mRemoteBrowser && !TryRemoteBrowser()) {
if (!mRemoteBrowser && !mRemoteFrameChild && !TryRemoteBrowser()) {
NS_ERROR("Couldn't create child process.");
return false;
}
@ -1648,6 +1650,11 @@ void nsFrameLoader::DestroyDocShell() {
mRemoteBrowser->Destroy();
}
if (mRemoteFrameChild) {
Unused << mRemoteFrameChild->Send__delete__(mRemoteFrameChild);
mRemoteFrameChild = nullptr;
}
// Fire the "unload" event if we're in-process.
if (mChildMessageManager) {
mChildMessageManager->FireUnloadEvent();
@ -1689,6 +1696,11 @@ void nsFrameLoader::DestroyComplete() {
mRemoteBrowser = nullptr;
}
if (mRemoteFrameChild) {
Unused << mRemoteFrameChild->Send__delete__(mRemoteFrameChild);
mRemoteFrameChild = nullptr;
}
if (mMessageManager) {
mMessageManager->Disconnect();
}
@ -1764,6 +1776,13 @@ bool nsFrameLoader::ShouldUseRemoteProcess() {
return false;
}
// Check if the force fission test attribute is enabled.
if (XRE_IsContentProcess() &&
Preferences::GetBool("browser.fission.oopif.attribute", false) &&
mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::fission)) {
return true;
}
if (XRE_IsContentProcess() &&
!(PR_GetEnv("MOZ_NESTED_OOP_TABS") ||
Preferences::GetBool("dom.ipc.tabs.nested.enabled", false))) {
@ -1785,14 +1804,6 @@ bool nsFrameLoader::ShouldUseRemoteProcess() {
nsGkAtoms::_true, eCaseMatters);
}
bool nsFrameLoader::IsRemoteFrame() {
if (mRemoteFrame) {
MOZ_ASSERT(!mDocShell, "Found a remote frame with a DocShell");
return true;
}
return false;
}
static already_AddRefed<BrowsingContext> CreateBrowsingContext(
BrowsingContext* aParentContext, BrowsingContext* aOpenerContext,
const nsAString& aName, bool aIsContent) {
@ -2371,7 +2382,7 @@ static Tuple<ContentParent*, TabParent*> GetContentParent(Element* aBrowser) {
}
bool nsFrameLoader::TryRemoteBrowser() {
NS_ASSERTION(!mRemoteBrowser,
NS_ASSERTION(!mRemoteBrowser && !mRemoteFrameChild,
"TryRemoteBrowser called with a remote browser already?");
if (!mOwnerContent) {
@ -2417,7 +2428,9 @@ bool nsFrameLoader::TryRemoteBrowser() {
// iframes for JS plugins also get to skip these checks. We control the URL
// that gets loaded, but the load is triggered from the document containing
// the plugin.
if (!OwnerIsMozBrowserFrame() && !IsForJSPlugin()) {
// out of process iframes also get to skip this check.
if (!OwnerIsMozBrowserFrame() && !IsForJSPlugin() &&
!XRE_IsContentProcess()) {
if (parentDocShell->ItemType() != nsIDocShellTreeItem::typeChrome) {
// Allow about:addon an exception to this rule so it can load remote
// extension options pages.
@ -2487,6 +2500,14 @@ bool nsFrameLoader::TryRemoteBrowser() {
}
nsCOMPtr<Element> ownerElement = mOwnerContent;
// If we're in a content process, create a RemoteFrameChild actor.
if (XRE_IsContentProcess()) {
mRemoteFrameChild = RemoteFrameChild::Create(
this, context, NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE));
return !!mRemoteFrameChild;
}
mRemoteBrowser =
ContentParent::CreateBrowser(context, ownerElement, openerContentParent,
sameTabGroupAs, nextTabParentId);
@ -2546,6 +2567,14 @@ bool nsFrameLoader::TryRemoteBrowser() {
return true;
}
bool nsFrameLoader::IsRemoteFrame() {
if (mRemoteFrame) {
MOZ_ASSERT(!mDocShell, "Found a remote frame with a DocShell");
return true;
}
return false;
}
mozilla::dom::PBrowserParent* nsFrameLoader::GetRemoteBrowser() const {
return mRemoteBrowser;
}

View File

@ -58,6 +58,7 @@ class ProcessMessageManager;
class Promise;
class TabParent;
class MutableTabContext;
class RemoteFrameChild;
namespace ipc {
class StructuredCloneData;
@ -270,6 +271,18 @@ class nsFrameLoader final : public nsStubMutationObserver,
return mOwnerContent ? mOwnerContent->OwnerDoc() : nullptr;
}
/**
* Returns whether this frame is a remote frame.
*
* This is true for either a top-level remote browser in the parent process,
* or a remote subframe in the child process.
*/
bool IsRemoteFrame();
/**
* Returns the IPDL actor used if this is a top-level remote browser, or null
* otherwise.
*/
PBrowserParent* GetRemoteBrowser() const;
/**
@ -358,11 +371,6 @@ class nsFrameLoader final : public nsStubMutationObserver,
bool ShouldUseRemoteProcess();
/**
* Return true if the frame is a remote frame. Return false otherwise
*/
bool IsRemoteFrame();
bool IsForJSPlugin() { return mJSPluginID != nsFakePluginTag::NOT_JSPLUGIN; }
/**
@ -456,6 +464,9 @@ class nsFrameLoader final : public nsStubMutationObserver,
TabParent* mRemoteBrowser;
uint64_t mChildID;
// This is used when this refers to a remote sub frame
RefPtr<mozilla::dom::RemoteFrameChild> mRemoteFrameChild;
int32_t mJSPluginID;
// Holds the last known size of the frame.

View File

@ -424,6 +424,7 @@ STATIC_ATOMS = [
Atom("figure", "figure"),
Atom("findbar", "findbar"),
Atom("fixed", "fixed"),
Atom("fission", "fission"),
Atom("flags", "flags"),
Atom("flex", "flex"),
Atom("flip", "flip"),