Bug 1582237 - Expose embedder inner window ID on BrowsingContext in all processes, r=farre

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Nika Layzell 2019-09-26 16:16:32 +00:00
Родитель 6135c6c044
Коммит 08192838cd
9 изменённых файлов: 94 добавлений и 60 удалений

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

@ -259,9 +259,6 @@ void BrowsingContext::SetEmbedderElement(Element* 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 (aEmbedder) {
nsCOMPtr<nsIDocShell> container =
do_QueryInterface(aEmbedder->OwnerDoc()->GetContainer());
// If our embedder element is being mutated to a different embedder, and we
// have a parent edge, bad things might be happening!
//
@ -276,7 +273,8 @@ void BrowsingContext::SetEmbedderElement(Element* aEmbedder) {
"cannot be in bfcache");
RefPtr<BrowsingContext> kungFuDeathGrip(this);
RefPtr<BrowsingContext> newParent(container->GetBrowsingContext());
RefPtr<BrowsingContext> newParent(
aEmbedder->OwnerDoc()->GetBrowsingContext());
mParent->mChildren.RemoveElement(this);
if (newParent) {
newParent->mChildren.AppendElement(this);
@ -286,18 +284,9 @@ void BrowsingContext::SetEmbedderElement(Element* aEmbedder) {
nsCOMPtr<nsPIDOMWindowInner> inner =
do_QueryInterface(aEmbedder->GetOwnerGlobal());
if (inner) {
RefPtr<WindowGlobalChild> wgc = inner->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);
}
}
SetEmbedderInnerWindowId(inner ? inner->WindowID() : 0);
} else {
SetEmbedderInnerWindowId(0);
}
mEmbedderElement = aEmbedder;
@ -1026,9 +1015,8 @@ bool BrowsingContext::Transaction::Validate(BrowsingContext* aBrowsingContext,
return true;
}
bool BrowsingContext::Transaction::Validate(BrowsingContext* aBrowsingContext,
ContentParent* aSource,
uint64_t aEpoch) {
bool BrowsingContext::Transaction::ValidateEpochs(
BrowsingContext* aBrowsingContext, uint64_t aEpoch) {
MOZ_DIAGNOSTIC_ASSERT(XRE_IsContentProcess(),
"Should only be called in content process");
@ -1039,7 +1027,11 @@ bool BrowsingContext::Transaction::Validate(BrowsingContext* aBrowsingContext,
}
#include "mozilla/dom/BrowsingContextFieldList.h"
return Validate(aBrowsingContext, aSource);
// NOTE: We don't call MaySet in a content process for messages sent from over
// IPC. The message has already been validated in both the original sending
// process (to get good errors), and in the parent process (to enforce trust).
mValidated = true;
return true;
}
void BrowsingContext::Transaction::Apply(BrowsingContext* aBrowsingContext) {
@ -1124,6 +1116,60 @@ void BrowsingContext::DidSetMuted() {
});
}
bool BrowsingContext::MaySetEmbedderInnerWindowId(const uint64_t& aValue,
ContentParent* aSource) {
// Generally allow clearing this. We may want to be more precise about this
// check in the future.
if (aValue == 0) {
return true;
}
// If we don't have a specified source, we're the setting process. The window
// which we're setting this to must be in-process.
RefPtr<BrowsingContext> impliedParent;
if (!aSource) {
nsGlobalWindowInner* innerWindow =
nsGlobalWindowInner::GetInnerWindowWithId(aValue);
if (NS_WARN_IF(!innerWindow)) {
return false;
}
impliedParent = innerWindow->GetBrowsingContext();
}
// If in the parent process, double-check ownership and WindowGlobalParent as
// well.
if (XRE_IsParentProcess()) {
RefPtr<WindowGlobalParent> wgp =
WindowGlobalParent::GetByInnerWindowId(aValue);
if (NS_WARN_IF(!wgp)) {
return false;
}
// Deduce the implied parent from the WindowGlobalParent actor.
if (impliedParent) {
MOZ_ASSERT(impliedParent == wgp->BrowsingContext());
}
impliedParent = wgp->BrowsingContext();
// Double-check ownership if we aren't the setter.
if (aSource &&
!impliedParent->Canonical()->IsOwnedByProcess(aSource->ChildID()) &&
aSource->ChildID() !=
impliedParent->Canonical()->GetInFlightProcessId()) {
return false;
}
}
// If we would have an invalid implied parent, something has gone wrong.
MOZ_ASSERT(impliedParent);
if (NS_WARN_IF(mParent && mParent != impliedParent)) {
return false;
}
return true;
}
} // namespace dom
namespace ipc {

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

@ -375,14 +375,17 @@ class BrowsingContext : public nsWrapperCache, public BrowsingContextBase {
nsresult Commit(BrowsingContext* aOwner);
// This method should be called before invoking `Apply` on this transaction
// object.
// object in the original process, and the parent process.
//
// |aSource| is the ContentParent which is performing the mutation in the
// parent process.
MOZ_MUST_USE bool Validate(BrowsingContext* aOwner, ContentParent* aSource,
uint64_t aEpoch);
MOZ_MUST_USE bool Validate(BrowsingContext* aOwner, ContentParent* aSource);
// This method shold be called before invoking `Apply` on this transaction
// object in child processes messaged by the parent process. It clears out
// out-of-date sets resolving epoch conflicts.
MOZ_MUST_USE bool ValidateEpochs(BrowsingContext* aOwner, uint64_t aEpoch);
// You probably don't want to directly call this method - instead call
// `Commit`, which will perform the necessary synchronization.
//
@ -522,6 +525,9 @@ class BrowsingContext : public nsWrapperCache, public BrowsingContextBase {
// volume of all media elements.
void DidSetMuted();
bool MaySetEmbedderInnerWindowId(const uint64_t& aValue,
ContentParent* aSource);
// Type of BrowsingContent
const Type mType;

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

@ -21,6 +21,9 @@ MOZ_BC_FIELD(OpenerId, uint64_t)
MOZ_BC_FIELD(OnePermittedSandboxedNavigatorId, uint64_t)
// Window ID of the inner window which embeds this BrowsingContext.
MOZ_BC_FIELD(EmbedderInnerWindowId, uint64_t)
MOZ_BC_FIELD(HadOriginalOpener, bool)
// This field controls whether the browsing context is currently considered to

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

@ -132,15 +132,14 @@ void CanonicalBrowsingContext::SetCurrentWindowGlobal(
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");
already_AddRefed<WindowGlobalParent>
CanonicalBrowsingContext::GetEmbedderWindowGlobal() const {
uint64_t windowId = GetEmbedderInnerWindowId();
if (windowId == 0) {
return nullptr;
}
mEmbedderWindowGlobal = aGlobal;
return WindowGlobalParent::GetByInnerWindowId(windowId);
}
JSObject* CanonicalBrowsingContext::WrapObject(
@ -151,14 +150,12 @@ JSObject* CanonicalBrowsingContext::WrapObject(
void CanonicalBrowsingContext::Traverse(
nsCycleCollectionTraversalCallback& cb) {
CanonicalBrowsingContext* tmp = this;
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindowGlobals, mCurrentWindowGlobal,
mEmbedderWindowGlobal);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindowGlobals, mCurrentWindowGlobal);
}
void CanonicalBrowsingContext::Unlink() {
CanonicalBrowsingContext* tmp = this;
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindowGlobals, mCurrentWindowGlobal,
mEmbedderWindowGlobal);
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindowGlobals, mCurrentWindowGlobal);
}
void CanonicalBrowsingContext::NotifyStartDelayedAutoplayMedia() {

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

@ -56,10 +56,7 @@ class CanonicalBrowsingContext final : public BrowsingContext {
}
void SetCurrentWindowGlobal(WindowGlobalParent* aGlobal);
WindowGlobalParent* GetEmbedderWindowGlobal() const {
return mEmbedderWindowGlobal;
}
void SetEmbedderWindowGlobal(WindowGlobalParent* aGlobal);
already_AddRefed<WindowGlobalParent> GetEmbedderWindowGlobal() const;
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
@ -103,7 +100,6 @@ class CanonicalBrowsingContext final : public BrowsingContext {
// All live window globals within this browsing context.
nsTHashtable<nsRefPtrHashKey<WindowGlobalParent>> mWindowGlobals;
RefPtr<WindowGlobalParent> mCurrentWindowGlobal;
RefPtr<WindowGlobalParent> mEmbedderWindowGlobal;
};
} // namespace dom

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

@ -4031,7 +4031,7 @@ mozilla::ipc::IPCResult ContentChild::RecvCommitBrowsingContextTransaction(
return IPC_OK();
}
if (!aTransaction.Validate(aContext, nullptr, aEpoch)) {
if (!aTransaction.ValidateEpochs(aContext, aEpoch)) {
return IPC_FAIL(this, "Invalid BrowsingContext transaction from Parent");
}

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

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

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

@ -89,7 +89,7 @@ void WindowGlobalParent::Init(const WindowGlobalInit& aInit) {
MOZ_DIAGNOSTIC_ASSERT(
!mBrowsingContext->GetParent() ||
mBrowsingContext->GetEmbedderWindowGlobal(),
mBrowsingContext->GetEmbedderInnerWindowId(),
"When creating a non-root WindowGlobalParent, the WindowGlobalParent "
"for our embedder should've already been created.");
@ -165,7 +165,8 @@ bool WindowGlobalParent::IsProcessRoot() {
return true;
}
auto* embedder = BrowsingContext()->GetEmbedderWindowGlobal();
RefPtr<WindowGlobalParent> embedder =
BrowsingContext()->GetEmbedderWindowGlobal();
if (NS_WARN_IF(!embedder)) {
return false;
}
@ -174,8 +175,7 @@ bool WindowGlobalParent::IsProcessRoot() {
}
mozilla::ipc::IPCResult WindowGlobalParent::RecvLoadURI(
dom::BrowsingContext* aTargetBC,
nsDocShellLoadState* aLoadState) {
dom::BrowsingContext* aTargetBC, nsDocShellLoadState* aLoadState) {
if (!aTargetBC || aTargetBC->IsDiscarded()) {
MOZ_LOG(
BrowsingContext::GetLog(), LogLevel::Debug,
@ -195,9 +195,8 @@ mozilla::ipc::IPCResult WindowGlobalParent::RecvLoadURI(
WindowGlobalParent* wgp = aTargetBC->Canonical()->GetCurrentWindowGlobal();
if (!wgp) {
MOZ_LOG(
BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Target BrowsingContext has no WindowGlobalParent"));
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Target BrowsingContext has no WindowGlobalParent"));
return IPC_OK();
}
@ -303,13 +302,6 @@ bool WindowGlobalParent::IsCurrentGlobal() {
return CanSend() && mBrowsingContext->GetCurrentWindowGlobal() == this;
}
IPCResult WindowGlobalParent::RecvDidEmbedBrowsingContext(
dom::BrowsingContext* aContext) {
MOZ_ASSERT(aContext);
aContext->Canonical()->SetEmbedderWindowGlobal(this);
return IPC_OK();
}
already_AddRefed<Promise> WindowGlobalParent::ChangeFrameRemoteness(
dom::BrowsingContext* aBc, const nsAString& aRemoteType,
uint64_t aPendingSwitchId, ErrorResult& aRv) {

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

@ -151,8 +151,6 @@ class WindowGlobalParent final : public WindowGlobalActor,
mozilla::ipc::IPCResult RecvDestroy();
mozilla::ipc::IPCResult RecvRawMessage(const JSWindowActorMessageMeta& aMeta,
const ClonedMessageData& aData);
mozilla::ipc::IPCResult RecvDidEmbedBrowsingContext(
dom::BrowsingContext* aContext);
void ActorDestroy(ActorDestroyReason aWhy) override;