fune/docshell/base/WindowContext.cpp
Nika Layzell 2b70befb83 Bug 1636186 - Remove unnecessary CookieJarSettingsArgs data from WindowContext, r=timhuang
The entire CookieJarSettingsArgs is currently being synced into every content
process, when only two fields of that structure are actually needed.

Those two fields are extracted from the CookieJarSettingsArgs and synchronized
separately to avoid leaking information such as principals into every content
process.

Differential Revision: https://phabricator.services.mozilla.com/D74258
2020-05-08 20:10:56 +00:00

319 lines
10 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/WindowContext.h"
#include "mozilla/dom/WindowGlobalActorsBinding.h"
#include "mozilla/dom/WindowGlobalChild.h"
#include "mozilla/dom/WindowGlobalParent.h"
#include "mozilla/dom/SyncedContextInlines.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/ClearOnShutdown.h"
#include "nsRefPtrHashtable.h"
namespace mozilla {
namespace dom {
// Explicit specialization of the `Transaction` type. Required by the `extern
// template class` declaration in the header.
template class syncedcontext::Transaction<WindowContext>;
static LazyLogModule gWindowContextLog("WindowContext");
using WindowContextByIdMap = nsDataHashtable<nsUint64HashKey, WindowContext*>;
static StaticAutoPtr<WindowContextByIdMap> gWindowContexts;
/* static */
LogModule* WindowContext::GetLog() { return gWindowContextLog; }
/* static */
already_AddRefed<WindowContext> WindowContext::GetById(
uint64_t aInnerWindowId) {
if (!gWindowContexts) {
return nullptr;
}
return do_AddRef(gWindowContexts->Get(aInnerWindowId));
}
BrowsingContextGroup* WindowContext::Group() const {
return mBrowsingContext->Group();
}
WindowGlobalParent* WindowContext::Canonical() {
MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
return static_cast<WindowGlobalParent*>(this);
}
bool WindowContext::IsCached() const {
return mBrowsingContext->mCurrentWindowContext != this;
}
WindowContext* WindowContext::GetParentWindowContext() {
return mBrowsingContext->GetParentWindowContext();
}
WindowContext* WindowContext::TopWindowContext() {
WindowContext* current = this;
while (current->GetParentWindowContext()) {
current = current->GetParentWindowContext();
}
return current;
}
nsIGlobalObject* WindowContext::GetParentObject() const {
return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
}
void WindowContext::AppendChildBrowsingContext(
BrowsingContext* aBrowsingContext) {
MOZ_DIAGNOSTIC_ASSERT(Group() == aBrowsingContext->Group(),
"Mismatched groups?");
MOZ_DIAGNOSTIC_ASSERT(!mChildren.Contains(aBrowsingContext));
mChildren.AppendElement(aBrowsingContext);
// If we're the current WindowContext in our BrowsingContext, make sure to
// clear any cached `children` value.
if (!IsCached()) {
BrowsingContext_Binding::ClearCachedChildrenValue(mBrowsingContext);
}
}
void WindowContext::RemoveChildBrowsingContext(
BrowsingContext* aBrowsingContext) {
MOZ_DIAGNOSTIC_ASSERT(Group() == aBrowsingContext->Group(),
"Mismatched groups?");
mChildren.RemoveElement(aBrowsingContext);
// If we're the current WindowContext in our BrowsingContext, make sure to
// clear any cached `children` value.
if (!IsCached()) {
BrowsingContext_Binding::ClearCachedChildrenValue(mBrowsingContext);
}
}
void WindowContext::SendCommitTransaction(ContentParent* aParent,
const BaseTransaction& aTxn,
uint64_t aEpoch) {
Unused << aParent->SendCommitWindowContextTransaction(this, aTxn, aEpoch);
}
void WindowContext::SendCommitTransaction(ContentChild* aChild,
const BaseTransaction& aTxn,
uint64_t aEpoch) {
aChild->SendCommitWindowContextTransaction(this, aTxn, aEpoch);
}
bool WindowContext::CheckOnlyOwningProcessCanSet(ContentParent* aSource) {
if (mInProcess) {
return true;
}
if (XRE_IsParentProcess() && aSource) {
return Canonical()->GetContentParent() == aSource;
}
return false;
}
bool WindowContext::CanSet(FieldIndex<IDX_AllowMixedContent>,
const bool& aAllowMixedContent,
ContentParent* aSource) {
return CheckOnlyOwningProcessCanSet(aSource);
}
bool WindowContext::CanSet(FieldIndex<IDX_CookieBehavior>,
const Maybe<uint32_t>& aValue,
ContentParent* aSource) {
return CheckOnlyOwningProcessCanSet(aSource);
}
bool WindowContext::CanSet(FieldIndex<IDX_IsOnContentBlockingAllowList>,
const bool& aValue, ContentParent* aSource) {
return CheckOnlyOwningProcessCanSet(aSource);
}
bool WindowContext::CanSet(FieldIndex<IDX_IsThirdPartyWindow>,
const bool& IsThirdPartyWindow,
ContentParent* aSource) {
return CheckOnlyOwningProcessCanSet(aSource);
}
bool WindowContext::CanSet(FieldIndex<IDX_IsThirdPartyTrackingResourceWindow>,
const bool& aIsThirdPartyTrackingResourceWindow,
ContentParent* aSource) {
return CheckOnlyOwningProcessCanSet(aSource);
}
already_AddRefed<WindowContext> WindowContext::Create(
WindowGlobalChild* aWindow) {
MOZ_RELEASE_ASSERT(XRE_IsContentProcess(),
"Should be a WindowGlobalParent in the parent");
FieldTuple init;
mozilla::Get<IDX_OuterWindowId>(init) = aWindow->OuterWindowId();
RefPtr<WindowContext> context =
new WindowContext(aWindow->BrowsingContext(), aWindow->InnerWindowId(),
/* aInProcess */ true, std::move(init));
context->Init();
return context.forget();
}
void WindowContext::CreateFromIPC(IPCInitializer&& aInit) {
MOZ_RELEASE_ASSERT(XRE_IsContentProcess(),
"Should be a WindowGlobalParent in the parent");
RefPtr<BrowsingContext> bc = BrowsingContext::Get(aInit.mBrowsingContextId);
MOZ_RELEASE_ASSERT(bc);
if (bc->IsDiscarded()) {
// If we have already closed our browsing context, the
// WindowGlobalChild actor is bound to be destroyed soon and it's
// safe to ignore creating the WindowContext.
return;
}
RefPtr<WindowContext> context =
new WindowContext(bc, aInit.mInnerWindowId, /* aInProcess */ false,
std::move(aInit.mFields));
context->Init();
}
void WindowContext::Init() {
MOZ_LOG(GetLog(), LogLevel::Debug,
("Registering 0x%" PRIx64 " (bc=0x%" PRIx64 ")", mInnerWindowId,
mBrowsingContext->Id()));
// Register the WindowContext in the `WindowContextByIdMap`.
if (!gWindowContexts) {
gWindowContexts = new WindowContextByIdMap();
ClearOnShutdown(&gWindowContexts);
}
auto& entry = gWindowContexts->GetOrInsert(mInnerWindowId);
MOZ_RELEASE_ASSERT(!entry, "Duplicate WindowContext for ID!");
entry = this;
// Register this to the browsing context.
mBrowsingContext->RegisterWindowContext(this);
Group()->Register(this);
}
void WindowContext::Discard() {
MOZ_LOG(GetLog(), LogLevel::Debug,
("Discarding 0x%" PRIx64 " (bc=0x%" PRIx64 ")", mInnerWindowId,
mBrowsingContext->Id()));
if (mIsDiscarded) {
return;
}
mIsDiscarded = true;
gWindowContexts->Remove(InnerWindowId());
mBrowsingContext->UnregisterWindowContext(this);
Group()->Unregister(this);
}
WindowContext::WindowContext(BrowsingContext* aBrowsingContext,
uint64_t aInnerWindowId, bool aInProcess,
FieldTuple&& aFields)
: mFields(std::move(aFields)),
mInnerWindowId(aInnerWindowId),
mBrowsingContext(aBrowsingContext),
mInProcess(aInProcess) {
MOZ_ASSERT(mBrowsingContext);
MOZ_ASSERT(mInnerWindowId);
}
WindowContext::~WindowContext() {
if (gWindowContexts) {
gWindowContexts->Remove(InnerWindowId());
}
}
JSObject* WindowContext::WrapObject(JSContext* cx,
JS::Handle<JSObject*> aGivenProto) {
return WindowContext_Binding::Wrap(cx, this, aGivenProto);
}
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WindowContext)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(WindowContext)
NS_IMPL_CYCLE_COLLECTING_RELEASE(WindowContext)
NS_IMPL_CYCLE_COLLECTION_CLASS(WindowContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WindowContext)
if (gWindowContexts) {
gWindowContexts->Remove(tmp->InnerWindowId());
}
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowsingContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildren)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WindowContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildren)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(WindowContext)
} // namespace dom
namespace ipc {
void IPDLParamTraits<dom::MaybeDiscarded<dom::WindowContext>>::Write(
IPC::Message* aMsg, IProtocol* aActor,
const dom::MaybeDiscarded<dom::WindowContext>& aParam) {
uint64_t id = aParam.ContextId();
WriteIPDLParam(aMsg, aActor, id);
}
bool IPDLParamTraits<dom::MaybeDiscarded<dom::WindowContext>>::Read(
const IPC::Message* aMsg, PickleIterator* aIter, IProtocol* aActor,
dom::MaybeDiscarded<dom::WindowContext>* aResult) {
uint64_t id = 0;
if (!ReadIPDLParam(aMsg, aIter, aActor, &id)) {
return false;
}
if (id == 0) {
*aResult = nullptr;
} else if (RefPtr<dom::WindowContext> wc = dom::WindowContext::GetById(id)) {
*aResult = std::move(wc);
} else {
aResult->SetDiscarded(id);
}
return true;
}
void IPDLParamTraits<dom::WindowContext::IPCInitializer>::Write(
IPC::Message* aMessage, IProtocol* aActor,
const dom::WindowContext::IPCInitializer& aInit) {
// Write actor ID parameters.
WriteIPDLParam(aMessage, aActor, aInit.mInnerWindowId);
WriteIPDLParam(aMessage, aActor, aInit.mBrowsingContextId);
WriteIPDLParam(aMessage, aActor, aInit.mFields);
}
bool IPDLParamTraits<dom::WindowContext::IPCInitializer>::Read(
const IPC::Message* aMessage, PickleIterator* aIterator, IProtocol* aActor,
dom::WindowContext::IPCInitializer* aInit) {
// Read actor ID parameters.
return ReadIPDLParam(aMessage, aIterator, aActor, &aInit->mInnerWindowId) &&
ReadIPDLParam(aMessage, aIterator, aActor,
&aInit->mBrowsingContextId) &&
ReadIPDLParam(aMessage, aIterator, aActor, &aInit->mFields);
}
template struct IPDLParamTraits<dom::WindowContext::BaseTransaction>;
} // namespace ipc
} // namespace mozilla