зеркало из https://github.com/mozilla/gecko-dev.git
560 строки
18 KiB
C++
560 строки
18 KiB
C++
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
|
/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
|
|
/* 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/WindowGlobalParent.h"
|
|
|
|
#include "mozilla/ClearOnShutdown.h"
|
|
#include "mozilla/ipc/InProcessParent.h"
|
|
#include "mozilla/dom/BrowserBridgeParent.h"
|
|
#include "mozilla/dom/CanonicalBrowsingContext.h"
|
|
#include "mozilla/dom/ContentParent.h"
|
|
#include "mozilla/dom/BrowserHost.h"
|
|
#include "mozilla/dom/BrowserParent.h"
|
|
#include "mozilla/dom/WindowGlobalActorsBinding.h"
|
|
#include "mozilla/dom/WindowGlobalChild.h"
|
|
#include "mozilla/dom/ChromeUtils.h"
|
|
#include "mozilla/dom/ipc/IdType.h"
|
|
#include "mozilla/dom/ipc/StructuredCloneData.h"
|
|
#include "mozilla/ServoCSSParser.h"
|
|
#include "mozilla/ServoStyleSet.h"
|
|
#include "mozJSComponentLoader.h"
|
|
#include "nsContentUtils.h"
|
|
#include "nsDocShell.h"
|
|
#include "nsError.h"
|
|
#include "nsFrameLoader.h"
|
|
#include "nsFrameLoaderOwner.h"
|
|
#include "nsGlobalWindowInner.h"
|
|
#include "nsQueryObject.h"
|
|
#include "nsFrameLoaderOwner.h"
|
|
#include "nsSerializationHelper.h"
|
|
#include "nsITransportSecurityInfo.h"
|
|
#include "nsISharePicker.h"
|
|
|
|
#include "mozilla/dom/DOMException.h"
|
|
#include "mozilla/dom/DOMExceptionBinding.h"
|
|
|
|
#include "mozilla/dom/JSWindowActorBinding.h"
|
|
#include "mozilla/dom/JSWindowActorParent.h"
|
|
#include "mozilla/dom/JSWindowActorService.h"
|
|
|
|
using namespace mozilla::ipc;
|
|
using namespace mozilla::dom::ipc;
|
|
|
|
namespace mozilla {
|
|
namespace dom {
|
|
|
|
typedef nsRefPtrHashtable<nsUint64HashKey, WindowGlobalParent> WGPByIdMap;
|
|
static StaticAutoPtr<WGPByIdMap> gWindowGlobalParentsById;
|
|
|
|
WindowGlobalParent::WindowGlobalParent(const WindowGlobalInit& aInit,
|
|
bool aInProcess)
|
|
: mDocumentPrincipal(aInit.principal()),
|
|
mDocumentURI(aInit.documentURI()),
|
|
mInnerWindowId(aInit.innerWindowId()),
|
|
mOuterWindowId(aInit.outerWindowId()),
|
|
mInProcess(aInProcess),
|
|
mIsInitialDocument(false),
|
|
mHasBeforeUnload(false) {
|
|
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess(), "Parent process only");
|
|
MOZ_RELEASE_ASSERT(mDocumentPrincipal, "Must have a valid principal");
|
|
|
|
// NOTE: mBrowsingContext initialized in Init()
|
|
MOZ_RELEASE_ASSERT(aInit.browsingContext(),
|
|
"Must be made in BrowsingContext");
|
|
}
|
|
|
|
void WindowGlobalParent::Init(const WindowGlobalInit& aInit) {
|
|
MOZ_ASSERT(Manager(), "Should have a manager!");
|
|
|
|
// Register this WindowGlobal in the gWindowGlobalParentsById map.
|
|
if (!gWindowGlobalParentsById) {
|
|
gWindowGlobalParentsById = new WGPByIdMap();
|
|
ClearOnShutdown(&gWindowGlobalParentsById);
|
|
}
|
|
auto entry = gWindowGlobalParentsById->LookupForAdd(mInnerWindowId);
|
|
MOZ_RELEASE_ASSERT(!entry, "Duplicate WindowGlobalParent entry for ID!");
|
|
entry.OrInsert([&] { return this; });
|
|
|
|
// Determine which content process the window global is coming from.
|
|
dom::ContentParentId processId(0);
|
|
if (!mInProcess) {
|
|
ContentParent* cp = static_cast<ContentParent*>(Manager()->Manager());
|
|
processId = cp->ChildID();
|
|
|
|
// Ensure the content process has permissions for this principal.
|
|
cp->TransmitPermissionsForPrincipal(mDocumentPrincipal);
|
|
}
|
|
|
|
mBrowsingContext = CanonicalBrowsingContext::Cast(aInit.browsingContext());
|
|
MOZ_ASSERT(mBrowsingContext);
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(
|
|
!mBrowsingContext->GetParent() ||
|
|
mBrowsingContext->GetEmbedderInnerWindowId(),
|
|
"When creating a non-root WindowGlobalParent, the WindowGlobalParent "
|
|
"for our embedder should've already been created.");
|
|
|
|
// Attach ourself to the browsing context.
|
|
mBrowsingContext->RegisterWindowGlobal(this);
|
|
|
|
// If there is no current window global, assume we're about to become it
|
|
// optimistically.
|
|
if (!mBrowsingContext->GetCurrentWindowGlobal()) {
|
|
mBrowsingContext->SetCurrentWindowGlobal(this);
|
|
}
|
|
|
|
// Ensure we have a document URI
|
|
if (!mDocumentURI) {
|
|
NS_NewURI(getter_AddRefs(mDocumentURI), "about:blank");
|
|
}
|
|
|
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
if (obs) {
|
|
obs->NotifyObservers(this, "window-global-created", nullptr);
|
|
}
|
|
}
|
|
|
|
/* static */
|
|
already_AddRefed<WindowGlobalParent> WindowGlobalParent::GetByInnerWindowId(
|
|
uint64_t aInnerWindowId) {
|
|
if (!gWindowGlobalParentsById) {
|
|
return nullptr;
|
|
}
|
|
return gWindowGlobalParentsById->Get(aInnerWindowId);
|
|
}
|
|
|
|
already_AddRefed<WindowGlobalChild> WindowGlobalParent::GetChildActor() {
|
|
if (!CanSend()) {
|
|
return nullptr;
|
|
}
|
|
IProtocol* otherSide = InProcessParent::ChildActorFor(this);
|
|
return do_AddRef(static_cast<WindowGlobalChild*>(otherSide));
|
|
}
|
|
|
|
already_AddRefed<BrowserParent> WindowGlobalParent::GetBrowserParent() {
|
|
if (IsInProcess() || !CanSend()) {
|
|
return nullptr;
|
|
}
|
|
return do_AddRef(static_cast<BrowserParent*>(Manager()));
|
|
}
|
|
|
|
already_AddRefed<nsFrameLoader> WindowGlobalParent::GetRootFrameLoader() {
|
|
dom::BrowsingContext* top = BrowsingContext()->Top();
|
|
|
|
RefPtr<nsFrameLoaderOwner> frameLoaderOwner =
|
|
do_QueryObject(top->GetEmbedderElement());
|
|
if (frameLoaderOwner) {
|
|
return frameLoaderOwner->GetFrameLoader();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
uint64_t WindowGlobalParent::ContentParentId() {
|
|
RefPtr<BrowserParent> browserParent = GetBrowserParent();
|
|
return browserParent ? browserParent->Manager()->ChildID() : 0;
|
|
}
|
|
|
|
int32_t WindowGlobalParent::OsPid() {
|
|
RefPtr<BrowserParent> browserParent = GetBrowserParent();
|
|
return browserParent ? browserParent->Manager()->Pid() : -1;
|
|
}
|
|
|
|
// A WindowGlobalPaernt is the root in its process if it has no parent, or its
|
|
// embedder is in a different process.
|
|
bool WindowGlobalParent::IsProcessRoot() {
|
|
if (!BrowsingContext()->GetParent()) {
|
|
return true;
|
|
}
|
|
|
|
RefPtr<WindowGlobalParent> embedder =
|
|
BrowsingContext()->GetEmbedderWindowGlobal();
|
|
if (NS_WARN_IF(!embedder)) {
|
|
return false;
|
|
}
|
|
|
|
return ContentParentId() != embedder->ContentParentId();
|
|
}
|
|
|
|
mozilla::ipc::IPCResult WindowGlobalParent::RecvLoadURI(
|
|
dom::BrowsingContext* aTargetBC, nsDocShellLoadState* aLoadState,
|
|
bool aSetNavigating) {
|
|
if (!aTargetBC || aTargetBC->IsDiscarded()) {
|
|
MOZ_LOG(
|
|
BrowsingContext::GetLog(), LogLevel::Debug,
|
|
("ParentIPC: Trying to send a message with dead or detached context"));
|
|
return IPC_OK();
|
|
}
|
|
|
|
// FIXME: For cross-process loads, we should double check CanAccess() for the
|
|
// source browsing context in the parent process.
|
|
|
|
if (aTargetBC->Group() != BrowsingContext()->Group()) {
|
|
return IPC_FAIL(this, "Illegal cross-group BrowsingContext load");
|
|
}
|
|
|
|
// FIXME: We should really initiate the load in the parent before bouncing
|
|
// back down to the child.
|
|
|
|
WindowGlobalParent* wgp = aTargetBC->Canonical()->GetCurrentWindowGlobal();
|
|
if (!wgp) {
|
|
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
|
|
("ParentIPC: Target BrowsingContext has no WindowGlobalParent"));
|
|
return IPC_OK();
|
|
}
|
|
|
|
Unused << wgp->SendLoadURIInChild(aLoadState, aSetNavigating);
|
|
return IPC_OK();
|
|
}
|
|
|
|
mozilla::ipc::IPCResult WindowGlobalParent::RecvInternalLoad(
|
|
dom::BrowsingContext* aTargetBC, nsDocShellLoadState* aLoadState) {
|
|
if (!aTargetBC || aTargetBC->IsDiscarded()) {
|
|
MOZ_LOG(
|
|
BrowsingContext::GetLog(), LogLevel::Debug,
|
|
("ParentIPC: Trying to send a message with dead or detached context"));
|
|
return IPC_OK();
|
|
}
|
|
|
|
// FIXME: For cross-process loads, we should double check CanAccess() for the
|
|
// source browsing context in the parent process.
|
|
|
|
if (aTargetBC->Group() != BrowsingContext()->Group()) {
|
|
return IPC_FAIL(this, "Illegal cross-group BrowsingContext load");
|
|
}
|
|
|
|
// FIXME: We should really initiate the load in the parent before bouncing
|
|
// back down to the child.
|
|
|
|
WindowGlobalParent* wgp = aTargetBC->Canonical()->GetCurrentWindowGlobal();
|
|
if (!wgp) {
|
|
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
|
|
("ParentIPC: Target BrowsingContext has no WindowGlobalParent"));
|
|
return IPC_OK();
|
|
}
|
|
|
|
bool takeFocus =
|
|
mBrowsingContext->GetIsActive() && !aTargetBC->GetIsActive() &&
|
|
!Preferences::GetBool("browser.tabs.loadDivertedInBackground", false);
|
|
Unused << wgp->SendInternalLoadInChild(aLoadState, takeFocus);
|
|
return IPC_OK();
|
|
}
|
|
|
|
IPCResult WindowGlobalParent::RecvUpdateDocumentURI(nsIURI* aURI) {
|
|
// XXX(nika): Assert that the URI change was one which makes sense (either
|
|
// about:blank -> a real URI, or a legal push/popstate URI change?)
|
|
mDocumentURI = aURI;
|
|
return IPC_OK();
|
|
}
|
|
|
|
IPCResult WindowGlobalParent::RecvSetHasBeforeUnload(bool aHasBeforeUnload) {
|
|
mHasBeforeUnload = aHasBeforeUnload;
|
|
return IPC_OK();
|
|
}
|
|
|
|
IPCResult WindowGlobalParent::RecvBecomeCurrentWindowGlobal() {
|
|
mBrowsingContext->SetCurrentWindowGlobal(this);
|
|
return IPC_OK();
|
|
}
|
|
|
|
IPCResult WindowGlobalParent::RecvDestroy() {
|
|
if (CanSend()) {
|
|
RefPtr<BrowserParent> browserParent = GetBrowserParent();
|
|
if (!browserParent || !browserParent->IsDestroyed()) {
|
|
// Make a copy so that we can avoid potential iterator invalidation when
|
|
// calling the user-provided Destroy() methods.
|
|
nsTArray<RefPtr<JSWindowActorParent>> windowActors(mWindowActors.Count());
|
|
for (auto iter = mWindowActors.Iter(); !iter.Done(); iter.Next()) {
|
|
windowActors.AppendElement(iter.UserData());
|
|
}
|
|
|
|
for (auto& windowActor : windowActors) {
|
|
windowActor->StartDestroy();
|
|
}
|
|
Unused << Send__delete__(this);
|
|
}
|
|
}
|
|
return IPC_OK();
|
|
}
|
|
|
|
IPCResult WindowGlobalParent::RecvRawMessage(
|
|
const JSWindowActorMessageMeta& aMeta, const ClonedMessageData& aData) {
|
|
StructuredCloneData data;
|
|
data.BorrowFromClonedMessageDataForParent(aData);
|
|
ReceiveRawMessage(aMeta, std::move(data));
|
|
return IPC_OK();
|
|
}
|
|
|
|
void WindowGlobalParent::ReceiveRawMessage(
|
|
const JSWindowActorMessageMeta& aMeta, StructuredCloneData&& aData) {
|
|
RefPtr<JSWindowActorParent> actor =
|
|
GetActor(aMeta.actorName(), IgnoreErrors());
|
|
if (actor) {
|
|
actor->ReceiveRawMessage(aMeta, std::move(aData));
|
|
}
|
|
}
|
|
|
|
const nsAString& WindowGlobalParent::GetRemoteType() {
|
|
if (RefPtr<BrowserParent> browserParent = GetBrowserParent()) {
|
|
return browserParent->Manager()->GetRemoteType();
|
|
}
|
|
|
|
return VoidString();
|
|
}
|
|
|
|
already_AddRefed<JSWindowActorParent> WindowGlobalParent::GetActor(
|
|
const nsAString& aName, ErrorResult& aRv) {
|
|
if (!CanSend()) {
|
|
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
return nullptr;
|
|
}
|
|
|
|
// Check if this actor has already been created, and return it if it has.
|
|
if (mWindowActors.Contains(aName)) {
|
|
return do_AddRef(mWindowActors.GetWeak(aName));
|
|
}
|
|
|
|
// Otherwise, we want to create a new instance of this actor.
|
|
JS::RootedObject obj(RootingCx());
|
|
ConstructActor(aName, &obj, aRv);
|
|
if (aRv.Failed()) {
|
|
return nullptr;
|
|
}
|
|
|
|
// Unwrap our actor to a JSWindowActorParent object.
|
|
RefPtr<JSWindowActorParent> actor;
|
|
if (NS_FAILED(UNWRAP_OBJECT(JSWindowActorParent, &obj, actor))) {
|
|
return nullptr;
|
|
}
|
|
|
|
MOZ_RELEASE_ASSERT(!actor->GetManager(),
|
|
"mManager was already initialized once!");
|
|
actor->Init(aName, this);
|
|
mWindowActors.Put(aName, actor);
|
|
return actor.forget();
|
|
}
|
|
|
|
bool WindowGlobalParent::IsCurrentGlobal() {
|
|
return CanSend() && mBrowsingContext->GetCurrentWindowGlobal() == this;
|
|
}
|
|
|
|
namespace {
|
|
|
|
class ShareHandler final : public PromiseNativeHandler {
|
|
public:
|
|
explicit ShareHandler(
|
|
mozilla::dom::WindowGlobalParent::ShareResolver&& aResolver)
|
|
: mResolver(std::move(aResolver)) {}
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
public:
|
|
virtual void ResolvedCallback(JSContext* aCx,
|
|
JS::Handle<JS::Value> aValue) override {
|
|
mResolver(NS_OK);
|
|
}
|
|
|
|
virtual void RejectedCallback(JSContext* aCx,
|
|
JS::Handle<JS::Value> aValue) override {
|
|
if (NS_WARN_IF(!aValue.isObject())) {
|
|
mResolver(NS_ERROR_FAILURE);
|
|
return;
|
|
}
|
|
|
|
// nsresult is stored as Exception internally in Promise
|
|
JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
|
|
RefPtr<DOMException> unwrapped;
|
|
nsresult rv = UNWRAP_OBJECT(DOMException, &obj, unwrapped);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
mResolver(NS_ERROR_FAILURE);
|
|
return;
|
|
}
|
|
|
|
mResolver(unwrapped->GetResult());
|
|
}
|
|
|
|
private:
|
|
~ShareHandler() = default;
|
|
|
|
mozilla::dom::WindowGlobalParent::ShareResolver mResolver;
|
|
};
|
|
|
|
NS_IMPL_ISUPPORTS0(ShareHandler)
|
|
|
|
} // namespace
|
|
|
|
mozilla::ipc::IPCResult WindowGlobalParent::RecvShare(
|
|
IPCWebShareData&& aData, WindowGlobalParent::ShareResolver&& aResolver) {
|
|
// Widget Layer handoff...
|
|
nsCOMPtr<nsISharePicker> sharePicker =
|
|
do_GetService("@mozilla.org/sharepicker;1");
|
|
if (!sharePicker) {
|
|
aResolver(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
|
return IPC_OK();
|
|
}
|
|
|
|
// Initialize the ShareWidget
|
|
RefPtr<BrowserParent> parent = GetBrowserParent();
|
|
if (NS_WARN_IF(!parent)) {
|
|
aResolver(NS_ERROR_FAILURE);
|
|
return IPC_OK();
|
|
}
|
|
nsCOMPtr<mozIDOMWindowProxy> openerWindow = parent->GetParentWindowOuter();
|
|
if (!openerWindow) {
|
|
aResolver(NS_ERROR_FAILURE);
|
|
return IPC_OK();
|
|
}
|
|
sharePicker->Init(openerWindow);
|
|
|
|
// And finally share the data...
|
|
RefPtr<Promise> promise;
|
|
nsresult rv = sharePicker->Share(aData.title(), aData.text(), aData.url(),
|
|
getter_AddRefs(promise));
|
|
if (NS_FAILED(rv)) {
|
|
aResolver(rv);
|
|
return IPC_OK();
|
|
}
|
|
|
|
// Handler finally awaits response...
|
|
RefPtr<ShareHandler> handler = new ShareHandler(std::move(aResolver));
|
|
promise->AppendNativeHandler(handler);
|
|
|
|
return IPC_OK();
|
|
}
|
|
|
|
already_AddRefed<mozilla::dom::Promise> WindowGlobalParent::DrawSnapshot(
|
|
const DOMRect* aRect, double aScale, const nsAString& aBackgroundColor,
|
|
mozilla::ErrorResult& aRv) {
|
|
nsIGlobalObject* global = GetParentObject();
|
|
RefPtr<Promise> promise = Promise::Create(global, aRv);
|
|
if (NS_WARN_IF(aRv.Failed())) {
|
|
return nullptr;
|
|
}
|
|
|
|
nscolor color;
|
|
if (NS_WARN_IF(!ServoCSSParser::ComputeColor(nullptr, NS_RGB(0, 0, 0),
|
|
aBackgroundColor, &color,
|
|
nullptr, nullptr))) {
|
|
aRv = NS_ERROR_FAILURE;
|
|
return nullptr;
|
|
}
|
|
|
|
if (!gfx::CrossProcessPaint::Start(this, aRect, (float)aScale, color,
|
|
gfx::CrossProcessPaintFlags::None,
|
|
promise)) {
|
|
aRv = NS_ERROR_FAILURE;
|
|
return nullptr;
|
|
}
|
|
return promise.forget();
|
|
}
|
|
|
|
void WindowGlobalParent::DrawSnapshotInternal(gfx::CrossProcessPaint* aPaint,
|
|
const Maybe<IntRect>& aRect,
|
|
float aScale,
|
|
nscolor aBackgroundColor,
|
|
uint32_t aFlags) {
|
|
auto promise = SendDrawSnapshot(aRect, aScale, aBackgroundColor, aFlags);
|
|
|
|
RefPtr<gfx::CrossProcessPaint> paint(aPaint);
|
|
RefPtr<WindowGlobalParent> wgp(this);
|
|
promise->Then(
|
|
GetMainThreadSerialEventTarget(), __func__,
|
|
[paint, wgp](PaintFragment&& aFragment) {
|
|
paint->ReceiveFragment(wgp, std::move(aFragment));
|
|
},
|
|
[paint, wgp](ResponseRejectReason&& aReason) {
|
|
paint->LostFragment(wgp);
|
|
});
|
|
}
|
|
|
|
already_AddRefed<Promise> WindowGlobalParent::GetSecurityInfo(
|
|
ErrorResult& aRv) {
|
|
RefPtr<BrowserParent> browserParent = GetBrowserParent();
|
|
if (NS_WARN_IF(!browserParent)) {
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
return nullptr;
|
|
}
|
|
|
|
nsIGlobalObject* global = GetParentObject();
|
|
RefPtr<Promise> promise = Promise::Create(global, aRv);
|
|
if (aRv.Failed()) {
|
|
return nullptr;
|
|
}
|
|
|
|
SendGetSecurityInfo(
|
|
[promise](Maybe<nsCString>&& aResult) {
|
|
if (aResult) {
|
|
nsCOMPtr<nsISupports> infoObj;
|
|
nsresult rv =
|
|
NS_DeserializeObject(aResult.value(), getter_AddRefs(infoObj));
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
promise->MaybeReject(NS_ERROR_FAILURE);
|
|
}
|
|
nsCOMPtr<nsITransportSecurityInfo> info = do_QueryInterface(infoObj);
|
|
if (!info) {
|
|
promise->MaybeReject(NS_ERROR_FAILURE);
|
|
}
|
|
promise->MaybeResolve(info);
|
|
} else {
|
|
promise->MaybeResolveWithUndefined();
|
|
}
|
|
},
|
|
[promise](ResponseRejectReason&& aReason) {
|
|
promise->MaybeReject(NS_ERROR_FAILURE);
|
|
});
|
|
|
|
return promise.forget();
|
|
}
|
|
|
|
void WindowGlobalParent::ActorDestroy(ActorDestroyReason aWhy) {
|
|
gWindowGlobalParentsById->Remove(mInnerWindowId);
|
|
mBrowsingContext->UnregisterWindowGlobal(this);
|
|
|
|
// Destroy our JSWindowActors, and reject any pending queries.
|
|
nsRefPtrHashtable<nsStringHashKey, JSWindowActorParent> windowActors;
|
|
mWindowActors.SwapElements(windowActors);
|
|
for (auto iter = windowActors.Iter(); !iter.Done(); iter.Next()) {
|
|
iter.Data()->RejectPendingQueries();
|
|
iter.Data()->AfterDestroy();
|
|
}
|
|
windowActors.Clear();
|
|
|
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
if (obs) {
|
|
obs->NotifyObservers(this, "window-global-destroyed", nullptr);
|
|
}
|
|
}
|
|
|
|
WindowGlobalParent::~WindowGlobalParent() {
|
|
MOZ_ASSERT(!gWindowGlobalParentsById ||
|
|
!gWindowGlobalParentsById->Contains(mInnerWindowId));
|
|
MOZ_ASSERT(!mWindowActors.Count());
|
|
}
|
|
|
|
JSObject* WindowGlobalParent::WrapObject(JSContext* aCx,
|
|
JS::Handle<JSObject*> aGivenProto) {
|
|
return WindowGlobalParent_Binding::Wrap(aCx, this, aGivenProto);
|
|
}
|
|
|
|
nsIGlobalObject* WindowGlobalParent::GetParentObject() {
|
|
return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_INHERITED(WindowGlobalParent, WindowGlobalActor,
|
|
mBrowsingContext, mWindowActors)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(WindowGlobalParent,
|
|
WindowGlobalActor)
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WindowGlobalParent)
|
|
NS_INTERFACE_MAP_END_INHERITING(WindowGlobalActor)
|
|
|
|
NS_IMPL_ADDREF_INHERITED(WindowGlobalParent, WindowGlobalActor)
|
|
NS_IMPL_RELEASE_INHERITED(WindowGlobalParent, WindowGlobalActor)
|
|
|
|
} // namespace dom
|
|
} // namespace mozilla
|