Skip to content
This repository has been archived by the owner on Aug 4, 2022. It is now read-only.

Commit

Permalink
Bug 966439 - BroadcastChannel API - patch 1 - BroadcastChannel for ma…
Browse files Browse the repository at this point in the history
…in-thread, r=smaug, r=bent
  • Loading branch information
bakulf committed Jan 14, 2015
1 parent d98a4e2 commit d693b1f
Show file tree
Hide file tree
Showing 30 changed files with 1,582 additions and 4 deletions.
516 changes: 516 additions & 0 deletions dom/broadcastchannel/BroadcastChannel.cpp

Large diffs are not rendered by default.

103 changes: 103 additions & 0 deletions dom/broadcastchannel/BroadcastChannel.h
Original file line number Diff line number Diff line change
@@ -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
108 changes: 108 additions & 0 deletions dom/broadcastchannel/BroadcastChannelChild.cpp
Original file line number Diff line number Diff line change
@@ -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
63 changes: 63 additions & 0 deletions dom/broadcastchannel/BroadcastChannelChild.h
Original file line number Diff line number Diff line change
@@ -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
88 changes: 88 additions & 0 deletions dom/broadcastchannel/BroadcastChannelParent.cpp
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit d693b1f

Please sign in to comment.