diff options
Diffstat (limited to 'dom/broadcastchannel/BroadcastChannelService.cpp')
-rw-r--r-- | dom/broadcastchannel/BroadcastChannelService.cpp | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/dom/broadcastchannel/BroadcastChannelService.cpp b/dom/broadcastchannel/BroadcastChannelService.cpp new file mode 100644 index 000000000..f88108c3a --- /dev/null +++ b/dom/broadcastchannel/BroadcastChannelService.cpp @@ -0,0 +1,132 @@ +/* -*- 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 "BroadcastChannelService.h" +#include "BroadcastChannelParent.h" +#include "mozilla/dom/File.h" +#include "mozilla/dom/ipc/BlobParent.h" +#include "mozilla/ipc/BackgroundParent.h" + +#ifdef XP_WIN +#undef PostMessage +#endif + +namespace mozilla { + +using namespace ipc; + +namespace dom { + +namespace { + +BroadcastChannelService* sInstance = nullptr; + +} // namespace + +BroadcastChannelService::BroadcastChannelService() +{ + AssertIsOnBackgroundThread(); + + // sInstance is a raw BroadcastChannelService*. + MOZ_ASSERT(!sInstance); + sInstance = this; +} + +BroadcastChannelService::~BroadcastChannelService() +{ + AssertIsOnBackgroundThread(); + MOZ_ASSERT(sInstance == this); + MOZ_ASSERT(mAgents.Count() == 0); + + sInstance = nullptr; +} + +// static +already_AddRefed<BroadcastChannelService> +BroadcastChannelService::GetOrCreate() +{ + AssertIsOnBackgroundThread(); + + RefPtr<BroadcastChannelService> instance = sInstance; + if (!instance) { + instance = new BroadcastChannelService(); + } + return instance.forget(); +} + +void +BroadcastChannelService::RegisterActor(BroadcastChannelParent* aParent, + const nsAString& aOriginChannelKey) +{ + AssertIsOnBackgroundThread(); + MOZ_ASSERT(aParent); + + nsTArray<BroadcastChannelParent*>* parents; + if (!mAgents.Get(aOriginChannelKey, &parents)) { + parents = new nsTArray<BroadcastChannelParent*>(); + mAgents.Put(aOriginChannelKey, parents); + } + + MOZ_ASSERT(!parents->Contains(aParent)); + parents->AppendElement(aParent); +} + +void +BroadcastChannelService::UnregisterActor(BroadcastChannelParent* aParent, + const nsAString& aOriginChannelKey) +{ + AssertIsOnBackgroundThread(); + MOZ_ASSERT(aParent); + + nsTArray<BroadcastChannelParent*>* parents; + if (!mAgents.Get(aOriginChannelKey, &parents)) { + MOZ_CRASH("Invalid state"); + } + + parents->RemoveElement(aParent); + if (parents->IsEmpty()) { + mAgents.Remove(aOriginChannelKey); + } +} + +void +BroadcastChannelService::PostMessage(BroadcastChannelParent* aParent, + const ClonedMessageData& aData, + const nsAString& aOriginChannelKey) +{ + AssertIsOnBackgroundThread(); + MOZ_ASSERT(aParent); + + nsTArray<BroadcastChannelParent*>* parents; + if (!mAgents.Get(aOriginChannelKey, &parents)) { + MOZ_CRASH("Invalid state"); + } + + // We need to keep the array alive for the life-time of this operation. + nsTArray<RefPtr<BlobImpl>> blobs; + if (!aData.blobsParent().IsEmpty()) { + blobs.SetCapacity(aData.blobsParent().Length()); + + for (uint32_t i = 0, len = aData.blobsParent().Length(); i < len; ++i) { + RefPtr<BlobImpl> impl = + static_cast<BlobParent*>(aData.blobsParent()[i])->GetBlobImpl(); + MOZ_ASSERT(impl); + blobs.AppendElement(impl); + } + } + + for (uint32_t i = 0; i < parents->Length(); ++i) { + BroadcastChannelParent* parent = parents->ElementAt(i); + MOZ_ASSERT(parent); + + if (parent != aParent) { + parent->Deliver(aData); + } + } +} + +} // namespace dom +} // namespace mozilla |