Bug 1523638 - Part 5: Create a WindowGlobal actor during normal PBrowser construction, r=kmag

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Nika Layzell 2019-08-08 16:07:05 +00:00
Родитель 4b42c1ee29
Коммит 4a51ab6ceb
16 изменённых файлов: 141 добавлений и 43 удалений

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

@ -13,6 +13,7 @@
#include "mozilla/dom/ContentProcessManager.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/BrowsingContextGroup.h"
#include "mozilla/dom/WindowGlobalParent.h"
#include "mozilla/layers/InputAPZContext.h"
using namespace mozilla::ipc;
@ -34,10 +35,13 @@ BrowserBridgeParent::~BrowserBridgeParent() { Destroy(); }
nsresult BrowserBridgeParent::Init(const nsString& aPresentationURL,
const nsString& aRemoteType,
CanonicalBrowsingContext* aBrowsingContext,
const WindowGlobalInit& aWindowInit,
const uint32_t& aChromeFlags, TabId aTabId) {
mIPCOpen = true;
RefPtr<CanonicalBrowsingContext> browsingContext =
aWindowInit.browsingContext()->Canonical();
// We can inherit most TabContext fields for the new BrowserParent actor from
// our Manager BrowserParent.
MutableTabContext tabContext;
@ -59,8 +63,8 @@ nsresult BrowserBridgeParent::Init(const nsString& aPresentationURL,
// Ensure that our content process is subscribed to our newly created
// BrowsingContextGroup.
aBrowsingContext->Group()->EnsureSubscribed(constructorSender);
aBrowsingContext->SetOwnerProcessId(constructorSender->ChildID());
browsingContext->Group()->EnsureSubscribed(constructorSender);
browsingContext->SetOwnerProcessId(constructorSender->ChildID());
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
cpm->RegisterRemoteFrame(aTabId, ContentParentId(0), TabId(0),
@ -68,8 +72,8 @@ nsresult BrowserBridgeParent::Init(const nsString& aPresentationURL,
constructorSender->ChildID());
// Construct the BrowserParent object for our subframe.
RefPtr<BrowserParent> browserParent(new BrowserParent(
constructorSender, aTabId, tabContext, aBrowsingContext, aChromeFlags));
auto browserParent = MakeRefPtr<BrowserParent>(
constructorSender, aTabId, tabContext, browsingContext, aChromeFlags);
browserParent->SetBrowserBridgeParent(this);
// Open a remote endpoint for our PBrowser actor. DeallocPBrowserParent
@ -81,11 +85,23 @@ nsresult BrowserBridgeParent::Init(const nsString& aPresentationURL,
return NS_ERROR_FAILURE;
}
auto windowParent =
MakeRefPtr<WindowGlobalParent>(aWindowInit, /* inprocess */ false);
// DeallocPWindowGlobalParent releases the ref taken.
ManagedEndpoint<PWindowGlobalChild> windowChildEp =
browserParent->OpenPWindowGlobalEndpoint(do_AddRef(windowParent).take());
if (NS_WARN_IF(!windowChildEp.IsValid())) {
MOZ_ASSERT(false, "WindowGlobal Open Endpoint Failed");
return NS_ERROR_FAILURE;
}
// Tell the content process to set up its PBrowserChild.
bool ok = constructorSender->SendConstructBrowser(
std::move(childEp), aTabId, TabId(0), tabContext.AsIPCTabContext(),
aBrowsingContext, aChromeFlags, constructorSender->ChildID(),
constructorSender->IsForBrowser(), /* aIsTopLevel */ false);
std::move(childEp), std::move(windowChildEp), aTabId, TabId(0),
tabContext.AsIPCTabContext(), aWindowInit, aChromeFlags,
constructorSender->ChildID(), constructorSender->IsForBrowser(),
/* aIsTopLevel */ false);
if (NS_WARN_IF(!ok)) {
MOZ_ASSERT(false, "Browser Constructor Failed");
return NS_ERROR_FAILURE;
@ -96,6 +112,8 @@ nsresult BrowserBridgeParent::Init(const nsString& aPresentationURL,
mBrowserParent->SetOwnerElement(Manager()->GetOwnerElement());
mBrowserParent->InitRendering();
windowParent->Init(aWindowInit);
// Send the newly created layers ID back into content.
Unused << SendSetLayersId(mBrowserParent->GetLayersId());
return NS_OK;

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

@ -33,7 +33,7 @@ class BrowserBridgeParent : public PBrowserBridgeParent {
// Initialize this actor after performing startup.
nsresult Init(const nsString& aPresentationURL, const nsString& aRemoteType,
CanonicalBrowsingContext* aBrowsingContext,
const WindowGlobalInit& aWindowInit,
const uint32_t& aChromeFlags, TabId aTabId);
BrowserParent* GetBrowserParent() { return mBrowserParent; }

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

@ -492,8 +492,11 @@ bool BrowserChild::DoUpdateZoomConstraints(
return true;
}
nsresult BrowserChild::Init(mozIDOMWindowProxy* aParent) {
nsresult BrowserChild::Init(mozIDOMWindowProxy* aParent,
WindowGlobalChild* aInitialWindowChild) {
MOZ_DIAGNOSTIC_ASSERT(mTabGroup);
MOZ_ASSERT_IF(aInitialWindowChild,
aInitialWindowChild->BrowsingContext() == mBrowsingContext);
nsCOMPtr<nsIWidget> widget = nsIWidget::CreatePuppetWidget(this);
mPuppetWidget = static_cast<PuppetWidget*>(widget.get());
@ -504,8 +507,7 @@ nsresult BrowserChild::Init(mozIDOMWindowProxy* aParent) {
mPuppetWidget->InfallibleCreate(nullptr,
nullptr, // no parents
LayoutDeviceIntRect(0, 0, 0, 0),
nullptr // HandleWidgetEvent
);
nullptr); // HandleWidgetEvent
mWebBrowser = nsWebBrowser::Create(this, mPuppetWidget, OriginAttributesRef(),
mBrowsingContext);

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

@ -190,7 +190,8 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
const TabContext& aContext, BrowsingContext* aBrowsingContext,
uint32_t aChromeFlags, bool aIsTopLevel);
nsresult Init(mozIDOMWindowProxy* aParent);
nsresult Init(mozIDOMWindowProxy* aParent,
WindowGlobalChild* aInitialWindowChild);
/** Return a BrowserChild with the given attributes. */
static already_AddRefed<BrowserChild> Create(

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

@ -1256,11 +1256,10 @@ bool BrowserParent::DeallocPWindowGlobalParent(PWindowGlobalParent* aActor) {
IPCResult BrowserParent::RecvPBrowserBridgeConstructor(
PBrowserBridgeParent* aActor, const nsString& aName,
const nsString& aRemoteType, BrowsingContext* aBrowsingContext,
const nsString& aRemoteType, const WindowGlobalInit& aWindowInit,
const uint32_t& aChromeFlags, const TabId& aTabId) {
nsresult rv = static_cast<BrowserBridgeParent*>(aActor)->Init(
aName, aRemoteType, CanonicalBrowsingContext::Cast(aBrowsingContext),
aChromeFlags, aTabId);
aName, aRemoteType, aWindowInit, aChromeFlags, aTabId);
if (NS_FAILED(rv)) {
return IPC_FAIL(this, "Failed to construct BrowserBridgeParent");
}
@ -1269,7 +1268,7 @@ IPCResult BrowserParent::RecvPBrowserBridgeConstructor(
already_AddRefed<PBrowserBridgeParent> BrowserParent::AllocPBrowserBridgeParent(
const nsString& aName, const nsString& aRemoteType,
BrowsingContext* aBrowsingContext, const uint32_t& aChromeFlags,
const WindowGlobalInit& aWindowInit, const uint32_t& aChromeFlags,
const TabId& aTabId) {
return do_AddRef(new BrowserBridgeParent());
}

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

@ -481,12 +481,12 @@ class BrowserParent final : public PBrowserParent,
already_AddRefed<PBrowserBridgeParent> AllocPBrowserBridgeParent(
const nsString& aPresentationURL, const nsString& aRemoteType,
BrowsingContext* aBrowsingContext, const uint32_t& aChromeFlags,
const WindowGlobalInit& aWindowInit, const uint32_t& aChromeFlags,
const TabId& aTabId);
virtual mozilla::ipc::IPCResult RecvPBrowserBridgeConstructor(
PBrowserBridgeParent* aActor, const nsString& aPresentationURL,
const nsString& aRemoteType, BrowsingContext* aBrowsingContext,
const nsString& aRemoteType, const WindowGlobalInit& aWindowInit,
const uint32_t& aChromeFlags, const TabId& aTabId) override;
void LoadURL(nsIURI* aURI);

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

@ -56,6 +56,7 @@
#include "mozilla/dom/ServiceWorkerManager.h"
#include "mozilla/dom/TabGroup.h"
#include "mozilla/dom/URLClassifierChild.h"
#include "mozilla/dom/WindowGlobalChild.h"
#include "mozilla/dom/WorkerDebugger.h"
#include "mozilla/dom/WorkerDebuggerManager.h"
#include "mozilla/dom/ipc/SharedMap.h"
@ -975,9 +976,10 @@ nsresult ContentChild::ProvideWindowCommon(
nullptr, openerBC, aName, BrowsingContext::Type::Content);
TabContext newTabContext = aTabOpener ? *aTabOpener : TabContext();
RefPtr<BrowserChild> newChild =
new BrowserChild(this, tabId, tabGroup, newTabContext, browsingContext,
aChromeFlags, /* aIsTopLevel */ true);
auto newChild = MakeRefPtr<BrowserChild>(
this, tabId, tabGroup, newTabContext, browsingContext,
/* aInitialWindowChild */ nullptr, aChromeFlags, /* aIsTopLevel */ true);
if (aTabOpener) {
MOZ_ASSERT(ipcContext->type() == IPCTabContext::TPopupIPCTabContext);
@ -1806,9 +1808,10 @@ bool ContentChild::DeallocPJavaScriptChild(PJavaScriptChild* aChild) {
}
mozilla::ipc::IPCResult ContentChild::RecvConstructBrowser(
ManagedEndpoint<PBrowserChild>&& aBrowserEp, const TabId& aTabId,
ManagedEndpoint<PBrowserChild>&& aBrowserEp,
ManagedEndpoint<PWindowGlobalChild>&& aWindowEp, const TabId& aTabId,
const TabId& aSameTabGroupAs, const IPCTabContext& aContext,
BrowsingContext* aBrowsingContext, const uint32_t& aChromeFlags,
const WindowGlobalInit& aWindowInit, const uint32_t& aChromeFlags,
const ContentParentId& aCpID, const bool& aIsForBrowser,
const bool& aIsTopLevel) {
MOZ_ASSERT(!IsShuttingDown());
@ -1839,9 +1842,11 @@ mozilla::ipc::IPCResult ContentChild::RecvConstructBrowser(
MOZ_CRASH("Invalid TabContext received from the parent process.");
}
RefPtr<BrowserChild> browserChild =
BrowserChild::Create(this, aTabId, aSameTabGroupAs, tc.GetTabContext(),
aBrowsingContext, aChromeFlags, aIsTopLevel);
auto windowChild = MakeRefPtr<WindowGlobalChild>(aWindowInit, nullptr);
RefPtr<BrowserChild> browserChild = BrowserChild::Create(
this, aTabId, aSameTabGroupAs, tc.GetTabContext(),
aWindowInit.browsingContext(), aChromeFlags, aIsTopLevel);
// Bind the created BrowserChild to IPC to actually link the actor. The ref
// here is released in DeallocPBrowserChild.
@ -1850,6 +1855,14 @@ mozilla::ipc::IPCResult ContentChild::RecvConstructBrowser(
return IPC_FAIL(this, "BindPBrowserEndpoint failed");
}
// The ref here is released in DeallocPWindowGlobalChild.
if (NS_WARN_IF(!browserChild->BindPWindowGlobalEndpoint(
std::move(aWindowEp), do_AddRef(windowChild).take()))) {
return IPC_FAIL(this, "BindPWindowGlobalEndpoint failed");
}
windowChild->Init();
// Ensure that a TabGroup is set for our BrowserChild before running `Init`.
if (!browserChild->mTabGroup) {
browserChild->mTabGroup = TabGroup::GetFromActor(browserChild);
@ -1859,7 +1872,8 @@ mozilla::ipc::IPCResult ContentChild::RecvConstructBrowser(
}
}
if (NS_WARN_IF(NS_FAILED(browserChild->Init(/* aOpener */ nullptr)))) {
if (NS_WARN_IF(
NS_FAILED(browserChild->Init(/* aOpener */ nullptr, windowChild)))) {
return IPC_FAIL(browserChild, "BrowserChild::Init failed");
}
@ -2068,12 +2082,15 @@ already_AddRefed<RemoteBrowser> ContentChild::CreateBrowser(
chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME;
}
WindowGlobalInit windowInit = WindowGlobalActor::AboutBlankInitializer(
aBrowsingContext, owner->NodePrincipal());
TabId tabId(nsContentUtils::GenerateTabId());
RefPtr<BrowserBridgeChild> browserBridge =
new BrowserBridgeChild(aFrameLoader, aBrowsingContext, tabId);
browserChild->SendPBrowserBridgeConstructor(
browserBridge, PromiseFlatString(aContext.PresentationURL()), aRemoteType,
aBrowsingContext, chromeFlags, tabId);
windowInit, chromeFlags, tabId);
browserBridge->mIPCOpen = true;
#if defined(ACCESSIBILITY)
@ -3739,12 +3756,17 @@ already_AddRefed<nsIEventTarget> ContentChild::GetSpecificMessageEventTarget(
// our newly created actor, and sameTabGroupAs is needed to determine if
// we're going to join an existing TabGroup.
ManagedEndpoint<PBrowserChild> endpoint;
ManagedEndpoint<PWindowGlobalChild> windowGlobalEndpoint;
TabId tabId, sameTabGroupAs;
PickleIterator iter(aMsg);
if (NS_WARN_IF(!IPC::ReadParam(&aMsg, &iter, &endpoint))) {
return nullptr;
}
aMsg.IgnoreSentinel(&iter);
if (NS_WARN_IF(!IPC::ReadParam(&aMsg, &iter, &windowGlobalEndpoint))) {
return nullptr;
}
aMsg.IgnoreSentinel(&iter);
if (NS_WARN_IF(!IPC::ReadParam(&aMsg, &iter, &tabId))) {
return nullptr;
}

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

@ -527,9 +527,10 @@ class ContentChild final : public PContentChild,
bool DeallocPFileDescriptorSetChild(PFileDescriptorSetChild*);
mozilla::ipc::IPCResult RecvConstructBrowser(
ManagedEndpoint<PBrowserChild>&& aBrowserEp, const TabId& aTabId,
ManagedEndpoint<PBrowserChild>&& aBrowserEp,
ManagedEndpoint<PWindowGlobalChild>&& aWindowEp, const TabId& aTabId,
const TabId& aSameTabGroupAs, const IPCTabContext& aContext,
BrowsingContext* aBrowsingContext, const uint32_t& aChromeFlags,
const WindowGlobalInit& aWindowInit, const uint32_t& aChromeFlags,
const ContentParentId& aCpID, const bool& aIsForBrowser,
const bool& aIsTopLevel);

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

@ -1218,17 +1218,36 @@ already_AddRefed<RemoteBrowser> ContentParent::CreateBrowser(
return nullptr;
}
nsCOMPtr<nsIPrincipal> initialPrincipal =
NullPrincipal::Create(aContext.OriginAttributesRef());
WindowGlobalInit windowInit = WindowGlobalActor::AboutBlankInitializer(
aBrowsingContext, initialPrincipal);
auto windowParent =
MakeRefPtr<WindowGlobalParent>(windowInit, /* inprocess */ false);
// Open a remote endpoint for the initial PWindowGlobal actor.
// DeallocPWindowGlobalParent releases the ref taken.
ManagedEndpoint<PWindowGlobalChild> windowEp =
browserParent->OpenPWindowGlobalEndpoint(
do_AddRef(windowParent).take());
if (NS_WARN_IF(!windowEp.IsValid())) {
return nullptr;
}
// Tell the content process to set up its PBrowserChild.
bool ok = constructorSender->SendConstructBrowser(
std::move(childEp), tabId,
std::move(childEp), std::move(windowEp), tabId,
aSameTabGroupAs ? aSameTabGroupAs->GetTabId() : TabId(0),
aContext.AsIPCTabContext(), aBrowsingContext, chromeFlags,
aContext.AsIPCTabContext(), windowInit, chromeFlags,
constructorSender->ChildID(), constructorSender->IsForBrowser(),
/* aIsTopLevel */ true);
if (NS_WARN_IF(!ok)) {
return nullptr;
}
windowParent->Init(windowInit);
if (remoteType.EqualsLiteral(LARGE_ALLOCATION_REMOTE_TYPE)) {
// Tell the BrowserChild object that it was created due to a
// Large-Allocation request.

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

@ -207,7 +207,7 @@ parent:
* Construct a new Remote iframe actor.
*/
async PBrowserBridge(nsString aPresentationURL, nsString aRemoteType,
BrowsingContext aBrowsingContext, uint32_t aChromeFlags,
WindowGlobalInit aWindowInit, uint32_t aChromeFlags,
TabId tabId);
/**

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

@ -37,6 +37,7 @@ include protocol PJavaScript;
include protocol PRemoteSpellcheckEngine;
include protocol PWebBrowserPersistDocument;
include protocol PWebrtcGlobal;
include protocol PWindowGlobal;
include protocol PPresentation;
include protocol PURLClassifier;
include protocol PURLClassifierLocal;
@ -389,9 +390,10 @@ parent:
child:
async ConstructBrowser(ManagedEndpoint<PBrowserChild> browserEp,
ManagedEndpoint<PWindowGlobalChild> windowEp,
TabId tabId, TabId sameTabGroupAs,
IPCTabContext context,
BrowsingContext browsingContext,
WindowGlobalInit windowInit,
uint32_t chromeFlags, ContentParentId cpId,
bool isForBrowser, bool isTopLevel);

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

@ -6,6 +6,7 @@
#include "mozilla/dom/WindowGlobalActor.h"
#include "nsContentUtils.h"
#include "mozJSComponentLoader.h"
#include "mozilla/Logging.h"
#include "mozilla/dom/JSWindowActorService.h"
@ -15,6 +16,21 @@
namespace mozilla {
namespace dom {
WindowGlobalInit WindowGlobalActor::AboutBlankInitializer(
dom::BrowsingContext* aBrowsingContext, nsIPrincipal* aPrincipal) {
MOZ_ASSERT(aBrowsingContext);
MOZ_ASSERT(aPrincipal);
nsCOMPtr<nsIURI> documentURI;
Unused << NS_NewURI(getter_AddRefs(documentURI), "about:blank");
uint64_t outerWindowId = nsContentUtils::GenerateWindowId();
uint64_t innerWindowId = nsContentUtils::GenerateWindowId();
return WindowGlobalInit(aPrincipal, documentURI, aBrowsingContext,
innerWindowId, outerWindowId);
}
void WindowGlobalActor::ConstructActor(const nsAString& aName,
JS::MutableHandleObject aActor,
ErrorResult& aRv) {

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

@ -24,6 +24,9 @@ class WindowGlobalActor : public nsISupports, public nsWrapperCache {
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WindowGlobalActor)
static WindowGlobalInit AboutBlankInitializer(
dom::BrowsingContext* aBrowsingContext, nsIPrincipal* aPrincipal);
protected:
virtual ~WindowGlobalActor() = default;

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

@ -52,8 +52,9 @@ WindowGlobalChild::WindowGlobalChild(const WindowGlobalInit& aInit,
MOZ_DIAGNOSTIC_ASSERT(mBrowsingContext);
MOZ_DIAGNOSTIC_ASSERT(mDocumentPrincipal);
MOZ_ASSERT(mInnerWindowId == aWindow->WindowID());
MOZ_ASSERT(mOuterWindowId == aWindow->GetOuterWindow()->WindowID());
MOZ_ASSERT_IF(aWindow, mInnerWindowId == aWindow->WindowID());
MOZ_ASSERT_IF(aWindow,
mOuterWindowId == aWindow->GetOuterWindow()->WindowID());
}
already_AddRefed<WindowGlobalChild> WindowGlobalChild::Create(
@ -120,16 +121,23 @@ already_AddRefed<WindowGlobalChild> WindowGlobalChild::Create(
browserChild->SendNewWindowGlobal(std::move(endpoint), init);
}
wgc->Init();
return wgc.forget();
}
void WindowGlobalChild::Init() {
if (!mDocumentURI) {
NS_NewURI(getter_AddRefs(mDocumentURI), "about:blank");
}
// Register this WindowGlobal in the gWindowGlobalParentsById map.
if (!gWindowGlobalChildById) {
gWindowGlobalChildById = new WGCByIdMap();
ClearOnShutdown(&gWindowGlobalChildById);
}
auto entry = gWindowGlobalChildById->LookupForAdd(wgc->mInnerWindowId);
auto entry = gWindowGlobalChildById->LookupForAdd(mInnerWindowId);
MOZ_RELEASE_ASSERT(!entry, "Duplicate WindowGlobalChild entry for ID!");
entry.OrInsert([&] { return wgc; });
return wgc.forget();
entry.OrInsert([&] { return this; });
}
/* static */

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

@ -96,6 +96,8 @@ class WindowGlobalChild final : public WindowGlobalActor,
WindowGlobalChild(const WindowGlobalInit& aInit,
nsGlobalWindowInner* aWindow);
void Init();
nsISupports* GetParentObject();
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;

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

@ -128,6 +128,11 @@ void WindowGlobalParent::Init(const WindowGlobalInit& aInit) {
mFrameLoader = flOwner->GetFrameLoader();
}
// Ensure we have a document URI
if (!mDocumentURI) {
NS_NewURI(getter_AddRefs(mDocumentURI), "about:blank");
}
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (obs) {
obs->NotifyObservers(this, "window-global-created", nullptr);