зеркало из https://github.com/mozilla/gecko-dev.git
188 строки
5.0 KiB
C++
188 строки
5.0 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 "BrowsingContext.h"
|
||
|
|
||
|
#include "mozilla/dom/ContentChild.h"
|
||
|
#include "mozilla/Assertions.h"
|
||
|
#include "mozilla/ClearOnShutdown.h"
|
||
|
#include "mozilla/Logging.h"
|
||
|
#include "mozilla/StaticPtr.h"
|
||
|
|
||
|
#include "nsDataHashtable.h"
|
||
|
#include "nsIDocShell.h"
|
||
|
#include "nsContentUtils.h"
|
||
|
|
||
|
namespace mozilla {
|
||
|
namespace dom {
|
||
|
|
||
|
static LazyLogModule gBrowsingContextLog("BrowsingContext");
|
||
|
|
||
|
static StaticAutoPtr<BrowsingContext::Children> sRootBrowsingContexts;
|
||
|
|
||
|
static StaticAutoPtr<nsDataHashtable<nsUint64HashKey, BrowsingContext*>>
|
||
|
sBrowsingContexts;
|
||
|
|
||
|
/* static */ void
|
||
|
BrowsingContext::Init()
|
||
|
{
|
||
|
if (!sRootBrowsingContexts) {
|
||
|
sRootBrowsingContexts = new BrowsingContext::Children();
|
||
|
ClearOnShutdown(&sRootBrowsingContexts);
|
||
|
}
|
||
|
|
||
|
if (!sBrowsingContexts) {
|
||
|
sBrowsingContexts =
|
||
|
new nsDataHashtable<nsUint64HashKey, BrowsingContext*>();
|
||
|
ClearOnShutdown(&sBrowsingContexts);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* static */ LogModule*
|
||
|
BrowsingContext::GetLog()
|
||
|
{
|
||
|
return gBrowsingContextLog;
|
||
|
}
|
||
|
|
||
|
/* static */ already_AddRefed<BrowsingContext>
|
||
|
BrowsingContext::Get(uint64_t aId)
|
||
|
{
|
||
|
RefPtr<BrowsingContext> abc = sBrowsingContexts->Get(aId);
|
||
|
return abc.forget();
|
||
|
}
|
||
|
|
||
|
BrowsingContext::BrowsingContext(nsIDocShell* aDocShell)
|
||
|
: mBrowsingContextId(nsContentUtils::GenerateBrowsingContextId())
|
||
|
, mProcessId(Nothing())
|
||
|
, mDocShell(aDocShell)
|
||
|
{
|
||
|
sBrowsingContexts->Put(mBrowsingContextId, this);
|
||
|
}
|
||
|
|
||
|
BrowsingContext::BrowsingContext(uint64_t aBrowsingContextId,
|
||
|
const nsAString& aName,
|
||
|
const Maybe<uint64_t>& aProcessId)
|
||
|
: mBrowsingContextId(aBrowsingContextId)
|
||
|
, mProcessId(aProcessId)
|
||
|
, mName(aName)
|
||
|
{
|
||
|
// mProcessId only really has a meaning in the parent process, where
|
||
|
// it keeps track of which BrowsingContext is actually holding the
|
||
|
// nsDocShell.
|
||
|
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess() || aProcessId.isNothing());
|
||
|
sBrowsingContexts->Put(mBrowsingContextId, this);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
BrowsingContext::Attach(BrowsingContext* aParent)
|
||
|
{
|
||
|
if (isInList()) {
|
||
|
MOZ_LOG(GetLog(),
|
||
|
LogLevel::Debug,
|
||
|
("%s: Connecting already existing 0x%08" PRIx64 " to 0x%08" PRIx64,
|
||
|
XRE_IsParentProcess() ? "Parent" : "Child",
|
||
|
Id(),
|
||
|
aParent ? aParent->Id() : 0));
|
||
|
MOZ_DIAGNOSTIC_ASSERT(sBrowsingContexts->Contains(Id()));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
MOZ_LOG(GetLog(),
|
||
|
LogLevel::Debug,
|
||
|
("%s: Connecting 0x%08" PRIx64 " to 0x%08" PRIx64 "\n",
|
||
|
XRE_IsParentProcess() ? "Parent" : "Child",
|
||
|
Id(),
|
||
|
aParent ? aParent->Id() : 0));
|
||
|
|
||
|
auto* children = aParent ? &aParent->mChildren : sRootBrowsingContexts.get();
|
||
|
children->insertBack(this);
|
||
|
mParent = aParent;
|
||
|
|
||
|
if (!XRE_IsContentProcess()) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
auto cc = dom::ContentChild::GetSingleton();
|
||
|
MOZ_DIAGNOSTIC_ASSERT(cc);
|
||
|
cc->SendAttachBrowsingContext(
|
||
|
dom::BrowsingContextId(mParent ? mParent->Id() : 0),
|
||
|
dom::BrowsingContextId(Id()),
|
||
|
mName);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
BrowsingContext::Detach()
|
||
|
{
|
||
|
RefPtr<BrowsingContext> kungFuDeathGrip(this);
|
||
|
|
||
|
if (!isInList()) {
|
||
|
MOZ_LOG(GetLog(),
|
||
|
LogLevel::Debug,
|
||
|
("%s: Detaching already detached 0x%08" PRIx64,
|
||
|
XRE_IsParentProcess() ? "Parent" : "Child",
|
||
|
Id()));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
MOZ_LOG(GetLog(),
|
||
|
LogLevel::Debug,
|
||
|
("%s: Detaching 0x%08" PRIx64 " from 0x%08" PRIx64,
|
||
|
XRE_IsParentProcess() ? "Parent" : "Child",
|
||
|
Id(),
|
||
|
mParent ? mParent->Id() : 0));
|
||
|
|
||
|
remove();
|
||
|
|
||
|
if (!XRE_IsContentProcess()) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
auto cc = dom::ContentChild::GetSingleton();
|
||
|
MOZ_DIAGNOSTIC_ASSERT(cc);
|
||
|
cc->SendDetachBrowsingContext(dom::BrowsingContextId(Id()));
|
||
|
}
|
||
|
|
||
|
uint64_t
|
||
|
BrowsingContext::OwnerProcessId() const
|
||
|
{
|
||
|
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());
|
||
|
return mProcessId.value();
|
||
|
}
|
||
|
|
||
|
BrowsingContext::~BrowsingContext()
|
||
|
{
|
||
|
MOZ_DIAGNOSTIC_ASSERT(!isInList());
|
||
|
|
||
|
if (sBrowsingContexts) {
|
||
|
sBrowsingContexts->Remove(mBrowsingContextId);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
ImplCycleCollectionUnlink(BrowsingContext::Children& aField)
|
||
|
{
|
||
|
aField.clear();
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
|
||
|
BrowsingContext::Children& aField,
|
||
|
const char* aName,
|
||
|
uint32_t aFlags = 0)
|
||
|
{
|
||
|
for (BrowsingContext* aContext : aField) {
|
||
|
aCallback.NoteNativeChild(aContext,
|
||
|
NS_CYCLE_COLLECTION_PARTICIPANT(BrowsingContext));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
NS_IMPL_CYCLE_COLLECTION(BrowsingContext, mDocShell, mChildren)
|
||
|
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(BrowsingContext, AddRef)
|
||
|
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(BrowsingContext, Release)
|
||
|
|
||
|
} // namespace dom
|
||
|
} // namespace mozilla
|