diff options
Diffstat (limited to 'dom/broadcastchannel/BroadcastChannelChild.cpp')
-rw-r--r-- | dom/broadcastchannel/BroadcastChannelChild.cpp | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/dom/broadcastchannel/BroadcastChannelChild.cpp b/dom/broadcastchannel/BroadcastChannelChild.cpp new file mode 100644 index 000000000..98bd21999 --- /dev/null +++ b/dom/broadcastchannel/BroadcastChannelChild.cpp @@ -0,0 +1,135 @@ +/* -*- 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 "BroadcastChannelChild.h" +#include "BroadcastChannel.h" +#include "jsapi.h" +#include "mozilla/dom/ipc/BlobChild.h" +#include "mozilla/dom/File.h" +#include "mozilla/dom/MessageEvent.h" +#include "mozilla/dom/MessageEventBinding.h" +#include "mozilla/dom/WorkerPrivate.h" +#include "mozilla/dom/WorkerScope.h" +#include "mozilla/dom/ScriptSettings.h" +#include "mozilla/ipc/PBackgroundChild.h" +#include "mozilla/dom/ipc/StructuredCloneData.h" +#include "WorkerPrivate.h" + +namespace mozilla { + +using namespace ipc; + +namespace dom { + +using namespace workers; + +BroadcastChannelChild::BroadcastChannelChild(const nsACString& aOrigin) + : mBC(nullptr) + , mActorDestroyed(false) +{ + CopyUTF8toUTF16(aOrigin, mOrigin); +} + +BroadcastChannelChild::~BroadcastChannelChild() +{ + MOZ_ASSERT(!mBC); +} + +bool +BroadcastChannelChild::RecvNotify(const ClonedMessageData& aData) +{ + // Make sure to retrieve all blobs from the message before returning to avoid + // leaking their actors. + nsTArray<RefPtr<BlobImpl>> blobs; + if (!aData.blobsChild().IsEmpty()) { + blobs.SetCapacity(aData.blobsChild().Length()); + + for (uint32_t i = 0, len = aData.blobsChild().Length(); i < len; ++i) { + RefPtr<BlobImpl> impl = + static_cast<BlobChild*>(aData.blobsChild()[i])->GetBlobImpl(); + + blobs.AppendElement(impl); + } + } + + nsCOMPtr<DOMEventTargetHelper> helper = mBC; + nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(helper); + + // The object is going to be deleted soon. No notify is required. + if (!eventTarget) { + return true; + } + + // CheckInnerWindowCorrectness can be used also without a window when + // BroadcastChannel is running in a worker. In this case, it's a NOP. + if (NS_FAILED(mBC->CheckInnerWindowCorrectness())) { + return true; + } + + mBC->RemoveDocFromBFCache(); + + AutoJSAPI jsapi; + nsCOMPtr<nsIGlobalObject> globalObject; + + if (NS_IsMainThread()) { + globalObject = do_QueryInterface(mBC->GetParentObject()); + } else { + WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); + MOZ_ASSERT(workerPrivate); + globalObject = workerPrivate->GlobalScope(); + } + + if (!globalObject || !jsapi.Init(globalObject)) { + NS_WARNING("Failed to initialize AutoJSAPI object."); + return true; + } + + ipc::StructuredCloneData cloneData; + cloneData.BlobImpls().AppendElements(blobs); + + const SerializedStructuredCloneBuffer& buffer = aData.data(); + JSContext* cx = jsapi.cx(); + JS::Rooted<JS::Value> value(cx, JS::NullValue()); + if (buffer.data.Size()) { + ErrorResult rv; + cloneData.UseExternalData(buffer.data); + cloneData.Read(cx, &value, rv); + if (NS_WARN_IF(rv.Failed())) { + rv.SuppressException(); + return true; + } + } + + RootedDictionary<MessageEventInit> init(cx); + init.mBubbles = false; + init.mCancelable = false; + init.mOrigin = mOrigin; + init.mData = value; + + ErrorResult rv; + RefPtr<MessageEvent> event = + MessageEvent::Constructor(mBC, NS_LITERAL_STRING("message"), init, rv); + if (NS_WARN_IF(rv.Failed())) { + rv.SuppressException(); + return true; + } + + event->SetTrusted(true); + + bool status; + mBC->DispatchEvent(static_cast<Event*>(event.get()), &status); + + return true; +} + +void +BroadcastChannelChild::ActorDestroy(ActorDestroyReason aWhy) +{ + mActorDestroyed = true; +} + +} // namespace dom +} // namespace mozilla |