Bug 1525720, part 11 - Use RemoteBrowser interface instead of IPDL actors in nsFrameLoader. r=nika

This commit replaces the direct use of the IPDL actors in nsFrameLoader with
the RemoteBrowser interface. Some special use cases are adapted to still use
the IPDL actors. In the future, we should burn these use cases down.

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

--HG--
extra : rebase_source : f3a53c733cfaee33bec4a74615f87fd636ddd22a
extra : histedit_source : 10c5071221fe61418ee7dc72668c99243f50087d
This commit is contained in:
Ryan Hunt 2019-05-06 21:29:48 -05:00
parent ad5807c04e
commit 9196bf1d7b
6 changed files with 114 additions and 122 deletions

View File

@ -109,6 +109,8 @@
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/BrowserBridgeChild.h"
#include "mozilla/dom/BrowserHost.h"
#include "mozilla/dom/BrowserBridgeHost.h"
#include "mozilla/dom/HTMLBodyElement.h"
@ -155,7 +157,7 @@ typedef ScrollableLayerGuid::ViewID ViewID;
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsFrameLoader, mBrowsingContext,
mMessageManager, mChildMessageManager,
mParentSHistory, mBrowserParent)
mParentSHistory)
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameLoader)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameLoader)
@ -172,7 +174,6 @@ nsFrameLoader::nsFrameLoader(Element* aOwner, BrowsingContext* aBrowsingContext,
mOwnerContent(aOwner),
mDetachedSubdocFrame(nullptr),
mPendingSwitchID(0),
mBrowserParent(nullptr),
mChildID(0),
mDepthTooGreat(false),
mIsTopLevelContent(false),
@ -197,7 +198,6 @@ nsFrameLoader::nsFrameLoader(Element* aOwner, BrowsingContext* aBrowsingContext,
mOwnerContent(aOwner),
mDetachedSubdocFrame(nullptr),
mPendingSwitchID(0),
mBrowserParent(nullptr),
mChildID(0),
mDepthTooGreat(false),
mIsTopLevelContent(false),
@ -543,28 +543,16 @@ nsresult nsFrameLoader::ReallyStartLoadingInternal() {
AUTO_PROFILER_LABEL("nsFrameLoader::ReallyStartLoadingInternal", OTHER);
if (IsRemoteFrame()) {
if (!mBrowserParent && !mBrowserBridgeChild && !TryRemoteBrowser()) {
if (!EnsureRemoteBrowser()) {
NS_WARNING("Couldn't create child process for iframe.");
return NS_ERROR_FAILURE;
}
if (mPendingSwitchID) {
if (mBrowserBridgeChild) {
Unused << mBrowserBridgeChild->SendResumeLoad(mPendingSwitchID);
} else {
mBrowserParent->ResumeLoad(mPendingSwitchID);
}
mRemoteBrowser->ResumeLoad(mPendingSwitchID);
mPendingSwitchID = 0;
} else {
if (mBrowserBridgeChild) {
nsAutoCString spec;
mURIToLoad->GetSpec(spec);
Unused << mBrowserBridgeChild->SendLoadURL(spec);
} else {
// FIXME get error codes from child
mBrowserParent->LoadURL(mURIToLoad);
}
mRemoteBrowser->LoadURL(mURIToLoad);
}
if (!mRemoteBrowserShown) {
@ -1029,7 +1017,7 @@ bool nsFrameLoader::ShowRemoteFrame(const ScreenIntSize& size,
NS_ASSERTION(IsRemoteFrame(),
"ShowRemote only makes sense on remote frames.");
if (!mBrowserParent && !mBrowserBridgeChild && !TryRemoteBrowser()) {
if (!EnsureRemoteBrowser()) {
NS_ERROR("Couldn't create child process.");
return false;
}
@ -1048,7 +1036,8 @@ bool nsFrameLoader::ShowRemoteFrame(const ScreenIntSize& size,
return false;
}
if (mBrowserBridgeChild) {
if (RefPtr<BrowserBridgeChild> browserBridgeChild =
GetBrowserBridgeChild()) {
nsCOMPtr<nsISupports> container =
mOwnerContent->OwnerDoc()->GetContainer();
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(container);
@ -1057,13 +1046,13 @@ bool nsFrameLoader::ShowRemoteFrame(const ScreenIntSize& size,
nsSizeMode sizeMode =
mainWidget ? mainWidget->SizeMode() : nsSizeMode_Normal;
Unused << mBrowserBridgeChild->SendShow(
Unused << browserBridgeChild->SendShow(
size, ParentWindowIsActive(mOwnerContent->OwnerDoc()), sizeMode);
mRemoteBrowserShown = true;
return true;
}
if (!mBrowserParent->Show(
if (!mRemoteBrowser->Show(
size, ParentWindowIsActive(mOwnerContent->OwnerDoc()))) {
return false;
}
@ -1079,11 +1068,7 @@ bool nsFrameLoader::ShowRemoteFrame(const ScreenIntSize& size,
// Don't show remote iframe if we are waiting for the completion of reflow.
if (!aFrame || !(aFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
if (mBrowserParent) {
mBrowserParent->UpdateDimensions(dimensions, size);
} else if (mBrowserBridgeChild) {
mBrowserBridgeChild->UpdateDimensions(dimensions, size);
}
mRemoteBrowser->UpdateDimensions(dimensions, size);
}
}
@ -1793,7 +1778,7 @@ void nsFrameLoader::StartDestroy() {
// Retain references to the <browser> element and the frameloader in case we
// receive any messages from the message manager on the frame. These
// references are dropped in DestroyComplete.
if (mChildMessageManager || mBrowserParent) {
if (mChildMessageManager || mRemoteBrowser) {
mOwnerContentStrong = mOwnerContent;
if (auto* browserParent = GetBrowserParent()) {
browserParent->CacheFrameLoader(this);
@ -1905,13 +1890,8 @@ void nsFrameLoader::DestroyDocShell() {
// Ask the BrowserChild to fire the frame script "unload" event, destroy its
// docshell, and finally destroy the PBrowser actor. This eventually leads to
// nsFrameLoader::DestroyComplete being called.
if (mBrowserParent) {
mBrowserParent->Destroy();
}
if (mBrowserBridgeChild) {
Unused << mBrowserBridgeChild->Send__delete__(mBrowserBridgeChild);
mBrowserBridgeChild = nullptr;
if (mRemoteBrowser) {
mRemoteBrowser->DestroyStart();
}
// Fire the "unload" event if we're in-process.
@ -1944,7 +1924,7 @@ void nsFrameLoader::DestroyComplete() {
// case, StartDestroy might not have been called.
// Drop the strong references created in StartDestroy.
if (mChildMessageManager || mBrowserParent) {
if (mChildMessageManager || mRemoteBrowser) {
mOwnerContentStrong = nullptr;
if (auto* browserParent = GetBrowserParent()) {
browserParent->CacheFrameLoader(nullptr);
@ -1955,15 +1935,9 @@ void nsFrameLoader::DestroyComplete() {
}
// Call BrowserParent::Destroy if we haven't already (in case of a crash).
if (mBrowserParent) {
mBrowserParent->SetOwnerElement(nullptr);
mBrowserParent->Destroy();
mBrowserParent = nullptr;
}
if (mBrowserBridgeChild) {
Unused << mBrowserBridgeChild->Send__delete__(mBrowserBridgeChild);
mBrowserBridgeChild = nullptr;
if (mRemoteBrowser) {
mRemoteBrowser->DestroyComplete();
mRemoteBrowser = nullptr;
}
if (mMessageManager) {
@ -2487,7 +2461,7 @@ nsresult nsFrameLoader::GetWindowDimensions(nsIntRect& aRect) {
nsresult nsFrameLoader::UpdatePositionAndSize(nsSubDocumentFrame* aIFrame) {
if (IsRemoteFrame()) {
if (mBrowserParent || mBrowserBridgeChild) {
if (mRemoteBrowser) {
ScreenIntSize size = aIFrame->GetSubdocumentSize();
// If we were not able to show remote frame before, we should probably
// retry now to send correct showInfo.
@ -2497,11 +2471,7 @@ nsresult nsFrameLoader::UpdatePositionAndSize(nsSubDocumentFrame* aIFrame) {
nsIntRect dimensions;
NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), NS_ERROR_FAILURE);
mLazySize = size;
if (mBrowserParent) {
mBrowserParent->UpdateDimensions(dimensions, size);
} else if (mBrowserBridgeChild) {
mBrowserBridgeChild->UpdateDimensions(dimensions, size);
}
mRemoteBrowser->UpdateDimensions(dimensions, size);
}
return NS_OK;
}
@ -2590,8 +2560,13 @@ static Tuple<ContentParent*, BrowserParent*> GetContentParent(
return ReturnTuple(nullptr, nullptr);
}
bool nsFrameLoader::EnsureRemoteBrowser() {
MOZ_ASSERT(IsRemoteFrame());
return mRemoteBrowser || TryRemoteBrowser();
}
bool nsFrameLoader::TryRemoteBrowser() {
NS_ASSERTION(!mBrowserParent && !mBrowserBridgeChild,
NS_ASSERTION(!mRemoteBrowser,
"TryRemoteBrowser called with a remote browser already?");
if (!mOwnerContent) {
@ -2713,16 +2688,16 @@ bool nsFrameLoader::TryRemoteBrowser() {
if (XRE_IsContentProcess()) {
mBrowsingContext->SetEmbedderElement(mOwnerContent);
mBrowserBridgeChild = ContentChild::CreateBrowser(
mRemoteBrowser = ContentChild::CreateBrowser(
this, context, NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE),
mBrowsingContext);
return !!mBrowserBridgeChild;
return !!mRemoteBrowser;
}
mBrowserParent = ContentParent::CreateBrowser(
mRemoteBrowser = ContentParent::CreateBrowser(
context, ownerElement, mBrowsingContext, openerContentParent,
sameTabGroupAs, nextRemoteTabId);
if (!mBrowserParent) {
if (!mRemoteBrowser) {
return false;
}
@ -2790,11 +2765,26 @@ bool nsFrameLoader::IsRemoteFrame() {
}
BrowserParent* nsFrameLoader::GetBrowserParent() const {
return mBrowserParent;
if (!mRemoteBrowser) {
return nullptr;
}
RefPtr<BrowserHost> browserHost = mRemoteBrowser->AsBrowserHost();
if (!browserHost) {
return nullptr;
}
return browserHost->GetActor();
}
BrowserBridgeChild* nsFrameLoader::GetBrowserBridgeChild() const {
return mBrowserBridgeChild;
if (!mRemoteBrowser) {
return nullptr;
}
RefPtr<BrowserBridgeHost> browserBridgeHost =
mRemoteBrowser->AsBrowserBridgeHost();
if (!browserBridgeHost) {
return nullptr;
}
return browserBridgeHost->GetActor();
}
mozilla::layers::LayersId nsFrameLoader::GetLayersId() const {
@ -3048,14 +3038,14 @@ already_AddRefed<Element> nsFrameLoader::GetOwnerElement() {
}
void nsFrameLoader::InitializeFromBrowserParent(BrowserParent* aBrowserParent) {
MOZ_ASSERT(!mBrowserParent);
MOZ_ASSERT(!mRemoteBrowser);
mIsRemoteFrame = true;
mBrowserParent = aBrowserParent;
mChildID = mBrowserParent ? mBrowserParent->Manager()->ChildID() : 0;
mRemoteBrowser = new BrowserHost(aBrowserParent);
mChildID = aBrowserParent ? aBrowserParent->Manager()->ChildID() : 0;
MaybeUpdatePrimaryBrowserParent(eBrowserParentChanged);
ReallyLoadFrameScripts();
InitializeBrowserAPI();
mBrowserParent->InitRendering();
aBrowserParent->InitRendering();
ShowRemoteFrame(ScreenIntSize(0, 0));
}
@ -3285,18 +3275,13 @@ already_AddRefed<mozilla::dom::Promise> nsFrameLoader::DrawSnapshot(
}
already_AddRefed<nsIRemoteTab> nsFrameLoader::GetRemoteTab() {
return do_AddRef(mBrowserParent);
return do_AddRef(GetBrowserParent());
}
already_AddRefed<nsILoadContext> nsFrameLoader::LoadContext() {
nsCOMPtr<nsILoadContext> loadContext;
if (IsRemoteFrame() &&
(mBrowserParent || mBrowserBridgeChild || TryRemoteBrowser())) {
if (mBrowserParent) {
loadContext = mBrowserParent->GetLoadContext();
} else {
loadContext = mBrowserBridgeChild->GetLoadContext();
}
if (IsRemoteFrame() && EnsureRemoteBrowser()) {
loadContext = mRemoteBrowser->GetLoadContext();
} else {
loadContext = do_GetInterface(ToSupports(GetDocShell(IgnoreErrors())));
}
@ -3305,13 +3290,8 @@ already_AddRefed<nsILoadContext> nsFrameLoader::LoadContext() {
already_AddRefed<BrowsingContext> nsFrameLoader::GetBrowsingContext() {
RefPtr<BrowsingContext> browsingContext;
if (IsRemoteFrame() &&
(mBrowserParent || mBrowserBridgeChild || TryRemoteBrowser())) {
if (mBrowserParent) {
browsingContext = mBrowserParent->GetBrowsingContext();
} else {
browsingContext = mBrowserBridgeChild->GetBrowsingContext();
}
if (IsRemoteFrame() && EnsureRemoteBrowser()) {
browsingContext = mRemoteBrowser->GetBrowsingContext();
} else if (GetDocShell(IgnoreErrors())) {
browsingContext = GetDocShell()->GetBrowsingContext();
}
@ -3381,34 +3361,41 @@ void nsFrameLoader::StartPersistence(
void nsFrameLoader::MaybeUpdatePrimaryBrowserParent(
BrowserParentChange aChange) {
if (mBrowserParent && mOwnerContent) {
nsCOMPtr<nsIDocShell> docShell = mOwnerContent->OwnerDoc()->GetDocShell();
if (!docShell) {
return;
}
if (!mOwnerContent) {
return;
}
int32_t parentType = docShell->ItemType();
if (parentType != nsIDocShellTreeItem::typeChrome) {
return;
}
RefPtr<BrowserParent> browserParent = GetBrowserParent();
if (!browserParent) {
return;
}
nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
docShell->GetTreeOwner(getter_AddRefs(parentTreeOwner));
if (!parentTreeOwner) {
return;
}
nsCOMPtr<nsIDocShell> docShell = mOwnerContent->OwnerDoc()->GetDocShell();
if (!docShell) {
return;
}
if (!mObservingOwnerContent) {
mOwnerContent->AddMutationObserver(this);
mObservingOwnerContent = true;
}
int32_t parentType = docShell->ItemType();
if (parentType != nsIDocShellTreeItem::typeChrome) {
return;
}
parentTreeOwner->RemoteTabRemoved(mBrowserParent);
if (aChange == eBrowserParentChanged) {
bool isPrimary = mOwnerContent->AttrValueIs(
kNameSpaceID_None, nsGkAtoms::primary, nsGkAtoms::_true, eIgnoreCase);
parentTreeOwner->RemoteTabAdded(mBrowserParent, isPrimary);
}
nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
docShell->GetTreeOwner(getter_AddRefs(parentTreeOwner));
if (!parentTreeOwner) {
return;
}
if (!mObservingOwnerContent) {
mOwnerContent->AddMutationObserver(this);
mObservingOwnerContent = true;
}
parentTreeOwner->RemoteTabRemoved(browserParent);
if (aChange == eBrowserParentChanged) {
bool isPrimary = mOwnerContent->AttrValueIs(
kNameSpaceID_None, nsGkAtoms::primary, nsGkAtoms::_true, eIgnoreCase);
parentTreeOwner->RemoteTabAdded(browserParent, isPrimary);
}
}

View File

@ -23,6 +23,7 @@
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ParentSHistory.h"
#include "mozilla/dom/RemoteBrowser.h"
#include "mozilla/Attributes.h"
#include "mozilla/layers/LayersTypes.h"
#include "nsStubMutationObserver.h"
@ -445,6 +446,10 @@ class nsFrameLoader final : public nsStubMutationObserver,
void FireErrorEvent();
nsresult ReallyStartLoadingInternal();
// Returns true if we have a remote browser or else attempts to create a
// remote browser and returns true if successful.
bool EnsureRemoteBrowser();
// Return true if remote browser created; nothing else to do
bool TryRemoteBrowser();
@ -492,11 +497,8 @@ class nsFrameLoader final : public nsStubMutationObserver,
// target process.
uint64_t mPendingSwitchID;
RefPtr<BrowserParent> mBrowserParent;
uint64_t mChildID;
// This is used when this refers to a remote sub frame
RefPtr<mozilla::dom::BrowserBridgeChild> mBrowserBridgeChild;
RefPtr<mozilla::dom::RemoteBrowser> mRemoteBrowser;
// Holds the last known size of the frame.
mozilla::ScreenIntSize mLazySize;

View File

@ -30,6 +30,7 @@
#include "mozilla/docshell/OfflineCacheUpdateChild.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/BrowsingContextGroup.h"
#include "mozilla/dom/BrowserBridgeHost.h"
#include "mozilla/dom/ClientManager.h"
#include "mozilla/dom/ClientOpenWindowOpActors.h"
#include "mozilla/dom/ChildProcessMessageManager.h"
@ -2007,7 +2008,7 @@ void ContentChild::UpdateCookieStatus(nsIChannel* aChannel) {
csChild->TrackCookieLoad(aChannel);
}
already_AddRefed<BrowserBridgeChild> ContentChild::CreateBrowser(
already_AddRefed<RemoteBrowser> ContentChild::CreateBrowser(
nsFrameLoader* aFrameLoader, const TabContext& aContext,
const nsString& aRemoteType, BrowsingContext* aBrowsingContext) {
MOZ_ASSERT(XRE_IsContentProcess());
@ -2054,7 +2055,9 @@ already_AddRefed<BrowserBridgeChild> ContentChild::CreateBrowser(
aBrowsingContext, chromeFlags);
browserBridge->mIPCOpen = true;
return browserBridge.forget();
RefPtr<BrowserBridgeHost> browserBridgeHost =
new BrowserBridgeHost(browserBridge);
return browserBridgeHost.forget();
}
PScriptCacheChild* ContentChild::AllocPScriptCacheChild(

View File

@ -13,6 +13,7 @@
#include "mozilla/dom/BrowserBridgeChild.h"
#include "mozilla/dom/PBrowserOrId.h"
#include "mozilla/dom/PContentChild.h"
#include "mozilla/dom/RemoteBrowser.h"
#include "mozilla/dom/CPOWManagerGetter.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/ipc/Shmem.h"
@ -162,7 +163,7 @@ class ContentChild final : public PContentChild,
static void UpdateCookieStatus(nsIChannel* aChannel);
static already_AddRefed<BrowserBridgeChild> CreateBrowser(
static already_AddRefed<RemoteBrowser> CreateBrowser(
nsFrameLoader* aFrameLoader, const TabContext& aContext,
const nsString& aRemoteType, BrowsingContext* aBrowsingContext);

View File

@ -1083,12 +1083,10 @@ mozilla::ipc::IPCResult ContentParent::RecvLaunchRDDProcess(
}
/*static*/
BrowserParent* ContentParent::CreateBrowser(const TabContext& aContext,
Element* aFrameElement,
BrowsingContext* aBrowsingContext,
ContentParent* aOpenerContentParent,
BrowserParent* aSameTabGroupAs,
uint64_t aNextRemoteTabId) {
already_AddRefed<RemoteBrowser> ContentParent::CreateBrowser(
const TabContext& aContext, Element* aFrameElement,
BrowsingContext* aBrowsingContext, ContentParent* aOpenerContentParent,
BrowserParent* aSameTabGroupAs, uint64_t aNextRemoteTabId) {
AUTO_PROFILER_LABEL("ContentParent::CreateBrowser", OTHER);
if (!sCanLaunchSubprocesses) {
@ -1105,10 +1103,11 @@ BrowserParent* ContentParent::CreateBrowser(const TabContext& aContext,
if (BrowserParent* parent =
sNextBrowserParents.GetAndRemove(aNextRemoteTabId)
.valueOr(nullptr)) {
RefPtr<BrowserHost> browserHost = new BrowserHost(parent);
MOZ_ASSERT(!parent->GetOwnerElement(),
"Shouldn't have an owner elemnt before");
parent->SetOwnerElement(aFrameElement);
return parent;
return browserHost.forget();
}
}
@ -1216,8 +1215,9 @@ BrowserParent* ContentParent::CreateBrowser(const TabContext& aContext,
Unused << browserParent->SendAwaitLargeAlloc();
}
RefPtr<BrowserHost> browserHost = new BrowserHost(browserParent);
browserParent->SetOwnerElement(aFrameElement);
return browserParent;
return browserHost.forget();
}
return nullptr;
}

View File

@ -10,6 +10,7 @@
#include "mozilla/dom/PContentParent.h"
#include "mozilla/dom/CPOWManagerGetter.h"
#include "mozilla/dom/ipc/IdType.h"
#include "mozilla/dom/RemoteBrowser.h"
#include "mozilla/gfx/gfxVarReceiver.h"
#include "mozilla/gfx/GPUProcessListener.h"
#include "mozilla/ipc/BackgroundUtils.h"
@ -208,12 +209,10 @@ class ContentParent final : public PContentParent,
* should be the frame/iframe element with which this process will
* associated.
*/
static BrowserParent* CreateBrowser(const TabContext& aContext,
Element* aFrameElement,
BrowsingContext* aBrowsingContext,
ContentParent* aOpenerContentParent,
BrowserParent* aSameTabGroupAs,
uint64_t aNextRemoteTabId);
static already_AddRefed<RemoteBrowser> CreateBrowser(
const TabContext& aContext, Element* aFrameElement,
BrowsingContext* aBrowsingContext, ContentParent* aOpenerContentParent,
BrowserParent* aSameTabGroupAs, uint64_t aNextRemoteTabId);
static void GetAll(nsTArray<ContentParent*>& aArray);