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/. */
|
|
|
|
|
2018-10-20 01:00:59 +03:00
|
|
|
#include "mozilla/dom/BrowsingContext.h"
|
2018-07-26 10:31:00 +03:00
|
|
|
|
2019-01-29 20:32:28 +03:00
|
|
|
#include "mozilla/dom/CanonicalBrowsingContext.h"
|
2019-01-30 19:07:21 +03:00
|
|
|
#include "mozilla/dom/BrowsingContextGroup.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"
|
2019-01-02 16:29:18 +03:00
|
|
|
#include "mozilla/dom/Location.h"
|
|
|
|
#include "mozilla/dom/LocationBinding.h"
|
|
|
|
#include "mozilla/dom/WindowBinding.h"
|
2019-01-03 10:11:00 +03:00
|
|
|
#include "mozilla/dom/WindowProxyHolder.h"
|
2018-07-26 10:31:00 +03:00
|
|
|
#include "mozilla/Assertions.h"
|
|
|
|
#include "mozilla/ClearOnShutdown.h"
|
2018-12-17 13:45:37 +03:00
|
|
|
#include "mozilla/HashTable.h"
|
2018-07-26 10:31:00 +03:00
|
|
|
#include "mozilla/Logging.h"
|
|
|
|
#include "mozilla/StaticPtr.h"
|
|
|
|
|
2018-11-05 15:43:10 +03:00
|
|
|
#include "nsDocShell.h"
|
2019-01-02 16:29:18 +03:00
|
|
|
#include "nsGlobalWindowOuter.h"
|
2018-07-26 10:31:00 +03:00
|
|
|
#include "nsContentUtils.h"
|
2019-01-02 16:29:18 +03:00
|
|
|
#include "nsScriptError.h"
|
2018-06-29 02:41:00 +03:00
|
|
|
#include "nsThreadUtils.h"
|
2018-07-26 10:31:00 +03:00
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace dom {
|
|
|
|
|
2019-01-15 02:09:42 +03:00
|
|
|
extern mozilla::LazyLogModule gUserInteractionPRLog;
|
|
|
|
|
|
|
|
#define USER_ACTIVATION_LOG(msg, ...) \
|
|
|
|
MOZ_LOG(gUserInteractionPRLog, LogLevel::Debug, (msg, ##__VA_ARGS__))
|
|
|
|
|
2018-07-26 10:31:00 +03:00
|
|
|
static LazyLogModule gBrowsingContextLog("BrowsingContext");
|
|
|
|
|
2018-12-17 13:45:37 +03:00
|
|
|
template <template <typename> class PtrType>
|
|
|
|
using BrowsingContextMap =
|
|
|
|
HashMap<uint64_t, PtrType<BrowsingContext>, DefaultHasher<uint64_t>,
|
|
|
|
InfallibleAllocPolicy>;
|
|
|
|
|
|
|
|
static StaticAutoPtr<BrowsingContextMap<WeakPtr>> sBrowsingContexts;
|
2018-07-26 10:31:00 +03:00
|
|
|
|
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]
|
2018-12-17 13:45:37 +03:00
|
|
|
static StaticAutoPtr<BrowsingContextMap<RefPtr>> sCachedBrowsingContexts;
|
2018-06-28 05:40:00 +03:00
|
|
|
|
2018-11-05 15:43:10 +03:00
|
|
|
static void Register(BrowsingContext* aBrowsingContext) {
|
2018-12-17 13:45:37 +03:00
|
|
|
MOZ_ALWAYS_TRUE(
|
|
|
|
sBrowsingContexts->putNew(aBrowsingContext->Id(), aBrowsingContext));
|
2019-01-30 19:07:21 +03:00
|
|
|
|
|
|
|
aBrowsingContext->Group()->Register(aBrowsingContext);
|
2018-11-05 15:43:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void Sync(BrowsingContext* aBrowsingContext) {
|
|
|
|
if (!XRE_IsContentProcess()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto cc = ContentChild::GetSingleton();
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(cc);
|
|
|
|
RefPtr<BrowsingContext> parent = aBrowsingContext->GetParent();
|
2018-11-27 12:59:44 +03:00
|
|
|
BrowsingContext* opener = aBrowsingContext->GetOpener();
|
2018-11-05 15:43:10 +03:00
|
|
|
cc->SendAttachBrowsingContext(BrowsingContextId(parent ? parent->Id() : 0),
|
2018-11-27 12:59:44 +03:00
|
|
|
BrowsingContextId(opener ? opener->Id() : 0),
|
2018-11-05 15:43:10 +03:00
|
|
|
BrowsingContextId(aBrowsingContext->Id()),
|
2019-01-02 16:29:18 +03:00
|
|
|
aBrowsingContext->Name());
|
2018-11-05 15:43:10 +03:00
|
|
|
}
|
|
|
|
|
2019-01-15 02:09:42 +03:00
|
|
|
BrowsingContext* BrowsingContext::TopLevelBrowsingContext() {
|
|
|
|
BrowsingContext* bc = this;
|
|
|
|
while (bc->mParent) {
|
|
|
|
bc = bc->mParent;
|
|
|
|
}
|
|
|
|
return bc;
|
|
|
|
}
|
|
|
|
|
2018-07-26 10:31:00 +03:00
|
|
|
/* static */ void BrowsingContext::Init() {
|
|
|
|
if (!sBrowsingContexts) {
|
2018-12-17 13:45:37 +03:00
|
|
|
sBrowsingContexts = new BrowsingContextMap<WeakPtr>();
|
2018-07-26 10:31:00 +03:00
|
|
|
ClearOnShutdown(&sBrowsingContexts);
|
|
|
|
}
|
2018-06-28 05:40:00 +03:00
|
|
|
|
|
|
|
if (!sCachedBrowsingContexts) {
|
2018-12-17 13:45:37 +03:00
|
|
|
sCachedBrowsingContexts = new BrowsingContextMap<RefPtr>();
|
2018-06-28 05:40:00 +03:00
|
|
|
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) {
|
2018-12-17 13:45:37 +03:00
|
|
|
if (BrowsingContextMap<WeakPtr>::Ptr abc = sBrowsingContexts->lookup(aId)) {
|
|
|
|
return do_AddRef(abc->value().get());
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
2018-07-26 10:31:00 +03:00
|
|
|
}
|
|
|
|
|
2018-09-14 17:57:18 +03:00
|
|
|
/* static */ already_AddRefed<BrowsingContext> BrowsingContext::Create(
|
2018-11-05 15:43:10 +03:00
|
|
|
BrowsingContext* aParent, BrowsingContext* aOpener, const nsAString& aName,
|
|
|
|
Type aType) {
|
|
|
|
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()) {
|
2019-01-29 20:32:28 +03:00
|
|
|
context = new CanonicalBrowsingContext(aParent, aOpener, aName, id,
|
2019-02-04 22:10:18 +03:00
|
|
|
/* aProcessId */ 0, aType);
|
2018-09-14 17:57:18 +03:00
|
|
|
} else {
|
2018-11-27 12:59:44 +03:00
|
|
|
context = new BrowsingContext(aParent, aOpener, 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(
|
2018-11-27 12:59:44 +03:00
|
|
|
BrowsingContext* aParent, BrowsingContext* aOpener, const nsAString& aName,
|
|
|
|
uint64_t aId, ContentParent* aOriginProcess) {
|
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()) {
|
2019-01-29 20:32:28 +03:00
|
|
|
context = new CanonicalBrowsingContext(
|
2018-11-27 12:59:44 +03:00
|
|
|
aParent, aOpener, aName, aId, aOriginProcess->ChildID(), Type::Content);
|
2018-11-05 15:43:10 +03:00
|
|
|
} else {
|
2018-11-27 12:59:44 +03:00
|
|
|
context = new BrowsingContext(aParent, aOpener, aName, aId, Type::Content);
|
2018-11-05 15:43:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
2018-11-27 12:59:44 +03:00
|
|
|
BrowsingContext* aOpener,
|
2018-11-05 15:43:10 +03:00
|
|
|
const nsAString& aName,
|
|
|
|
uint64_t aBrowsingContextId, Type aType)
|
|
|
|
: mType(aType),
|
|
|
|
mBrowsingContextId(aBrowsingContextId),
|
|
|
|
mParent(aParent),
|
2018-11-27 12:59:44 +03:00
|
|
|
mOpener(aOpener),
|
2019-01-02 16:29:18 +03:00
|
|
|
mName(aName),
|
2019-01-15 02:09:42 +03:00
|
|
|
mClosed(false),
|
|
|
|
mIsActivatedByUserGesture(false) {
|
2019-01-30 19:07:21 +03:00
|
|
|
// Specify our group in our constructor. We will explicitly join the group
|
|
|
|
// when we are registered, as doing so will take a reference.
|
2018-12-17 13:45:37 +03:00
|
|
|
if (mParent) {
|
2019-01-30 19:07:21 +03:00
|
|
|
mGroup = mParent->Group();
|
2018-12-17 13:45:37 +03:00
|
|
|
} else if (mOpener) {
|
2019-01-30 19:07:21 +03:00
|
|
|
mGroup = mOpener->Group();
|
2018-12-17 13:45:37 +03:00
|
|
|
} else {
|
2019-01-30 19:07:21 +03:00
|
|
|
// To ensure the group has a unique ID, we will use our ID, as the founder
|
|
|
|
// of this BrowsingContextGroup.
|
|
|
|
mGroup = new BrowsingContextGroup();
|
2018-12-17 13:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2018-11-05 15:43:10 +03:00
|
|
|
void 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
|
|
|
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-12-17 13:45:37 +03:00
|
|
|
sCachedBrowsingContexts->has(Id()) ? "Re-connecting" : "Connecting",
|
|
|
|
Id(), mParent ? mParent->Id() : 0));
|
|
|
|
|
|
|
|
sCachedBrowsingContexts->remove(Id());
|
2018-07-26 10:31:00 +03:00
|
|
|
|
2019-01-30 19:07:21 +03:00
|
|
|
auto* children = mParent ? &mParent->mChildren : &mGroup->Toplevels();
|
2018-12-17 13:45:37 +03:00
|
|
|
MOZ_DIAGNOSTIC_ASSERT(!children->Contains(this));
|
|
|
|
|
|
|
|
children->AppendElement(this);
|
2018-07-26 10:31:00 +03:00
|
|
|
|
2018-11-05 15:43:10 +03:00
|
|
|
Sync(this);
|
2018-07-26 10:31:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void BrowsingContext::Detach() {
|
|
|
|
MOZ_LOG(GetLog(), LogLevel::Debug,
|
|
|
|
("%s: Detaching 0x%08" PRIx64 " from 0x%08" PRIx64,
|
|
|
|
XRE_IsParentProcess() ? "Parent" : "Child", Id(),
|
|
|
|
mParent ? mParent->Id() : 0));
|
|
|
|
|
2018-12-17 13:45:37 +03:00
|
|
|
RefPtr<BrowsingContext> kungFuDeathGrip(this);
|
|
|
|
|
|
|
|
BrowsingContextMap<RefPtr>::Ptr p;
|
|
|
|
if (sCachedBrowsingContexts && (p = sCachedBrowsingContexts->lookup(Id()))) {
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(!mParent || !mParent->mChildren.Contains(this));
|
2019-01-30 19:07:21 +03:00
|
|
|
MOZ_DIAGNOSTIC_ASSERT(!mGroup || !mGroup->Toplevels().Contains(this));
|
2018-12-17 13:45:37 +03:00
|
|
|
sCachedBrowsingContexts->remove(p);
|
|
|
|
} else {
|
2019-01-30 19:07:21 +03:00
|
|
|
auto* children = mParent ? &mParent->mChildren : &mGroup->Toplevels();
|
|
|
|
|
2018-12-17 13:45:37 +03:00
|
|
|
// TODO(farre): This assert looks extremely fishy, I know, but
|
|
|
|
// what we're actually saying is this: if we're detaching, but our
|
|
|
|
// parent doesn't have any children, it is because we're being
|
|
|
|
// detached by the cycle collector destroying docshells out of
|
|
|
|
// order.
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(children->IsEmpty() || children->Contains(this));
|
|
|
|
|
|
|
|
children->RemoveElement(this);
|
|
|
|
}
|
2018-07-26 10:31:00 +03:00
|
|
|
|
2019-01-30 19:07:21 +03:00
|
|
|
Group()->Unregister(this);
|
|
|
|
|
2018-07-26 10:31:00 +03:00
|
|
|
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() {
|
2018-12-17 13:45:37 +03:00
|
|
|
if (mChildren.IsEmpty()) {
|
2018-06-28 05:40:00 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_LOG(GetLog(), LogLevel::Debug,
|
|
|
|
("%s: Caching children of 0x%08" PRIx64 "",
|
|
|
|
XRE_IsParentProcess() ? "Parent" : "Child", Id()));
|
|
|
|
|
2018-12-17 13:45:37 +03:00
|
|
|
MOZ_ALWAYS_TRUE(sCachedBrowsingContexts->reserve(mChildren.Length()));
|
|
|
|
|
|
|
|
for (BrowsingContext* child : mChildren) {
|
|
|
|
MOZ_ALWAYS_TRUE(sCachedBrowsingContexts->putNew(child->Id(), child));
|
2018-06-28 05:40:00 +03:00
|
|
|
}
|
2018-12-17 13:45:37 +03:00
|
|
|
mChildren.Clear();
|
2018-06-28 05:40:00 +03:00
|
|
|
|
|
|
|
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 */);
|
|
|
|
}
|
|
|
|
|
2018-12-17 13:45:37 +03:00
|
|
|
bool BrowsingContext::IsCached() { return sCachedBrowsingContexts->has(Id()); }
|
2018-07-26 10:31:00 +03:00
|
|
|
|
2018-08-29 05:00:00 +03:00
|
|
|
void BrowsingContext::GetChildren(
|
|
|
|
nsTArray<RefPtr<BrowsingContext>>& aChildren) {
|
2018-12-17 13:45:37 +03:00
|
|
|
MOZ_ALWAYS_TRUE(aChildren.AppendElements(mChildren));
|
2018-08-29 05:00:00 +03:00
|
|
|
}
|
|
|
|
|
2018-11-09 11:53:53 +03:00
|
|
|
void BrowsingContext::SetOpener(BrowsingContext* aOpener) {
|
|
|
|
if (mOpener == aOpener) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mOpener = aOpener;
|
|
|
|
|
|
|
|
if (!XRE_IsContentProcess()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto cc = ContentChild::GetSingleton();
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(cc);
|
|
|
|
cc->SendSetOpenerBrowsingContext(
|
|
|
|
BrowsingContextId(Id()), BrowsingContextId(aOpener ? aOpener->Id() : 0));
|
|
|
|
}
|
|
|
|
|
2018-07-26 10:31:00 +03:00
|
|
|
BrowsingContext::~BrowsingContext() {
|
2018-12-17 13:45:37 +03:00
|
|
|
MOZ_DIAGNOSTIC_ASSERT(!mParent || !mParent->mChildren.Contains(this));
|
2019-01-30 19:07:21 +03:00
|
|
|
MOZ_DIAGNOSTIC_ASSERT(!mGroup || !mGroup->Toplevels().Contains(this));
|
2018-12-17 13:45:37 +03:00
|
|
|
MOZ_DIAGNOSTIC_ASSERT(!sCachedBrowsingContexts ||
|
|
|
|
!sCachedBrowsingContexts->has(Id()));
|
2018-07-26 10:31:00 +03:00
|
|
|
|
|
|
|
if (sBrowsingContexts) {
|
2018-12-17 13:45:37 +03:00
|
|
|
sBrowsingContexts->remove(Id());
|
2018-07-26 10:31:00 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2019-01-15 02:09:42 +03:00
|
|
|
void BrowsingContext::NotifyUserGestureActivation() {
|
|
|
|
// We would set the user gesture activation flag on the top level browsing
|
|
|
|
// context, which would automatically be sync to other top level browsing
|
|
|
|
// contexts which are in the different process.
|
|
|
|
RefPtr<BrowsingContext> topLevelBC = TopLevelBrowsingContext();
|
2019-01-14 19:08:06 +03:00
|
|
|
USER_ACTIVATION_LOG("Get top level browsing context 0x%08" PRIx64,
|
|
|
|
topLevelBC->Id());
|
2019-01-15 02:09:42 +03:00
|
|
|
topLevelBC->SetUserGestureActivation();
|
2019-01-14 19:08:06 +03:00
|
|
|
|
|
|
|
if (!XRE_IsContentProcess()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
auto cc = ContentChild::GetSingleton();
|
|
|
|
MOZ_ASSERT(cc);
|
|
|
|
cc->SendSetUserGestureActivation(BrowsingContextId(topLevelBC->Id()), true);
|
2019-01-15 02:09:42 +03:00
|
|
|
}
|
|
|
|
|
2019-01-15 02:21:05 +03:00
|
|
|
void BrowsingContext::NotifyResetUserGestureActivation() {
|
|
|
|
// We would reset the user gesture activation flag on the top level browsing
|
|
|
|
// context, which would automatically be sync to other top level browsing
|
|
|
|
// contexts which are in the different process.
|
|
|
|
RefPtr<BrowsingContext> topLevelBC = TopLevelBrowsingContext();
|
|
|
|
USER_ACTIVATION_LOG("Get top level browsing context 0x%08" PRIx64,
|
|
|
|
topLevelBC->Id());
|
|
|
|
topLevelBC->ResetUserGestureActivation();
|
|
|
|
|
|
|
|
if (!XRE_IsContentProcess()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
auto cc = ContentChild::GetSingleton();
|
|
|
|
MOZ_ASSERT(cc);
|
|
|
|
cc->SendSetUserGestureActivation(BrowsingContextId(topLevelBC->Id()), false);
|
|
|
|
}
|
|
|
|
|
2019-01-15 02:09:42 +03:00
|
|
|
void BrowsingContext::SetUserGestureActivation() {
|
|
|
|
MOZ_ASSERT(!mParent, "Set user activation flag on non top-level context!");
|
|
|
|
USER_ACTIVATION_LOG(
|
|
|
|
"Set user gesture activation for browsing context 0x%08" PRIx64, Id());
|
|
|
|
mIsActivatedByUserGesture = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BrowsingContext::GetUserGestureActivation() {
|
|
|
|
RefPtr<BrowsingContext> topLevelBC = TopLevelBrowsingContext();
|
|
|
|
return topLevelBC->mIsActivatedByUserGesture;
|
|
|
|
}
|
|
|
|
|
2019-01-15 02:21:05 +03:00
|
|
|
void BrowsingContext::ResetUserGestureActivation() {
|
|
|
|
MOZ_ASSERT(!mParent, "Clear user activation flag on non top-level context!");
|
|
|
|
USER_ACTIVATION_LOG(
|
|
|
|
"Reset user gesture activation for browsing context 0x%08" PRIx64, Id());
|
|
|
|
mIsActivatedByUserGesture = false;
|
|
|
|
}
|
|
|
|
|
2018-09-14 17:57:18 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(BrowsingContext)
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BrowsingContext)
|
2019-01-30 19:07:21 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell, mChildren, mParent, mGroup)
|
2018-09-14 17:57:18 +03:00
|
|
|
if (XRE_IsParentProcess()) {
|
2019-01-29 20:32:28 +03:00
|
|
|
CanonicalBrowsingContext::Cast(tmp)->Unlink();
|
2018-09-14 17:57:18 +03:00
|
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BrowsingContext)
|
2019-01-30 19:07:21 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell, mChildren, mParent, mGroup)
|
2018-09-14 17:57:18 +03:00
|
|
|
if (XRE_IsParentProcess()) {
|
2019-01-29 20:32:28 +03:00
|
|
|
CanonicalBrowsingContext::Cast(tmp)->Traverse(cb);
|
2018-09-14 17:57:18 +03:00
|
|
|
}
|
|
|
|
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)
|
|
|
|
|
2019-01-02 16:29:18 +03:00
|
|
|
void BrowsingContext::Location(JSContext* aCx,
|
|
|
|
JS::MutableHandle<JSObject*> aLocation,
|
|
|
|
OOMReporter& aError) {}
|
|
|
|
|
|
|
|
void BrowsingContext::Close(CallerType aCallerType, ErrorResult& aError) {
|
|
|
|
// FIXME We need to set mClosed, but only once we're sending the
|
|
|
|
// DOMWindowClose event (which happens in the process where the
|
|
|
|
// document for this browsing context is loaded).
|
|
|
|
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1516343.
|
|
|
|
ContentChild* cc = ContentChild::GetSingleton();
|
|
|
|
cc->SendWindowClose(BrowsingContextId(mBrowsingContextId),
|
|
|
|
aCallerType == CallerType::System);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BrowsingContext::Focus(ErrorResult& aError) {
|
|
|
|
ContentChild* cc = ContentChild::GetSingleton();
|
|
|
|
cc->SendWindowFocus(BrowsingContextId(mBrowsingContextId));
|
|
|
|
}
|
|
|
|
|
|
|
|
void BrowsingContext::Blur(ErrorResult& aError) {
|
|
|
|
ContentChild* cc = ContentChild::GetSingleton();
|
|
|
|
cc->SendWindowBlur(BrowsingContextId(mBrowsingContextId));
|
|
|
|
}
|
|
|
|
|
|
|
|
Nullable<WindowProxyHolder> BrowsingContext::GetTop(ErrorResult& aError) {
|
|
|
|
// We never return null or throw an error, but the implementation in
|
|
|
|
// nsGlobalWindow does and we need to use the same signature.
|
2019-01-15 20:06:12 +03:00
|
|
|
return WindowProxyHolder(TopLevelBrowsingContext());
|
2019-01-02 16:29:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void BrowsingContext::GetOpener(JSContext* aCx,
|
|
|
|
JS::MutableHandle<JS::Value> aOpener,
|
|
|
|
ErrorResult& aError) const {
|
|
|
|
auto* opener = GetOpener();
|
|
|
|
if (!opener) {
|
|
|
|
aOpener.setNull();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ToJSValue(aCx, WindowProxyHolder(opener), aOpener)) {
|
|
|
|
aError.NoteJSContextException(aCx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Nullable<WindowProxyHolder> BrowsingContext::GetParent(
|
|
|
|
ErrorResult& aError) const {
|
|
|
|
// We never throw an error, but the implementation in nsGlobalWindow does and
|
|
|
|
// we need to use the same signature.
|
|
|
|
if (!mParent) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return WindowProxyHolder(mParent.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
void BrowsingContext::PostMessageMoz(JSContext* aCx,
|
|
|
|
JS::Handle<JS::Value> aMessage,
|
|
|
|
const nsAString& aTargetOrigin,
|
|
|
|
const Sequence<JSObject*>& aTransfer,
|
|
|
|
nsIPrincipal& aSubjectPrincipal,
|
|
|
|
ErrorResult& aError) {
|
|
|
|
RefPtr<BrowsingContext> sourceBc;
|
|
|
|
PostMessageData data;
|
|
|
|
data.targetOrigin() = aTargetOrigin;
|
|
|
|
data.subjectPrincipal() = &aSubjectPrincipal;
|
|
|
|
RefPtr<nsGlobalWindowInner> callerInnerWindow;
|
|
|
|
if (!nsGlobalWindowOuter::GatherPostMessageData(
|
|
|
|
aCx, aTargetOrigin, getter_AddRefs(sourceBc), data.origin(),
|
|
|
|
getter_AddRefs(data.targetOriginURI()),
|
|
|
|
getter_AddRefs(data.callerPrincipal()),
|
|
|
|
getter_AddRefs(callerInnerWindow),
|
|
|
|
getter_AddRefs(data.callerDocumentURI()), aError)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
data.source() = BrowsingContextId(sourceBc->Id());
|
|
|
|
data.isFromPrivateWindow() =
|
|
|
|
callerInnerWindow &&
|
|
|
|
nsScriptErrorBase::ComputeIsFromPrivateWindow(callerInnerWindow);
|
|
|
|
|
|
|
|
JS::Rooted<JS::Value> transferArray(aCx);
|
|
|
|
aError = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransfer,
|
|
|
|
&transferArray);
|
|
|
|
if (NS_WARN_IF(aError.Failed())) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ipc::StructuredCloneData message;
|
|
|
|
message.Write(aCx, aMessage, transferArray, aError);
|
|
|
|
if (NS_WARN_IF(aError.Failed())) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ContentChild* cc = ContentChild::GetSingleton();
|
|
|
|
ClonedMessageData messageData;
|
|
|
|
if (!message.BuildClonedMessageDataForChild(cc, messageData)) {
|
|
|
|
aError.Throw(NS_ERROR_FAILURE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cc->SendWindowPostMessage(BrowsingContextId(mBrowsingContextId), messageData,
|
|
|
|
data);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BrowsingContext::PostMessageMoz(JSContext* aCx,
|
|
|
|
JS::Handle<JS::Value> aMessage,
|
|
|
|
const WindowPostMessageOptions& aOptions,
|
|
|
|
nsIPrincipal& aSubjectPrincipal,
|
|
|
|
ErrorResult& aError) {
|
|
|
|
PostMessageMoz(aCx, aMessage, aOptions.mTargetOrigin, aOptions.mTransfer,
|
|
|
|
aSubjectPrincipal, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<BrowsingContext> BrowsingContext::FindChildWithName(
|
|
|
|
const nsAString& aName) {
|
|
|
|
// FIXME https://bugzilla.mozilla.org/show_bug.cgi?id=1515646 will reimplement
|
|
|
|
// this on top of the BC tree.
|
|
|
|
MOZ_ASSERT(mDocShell);
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> child;
|
|
|
|
mDocShell->FindChildWithName(aName, false, true, nullptr, nullptr,
|
|
|
|
getter_AddRefs(child));
|
|
|
|
nsCOMPtr<nsIDocShell> childDS = do_QueryInterface(child);
|
|
|
|
RefPtr<BrowsingContext> bc;
|
|
|
|
if (childDS) {
|
|
|
|
childDS->GetBrowsingContext(getter_AddRefs(bc));
|
|
|
|
}
|
|
|
|
return bc.forget();
|
|
|
|
}
|
|
|
|
|
2018-07-26 10:31:00 +03:00
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|