2018-07-26 10:31:00 +03:00
|
|
|
/* -*- 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"
|
|
|
|
|
2018-09-14 17:57:18 +03:00
|
|
|
#include "mozilla/dom/ChromeBrowsingContext.h"
|
2018-08-29 05:00:00 +03:00
|
|
|
#include "mozilla/dom/BrowsingContextBinding.h"
|
2018-07-26 10:31:00 +03:00
|
|
|
#include "mozilla/dom/ContentChild.h"
|
2018-11-05 15:43:10 +03:00
|
|
|
#include "mozilla/dom/ContentParent.h"
|
2018-07-26 10:31:00 +03:00
|
|
|
#include "mozilla/Assertions.h"
|
|
|
|
#include "mozilla/ClearOnShutdown.h"
|
|
|
|
#include "mozilla/Logging.h"
|
|
|
|
#include "mozilla/StaticPtr.h"
|
|
|
|
|
|
|
|
#include "nsDataHashtable.h"
|
2018-11-05 15:43:10 +03:00
|
|
|
#include "nsDocShell.h"
|
2018-06-28 05:40:00 +03:00
|
|
|
#include "nsRefPtrHashtable.h"
|
2018-07-26 10:31:00 +03:00
|
|
|
#include "nsContentUtils.h"
|
2018-06-29 02:41:00 +03:00
|
|
|
#include "nsThreadUtils.h"
|
2018-07-26 10:31:00 +03:00
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace dom {
|
|
|
|
|
|
|
|
static LazyLogModule gBrowsingContextLog("BrowsingContext");
|
|
|
|
|
|
|
|
static StaticAutoPtr<BrowsingContext::Children> sRootBrowsingContexts;
|
|
|
|
|
|
|
|
static StaticAutoPtr<nsDataHashtable<nsUint64HashKey, BrowsingContext*>>
|
|
|
|
sBrowsingContexts;
|
|
|
|
|
2018-06-28 05:40:00 +03:00
|
|
|
// TODO(farre): This duplicates some of the work performed by the
|
|
|
|
// bfcache. This should be unified. [Bug 1471601]
|
|
|
|
static StaticAutoPtr<nsRefPtrHashtable<nsUint64HashKey, BrowsingContext>>
|
|
|
|
sCachedBrowsingContexts;
|
|
|
|
|
2018-11-05 15:43:10 +03:00
|
|
|
static void
|
|
|
|
Register(BrowsingContext* aBrowsingContext)
|
|
|
|
{
|
|
|
|
auto entry = sBrowsingContexts->LookupForAdd(aBrowsingContext->Id());
|
|
|
|
MOZ_RELEASE_ASSERT(!entry, "Duplicate BrowsingContext ID");
|
|
|
|
entry.OrInsert([&] { return aBrowsingContext; });
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
Sync(BrowsingContext* aBrowsingContext)
|
|
|
|
{
|
|
|
|
if (!XRE_IsContentProcess()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto cc = ContentChild::GetSingleton();
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(cc);
|
|
|
|
nsAutoString name;
|
|
|
|
aBrowsingContext->GetName(name);
|
|
|
|
RefPtr<BrowsingContext> parent = aBrowsingContext->GetParent();
|
|
|
|
cc->SendAttachBrowsingContext(BrowsingContextId(parent ? parent->Id() : 0),
|
|
|
|
BrowsingContextId(aBrowsingContext->Id()),
|
|
|
|
name);
|
|
|
|
}
|
|
|
|
|
2018-07-26 10:31:00 +03:00
|
|
|
/* static */ void
|
|
|
|
BrowsingContext::Init()
|
|
|
|
{
|
|
|
|
if (!sRootBrowsingContexts) {
|
|
|
|
sRootBrowsingContexts = new BrowsingContext::Children();
|
|
|
|
ClearOnShutdown(&sRootBrowsingContexts);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!sBrowsingContexts) {
|
|
|
|
sBrowsingContexts =
|
|
|
|
new nsDataHashtable<nsUint64HashKey, BrowsingContext*>();
|
|
|
|
ClearOnShutdown(&sBrowsingContexts);
|
|
|
|
}
|
2018-06-28 05:40:00 +03:00
|
|
|
|
|
|
|
if (!sCachedBrowsingContexts) {
|
|
|
|
sCachedBrowsingContexts =
|
|
|
|
new nsRefPtrHashtable<nsUint64HashKey, BrowsingContext>();
|
|
|
|
ClearOnShutdown(&sCachedBrowsingContexts);
|
|
|
|
}
|
2018-07-26 10:31:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* static */ LogModule*
|
|
|
|
BrowsingContext::GetLog()
|
|
|
|
{
|
|
|
|
return gBrowsingContextLog;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */ already_AddRefed<BrowsingContext>
|
|
|
|
BrowsingContext::Get(uint64_t aId)
|
|
|
|
{
|
|
|
|
RefPtr<BrowsingContext> abc = sBrowsingContexts->Get(aId);
|
|
|
|
return abc.forget();
|
|
|
|
}
|
|
|
|
|
2018-09-14 17:57:18 +03:00
|
|
|
/* static */ already_AddRefed<BrowsingContext>
|
2018-11-05 15:43:10 +03:00
|
|
|
BrowsingContext::Create(BrowsingContext* aParent,
|
|
|
|
const nsAString& aName,
|
|
|
|
Type aType)
|
2018-09-14 17:57:18 +03:00
|
|
|
{
|
2018-11-05 15:43:10 +03:00
|
|
|
MOZ_DIAGNOSTIC_ASSERT(!aParent || aParent->mType == aType);
|
|
|
|
|
|
|
|
uint64_t id = nsContentUtils::GenerateBrowsingContextId();
|
|
|
|
|
|
|
|
MOZ_LOG(GetLog(),
|
|
|
|
LogLevel::Debug,
|
|
|
|
("Creating 0x%08" PRIx64 " in %s",
|
|
|
|
id,
|
|
|
|
XRE_IsParentProcess() ? "Parent" : "Child"));
|
|
|
|
|
2018-09-14 17:57:18 +03:00
|
|
|
RefPtr<BrowsingContext> context;
|
|
|
|
if (XRE_IsParentProcess()) {
|
2018-11-05 15:43:10 +03:00
|
|
|
context = new ChromeBrowsingContext(aParent, aName, id, /* aProcessId */ 0, aType);
|
2018-09-14 17:57:18 +03:00
|
|
|
} else {
|
2018-11-05 15:43:10 +03:00
|
|
|
context = new BrowsingContext(aParent, aName, id, aType);
|
2018-09-14 17:57:18 +03:00
|
|
|
}
|
|
|
|
|
2018-11-05 15:43:10 +03:00
|
|
|
Register(context);
|
|
|
|
|
|
|
|
// Attach the browsing context to the tree.
|
|
|
|
context->Attach();
|
|
|
|
|
2018-09-14 17:57:18 +03:00
|
|
|
return context.forget();
|
|
|
|
}
|
|
|
|
|
2018-11-05 15:43:10 +03:00
|
|
|
/* static */ already_AddRefed<BrowsingContext>
|
|
|
|
BrowsingContext::CreateFromIPC(BrowsingContext* aParent, const nsAString& aName,
|
|
|
|
uint64_t aId, ContentParent* aOriginProcess)
|
2018-07-26 10:31:00 +03:00
|
|
|
{
|
2018-11-05 15:43:10 +03:00
|
|
|
MOZ_DIAGNOSTIC_ASSERT(aOriginProcess || XRE_IsContentProcess(),
|
|
|
|
"Parent Process IPC contexts need a Content Process.");
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(!aParent || aParent->IsContent());
|
|
|
|
|
|
|
|
MOZ_LOG(GetLog(),
|
|
|
|
LogLevel::Debug,
|
|
|
|
("Creating 0x%08" PRIx64 " from IPC (origin=0x%08" PRIx64 ")",
|
|
|
|
aId, aOriginProcess ? uint64_t(aOriginProcess->ChildID()) : 0));
|
|
|
|
|
|
|
|
RefPtr<BrowsingContext> context;
|
|
|
|
if (XRE_IsParentProcess()) {
|
|
|
|
context = new ChromeBrowsingContext(
|
|
|
|
aParent, aName, aId, aOriginProcess->ChildID(), Type::Content);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
context = new BrowsingContext(aParent, aName, aId, Type::Content);
|
|
|
|
}
|
|
|
|
|
|
|
|
Register(context);
|
|
|
|
|
|
|
|
context->Attach();
|
|
|
|
|
|
|
|
return context.forget();
|
2018-07-26 10:31:00 +03:00
|
|
|
}
|
|
|
|
|
2018-11-05 15:43:10 +03:00
|
|
|
BrowsingContext::BrowsingContext(BrowsingContext* aParent,
|
|
|
|
const nsAString& aName,
|
|
|
|
uint64_t aBrowsingContextId,
|
|
|
|
Type aType)
|
|
|
|
: mType(aType)
|
|
|
|
, mBrowsingContextId(aBrowsingContextId)
|
|
|
|
, mParent(aParent)
|
2018-07-26 10:31:00 +03:00
|
|
|
, mName(aName)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-05 15:43:10 +03:00
|
|
|
BrowsingContext::SetDocShell(nsIDocShell* aDocShell)
|
|
|
|
{
|
|
|
|
// XXX(nika): We should communicate that we are now an active BrowsingContext
|
|
|
|
// process to the parent & do other validation here.
|
|
|
|
MOZ_RELEASE_ASSERT(nsDocShell::Cast(aDocShell)->GetBrowsingContext() == this);
|
|
|
|
mDocShell = aDocShell;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
BrowsingContext::Attach()
|
2018-07-26 10:31:00 +03:00
|
|
|
{
|
|
|
|
if (isInList()) {
|
|
|
|
MOZ_LOG(GetLog(),
|
|
|
|
LogLevel::Debug,
|
|
|
|
("%s: Connecting already existing 0x%08" PRIx64 " to 0x%08" PRIx64,
|
|
|
|
XRE_IsParentProcess() ? "Parent" : "Child",
|
|
|
|
Id(),
|
2018-11-05 15:43:10 +03:00
|
|
|
mParent ? mParent->Id() : 0));
|
2018-07-26 10:31:00 +03:00
|
|
|
MOZ_DIAGNOSTIC_ASSERT(sBrowsingContexts->Contains(Id()));
|
2018-06-28 05:40:00 +03:00
|
|
|
MOZ_DIAGNOSTIC_ASSERT(!IsCached());
|
2018-07-26 10:31:00 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-06-28 05:40:00 +03:00
|
|
|
bool wasCached = sCachedBrowsingContexts->Remove(Id());
|
|
|
|
|
2018-07-26 10:31:00 +03:00
|
|
|
MOZ_LOG(GetLog(),
|
|
|
|
LogLevel::Debug,
|
2018-06-28 05:40:00 +03:00
|
|
|
("%s: %s 0x%08" PRIx64 " to 0x%08" PRIx64,
|
2018-07-26 10:31:00 +03:00
|
|
|
XRE_IsParentProcess() ? "Parent" : "Child",
|
2018-08-29 05:00:00 +03:00
|
|
|
wasCached ? "Re-connecting" : "Connecting",
|
2018-07-26 10:31:00 +03:00
|
|
|
Id(),
|
2018-11-05 15:43:10 +03:00
|
|
|
mParent ? mParent->Id() : 0));
|
2018-07-26 10:31:00 +03:00
|
|
|
|
2018-11-05 15:43:10 +03:00
|
|
|
auto* children = mParent ? &mParent->mChildren : sRootBrowsingContexts.get();
|
2018-07-26 10:31:00 +03:00
|
|
|
children->insertBack(this);
|
|
|
|
|
2018-11-05 15:43:10 +03:00
|
|
|
Sync(this);
|
2018-07-26 10:31:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
BrowsingContext::Detach()
|
|
|
|
{
|
|
|
|
RefPtr<BrowsingContext> kungFuDeathGrip(this);
|
|
|
|
|
2018-06-28 05:40:00 +03:00
|
|
|
if (sCachedBrowsingContexts) {
|
|
|
|
sCachedBrowsingContexts->Remove(Id());
|
|
|
|
}
|
|
|
|
|
2018-07-26 10:31:00 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-09-14 17:57:18 +03:00
|
|
|
auto cc = ContentChild::GetSingleton();
|
2018-07-26 10:31:00 +03:00
|
|
|
MOZ_DIAGNOSTIC_ASSERT(cc);
|
2018-09-14 17:57:18 +03:00
|
|
|
cc->SendDetachBrowsingContext(BrowsingContextId(Id()),
|
2018-06-28 05:40:00 +03:00
|
|
|
false /* aMoveToBFCache */);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
BrowsingContext::CacheChildren()
|
|
|
|
{
|
|
|
|
if (mChildren.isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_LOG(GetLog(),
|
|
|
|
LogLevel::Debug,
|
|
|
|
("%s: Caching children of 0x%08" PRIx64 "",
|
|
|
|
XRE_IsParentProcess() ? "Parent" : "Child",
|
|
|
|
Id()));
|
|
|
|
|
|
|
|
while (!mChildren.isEmpty()) {
|
|
|
|
RefPtr<BrowsingContext> child = mChildren.popFirst();
|
|
|
|
sCachedBrowsingContexts->Put(child->Id(), child);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!XRE_IsContentProcess()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-09-14 17:57:18 +03:00
|
|
|
auto cc = ContentChild::GetSingleton();
|
2018-06-28 05:40:00 +03:00
|
|
|
MOZ_DIAGNOSTIC_ASSERT(cc);
|
2018-09-14 17:57:18 +03:00
|
|
|
cc->SendDetachBrowsingContext(BrowsingContextId(Id()),
|
2018-06-28 05:40:00 +03:00
|
|
|
true /* aMoveToBFCache */);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
BrowsingContext::IsCached()
|
|
|
|
{
|
|
|
|
return sCachedBrowsingContexts->Contains(Id());
|
2018-07-26 10:31:00 +03:00
|
|
|
}
|
|
|
|
|
2018-08-29 05:00:00 +03:00
|
|
|
void
|
|
|
|
BrowsingContext::GetChildren(nsTArray<RefPtr<BrowsingContext>>& aChildren)
|
|
|
|
{
|
|
|
|
for (BrowsingContext* context : mChildren) {
|
|
|
|
aChildren.AppendElement(context);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */ void
|
|
|
|
BrowsingContext::GetRootBrowsingContexts(nsTArray<RefPtr<BrowsingContext>>& aBrowsingContexts)
|
|
|
|
{
|
|
|
|
for (BrowsingContext* context : *sRootBrowsingContexts) {
|
|
|
|
aBrowsingContexts.AppendElement(context);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-26 10:31:00 +03:00
|
|
|
BrowsingContext::~BrowsingContext()
|
|
|
|
{
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(!isInList());
|
|
|
|
|
|
|
|
if (sBrowsingContexts) {
|
|
|
|
sBrowsingContexts->Remove(mBrowsingContextId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-29 05:00:00 +03:00
|
|
|
nsISupports*
|
|
|
|
BrowsingContext::GetParentObject() const
|
|
|
|
{
|
|
|
|
return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
|
|
|
|
}
|
|
|
|
|
|
|
|
JSObject*
|
|
|
|
BrowsingContext::WrapObject(JSContext* aCx,
|
|
|
|
JS::Handle<JSObject*> aGivenProto)
|
|
|
|
{
|
|
|
|
return BrowsingContext_Binding::Wrap(aCx, this, aGivenProto);
|
|
|
|
}
|
|
|
|
|
2018-07-26 10:31:00 +03:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-14 17:57:18 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(BrowsingContext)
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BrowsingContext)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell, mChildren)
|
|
|
|
if (XRE_IsParentProcess()) {
|
|
|
|
ChromeBrowsingContext::Cast(tmp)->Unlink();
|
|
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BrowsingContext)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell, mChildren)
|
|
|
|
if (XRE_IsParentProcess()) {
|
|
|
|
ChromeBrowsingContext::Cast(tmp)->Traverse(cb);
|
|
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(BrowsingContext)
|
|
|
|
|
2018-07-26 10:31:00 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(BrowsingContext, AddRef)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(BrowsingContext, Release)
|
|
|
|
|
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|