Bug 966439 - BroadcastChannel API - patch 1 - BroadcastChannel for main-thread, r=smaug, r=bent

This commit is contained in:
Andrea Marchesini 2015-01-14 11:50:31 +00:00
Родитель e9973161c9
Коммит 65afdf13d8
30 изменённых файлов: 1582 добавлений и 4 удалений

Просмотреть файл

@ -0,0 +1,516 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "BroadcastChannel.h"
#include "BroadcastChannelChild.h"
#include "mozilla/dom/BroadcastChannelBinding.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "WorkerPrivate.h"
#include "WorkerRunnable.h"
#include "nsIAppsService.h"
#include "nsIDocument.h"
#include "nsIScriptSecurityManager.h"
#include "nsServiceManagerUtils.h"
#include "nsISupportsPrimitives.h"
namespace mozilla {
using namespace ipc;
namespace dom {
using namespace workers;
namespace {
void
GetOrigin(nsIPrincipal* aPrincipal, nsAString& aOrigin, ErrorResult& aRv)
{
MOZ_ASSERT(aPrincipal);
uint16_t appStatus = aPrincipal->GetAppStatus();
if (appStatus == nsIPrincipal::APP_STATUS_NOT_INSTALLED) {
nsAutoString tmp;
aRv = nsContentUtils::GetUTFOrigin(aPrincipal, tmp);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
aOrigin = tmp;
return;
}
uint32_t appId = aPrincipal->GetAppId();
// If we are in "app code", use manifest URL as unique origin since
// multiple apps can share the same origin but not same broadcast messages.
nsresult rv;
nsCOMPtr<nsIAppsService> appsService =
do_GetService("@mozilla.org/AppsService;1", &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.Throw(rv);
return;
}
appsService->GetManifestURLByLocalId(appId, aOrigin);
}
class InitializeRunnable MOZ_FINAL : public WorkerMainThreadRunnable
{
public:
InitializeRunnable(WorkerPrivate* aWorkerPrivate, nsAString& aOrigin,
PrincipalInfo& aPrincipalInfo, ErrorResult& aRv)
: WorkerMainThreadRunnable(aWorkerPrivate)
, mWorkerPrivate(GetCurrentThreadWorkerPrivate())
, mOrigin(aOrigin)
, mPrincipalInfo(aPrincipalInfo)
, mRv(aRv)
{
MOZ_ASSERT(mWorkerPrivate);
}
bool MainThreadRun() MOZ_OVERRIDE
{
MOZ_ASSERT(NS_IsMainThread());
nsIPrincipal* principal = mWorkerPrivate->GetPrincipal();
bool isNullPrincipal;
mRv = principal->GetIsNullPrincipal(&isNullPrincipal);
if (NS_WARN_IF(mRv.Failed())) {
return true;
}
if (NS_WARN_IF(isNullPrincipal)) {
mRv.Throw(NS_ERROR_FAILURE);
return true;
}
mRv = PrincipalToPrincipalInfo(principal, &mPrincipalInfo);
if (NS_WARN_IF(mRv.Failed())) {
return true;
}
GetOrigin(principal, mOrigin, mRv);
if (NS_WARN_IF(mRv.Failed())) {
return true;
}
return true;
}
private:
WorkerPrivate* mWorkerPrivate;
nsAString& mOrigin;
PrincipalInfo& mPrincipalInfo;
ErrorResult& mRv;
};
class PostMessageRunnable MOZ_FINAL : public nsICancelableRunnable
{
public:
NS_DECL_ISUPPORTS
PostMessageRunnable(BroadcastChannelChild* aActor,
const nsAString& aMessage)
: mActor(aActor)
, mMessage(aMessage)
{
MOZ_ASSERT(mActor);
}
NS_IMETHODIMP Run()
{
MOZ_ASSERT(mActor);
if (!mActor->IsActorDestroyed()) {
mActor->SendPostMessage(mMessage);
}
return NS_OK;
}
NS_IMETHODIMP Cancel()
{
mActor = nullptr;
return NS_OK;
}
private:
~PostMessageRunnable() {}
nsRefPtr<BroadcastChannelChild> mActor;
nsString mMessage;
};
NS_IMPL_ISUPPORTS(PostMessageRunnable, nsICancelableRunnable, nsIRunnable)
class TeardownRunnable MOZ_FINAL : public nsICancelableRunnable
{
public:
NS_DECL_ISUPPORTS
TeardownRunnable(BroadcastChannelChild* aActor)
: mActor(aActor)
{
MOZ_ASSERT(mActor);
}
NS_IMETHODIMP Run()
{
MOZ_ASSERT(mActor);
if (!mActor->IsActorDestroyed()) {
mActor->SendClose();
}
return NS_OK;
}
NS_IMETHODIMP Cancel()
{
mActor = nullptr;
return NS_OK;
}
private:
~TeardownRunnable() {}
nsRefPtr<BroadcastChannelChild> mActor;
};
NS_IMPL_ISUPPORTS(TeardownRunnable, nsICancelableRunnable, nsIRunnable)
class BroadcastChannelFeature : public workers::WorkerFeature
{
BroadcastChannel* mChannel;
public:
BroadcastChannelFeature(BroadcastChannel* aChannel)
: mChannel(aChannel)
{
MOZ_ASSERT(aChannel);
}
virtual bool Notify(JSContext* aCx, workers::Status aStatus) MOZ_OVERRIDE
{
if (aStatus >= Canceling) {
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
MOZ_ASSERT(workerPrivate);
mChannel->Shutdown();
}
return true;
}
};
} // anonymous namespace
BroadcastChannel::BroadcastChannel(nsPIDOMWindow* aWindow,
const PrincipalInfo& aPrincipalInfo,
const nsAString& aOrigin,
const nsAString& aChannel)
: DOMEventTargetHelper(aWindow)
, mWorkerFeature(nullptr)
, mPrincipalInfo(aPrincipalInfo)
, mOrigin(aOrigin)
, mChannel(aChannel)
, mIsKeptAlive(false)
, mInnerID(0)
{
// Window can be null in workers
}
BroadcastChannel::~BroadcastChannel()
{
Shutdown();
MOZ_ASSERT(!mWorkerFeature);
}
JSObject*
BroadcastChannel::WrapObject(JSContext* aCx)
{
return BroadcastChannelBinding::Wrap(aCx, this);
}
/* static */ already_AddRefed<BroadcastChannel>
BroadcastChannel::Constructor(const GlobalObject& aGlobal,
const nsAString& aChannel,
ErrorResult& aRv)
{
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
// Window is null in workers.
nsAutoString origin;
PrincipalInfo principalInfo;
WorkerPrivate* workerPrivate = nullptr;
if (NS_IsMainThread()) {
nsCOMPtr<nsIGlobalObject> incumbent = mozilla::dom::GetIncumbentGlobal();
if (!incumbent) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsIPrincipal* principal = incumbent->PrincipalOrNull();
if (!principal) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
bool isNullPrincipal;
aRv = principal->GetIsNullPrincipal(&isNullPrincipal);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
if (NS_WARN_IF(isNullPrincipal)) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
GetOrigin(principal, origin, aRv);
aRv = PrincipalToPrincipalInfo(principal, &principalInfo);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
} else {
JSContext* cx = aGlobal.Context();
workerPrivate = GetWorkerPrivateFromContext(cx);
MOZ_ASSERT(workerPrivate);
nsRefPtr<InitializeRunnable> runnable =
new InitializeRunnable(workerPrivate, origin, principalInfo, aRv);
runnable->Dispatch(cx);
}
if (aRv.Failed()) {
return nullptr;
}
nsRefPtr<BroadcastChannel> bc =
new BroadcastChannel(window, principalInfo, origin, aChannel);
// Register this component to PBackground.
ipc::BackgroundChild::GetOrCreateForCurrentThread(bc);
if (!workerPrivate) {
MOZ_ASSERT(window);
MOZ_ASSERT(window->IsInnerWindow());
bc->mInnerID = window->WindowID();
// Register as observer for inner-window-destroyed.
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->AddObserver(bc, "inner-window-destroyed", false);
}
} else {
bc->mWorkerFeature = new BroadcastChannelFeature(bc);
JSContext* cx = workerPrivate->GetJSContext();
if (NS_WARN_IF(!workerPrivate->AddFeature(cx, bc->mWorkerFeature))) {
NS_WARNING("Failed to register the BroadcastChannel worker feature.");
return nullptr;
}
}
return bc.forget();
}
void
BroadcastChannel::PostMessage(const nsAString& aMessage)
{
if (mActor) {
nsRefPtr<PostMessageRunnable> runnable =
new PostMessageRunnable(mActor, aMessage);
if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
NS_WARNING("Failed to dispatch to the current thread!");
}
return;
}
mPendingMessages.AppendElement(aMessage);
}
void
BroadcastChannel::ActorFailed()
{
MOZ_CRASH("Failed to create a PBackgroundChild actor!");
}
void
BroadcastChannel::ActorCreated(ipc::PBackgroundChild* aActor)
{
MOZ_ASSERT(aActor);
PBroadcastChannelChild* actor =
aActor->SendPBroadcastChannelConstructor(mPrincipalInfo, mOrigin, mChannel);
mActor = static_cast<BroadcastChannelChild*>(actor);
MOZ_ASSERT(mActor);
mActor->SetEventTarget(this);
// Flush pending messages.
for (uint32_t i = 0; i < mPendingMessages.Length(); ++i) {
PostMessage(mPendingMessages[i]);
}
mPendingMessages.Clear();
}
void
BroadcastChannel::Shutdown()
{
// If shutdown() is called we have to release the reference if we still keep
// it.
if (mIsKeptAlive) {
mIsKeptAlive = false;
Release();
}
if (mWorkerFeature) {
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
workerPrivate->RemoveFeature(workerPrivate->GetJSContext(), mWorkerFeature);
mWorkerFeature = nullptr;
}
if (mActor) {
mActor->SetEventTarget(nullptr);
nsRefPtr<TeardownRunnable> runnable = new TeardownRunnable(mActor);
NS_DispatchToCurrentThread(runnable);
mActor = nullptr;
}
}
EventHandlerNonNull*
BroadcastChannel::GetOnmessage()
{
if (NS_IsMainThread()) {
return GetEventHandler(nsGkAtoms::onmessage, EmptyString());
}
return GetEventHandler(nullptr, NS_LITERAL_STRING("message"));
}
void
BroadcastChannel::SetOnmessage(EventHandlerNonNull* aCallback)
{
if (NS_IsMainThread()) {
SetEventHandler(nsGkAtoms::onmessage, EmptyString(), aCallback);
} else {
SetEventHandler(nullptr, NS_LITERAL_STRING("message"), aCallback);
}
UpdateMustKeepAlive();
}
void
BroadcastChannel::AddEventListener(const nsAString& aType,
EventListener* aCallback,
bool aCapture,
const dom::Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv)
{
DOMEventTargetHelper::AddEventListener(aType, aCallback, aCapture,
aWantsUntrusted, aRv);
if (aRv.Failed()) {
return;
}
UpdateMustKeepAlive();
}
void
BroadcastChannel::RemoveEventListener(const nsAString& aType,
EventListener* aCallback,
bool aCapture,
ErrorResult& aRv)
{
DOMEventTargetHelper::RemoveEventListener(aType, aCallback, aCapture, aRv);
if (aRv.Failed()) {
return;
}
UpdateMustKeepAlive();
}
void
BroadcastChannel::UpdateMustKeepAlive()
{
bool toKeepAlive = HasListenersFor(NS_LITERAL_STRING("message"));
if (toKeepAlive == mIsKeptAlive) {
return;
}
mIsKeptAlive = toKeepAlive;
if (toKeepAlive) {
AddRef();
} else {
Release();
}
}
NS_IMETHODIMP
BroadcastChannel::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!strcmp(aTopic, "inner-window-destroyed"));
// If the window is destroyed we have to release the reference that we are
// keeping.
if (!mIsKeptAlive) {
return NS_OK;
}
nsCOMPtr<nsISupportsPRUint64> wrapper = do_QueryInterface(aSubject);
NS_ENSURE_TRUE(wrapper, NS_ERROR_FAILURE);
uint64_t innerID;
nsresult rv = wrapper->GetData(&innerID);
NS_ENSURE_SUCCESS(rv, rv);
if (innerID == mInnerID) {
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->RemoveObserver(this, "inner-window-destroyed");
}
Shutdown();
}
return NS_OK;
}
NS_IMPL_CYCLE_COLLECTION_CLASS(BroadcastChannel)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BroadcastChannel,
DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BroadcastChannel,
DOMEventTargetHelper)
tmp->Shutdown();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BroadcastChannel)
NS_INTERFACE_MAP_ENTRY(nsIIPCBackgroundChildCreateCallback)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(BroadcastChannel, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(BroadcastChannel, DOMEventTargetHelper)
} // dom namespace
} // mozilla namespace

Просмотреть файл

@ -0,0 +1,103 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef mozilla_dom_BroadcastChannel_h
#define mozilla_dom_BroadcastChannel_h
#include "mozilla/Attributes.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "nsIIPCBackgroundChildCreateCallback.h"
#include "nsIObserver.h"
#include "nsTArray.h"
#include "nsRefPtr.h"
class nsPIDOMWindow;
namespace mozilla {
namespace dom {
namespace workers {
class WorkerFeature;
}
class BroadcastChannelChild;
class BroadcastChannel MOZ_FINAL
: public DOMEventTargetHelper
, public nsIIPCBackgroundChildCreateCallback
, public nsIObserver
{
NS_DECL_NSIIPCBACKGROUNDCHILDCREATECALLBACK
NS_DECL_NSIOBSERVER
typedef mozilla::ipc::PrincipalInfo PrincipalInfo;
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BroadcastChannel,
DOMEventTargetHelper)
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
static already_AddRefed<BroadcastChannel>
Constructor(const GlobalObject& aGlobal, const nsAString& aChannel,
ErrorResult& aRv);
void GetName(nsAString& aName) const
{
aName = mChannel;
}
void PostMessage(const nsAString& aMessage);
EventHandlerNonNull* GetOnmessage();
void SetOnmessage(EventHandlerNonNull* aCallback);
using nsIDOMEventTarget::AddEventListener;
using nsIDOMEventTarget::RemoveEventListener;
virtual void AddEventListener(const nsAString& aType,
EventListener* aCallback,
bool aCapture,
const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv) MOZ_OVERRIDE;
virtual void RemoveEventListener(const nsAString& aType,
EventListener* aCallback,
bool aCapture,
ErrorResult& aRv) MOZ_OVERRIDE;
void Shutdown();
private:
BroadcastChannel(nsPIDOMWindow* aWindow,
const PrincipalInfo& aPrincipalInfo,
const nsAString& aOrigin,
const nsAString& aChannel);
~BroadcastChannel();
void UpdateMustKeepAlive();
nsRefPtr<BroadcastChannelChild> mActor;
nsTArray<nsString> mPendingMessages;
workers::WorkerFeature* mWorkerFeature;
PrincipalInfo mPrincipalInfo;
nsString mOrigin;
nsString mChannel;
bool mIsKeptAlive;
uint64_t mInnerID;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_BroadcastChannel_h

Просмотреть файл

@ -0,0 +1,108 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/MessageEvent.h"
#include "mozilla/dom/MessageEventBinding.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "WorkerPrivate.h"
namespace mozilla {
using namespace ipc;
namespace dom {
using namespace workers;
BroadcastChannelChild::BroadcastChannelChild(const nsAString& aOrigin,
const nsAString& aChannel)
: mOrigin(aOrigin)
, mChannel(aChannel)
, mActorDestroyed(false)
{
}
BroadcastChannelChild::~BroadcastChannelChild()
{
MOZ_ASSERT(!mEventTarget);
}
bool
BroadcastChannelChild::RecvNotify(const nsString& aMessage)
{
// This object is going to be deleted soon. No notify is required.
if (!mEventTarget) {
return true;
}
if (NS_IsMainThread()) {
DOMEventTargetHelper* deth =
DOMEventTargetHelper::FromSupports(mEventTarget);
MOZ_ASSERT(deth);
AutoJSAPI autoJS;
if (!autoJS.Init(deth->GetParentObject())) {
NS_WARNING("Dropping message");
return true;
}
Notify(autoJS.cx(), aMessage);
return true;
}
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
Notify(workerPrivate->GetJSContext(), aMessage);
return true;
}
void
BroadcastChannelChild::Notify(JSContext* aCx, const nsString& aMessage)
{
JS::Rooted<JSString*> str(aCx,
JS_NewUCStringCopyN(aCx, aMessage.get(),
aMessage.Length()));
if (!str) {
// OOM, no exception needed.
NS_WARNING("Failed allocating a JS string. Probably OOM.");
return;
}
JS::Rooted<JS::Value> value(aCx, JS::StringValue(str));
RootedDictionary<MessageEventInit> init(aCx);
init.mBubbles = false;
init.mCancelable = false;
init.mOrigin.Construct(mOrigin);
init.mData = value;
ErrorResult rv;
nsRefPtr<MessageEvent> event =
MessageEvent::Constructor(mEventTarget, NS_LITERAL_STRING("message"),
init, rv);
if (rv.Failed()) {
NS_WARNING("Failed to create a MessageEvent object.");
return;
}
event->SetTrusted(true);
bool status;
mEventTarget->DispatchEvent(static_cast<Event*>(event.get()), &status);
}
void
BroadcastChannelChild::ActorDestroy(ActorDestroyReason aWhy)
{
mActorDestroyed = true;
}
} // dom namespace
} // mozilla namespace

Просмотреть файл

@ -0,0 +1,63 @@
/* 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/. */
#ifndef mozilla_dom_BroadcastChannelChild_h
#define mozilla_dom_BroadcastChannelChild_h
#include "mozilla/dom/EventTarget.h"
#include "mozilla/dom/PBroadcastChannelChild.h"
namespace mozilla {
namespace ipc {
class BackgroundChildImpl;
}
namespace dom {
class EventTarget;
class BroadcastChannelChild MOZ_FINAL : public PBroadcastChannelChild
{
friend class mozilla::ipc::BackgroundChildImpl;
public:
NS_INLINE_DECL_REFCOUNTING(BroadcastChannelChild)
void SetEventTarget(EventTarget* aEventTarget)
{
mEventTarget = aEventTarget;
}
virtual bool RecvNotify(const nsString& aMessage) MOZ_OVERRIDE;
bool IsActorDestroyed() const
{
return mActorDestroyed;
}
private:
BroadcastChannelChild(const nsAString& aOrigin,
const nsAString& aChannel);
~BroadcastChannelChild();
void Notify(JSContext* aCx, const nsString& aMessage);
void ActorDestroy(ActorDestroyReason aWhy);
// This raw pointer is actually the parent object.
// It's set to null when the parent object is deleted.
EventTarget* mEventTarget;
nsString mOrigin;
nsString mChannel;
bool mActorDestroyed;
};
} // dom namespace
} // mozilla namespace
#endif // mozilla_dom_BroadcastChannelChild_h

Просмотреть файл

@ -0,0 +1,88 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "BroadcastChannelParent.h"
#include "BroadcastChannelService.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/unused.h"
namespace mozilla {
using namespace ipc;
namespace dom {
BroadcastChannelParent::BroadcastChannelParent(
const nsAString& aOrigin,
const nsAString& aChannel)
: mService(BroadcastChannelService::GetOrCreate())
, mOrigin(aOrigin)
, mChannel(aChannel)
{
AssertIsOnBackgroundThread();
mService->RegisterActor(this);
}
BroadcastChannelParent::~BroadcastChannelParent()
{
AssertIsOnBackgroundThread();
}
bool
BroadcastChannelParent::RecvPostMessage(const nsString& aMessage)
{
AssertIsOnBackgroundThread();
if (NS_WARN_IF(!mService)) {
return false;
}
mService->PostMessage(this, aMessage, mOrigin, mChannel);
return true;
}
bool
BroadcastChannelParent::RecvClose()
{
AssertIsOnBackgroundThread();
if (NS_WARN_IF(!mService)) {
return false;
}
mService->UnregisterActor(this);
mService = nullptr;
unused << Send__delete__(this);
return true;
}
void
BroadcastChannelParent::ActorDestroy(ActorDestroyReason aWhy)
{
AssertIsOnBackgroundThread();
if (mService) {
// This object is about to be released and with it, also mService will be
// released too.
mService->UnregisterActor(this);
}
}
void
BroadcastChannelParent::CheckAndDeliver(const nsString& aMessage,
const nsString& aOrigin,
const nsString& aChannel)
{
AssertIsOnBackgroundThread();
if (aOrigin == mOrigin && aChannel == mChannel) {
unused << SendNotify(aMessage);
}
}
} // dom namespace
} // mozilla namespace

Просмотреть файл

@ -0,0 +1,48 @@
/* 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/. */
#ifndef mozilla_dom_BroadcastChannelParent_h
#define mozilla_dom_BroadcastChannelParent_h
#include "mozilla/dom/PBroadcastChannelParent.h"
namespace mozilla {
namespace ipc {
class BackgroundParentImpl;
}
namespace dom {
class BroadcastChannelService;
class BroadcastChannelParent MOZ_FINAL : public PBroadcastChannelParent
{
friend class mozilla::ipc::BackgroundParentImpl;
public:
void CheckAndDeliver(const nsString& aMessage,
const nsString& aOrigin,
const nsString& aChannel);
private:
BroadcastChannelParent(const nsAString& aOrigin,
const nsAString& aChannel);
~BroadcastChannelParent();
virtual bool RecvPostMessage(const nsString& aMessage) MOZ_OVERRIDE;
virtual bool RecvClose() MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
nsRefPtr<BroadcastChannelService> mService;
nsString mOrigin;
nsString mChannel;
};
} // dom namespace
} // mozilla namespace
#endif // mozilla_dom_BroadcastChannelParent_h

Просмотреть файл

@ -0,0 +1,134 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/ipc/BackgroundParent.h"
namespace mozilla {
using namespace ipc;
namespace dom {
namespace {
BroadcastChannelService* sInstance = nullptr;
} // anonymous 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();
nsRefPtr<BroadcastChannelService> instance = sInstance;
if (!instance) {
instance = new BroadcastChannelService();
}
return instance.forget();
}
void
BroadcastChannelService::RegisterActor(BroadcastChannelParent* aParent)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(aParent);
MOZ_ASSERT(!mAgents.Contains(aParent));
mAgents.PutEntry(aParent);
}
void
BroadcastChannelService::UnregisterActor(BroadcastChannelParent* aParent)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(aParent);
MOZ_ASSERT(mAgents.Contains(aParent));
mAgents.RemoveEntry(aParent);
}
namespace {
struct MOZ_STACK_CLASS PostMessageData MOZ_FINAL
{
PostMessageData(BroadcastChannelParent* aParent,
const nsAString& aMessage,
const nsAString& aOrigin,
const nsAString& aChannel)
: mParent(aParent)
, mMessage(aMessage)
, mOrigin(aOrigin)
, mChannel(aChannel)
{
MOZ_ASSERT(aParent);
MOZ_COUNT_CTOR(PostMessageData);
}
~PostMessageData()
{
MOZ_COUNT_DTOR(PostMessageData);
}
BroadcastChannelParent* mParent;
const nsString mMessage;
const nsString mOrigin;
const nsString mChannel;
};
PLDHashOperator
PostMessageEnumerator(nsPtrHashKey<BroadcastChannelParent>* aKey, void* aPtr)
{
AssertIsOnBackgroundThread();
auto* data = static_cast<PostMessageData*>(aPtr);
BroadcastChannelParent* parent = aKey->GetKey();
MOZ_ASSERT(parent);
if (parent != data->mParent) {
parent->CheckAndDeliver(data->mMessage, data->mOrigin, data->mChannel);
}
return PL_DHASH_NEXT;
}
} // anonymous namespace
void
BroadcastChannelService::PostMessage(BroadcastChannelParent* aParent,
const nsAString& aMessage,
const nsAString& aOrigin,
const nsAString& aChannel)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(aParent);
MOZ_ASSERT(mAgents.Contains(aParent));
PostMessageData data(aParent, aMessage, aOrigin, aChannel);
mAgents.EnumerateEntries(PostMessageEnumerator, &data);
}
} // dom namespace
} // mozilla namespace

Просмотреть файл

@ -0,0 +1,42 @@
/* 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/. */
#ifndef mozilla_dom_BroadcastChannelService_h
#define mozilla_dom_BroadcastChannelService_h
#include "nsISupportsImpl.h"
#include "nsHashKeys.h"
#include "nsTHashtable.h"
namespace mozilla {
namespace dom {
class BroadcastChannelParent;
class BroadcastChannelService MOZ_FINAL
{
public:
NS_INLINE_DECL_REFCOUNTING(BroadcastChannelService)
static already_AddRefed<BroadcastChannelService> GetOrCreate();
void RegisterActor(BroadcastChannelParent* aParent);
void UnregisterActor(BroadcastChannelParent* aParent);
void PostMessage(BroadcastChannelParent* aParent,
const nsAString& aMessage,
const nsAString& aOrigin,
const nsAString& aChannel);
private:
BroadcastChannelService();
~BroadcastChannelService();
nsTHashtable<nsPtrHashKey<BroadcastChannelParent>> mAgents;
};
} // dom namespace
} // mozilla namespace
#endif // mozilla_dom_BroadcastChannelService_h

Просмотреть файл

@ -0,0 +1,25 @@
/* 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 protocol PBackground;
namespace mozilla {
namespace dom {
// This protocol is used for the BroadcastChannel API
protocol PBroadcastChannel
{
manager PBackground;
parent:
PostMessage(nsString message);
Close();
child:
Notify(nsString message);
__delete__();
};
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,31 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
EXPORTS.mozilla.dom += [
'BroadcastChannel.h',
]
SOURCES += [
'BroadcastChannel.cpp',
'BroadcastChannelChild.cpp',
'BroadcastChannelParent.cpp',
'BroadcastChannelService.cpp',
]
IPDL_SOURCES += [
'PBroadcastChannel.ipdl',
]
LOCAL_INCLUDES += [
'../workers',
]
MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True

Просмотреть файл

@ -0,0 +1,9 @@
onmessage = function(evt) {
var bc = new BroadcastChannel('foobar');
bc.addEventListener('message', function(event) {
postMessage(event.data == "hello world from the window" ? "OK" : "KO");
bc.postMessage("hello world from the worker");
}, false);
postMessage("READY");
}

Просмотреть файл

@ -0,0 +1,35 @@
<!DOCTYPE HTML>
<html>
<body>
<script type="application/javascript">
function is(a, b, msg) {
ok(a == b, msg);
}
function ok(a, msg) {
window.parent.postMessage({ status: a ? "OK" : "KO", message: msg }, "*");
}
ok("BroadcastChannel" in window, "BroadcastChannel exists");
var bc = new BroadcastChannel("foobar");
ok(bc, "BroadcastChannel can be created");
is(bc.name, 'foobar', "BroadcastChannel.name is foobar");
ok("postMessage" in bc, "BroadcastChannel has postMessage() method");
bc.onmessage = function(evt) {
ok(evt instanceof MessageEvent, 'evt is a MessageEvent');
is(evt.target, bc, 'MessageEvent.target is bc');
is(evt.target.name, 'foobar', 'MessageEvent.target.name is foobar');
is(evt.target.name, bc.name, 'MessageEvent.target.name is bc.name');
is(evt.data, "Hello world from the window!", "Message received from the window");
bc.postMessage("Hello world from the iframe!");
}
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,8 @@
[DEFAULT]
support-files =
iframe_broadcastchannel.html
broadcastchannel_worker.js
[test_broadcastchannel_basic.html]
[test_broadcastchannel_self.html]
[test_broadcastchannel_worker.html]

Просмотреть файл

@ -0,0 +1,60 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for BroadcastChannel</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<div id="content"></div>
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
addEventListener('message', receiveMessage, false);
function receiveMessage(evt) {
if (evt.data.status == 'OK') {
ok(true, evt.data.message);
} else if (evt.data.status == 'KO') {
ok(false, evt.data.message);
} else {
ok(false, "Unknown message");
}
}
ok("BroadcastChannel" in window, "BroadcastChannel exists");
var bc = new BroadcastChannel("foobar");
ok(bc, "BroadcastChannel can be created");
is(bc.name, 'foobar', "BroadcastChannel.name is foobar");
ok("postMessage" in bc, "BroadcastChannel has postMessage() method");
bc.onmessage = function(evt) {
ok(evt instanceof MessageEvent, "This is a MessageEvent");
is(evt.target, bc, "MessageEvent.target is bc");
is(evt.target.name, 'foobar', "MessageEvent.target.name is foobar");
is(evt.target.name, bc.name, "MessageEvent.target.name == bc.name");
is(evt.origin, 'http://mochi.test:8888', "MessageEvent.origin is correct");
is(evt.data, "Hello world from the iframe!", "The message from the iframe has been received!");
SimpleTest.finish();
}
var div = document.getElementById("content");
ok(div, "Parent exists");
var ifr = document.createElement("iframe");
ifr.addEventListener("load", iframeLoaded, false);
ifr.setAttribute('src', "iframe_broadcastchannel.html");
div.appendChild(ifr);
function iframeLoaded() {
bc.postMessage("Hello world from the window!");
}
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,35 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for BroadcastChannel</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<div id="content"></div>
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
x = new BroadcastChannel('foo');
y = new BroadcastChannel('foo');
function func(e) {
is(e.target, y, "The target is !x");
SimpleTest.executeSoon(function() {
SimpleTest.finish();
});
}
x.onmessage = func;
y.onmessage = func;
x.postMessage('foo');
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,49 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<!--
Tests of DOM BroadcastChannel in workers
-->
<head>
<title>Test for BroadcastChannel in workers</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" language="javascript">
var worker = new Worker("broadcastchannel_worker.js");
var bc = new BroadcastChannel('foobar');
worker.onmessage = function(event) {
if (event.data == "READY") {
ok(true, "Worker is ready!");
bc.postMessage('hello world from the window');
} else if(event.data == "OK") {
ok(true, "Worker has received the message");
} else {
ok(false, "Something wrong happened");
}
};
bc.onmessage = function(event) {
is("hello world from the worker", event.data, "The message matches!");
SimpleTest.finish();
}
worker.postMessage('go');
SimpleTest.waitForExplicitFinish();
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -101,6 +101,11 @@ public:
return static_cast<DOMEventTargetHelper*>(target);
}
bool HasListenersFor(const nsAString& aType)
{
return mListenerManager && mListenerManager->HasListenersFor(aType);
}
bool HasListenersFor(nsIAtom* aTypeWithOn)
{
return mListenerManager && mListenerManager->HasListenersFor(aTypeWithOn);

Просмотреть файл

@ -1263,8 +1263,19 @@ EventListenerManager::MutationListenerBits()
bool
EventListenerManager::HasListenersFor(const nsAString& aEventName)
{
nsCOMPtr<nsIAtom> atom = do_GetAtom(NS_LITERAL_STRING("on") + aEventName);
return HasListenersFor(atom);
if (mIsMainThreadELM) {
nsCOMPtr<nsIAtom> atom = do_GetAtom(NS_LITERAL_STRING("on") + aEventName);
return HasListenersFor(atom);
}
uint32_t count = mListeners.Length();
for (uint32_t i = 0; i < count; ++i) {
Listener* listener = &mListeners.ElementAt(i);
if (listener->mTypeString == aEventName) {
return true;
}
}
return false;
}
bool

Просмотреть файл

@ -119,14 +119,23 @@ MessageEvent::Constructor(const GlobalObject& aGlobal,
ErrorResult& aRv)
{
nsCOMPtr<EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports());
nsRefPtr<MessageEvent> event = new MessageEvent(t, nullptr, nullptr);
return Constructor(t, aType, aParam, aRv);
}
/* static */ already_AddRefed<MessageEvent>
MessageEvent::Constructor(EventTarget* aEventTarget,
const nsAString& aType,
const MessageEventInit& aParam,
ErrorResult& aRv)
{
nsRefPtr<MessageEvent> event = new MessageEvent(aEventTarget, nullptr, nullptr);
aRv = event->InitEvent(aType, aParam.mBubbles, aParam.mCancelable);
if (aRv.Failed()) {
return nullptr;
}
bool trusted = event->Init(t);
bool trusted = event->Init(aEventTarget);
event->SetTrusted(trusted);
event->mData = aParam.mData;

Просмотреть файл

@ -74,6 +74,12 @@ public:
const MessageEventInit& aEventInit,
ErrorResult& aRv);
static already_AddRefed<MessageEvent>
Constructor(EventTarget* aEventTarget,
const nsAString& aType,
const MessageEventInit& aEventInit,
ErrorResult& aRv);
protected:
~MessageEvent();

Просмотреть файл

@ -93,6 +93,7 @@ DIRS += [
'workers',
'camera',
'audiochannel',
'broadcastchannel',
'promise',
'smil',
'telephony',

Просмотреть файл

@ -199,6 +199,8 @@ var interfaceNamesInGlobalScope =
{name: "BluetoothStatusChangedEvent", b2g: true, permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BoxObject", xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
"BroadcastChannel",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "CallEvent", b2g: true, pref: "dom.telephony.enabled"},
// IMPORTANT: Do not change this list without review from a DOM peer!

Просмотреть файл

@ -0,0 +1,18 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*
* For more information on this interface, please see
* http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.html#broadcasting-to-other-browsing-contexts
*/
[Constructor(DOMString channel),
Exposed=(Window,Worker)]
interface BroadcastChannel : EventTarget {
readonly attribute DOMString name;
void postMessage(DOMString message);
attribute EventHandler onmessage;
};

Просмотреть файл

@ -55,6 +55,7 @@ WEBIDL_FILES = [
'BiquadFilterNode.webidl',
'Blob.webidl',
'BoxObject.webidl',
'BroadcastChannel.webidl',
'BrowserElement.webidl',
'BrowserElementDictionaries.webidl',
'CallsList.webidl',

Просмотреть файл

@ -5,6 +5,7 @@
#include "BackgroundChildImpl.h"
#include "ActorsChild.h" // IndexedDB
#include "BroadcastChannelChild.h"
#include "FileDescriptorSetChild.h"
#include "mozilla/Assertions.h"
#include "mozilla/dom/PBlobChild.h"
@ -185,6 +186,30 @@ BackgroundChildImpl::DeallocPFileDescriptorSetChild(
return true;
}
// -----------------------------------------------------------------------------
// BroadcastChannel API
// -----------------------------------------------------------------------------
dom::PBroadcastChannelChild*
BackgroundChildImpl::AllocPBroadcastChannelChild(const PrincipalInfo& aPrincipalInfo,
const nsString& aOrigin,
const nsString& aChannel)
{
nsRefPtr<dom::BroadcastChannelChild> agent =
new dom::BroadcastChannelChild(aOrigin, aChannel);
return agent.forget().take();
}
bool
BackgroundChildImpl::DeallocPBroadcastChannelChild(
PBroadcastChannelChild* aActor)
{
nsRefPtr<dom::BroadcastChannelChild> child =
dont_AddRef(static_cast<dom::BroadcastChannelChild*>(aActor));
MOZ_ASSERT(child);
return true;
}
} // namespace ipc
} // namespace mozilla

Просмотреть файл

@ -70,6 +70,14 @@ protected:
virtual bool
DeallocPFileDescriptorSetChild(PFileDescriptorSetChild* aActor) MOZ_OVERRIDE;
virtual PBroadcastChannelChild*
AllocPBroadcastChannelChild(const PrincipalInfo& aPrincipalInfo,
const nsString& aOrigin,
const nsString& aChannel) MOZ_OVERRIDE;
virtual bool
DeallocPBroadcastChannelChild(PBroadcastChannelChild* aActor) MOZ_OVERRIDE;
};
class BackgroundChildImpl::ThreadLocal MOZ_FINAL

Просмотреть файл

@ -4,13 +4,18 @@
#include "BackgroundParentImpl.h"
#include "BroadcastChannelParent.h"
#include "FileDescriptorSetParent.h"
#include "mozilla/AppProcessChecker.h"
#include "mozilla/Assertions.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/PBlobParent.h"
#include "mozilla/dom/indexedDB/ActorsParent.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/ipc/PBackgroundTestParent.h"
#include "nsNetUtil.h"
#include "nsThreadUtils.h"
#include "nsTraceRefcnt.h"
#include "nsXULAppAPI.h"
@ -62,6 +67,9 @@ public:
namespace mozilla {
namespace ipc {
using mozilla::dom::ContentParent;
using mozilla::dom::BroadcastChannelParent;
BackgroundParentImpl::BackgroundParentImpl()
{
AssertIsInMainProcess();
@ -207,6 +215,116 @@ BackgroundParentImpl::DeallocPFileDescriptorSetParent(
return true;
}
mozilla::dom::PBroadcastChannelParent*
BackgroundParentImpl::AllocPBroadcastChannelParent(
const PrincipalInfo& aPrincipalInfo,
const nsString& aOrigin,
const nsString& aChannel)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
return new BroadcastChannelParent(aOrigin, aChannel);
}
namespace {
class CheckPrincipalRunnable MOZ_FINAL : public nsRunnable
{
public:
CheckPrincipalRunnable(already_AddRefed<ContentParent> aParent,
const PrincipalInfo& aPrincipalInfo,
const nsString& aOrigin)
: mContentParent(aParent)
, mPrincipalInfo(aPrincipalInfo)
, mOrigin(aOrigin)
, mBackgroundThread(NS_GetCurrentThread())
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
MOZ_ASSERT(mContentParent);
MOZ_ASSERT(mBackgroundThread);
}
NS_IMETHODIMP Run()
{
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIPrincipal> principal = PrincipalInfoToPrincipal(mPrincipalInfo);
AssertAppPrincipal(mContentParent, principal);
bool isNullPrincipal;
nsresult rv = principal->GetIsNullPrincipal(&isNullPrincipal);
if (NS_WARN_IF(NS_FAILED(rv)) || isNullPrincipal) {
mContentParent->KillHard();
return NS_OK;
}
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), mOrigin);
if (NS_FAILED(rv) || !uri) {
mContentParent->KillHard();
return NS_OK;
}
rv = principal->CheckMayLoad(uri, false, false);
if (NS_FAILED(rv)) {
mContentParent->KillHard();
return NS_OK;
}
mContentParent = nullptr;
return NS_OK;
}
private:
nsRefPtr<ContentParent> mContentParent;
PrincipalInfo mPrincipalInfo;
nsString mOrigin;
nsCOMPtr<nsIThread> mBackgroundThread;
};
} // anonymous namespace
bool
BackgroundParentImpl::RecvPBroadcastChannelConstructor(
PBroadcastChannelParent* actor,
const PrincipalInfo& aPrincipalInfo,
const nsString& aOrigin,
const nsString& aChannel)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
nsRefPtr<ContentParent> parent = BackgroundParent::GetContentParent(this);
// If the ContentParent is null we are dealing with a same-process actor.
if (!parent) {
MOZ_ASSERT(aPrincipalInfo.type() != PrincipalInfo::TNullPrincipalInfo);
return true;
}
nsRefPtr<CheckPrincipalRunnable> runnable =
new CheckPrincipalRunnable(parent.forget(), aPrincipalInfo, aOrigin);
nsresult rv = NS_DispatchToMainThread(runnable);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(rv));
return true;
}
bool
BackgroundParentImpl::DeallocPBroadcastChannelParent(
PBroadcastChannelParent* aActor)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
delete static_cast<BroadcastChannelParent*>(aActor);
return true;
}
} // namespace ipc
} // namespace mozilla

Просмотреть файл

@ -58,6 +58,20 @@ protected:
virtual bool
DeallocPFileDescriptorSetParent(PFileDescriptorSetParent* aActor)
MOZ_OVERRIDE;
virtual PBroadcastChannelParent*
AllocPBroadcastChannelParent(const PrincipalInfo& aPrincipalInfo,
const nsString& aOrigin,
const nsString& aChannel) MOZ_OVERRIDE;
virtual bool
RecvPBroadcastChannelConstructor(PBroadcastChannelParent* actor,
const PrincipalInfo& aPrincipalInfo,
const nsString& origin,
const nsString& channel) MOZ_OVERRIDE;
virtual bool
DeallocPBroadcastChannelParent(PBroadcastChannelParent* aActor) MOZ_OVERRIDE;
};
} // namespace ipc

Просмотреть файл

@ -5,9 +5,11 @@
include protocol PBackgroundIDBFactory;
include protocol PBackgroundTest;
include protocol PBlob;
include protocol PBroadcastChannel;
include protocol PFileDescriptorSet;
include DOMTypes;
include PBackgroundSharedTypes;
include PBackgroundIDBSharedTypes;
namespace mozilla {
@ -18,6 +20,7 @@ sync protocol PBackground
manages PBackgroundIDBFactory;
manages PBackgroundTest;
manages PBlob;
manages PBroadcastChannel;
manages PFileDescriptorSet;
parent:
@ -26,6 +29,8 @@ parent:
PBackgroundIDBFactory(LoggingInfo loggingInfo);
PBroadcastChannel(PrincipalInfo pInfo, nsString origin, nsString channel);
both:
PBlob(BlobConstructorParams params);

Просмотреть файл

@ -130,6 +130,7 @@ SOURCES += [
]
LOCAL_INCLUDES += [
'/dom/broadcastchannel',
'/dom/indexedDB',
'/xpcom/build',
]