dom/ipc/JSWindowActorParent.cpp
author John Dai <jdai@mozilla.com>
Fri, 10 May 2019 09:19:30 +0000
changeset 532182 8e065761738c199fc06388dcfc22df7e92827152
parent 532181 9df2b856b6550578f75d862a1fb4579b5665742e
child 532186 012ce6437a4cbb2bdffb1d641dd08f0a4ca66b75
permissions -rw-r--r--
Bug 1538979 - Part 2: Add WillDestroy and DidDestroy lifecycle methods on JSWindowActor; r=nika Differential Revision: https://phabricator.services.mozilla.com/D30196

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/JSWindowActorBinding.h"
#include "mozilla/dom/JSWindowActorParent.h"
#include "mozilla/dom/WindowGlobalParent.h"
#include "mozilla/dom/MessageManagerBinding.h"

namespace mozilla {
namespace dom {

JSWindowActorParent::~JSWindowActorParent() { MOZ_ASSERT(!mManager); }

JSObject* JSWindowActorParent::WrapObject(JSContext* aCx,
                                          JS::Handle<JSObject*> aGivenProto) {
  return JSWindowActorParent_Binding::Wrap(aCx, this, aGivenProto);
}

WindowGlobalParent* JSWindowActorParent::Manager() const { return mManager; }

void JSWindowActorParent::Init(const nsAString& aName,
                               WindowGlobalParent* aManager) {
  MOZ_ASSERT(!mManager, "Cannot Init() a JSWindowActorParent twice!");
  SetName(aName);
  mManager = aManager;
}

namespace {

class AsyncMessageToChild : public Runnable {
 public:
  AsyncMessageToChild(const JSWindowActorMessageMeta& aMetadata,
                      ipc::StructuredCloneData&& aData,
                      WindowGlobalChild* aChild)
      : mozilla::Runnable("WindowGlobalChild::HandleAsyncMessage"),
        mMetadata(aMetadata),
        mData(std::move(aData)),
        mChild(aChild) {}

  NS_IMETHOD Run() override {
    MOZ_ASSERT(NS_IsMainThread(), "Should be called on the main thread.");
    mChild->ReceiveRawMessage(mMetadata, std::move(mData));
    return NS_OK;
  }

 private:
  JSWindowActorMessageMeta mMetadata;
  ipc::StructuredCloneData mData;
  RefPtr<WindowGlobalChild> mChild;
};

}  // anonymous namespace

void JSWindowActorParent::SendRawMessage(const JSWindowActorMessageMeta& aMeta,
                                         ipc::StructuredCloneData&& aData,
                                         ErrorResult& aRv) {
  if (NS_WARN_IF(!mCanSend || !mManager || mManager->IsClosed())) {
    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
    return;
  }

  if (mManager->IsInProcess()) {
    RefPtr<WindowGlobalChild> wgc = mManager->GetChildActor();
    nsCOMPtr<nsIRunnable> runnable =
        new AsyncMessageToChild(aMeta, std::move(aData), wgc);
    NS_DispatchToMainThread(runnable.forget());
    return;
  }

  // Cross-process case - send data over WindowGlobalParent to other side.
  ClonedMessageData msgData;
  RefPtr<BrowserParent> browserParent = mManager->GetRemoteTab();
  ContentParent* cp = browserParent->Manager();
  if (NS_WARN_IF(!aData.BuildClonedMessageDataForParent(cp, msgData))) {
    aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
    return;
  }

  if (NS_WARN_IF(!mManager->SendRawMessage(aMeta, msgData))) {
    aRv.Throw(NS_ERROR_UNEXPECTED);
    return;
  }
}

void JSWindowActorParent::StartDestroy() {
  JSWindowActor::StartDestroy();
  mCanSend = false;
}

void JSWindowActorParent::AfterDestroy() {
  JSWindowActor::AfterDestroy();
  mManager = nullptr;
}

NS_IMPL_CYCLE_COLLECTION_INHERITED(JSWindowActorParent, JSWindowActor, mManager)

NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(JSWindowActorParent,
                                               JSWindowActor)
NS_IMPL_CYCLE_COLLECTION_TRACE_END

NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(JSWindowActorParent)
NS_INTERFACE_MAP_END_INHERITING(JSWindowActor)

NS_IMPL_ADDREF_INHERITED(JSWindowActorParent, JSWindowActor)
NS_IMPL_RELEASE_INHERITED(JSWindowActorParent, JSWindowActor)

}  // namespace dom
}  // namespace mozilla