forked from mirrors/gecko-dev
		
	Differential Revision: https://phabricator.services.mozilla.com/D49215 --HG-- extra : moz-landing-system : lando
		
			
				
	
	
		
			526 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			526 lines
		
	
	
	
		
			17 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();
 | 
						|
}
 | 
						|
 | 
						|
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
 |