Bug 1525427 - Part 1: Expose WindowGlobalParent & Element on BrowsingContext, r=farre

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Nika Layzell 2019-04-17 00:51:36 +00:00
Родитель 7f4ecdea61
Коммит 0bc40288dc
11 изменённых файлов: 108 добавлений и 4 удалений

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

@ -13,9 +13,12 @@
#include "mozilla/dom/BrowsingContextBinding.h" #include "mozilla/dom/BrowsingContextBinding.h"
#include "mozilla/dom/ContentChild.h" #include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h" #include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/Location.h" #include "mozilla/dom/Location.h"
#include "mozilla/dom/LocationBinding.h" #include "mozilla/dom/LocationBinding.h"
#include "mozilla/dom/WindowBinding.h" #include "mozilla/dom/WindowBinding.h"
#include "mozilla/dom/WindowGlobalChild.h"
#include "mozilla/dom/WindowGlobalParent.h"
#include "mozilla/dom/WindowProxyHolder.h" #include "mozilla/dom/WindowProxyHolder.h"
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
#include "mozilla/ClearOnShutdown.h" #include "mozilla/ClearOnShutdown.h"
@ -201,6 +204,27 @@ void BrowsingContext::SetDocShell(nsIDocShell* aDocShell) {
mIsInProcess = true; mIsInProcess = true;
} }
void BrowsingContext::SetEmbedderElement(Element* aEmbedder) {
mEmbedderElement = aEmbedder;
// Notify the parent process of the embedding status. We don't need to do
// this when clearing our embedder, as we're being destroyed either way.
if (mEmbedderElement) {
nsCOMPtr<nsPIDOMWindowInner> embedderGlobal =
do_QueryInterface(mEmbedderElement->GetOwnerGlobal());
RefPtr<WindowGlobalChild> wgc = embedderGlobal->GetWindowGlobalChild();
// If we're in-process, synchronously perform the update to ensure we don't
// get out of sync.
// XXX(nika): This is super gross, and I don't like it one bit.
if (RefPtr<WindowGlobalParent> wgp = wgc->GetParentActor()) {
Canonical()->SetEmbedderWindowGlobal(wgp);
} else {
wgc->SendDidEmbedBrowsingContext(this);
}
}
}
void BrowsingContext::Attach(bool aFromIPC) { void BrowsingContext::Attach(bool aFromIPC) {
MOZ_LOG(GetLog(), LogLevel::Debug, MOZ_LOG(GetLog(), LogLevel::Debug,
("%s: %s 0x%08" PRIx64 " to 0x%08" PRIx64, ("%s: %s 0x%08" PRIx64 " to 0x%08" PRIx64,
@ -518,7 +542,8 @@ bool BrowsingContext::GetUserGestureActivation() {
NS_IMPL_CYCLE_COLLECTION_CLASS(BrowsingContext) NS_IMPL_CYCLE_COLLECTION_CLASS(BrowsingContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BrowsingContext) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BrowsingContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell, mChildren, mParent, mGroup) NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell, mChildren, mParent, mGroup,
mEmbedderElement)
if (XRE_IsParentProcess()) { if (XRE_IsParentProcess()) {
CanonicalBrowsingContext::Cast(tmp)->Unlink(); CanonicalBrowsingContext::Cast(tmp)->Unlink();
} }
@ -526,7 +551,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BrowsingContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BrowsingContext) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BrowsingContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell, mChildren, mParent, mGroup) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell, mChildren, mParent, mGroup,
mEmbedderElement)
if (XRE_IsParentProcess()) { if (XRE_IsParentProcess()) {
CanonicalBrowsingContext::Cast(tmp)->Traverse(cb); CanonicalBrowsingContext::Cast(tmp)->Traverse(cb);
} }

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

@ -46,6 +46,7 @@ class BrowsingContent;
class BrowsingContextGroup; class BrowsingContextGroup;
class CanonicalBrowsingContext; class CanonicalBrowsingContext;
class ContentParent; class ContentParent;
class Element;
template <typename> template <typename>
struct Nullable; struct Nullable;
template <typename T> template <typename T>
@ -123,6 +124,11 @@ class BrowsingContext : public nsWrapperCache,
void SetDocShell(nsIDocShell* aDocShell); void SetDocShell(nsIDocShell* aDocShell);
void ClearDocShell() { mDocShell = nullptr; } void ClearDocShell() { mDocShell = nullptr; }
// Get the embedder element for this BrowsingContext if the embedder is
// in-process, or null if it's not.
Element* GetEmbedderElement() const { return mEmbedderElement; }
void SetEmbedderElement(Element* aEmbedder);
// Get the outer window object for this BrowsingContext if it is in-process // Get the outer window object for this BrowsingContext if it is in-process
// and still has a docshell, or null otherwise. // and still has a docshell, or null otherwise.
nsPIDOMWindowOuter* GetDOMWindow() const { nsPIDOMWindowOuter* GetDOMWindow() const {
@ -439,6 +445,8 @@ class BrowsingContext : public nsWrapperCache,
Children mChildren; Children mChildren;
nsCOMPtr<nsIDocShell> mDocShell; nsCOMPtr<nsIDocShell> mDocShell;
RefPtr<Element> mEmbedderElement;
// This is not a strong reference, but using a JS::Heap for that should be // This is not a strong reference, but using a JS::Heap for that should be
// fine. The JSObject stored in here should be a proxy with a // fine. The JSObject stored in here should be a proxy with a
// nsOuterWindowProxy handler, which will update the pointer from its // nsOuterWindowProxy handler, which will update the pointer from its

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

@ -116,6 +116,20 @@ void CanonicalBrowsingContext::SetCurrentWindowGlobal(
mCurrentWindowGlobal = aGlobal; mCurrentWindowGlobal = aGlobal;
} }
void CanonicalBrowsingContext::SetEmbedderWindowGlobal(
WindowGlobalParent* aGlobal) {
MOZ_RELEASE_ASSERT(aGlobal, "null embedder");
if (RefPtr<BrowsingContext> parent = GetParent()) {
MOZ_RELEASE_ASSERT(aGlobal->BrowsingContext() == parent,
"Embedder has incorrect browsing context");
} else {
MOZ_RELEASE_ASSERT(aGlobal->IsInProcess(),
"Toplevel must have a parent-process embedder");
}
mEmbedderWindowGlobal = aGlobal;
}
bool CanonicalBrowsingContext::ValidateTransaction( bool CanonicalBrowsingContext::ValidateTransaction(
const Transaction& aTransaction, ContentParent* aProcess) { const Transaction& aTransaction, ContentParent* aProcess) {
// Check that the correct process is performing sets for transactions with // Check that the correct process is performing sets for transactions with
@ -137,12 +151,14 @@ JSObject* CanonicalBrowsingContext::WrapObject(
void CanonicalBrowsingContext::Traverse( void CanonicalBrowsingContext::Traverse(
nsCycleCollectionTraversalCallback& cb) { nsCycleCollectionTraversalCallback& cb) {
CanonicalBrowsingContext* tmp = this; CanonicalBrowsingContext* tmp = this;
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindowGlobals); NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindowGlobals, mCurrentWindowGlobal,
mEmbedderWindowGlobal);
} }
void CanonicalBrowsingContext::Unlink() { void CanonicalBrowsingContext::Unlink() {
CanonicalBrowsingContext* tmp = this; CanonicalBrowsingContext* tmp = this;
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindowGlobals); NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindowGlobals, mCurrentWindowGlobal,
mEmbedderWindowGlobal);
} }
void CanonicalBrowsingContext::NotifyStartDelayedAutoplayMedia() { void CanonicalBrowsingContext::NotifyStartDelayedAutoplayMedia() {

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

@ -52,6 +52,11 @@ class CanonicalBrowsingContext final : public BrowsingContext {
} }
void SetCurrentWindowGlobal(WindowGlobalParent* aGlobal); void SetCurrentWindowGlobal(WindowGlobalParent* aGlobal);
WindowGlobalParent* GetEmbedderWindowGlobal() const {
return mEmbedderWindowGlobal;
}
void SetEmbedderWindowGlobal(WindowGlobalParent* aGlobal);
JSObject* WrapObject(JSContext* aCx, JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override; JS::Handle<JSObject*> aGivenProto) override;
@ -97,6 +102,7 @@ class CanonicalBrowsingContext final : public BrowsingContext {
// All live window globals within this browsing context. // All live window globals within this browsing context.
nsTHashtable<nsRefPtrHashKey<WindowGlobalParent>> mWindowGlobals; nsTHashtable<nsRefPtrHashKey<WindowGlobalParent>> mWindowGlobals;
RefPtr<WindowGlobalParent> mCurrentWindowGlobal; RefPtr<WindowGlobalParent> mCurrentWindowGlobal;
RefPtr<WindowGlobalParent> mEmbedderWindowGlobal;
// Generation information for each content process which has interacted with // Generation information for each content process which has interacted with
// this CanonicalBrowsingContext, by ChildID. // this CanonicalBrowsingContext, by ChildID.

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

@ -1893,6 +1893,10 @@ void nsFrameLoader::SetOwnerContent(Element* aContent) {
} }
mOwnerContent = aContent; mOwnerContent = aContent;
if (RefPtr<BrowsingContext> browsingContext = GetBrowsingContext()) {
browsingContext->SetEmbedderElement(mOwnerContent);
}
AutoJSAPI jsapi; AutoJSAPI jsapi;
jsapi.Init(); jsapi.Init();
@ -2009,6 +2013,8 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
RefPtr<nsDocShell> docShell = nsDocShell::Create(mBrowsingContext); RefPtr<nsDocShell> docShell = nsDocShell::Create(mBrowsingContext);
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
mBrowsingContext->SetEmbedderElement(mOwnerContent);
mIsTopLevelContent = mIsTopLevelContent =
mBrowsingContext->IsContent() && !mBrowsingContext->GetParent(); mBrowsingContext->IsContent() && !mBrowsingContext->GetParent();
if (!mNetworkCreated && !mIsTopLevelContent) { if (!mNetworkCreated && !mIsTopLevelContent) {
@ -2604,6 +2610,8 @@ bool nsFrameLoader::TryRemoteBrowser() {
// If we're in a content process, create a BrowserBridgeChild actor. // If we're in a content process, create a BrowserBridgeChild actor.
if (XRE_IsContentProcess()) { if (XRE_IsContentProcess()) {
mBrowsingContext->SetEmbedderElement(mOwnerContent);
mBrowserBridgeChild = BrowserBridgeChild::Create( mBrowserBridgeChild = BrowserBridgeChild::Create(
this, context, NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE), this, context, NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE),
mBrowsingContext); mBrowsingContext);

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

@ -22,6 +22,8 @@ interface BrowsingContext {
readonly attribute nsIDocShell? docShell; readonly attribute nsIDocShell? docShell;
readonly attribute Element? embedderElement;
readonly attribute unsigned long long id; readonly attribute unsigned long long id;
readonly attribute BrowsingContext? opener; readonly attribute BrowsingContext? opener;
@ -41,6 +43,8 @@ interface CanonicalBrowsingContext : BrowsingContext {
[Throws] [Throws]
readonly attribute DOMString? currentRemoteType; readonly attribute DOMString? currentRemoteType;
readonly attribute WindowGlobalParent? embedderWindowGlobal;
void notifyStartDelayedAutoplayMedia(); void notifyStartDelayedAutoplayMedia();
}; };

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

@ -1148,6 +1148,8 @@ TabParent* ContentParent::CreateBrowser(const TabContext& aContext,
} }
} }
aBrowsingContext->SetEmbedderElement(aFrameElement);
// Ensure that our content process is subscribed to our newly created // Ensure that our content process is subscribed to our newly created
// BrowsingContextGroup. // BrowsingContextGroup.
aBrowsingContext->Group()->EnsureSubscribed(constructorSender); aBrowsingContext->Group()->EnsureSubscribed(constructorSender);

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

@ -36,6 +36,10 @@ parent:
/// Notify the parent that this PWindowGlobal is now the current global. /// Notify the parent that this PWindowGlobal is now the current global.
async BecomeCurrentWindowGlobal(); async BecomeCurrentWindowGlobal();
/// Notify the parent that this PWindowGlobal has embedded the given
/// BrowsingContext.
async DidEmbedBrowsingContext(BrowsingContext aContext);
async Destroy(); async Destroy();
}; };

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

@ -334,6 +334,21 @@ void TabParent::SetOwnerElement(Element* aElement) {
if (mRenderFrame.IsInitialized()) { if (mRenderFrame.IsInitialized()) {
mRenderFrame.OwnerContentChanged(); mRenderFrame.OwnerContentChanged();
} }
// Set our BrowsingContext's embedder if we're not embedded within a
// BrowserBridgeParent.
if (!GetBrowserBridgeParent() && mBrowsingContext) {
mBrowsingContext->SetEmbedderElement(mFrameElement);
}
// Ensure all TabParent actors within BrowserBridges are also updated.
const auto& browserBridges = ManagedPBrowserBridgeParent();
for (auto iter = browserBridges.ConstIter(); !iter.Done(); iter.Next()) {
BrowserBridgeParent* browserBridge =
static_cast<BrowserBridgeParent*>(iter.Get()->GetKey());
browserBridge->GetTabParent()->SetOwnerElement(aElement);
}
} }
NS_IMETHODIMP TabParent::GetOwnerElement(Element** aElement) { NS_IMETHODIMP TabParent::GetOwnerElement(Element** aElement) {

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

@ -87,6 +87,12 @@ void WindowGlobalParent::Init(const WindowGlobalInit& aInit) {
// Attach ourself to the browsing context. // Attach ourself to the browsing context.
mBrowsingContext->RegisterWindowGlobal(this); mBrowsingContext->RegisterWindowGlobal(this);
// If there is no current window global, assume we're about to become it
// optimistically.
if (!mBrowsingContext->GetCurrentWindowGlobal()) {
mBrowsingContext->SetCurrentWindowGlobal(this);
}
// Determine what toplevel frame element our WindowGlobalParent is being // Determine what toplevel frame element our WindowGlobalParent is being
// embedded in. // embedded in.
RefPtr<Element> frameElement; RefPtr<Element> frameElement;
@ -252,6 +258,13 @@ bool WindowGlobalParent::IsCurrentGlobal() {
return !mIPCClosed && mBrowsingContext->GetCurrentWindowGlobal() == this; return !mIPCClosed && mBrowsingContext->GetCurrentWindowGlobal() == this;
} }
IPCResult WindowGlobalParent::RecvDidEmbedBrowsingContext(
dom::BrowsingContext* aContext) {
MOZ_ASSERT(aContext);
aContext->Canonical()->SetEmbedderWindowGlobal(this);
return IPC_OK();
}
void WindowGlobalParent::ActorDestroy(ActorDestroyReason aWhy) { void WindowGlobalParent::ActorDestroy(ActorDestroyReason aWhy) {
mIPCClosed = true; mIPCClosed = true;
gWindowGlobalParentsById->Remove(mInnerWindowId); gWindowGlobalParentsById->Remove(mInnerWindowId);

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

@ -111,6 +111,8 @@ class WindowGlobalParent final : public nsISupports,
mozilla::ipc::IPCResult RecvAsyncMessage(const nsString& aActorName, mozilla::ipc::IPCResult RecvAsyncMessage(const nsString& aActorName,
const nsString& aMessageName, const nsString& aMessageName,
const ClonedMessageData& aData); const ClonedMessageData& aData);
mozilla::ipc::IPCResult RecvDidEmbedBrowsingContext(
dom::BrowsingContext* aContext);
void ActorDestroy(ActorDestroyReason aWhy) override; void ActorDestroy(ActorDestroyReason aWhy) override;