зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1204775 - SharedWorker.port should be a 'real' MessagePort, r=khuey
This commit is contained in:
Родитель
995d2fc2f8
Коммит
ff25288854
|
@ -114,8 +114,7 @@ PostMessageEvent::Run()
|
|||
false /*cancelable */, messageData, mCallerOrigin,
|
||||
EmptyString(), mSource);
|
||||
|
||||
nsTArray<nsRefPtr<MessagePortBase>> ports;
|
||||
TakeTransferredPorts(ports);
|
||||
nsTArray<nsRefPtr<MessagePort>> ports = TakeTransferredPorts();
|
||||
|
||||
event->SetPorts(new MessagePortList(static_cast<dom::Event*>(event.get()),
|
||||
ports));
|
||||
|
|
|
@ -20,9 +20,6 @@ class nsPIDOMWindow;
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class MessagePortBase;
|
||||
class MessagePortIdentifier;
|
||||
|
||||
/**
|
||||
* Class used to represent events generated by calls to Window.postMessage,
|
||||
* which asynchronously creates and dispatches events.
|
||||
|
|
|
@ -1072,16 +1072,14 @@ StructuredCloneHelper::WriteTransferCallback(JSContext* aCx,
|
|||
}
|
||||
|
||||
{
|
||||
MessagePortBase* port = nullptr;
|
||||
MessagePort* port = nullptr;
|
||||
nsresult rv = UNWRAP_OBJECT(MessagePort, aObj, port);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// We use aExtraData to store the index of this new port identifier.
|
||||
*aExtraData = mPortIdentifiers.Length();
|
||||
MessagePortIdentifier* identifier = mPortIdentifiers.AppendElement();
|
||||
|
||||
if (!port->CloneAndDisentangle(*identifier)) {
|
||||
return false;
|
||||
}
|
||||
port->CloneAndDisentangle(*identifier);
|
||||
|
||||
*aTag = SCTAG_DOM_MAP_MESSAGEPORT;
|
||||
*aOwnership = JS::SCTAG_TMO_CUSTOM;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define mozilla_dom_StructuredCloneHelper_h
|
||||
|
||||
#include "js/StructuredClone.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsTArray.h"
|
||||
|
@ -111,7 +112,7 @@ protected:
|
|||
};
|
||||
|
||||
class BlobImpl;
|
||||
class MessagePortBase;
|
||||
class MessagePort;
|
||||
class MessagePortIdentifier;
|
||||
|
||||
class StructuredCloneHelper : public StructuredCloneHelperInternal
|
||||
|
@ -191,11 +192,10 @@ public:
|
|||
// This must be called if the transferring has ports generated by Read().
|
||||
// MessagePorts are not thread-safe and they must be retrieved in the thread
|
||||
// where they are created.
|
||||
void TakeTransferredPorts(nsTArray<nsRefPtr<MessagePortBase>>& aPorts)
|
||||
nsTArray<nsRefPtr<MessagePort>>&& TakeTransferredPorts()
|
||||
{
|
||||
MOZ_ASSERT(mSupportsTransferring);
|
||||
MOZ_ASSERT(aPorts.IsEmpty());
|
||||
aPorts.SwapElements(mTransferredPorts);
|
||||
return Move(mTransferredPorts);
|
||||
}
|
||||
|
||||
nsTArray<MessagePortIdentifier>& PortIdentifiers()
|
||||
|
@ -291,7 +291,7 @@ protected:
|
|||
|
||||
// This array contains the ports once we've finished the reading. It's
|
||||
// generated from the mPortIdentifiers array.
|
||||
nsTArray<nsRefPtr<MessagePortBase>> mTransferredPorts;
|
||||
nsTArray<nsRefPtr<MessagePort>> mTransferredPorts;
|
||||
|
||||
// This array contains the identifiers of the MessagePorts. Based on these we
|
||||
// are able to reconnect the new transferred ports with the other
|
||||
|
|
|
@ -739,11 +739,6 @@ DOMInterfaces = {
|
|||
'headerFile': 'MediaRecorder.h',
|
||||
},
|
||||
|
||||
'MessagePort': {
|
||||
'nativeType': 'mozilla::dom::MessagePortBase',
|
||||
'headerFile': 'mozilla/dom/MessagePort.h',
|
||||
},
|
||||
|
||||
'MimeType': {
|
||||
'headerFile' : 'nsMimeTypeArray.h',
|
||||
'nativeType': 'nsMimeType',
|
||||
|
|
|
@ -167,7 +167,7 @@ MessageEvent::Constructor(EventTarget* aEventTarget,
|
|||
}
|
||||
|
||||
if (aParam.mPorts.WasPassed() && !aParam.mPorts.Value().IsNull()) {
|
||||
nsTArray<nsRefPtr<MessagePortBase>> ports;
|
||||
nsTArray<nsRefPtr<MessagePort>> ports;
|
||||
for (uint32_t i = 0, len = aParam.mPorts.Value().Value().Length(); i < len; ++i) {
|
||||
ports.AppendElement(aParam.mPorts.Value().Value()[i].get());
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ namespace dom {
|
|||
|
||||
struct MessageEventInit;
|
||||
class MessagePort;
|
||||
class MessagePortBase;
|
||||
class MessagePortList;
|
||||
class OwningWindowProxyOrMessagePortOrClient;
|
||||
|
||||
|
@ -94,7 +93,7 @@ private:
|
|||
nsString mOrigin;
|
||||
nsString mLastEventId;
|
||||
nsCOMPtr<nsIDOMWindow> mWindowSource;
|
||||
nsRefPtr<MessagePortBase> mPortSource;
|
||||
nsRefPtr<MessagePort> mPortSource;
|
||||
nsRefPtr<workers::ServiceWorkerClient> mClientSource;
|
||||
nsRefPtr<MessagePortList> mPorts;
|
||||
};
|
||||
|
|
|
@ -49,7 +49,12 @@ MessageChannel::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
|
|||
{
|
||||
// window can be null in workers.
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
return Constructor(window, aRv);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<MessageChannel>
|
||||
MessageChannel::Constructor(nsPIDOMWindow* aWindow, ErrorResult& aRv)
|
||||
{
|
||||
nsID portUUID1;
|
||||
aRv = nsContentUtils::GenerateUUIDInPlace(portUUID1);
|
||||
if (aRv.Failed()) {
|
||||
|
@ -62,14 +67,14 @@ MessageChannel::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<MessageChannel> channel = new MessageChannel(window);
|
||||
nsRefPtr<MessageChannel> channel = new MessageChannel(aWindow);
|
||||
|
||||
channel->mPort1 = MessagePort::Create(window, portUUID1, portUUID2, aRv);
|
||||
channel->mPort1 = MessagePort::Create(aWindow, portUUID1, portUUID2, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
channel->mPort2 = MessagePort::Create(window, portUUID2, portUUID1, aRv);
|
||||
channel->mPort2 = MessagePort::Create(aWindow, portUUID2, portUUID1, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,9 @@ public:
|
|||
static already_AddRefed<MessageChannel>
|
||||
Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<MessageChannel>
|
||||
Constructor(nsPIDOMWindow* aWindow, ErrorResult& aRv);
|
||||
|
||||
MessagePort*
|
||||
Port1() const
|
||||
{
|
||||
|
|
|
@ -140,8 +140,7 @@ public:
|
|||
event->SetTrusted(true);
|
||||
event->SetSource(mPort);
|
||||
|
||||
nsTArray<nsRefPtr<MessagePortBase>> ports;
|
||||
mData->TakeTransferredPorts(ports);
|
||||
nsTArray<nsRefPtr<MessagePort>> ports = mData->TakeTransferredPorts();
|
||||
|
||||
nsRefPtr<MessagePortList> portList =
|
||||
new MessagePortList(static_cast<dom::Event*>(event.get()),
|
||||
|
@ -171,19 +170,10 @@ private:
|
|||
|
||||
NS_IMPL_ISUPPORTS(PostMessageRunnable, nsICancelableRunnable, nsIRunnable)
|
||||
|
||||
MessagePortBase::MessagePortBase(nsPIDOMWindow* aWindow)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
{
|
||||
}
|
||||
|
||||
MessagePortBase::MessagePortBase()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(MessagePort)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MessagePort,
|
||||
MessagePortBase)
|
||||
DOMEventTargetHelper)
|
||||
if (tmp->mDispatchRunnable) {
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDispatchRunnable->mPort);
|
||||
}
|
||||
|
@ -194,7 +184,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MessagePort,
|
|||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MessagePort,
|
||||
MessagePortBase)
|
||||
DOMEventTargetHelper)
|
||||
if (tmp->mDispatchRunnable) {
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDispatchRunnable->mPort);
|
||||
}
|
||||
|
@ -205,10 +195,10 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MessagePort)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIIPCBackgroundChildCreateCallback)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_INTERFACE_MAP_END_INHERITING(MessagePortBase)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(MessagePort, MessagePortBase)
|
||||
NS_IMPL_RELEASE_INHERITED(MessagePort, MessagePortBase)
|
||||
NS_IMPL_ADDREF_INHERITED(MessagePort, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(MessagePort, DOMEventTargetHelper)
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -287,7 +277,7 @@ NS_IMPL_ISUPPORTS(ForceCloseHelper, nsIIPCBackgroundChildCreateCallback)
|
|||
} // namespace
|
||||
|
||||
MessagePort::MessagePort(nsPIDOMWindow* aWindow)
|
||||
: MessagePortBase(aWindow)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
, mInnerID(0)
|
||||
, mMessageQueueEnabled(false)
|
||||
, mIsKeptAlive(false)
|
||||
|
@ -364,16 +354,7 @@ MessagePort::Initialize(const nsID& aUUID,
|
|||
// The port has to keep itself alive until it's entangled.
|
||||
UpdateMustKeepAlive();
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
MOZ_ASSERT(GetOwner());
|
||||
MOZ_ASSERT(GetOwner()->IsInnerWindow());
|
||||
mInnerID = GetOwner()->WindowID();
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->AddObserver(this, "inner-window-destroyed", false);
|
||||
}
|
||||
} else {
|
||||
if (!NS_IsMainThread()) {
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
MOZ_ASSERT(!mWorkerFeature);
|
||||
|
@ -386,6 +367,15 @@ MessagePort::Initialize(const nsID& aUUID,
|
|||
}
|
||||
|
||||
mWorkerFeature = Move(feature);
|
||||
} else if (GetOwner()) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(GetOwner()->IsInnerWindow());
|
||||
mInnerID = GetOwner()->WindowID();
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->AddObserver(this, "inner-window-destroyed", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -414,7 +404,7 @@ MessagePort::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
|||
continue;
|
||||
}
|
||||
|
||||
MessagePortBase* port = nullptr;
|
||||
MessagePort* port = nullptr;
|
||||
nsresult rv = UNWRAP_OBJECT(MessagePort, &value.toObject(), port);
|
||||
if (NS_FAILED(rv)) {
|
||||
continue;
|
||||
|
@ -520,11 +510,6 @@ MessagePort::Dispatch()
|
|||
void
|
||||
MessagePort::Close()
|
||||
{
|
||||
// Not entangled yet, but already closed.
|
||||
if (mNextStep != eNextStepNone) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mState == eStateUnshippedEntangled) {
|
||||
MOZ_ASSERT(mUnshippedEntangledPort);
|
||||
|
||||
|
@ -540,7 +525,7 @@ MessagePort::Close()
|
|||
}
|
||||
|
||||
// Not entangled yet, we have to wait.
|
||||
if (mState < eStateEntangling) {
|
||||
if (mState == eStateEntangling) {
|
||||
mNextStep = eNextStepClose;
|
||||
return;
|
||||
}
|
||||
|
@ -699,7 +684,7 @@ MessagePort::Disentangle()
|
|||
UpdateMustKeepAlive();
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
MessagePort::CloneAndDisentangle(MessagePortIdentifier& aIdentifier)
|
||||
{
|
||||
MOZ_ASSERT(mIdentifier);
|
||||
|
@ -710,13 +695,13 @@ MessagePort::CloneAndDisentangle(MessagePortIdentifier& aIdentifier)
|
|||
aIdentifier.neutered() = true;
|
||||
|
||||
if (mState > eStateEntangled) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
// We already have a 'next step'. We have to consider this port as already
|
||||
// cloned/closed/disentangled.
|
||||
if (mNextStep != eNextStepNone) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
aIdentifier.uuid() = mIdentifier->uuid();
|
||||
|
@ -739,24 +724,23 @@ MessagePort::CloneAndDisentangle(MessagePortIdentifier& aIdentifier)
|
|||
|
||||
mState = eStateDisentangled;
|
||||
UpdateMustKeepAlive();
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Register this component to PBackground.
|
||||
ConnectToPBackground();
|
||||
|
||||
mNextStep = eNextStepDisentangle;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Not entangled yet, we have to wait.
|
||||
if (mState < eStateEntangled) {
|
||||
mNextStep = eNextStepDisentangle;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
StartDisentangling();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -31,41 +31,7 @@ namespace workers {
|
|||
class WorkerFeature;
|
||||
} // namespace workers
|
||||
|
||||
class MessagePortBase : public DOMEventTargetHelper
|
||||
{
|
||||
protected:
|
||||
explicit MessagePortBase(nsPIDOMWindow* aWindow);
|
||||
MessagePortBase();
|
||||
|
||||
public:
|
||||
|
||||
virtual void
|
||||
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
ErrorResult& aRv) = 0;
|
||||
|
||||
virtual void
|
||||
Start() = 0;
|
||||
|
||||
virtual void
|
||||
Close() = 0;
|
||||
|
||||
// The 'message' event handler has to call |Start()| method, so we
|
||||
// cannot use IMPL_EVENT_HANDLER macro here.
|
||||
virtual EventHandlerNonNull*
|
||||
GetOnmessage() = 0;
|
||||
|
||||
virtual void
|
||||
SetOnmessage(EventHandlerNonNull* aCallback) = 0;
|
||||
|
||||
// Duplicate this message port. This method is used by the Structured Clone
|
||||
// Algorithm and populates a MessagePortIdentifier object with the information
|
||||
// useful to create new MessagePort.
|
||||
virtual bool
|
||||
CloneAndDisentangle(MessagePortIdentifier& aIdentifier) = 0;
|
||||
};
|
||||
|
||||
class MessagePort final : public MessagePortBase
|
||||
class MessagePort final : public DOMEventTargetHelper
|
||||
, public nsIIPCBackgroundChildCreateCallback
|
||||
, public nsIObserver
|
||||
{
|
||||
|
@ -76,7 +42,7 @@ public:
|
|||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MessagePort,
|
||||
MessagePortBase)
|
||||
DOMEventTargetHelper)
|
||||
|
||||
static already_AddRefed<MessagePort>
|
||||
Create(nsPIDOMWindow* aWindow, const nsID& aUUID,
|
||||
|
@ -92,24 +58,24 @@ public:
|
|||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
virtual void
|
||||
void
|
||||
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
ErrorResult& aRv) override;
|
||||
ErrorResult& aRv);
|
||||
|
||||
virtual void Start() override;
|
||||
void Start();
|
||||
|
||||
virtual void Close() override;
|
||||
void Close();
|
||||
|
||||
virtual EventHandlerNonNull* GetOnmessage() override;
|
||||
EventHandlerNonNull* GetOnmessage();
|
||||
|
||||
virtual void SetOnmessage(EventHandlerNonNull* aCallback) override;
|
||||
void SetOnmessage(EventHandlerNonNull* aCallback);
|
||||
|
||||
// Non WebIDL methods
|
||||
|
||||
void UnshippedEntangle(MessagePort* aEntangledPort);
|
||||
|
||||
virtual bool CloneAndDisentangle(MessagePortIdentifier& aIdentifier) override;
|
||||
void CloneAndDisentangle(MessagePortIdentifier& aIdentifier);
|
||||
|
||||
// These methods are useful for MessagePortChild
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
|
||||
public:
|
||||
MessagePortList(nsISupports* aOwner,
|
||||
const nsTArray<nsRefPtr<MessagePortBase>>& aPorts)
|
||||
const nsTArray<nsRefPtr<MessagePort>>& aPorts)
|
||||
: mOwner(aOwner)
|
||||
, mPorts(aPorts)
|
||||
{
|
||||
|
@ -50,13 +50,13 @@ public:
|
|||
return mPorts.Length();
|
||||
}
|
||||
|
||||
MessagePortBase*
|
||||
MessagePort*
|
||||
Item(uint32_t aIndex)
|
||||
{
|
||||
return mPorts.SafeElementAt(aIndex);
|
||||
}
|
||||
|
||||
MessagePortBase*
|
||||
MessagePort*
|
||||
IndexedGetter(uint32_t aIndex, bool &aFound)
|
||||
{
|
||||
aFound = aIndex < mPorts.Length();
|
||||
|
@ -68,7 +68,7 @@ public:
|
|||
|
||||
public:
|
||||
nsCOMPtr<nsISupports> mOwner;
|
||||
nsTArray<nsRefPtr<MessagePortBase>> mPorts;
|
||||
nsTArray<nsRefPtr<MessagePort>> mPorts;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -1,318 +0,0 @@
|
|||
/* -*- 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 "MessagePort.h"
|
||||
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/dom/MessagePortBinding.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
|
||||
#include "SharedWorker.h"
|
||||
#include "WorkerPrivate.h"
|
||||
#include "WorkerRunnable.h"
|
||||
|
||||
using mozilla::dom::EventHandlerNonNull;
|
||||
using mozilla::dom::MessagePortBase;
|
||||
using mozilla::dom::MessagePortIdentifier;
|
||||
using mozilla::dom::Optional;
|
||||
using mozilla::dom::Sequence;
|
||||
using mozilla::dom::AutoNoJSAPI;
|
||||
using namespace mozilla;
|
||||
|
||||
USING_WORKERS_NAMESPACE
|
||||
|
||||
namespace {
|
||||
|
||||
class DelayedEventRunnable final : public WorkerRunnable
|
||||
{
|
||||
nsRefPtr<mozilla::dom::workers::MessagePort> mMessagePort;
|
||||
nsTArray<nsCOMPtr<nsIDOMEvent>> mEvents;
|
||||
|
||||
public:
|
||||
DelayedEventRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
TargetAndBusyBehavior aBehavior,
|
||||
mozilla::dom::workers::MessagePort* aMessagePort,
|
||||
nsTArray<nsCOMPtr<nsIDOMEvent>>& aEvents)
|
||||
: WorkerRunnable(aWorkerPrivate, aBehavior), mMessagePort(aMessagePort)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aMessagePort);
|
||||
MOZ_ASSERT(aEvents.Length());
|
||||
|
||||
mEvents.SwapElements(aEvents);
|
||||
}
|
||||
|
||||
bool PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
if (mBehavior == WorkerThreadModifyBusyCount) {
|
||||
return aWorkerPrivate->ModifyBusyCount(aCx, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult)
|
||||
{
|
||||
if (!aDispatchResult) {
|
||||
if (mBehavior == WorkerThreadModifyBusyCount) {
|
||||
aWorkerPrivate->ModifyBusyCount(aCx, false);
|
||||
}
|
||||
if (aCx) {
|
||||
JS_ReportPendingException(aCx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
MessagePort::MessagePort(nsPIDOMWindow* aWindow, SharedWorker* aSharedWorker,
|
||||
uint64_t aSerial)
|
||||
: MessagePortBase(aWindow), mSharedWorker(aSharedWorker),
|
||||
mWorkerPrivate(nullptr), mSerial(aSerial), mStarted(false)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aSharedWorker);
|
||||
}
|
||||
|
||||
MessagePort::MessagePort(WorkerPrivate* aWorkerPrivate, uint64_t aSerial)
|
||||
: mWorkerPrivate(aWorkerPrivate), mSerial(aSerial), mStarted(false)
|
||||
{
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
|
||||
MessagePort::~MessagePort()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void
|
||||
MessagePort::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
AssertCorrectThread();
|
||||
|
||||
if (IsClosed()) {
|
||||
aRv = NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mSharedWorker) {
|
||||
mSharedWorker->PostMessage(aCx, aMessage, aTransferable, aRv);
|
||||
}
|
||||
else {
|
||||
mWorkerPrivate->PostMessageToParentMessagePort(aCx, Serial(), aMessage,
|
||||
aTransferable, aRv);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MessagePort::Start()
|
||||
{
|
||||
AssertCorrectThread();
|
||||
|
||||
if (IsClosed()) {
|
||||
NS_WARNING("Called start() after calling close()!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mStarted) {
|
||||
return;
|
||||
}
|
||||
|
||||
mStarted = true;
|
||||
|
||||
if (!mQueuedEvents.IsEmpty()) {
|
||||
WorkerPrivate* workerPrivate;
|
||||
WorkerRunnable::TargetAndBusyBehavior behavior;
|
||||
|
||||
if (mWorkerPrivate) {
|
||||
workerPrivate = mWorkerPrivate;
|
||||
behavior = WorkerRunnable::WorkerThreadModifyBusyCount;
|
||||
}
|
||||
else {
|
||||
workerPrivate = mSharedWorker->GetWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
|
||||
behavior = WorkerRunnable::ParentThreadUnchangedBusyCount;
|
||||
}
|
||||
|
||||
nsRefPtr<DelayedEventRunnable> runnable =
|
||||
new DelayedEventRunnable(workerPrivate, behavior, this, mQueuedEvents);
|
||||
runnable->Dispatch(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MessagePort::Close()
|
||||
{
|
||||
AssertCorrectThread();
|
||||
|
||||
if (!IsClosed()) {
|
||||
CloseInternal();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MessagePort::QueueEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
AssertCorrectThread();
|
||||
MOZ_ASSERT(aEvent);
|
||||
MOZ_ASSERT(!IsClosed());
|
||||
MOZ_ASSERT(!mStarted);
|
||||
|
||||
mQueuedEvents.AppendElement(aEvent);
|
||||
}
|
||||
|
||||
EventHandlerNonNull*
|
||||
MessagePort::GetOnmessage()
|
||||
{
|
||||
AssertCorrectThread();
|
||||
|
||||
return NS_IsMainThread() ? GetEventHandler(nsGkAtoms::onmessage, EmptyString())
|
||||
: GetEventHandler(nullptr, NS_LITERAL_STRING("message"));
|
||||
}
|
||||
|
||||
void
|
||||
MessagePort::SetOnmessage(EventHandlerNonNull* aCallback)
|
||||
{
|
||||
AssertCorrectThread();
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
SetEventHandler(nsGkAtoms::onmessage, EmptyString(), aCallback);
|
||||
}
|
||||
else {
|
||||
SetEventHandler(nullptr, NS_LITERAL_STRING("message"), aCallback);
|
||||
}
|
||||
|
||||
Start();
|
||||
}
|
||||
|
||||
bool
|
||||
MessagePort::CloneAndDisentangle(MessagePortIdentifier& aIdentifier)
|
||||
{
|
||||
NS_WARNING("Haven't implemented structured clone for these ports yet!");
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
MessagePort::CloseInternal()
|
||||
{
|
||||
AssertCorrectThread();
|
||||
MOZ_ASSERT(!IsClosed());
|
||||
MOZ_ASSERT_IF(mStarted, mQueuedEvents.IsEmpty());
|
||||
|
||||
if (!mStarted) {
|
||||
mQueuedEvents.Clear();
|
||||
}
|
||||
|
||||
mSharedWorker = nullptr;
|
||||
mWorkerPrivate = nullptr;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
MessagePort::AssertCorrectThread() const
|
||||
{
|
||||
if (IsClosed()) {
|
||||
return; // Can't assert anything if we nulled out our pointers.
|
||||
}
|
||||
|
||||
MOZ_ASSERT((mSharedWorker || mWorkerPrivate) &&
|
||||
!(mSharedWorker && mWorkerPrivate));
|
||||
|
||||
if (mSharedWorker) {
|
||||
AssertIsOnMainThread();
|
||||
}
|
||||
else {
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(mozilla::dom::workers::MessagePort, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(mozilla::dom::workers::MessagePort, DOMEventTargetHelper)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MessagePort)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(MessagePort)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MessagePort,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSharedWorker)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mQueuedEvents)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MessagePort,
|
||||
DOMEventTargetHelper)
|
||||
tmp->Close();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
JSObject*
|
||||
MessagePort::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
AssertCorrectThread();
|
||||
|
||||
return MessagePortBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
nsresult
|
||||
MessagePort::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||
{
|
||||
AssertCorrectThread();
|
||||
|
||||
nsIDOMEvent*& event = aVisitor.mDOMEvent;
|
||||
|
||||
if (event) {
|
||||
bool preventDispatch = false;
|
||||
|
||||
if (IsClosed()) {
|
||||
preventDispatch = true;
|
||||
} else if (NS_IsMainThread() && mSharedWorker->IsFrozen()) {
|
||||
mSharedWorker->QueueEvent(event);
|
||||
preventDispatch = true;
|
||||
} else if (!mStarted) {
|
||||
QueueEvent(event);
|
||||
preventDispatch = true;
|
||||
}
|
||||
|
||||
if (preventDispatch) {
|
||||
aVisitor.mCanHandle = false;
|
||||
aVisitor.mParentTarget = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return DOMEventTargetHelper::PreHandleEvent(aVisitor);
|
||||
}
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
||||
bool
|
||||
DelayedEventRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
MOZ_ASSERT(mMessagePort);
|
||||
mMessagePort->AssertCorrectThread();
|
||||
MOZ_ASSERT(mEvents.Length());
|
||||
|
||||
AutoNoJSAPI nojsapi;
|
||||
|
||||
bool ignored;
|
||||
for (uint32_t i = 0; i < mEvents.Length(); i++) {
|
||||
mMessagePort->DispatchEvent(mEvents[i], &ignored);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#ifndef mozilla_dom_workers_messageport_h_
|
||||
#define mozilla_dom_workers_messageport_h_
|
||||
|
||||
#include "mozilla/dom/workers/Workers.h"
|
||||
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/MessagePort.h"
|
||||
|
||||
class nsIDOMEvent;
|
||||
class nsPIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
class EventChainPreVisitor;
|
||||
} // namespace mozilla
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
class SharedWorker;
|
||||
class WorkerPrivate;
|
||||
|
||||
class MessagePort final : public mozilla::dom::MessagePortBase
|
||||
{
|
||||
friend class SharedWorker;
|
||||
friend class WorkerPrivate;
|
||||
|
||||
typedef mozilla::ErrorResult ErrorResult;
|
||||
|
||||
nsRefPtr<SharedWorker> mSharedWorker;
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
nsTArray<nsCOMPtr<nsIDOMEvent>> mQueuedEvents;
|
||||
uint64_t mSerial;
|
||||
bool mStarted;
|
||||
|
||||
public:
|
||||
static bool
|
||||
PrefEnabled();
|
||||
|
||||
virtual void
|
||||
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
ErrorResult& aRv) override;
|
||||
|
||||
virtual void
|
||||
Start() override;
|
||||
|
||||
virtual void
|
||||
Close() override;
|
||||
|
||||
uint64_t
|
||||
Serial() const
|
||||
{
|
||||
return mSerial;
|
||||
}
|
||||
|
||||
void
|
||||
QueueEvent(nsIDOMEvent* aEvent);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MessagePort, DOMEventTargetHelper)
|
||||
|
||||
virtual EventHandlerNonNull*
|
||||
GetOnmessage() override;
|
||||
|
||||
virtual void
|
||||
SetOnmessage(EventHandlerNonNull* aCallback) override;
|
||||
|
||||
virtual bool
|
||||
CloneAndDisentangle(MessagePortIdentifier& aIdentifier) override;
|
||||
|
||||
bool
|
||||
IsClosed() const
|
||||
{
|
||||
return !mSharedWorker && !mWorkerPrivate;
|
||||
}
|
||||
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
virtual nsresult
|
||||
PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
AssertCorrectThread() const;
|
||||
#else
|
||||
void
|
||||
AssertCorrectThread() const { }
|
||||
#endif
|
||||
|
||||
private:
|
||||
// This class can only be created by SharedWorker or WorkerPrivate.
|
||||
MessagePort(nsPIDOMWindow* aWindow, SharedWorker* aSharedWorker,
|
||||
uint64_t aSerial);
|
||||
MessagePort(WorkerPrivate* aWorkerPrivate, uint64_t aSerial);
|
||||
|
||||
// This class is reference-counted and will be destroyed from Release().
|
||||
~MessagePort();
|
||||
|
||||
void
|
||||
CloseInternal();
|
||||
};
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_workers_messageport_h_
|
|
@ -34,6 +34,7 @@
|
|||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/ErrorEventBinding.h"
|
||||
#include "mozilla/dom/EventTargetBinding.h"
|
||||
#include "mozilla/dom/MessageChannel.h"
|
||||
#include "mozilla/dom/MessageEventBinding.h"
|
||||
#include "mozilla/dom/WorkerBinding.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
|
@ -2493,8 +2494,8 @@ RuntimeService::CreateSharedWorkerFromLoadInfo(JSContext* aCx,
|
|||
nsCOMPtr<nsPIDOMWindow> window = aLoadInfo->mWindow;
|
||||
|
||||
bool created = false;
|
||||
ErrorResult rv;
|
||||
if (!workerPrivate) {
|
||||
ErrorResult rv;
|
||||
workerPrivate =
|
||||
WorkerPrivate::Constructor(aCx, aScriptURL, false,
|
||||
aType, aName, aLoadInfo, rv);
|
||||
|
@ -2508,9 +2509,18 @@ RuntimeService::CreateSharedWorkerFromLoadInfo(JSContext* aCx,
|
|||
workerPrivate->UpdateOverridenLoadGroup(aLoadInfo->mLoadGroup);
|
||||
}
|
||||
|
||||
nsRefPtr<SharedWorker> sharedWorker = new SharedWorker(window, workerPrivate);
|
||||
// We don't actually care about this MessageChannel, but we use it to 'steal'
|
||||
// its 2 connected ports.
|
||||
nsRefPtr<MessageChannel> channel = MessageChannel::Constructor(window, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
if (!workerPrivate->RegisterSharedWorker(aCx, sharedWorker)) {
|
||||
nsRefPtr<SharedWorker> sharedWorker = new SharedWorker(window, workerPrivate,
|
||||
channel->Port1());
|
||||
|
||||
if (!workerPrivate->RegisterSharedWorker(aCx, sharedWorker,
|
||||
channel->Port2())) {
|
||||
NS_WARNING("Worker is unreachable, this shouldn't happen!");
|
||||
sharedWorker->Close();
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -138,8 +138,7 @@ private:
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsTArray<nsRefPtr<MessagePortBase>> ports;
|
||||
TakeTransferredPorts(ports);
|
||||
nsTArray<nsRefPtr<MessagePort>> ports = TakeTransferredPorts();
|
||||
|
||||
nsRefPtr<MessagePortList> portList =
|
||||
new MessagePortList(static_cast<dom::Event*>(event.get()),
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "nsIInputStream.h"
|
||||
#include "nsILineInputStream.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsISafeOutputStream.h"
|
||||
|
||||
#include "MainThreadUtils.h"
|
||||
|
|
|
@ -10,12 +10,12 @@
|
|||
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/MessagePort.h"
|
||||
#include "mozilla/dom/SharedWorkerBinding.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
|
||||
#include "MessagePort.h"
|
||||
#include "RuntimeService.h"
|
||||
#include "WorkerPrivate.h"
|
||||
|
||||
|
@ -26,16 +26,14 @@ using namespace mozilla;
|
|||
USING_WORKERS_NAMESPACE
|
||||
|
||||
SharedWorker::SharedWorker(nsPIDOMWindow* aWindow,
|
||||
WorkerPrivate* aWorkerPrivate)
|
||||
: DOMEventTargetHelper(aWindow), mWorkerPrivate(aWorkerPrivate),
|
||||
mFrozen(false)
|
||||
WorkerPrivate* aWorkerPrivate,
|
||||
MessagePort* aMessagePort)
|
||||
: DOMEventTargetHelper(aWindow), mWorkerPrivate(aWorkerPrivate)
|
||||
, mMessagePort(aMessagePort)
|
||||
, mFrozen(false)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
|
||||
mSerial = aWorkerPrivate->NextMessagePortSerial();
|
||||
|
||||
mMessagePort = new MessagePort(aWindow, this, mSerial);
|
||||
}
|
||||
|
||||
SharedWorker::~SharedWorker()
|
||||
|
@ -76,13 +74,11 @@ SharedWorker::Constructor(const GlobalObject& aGlobal, JSContext* aCx,
|
|||
return sharedWorker.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<mozilla::dom::workers::MessagePort>
|
||||
MessagePort*
|
||||
SharedWorker::Port()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsRefPtr<MessagePort> messagePort = mMessagePort;
|
||||
return messagePort.forget();
|
||||
return mMessagePort;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -157,8 +153,7 @@ SharedWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
|||
MOZ_ASSERT(mWorkerPrivate);
|
||||
MOZ_ASSERT(mMessagePort);
|
||||
|
||||
mWorkerPrivate->PostMessageToMessagePort(aCx, mMessagePort->Serial(),
|
||||
aMessage, aTransferable, aRv);
|
||||
mMessagePort->PostMessage(aCx, aMessage, aTransferable, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "Workers.h"
|
||||
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/workers/bindings/MessagePort.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
|
||||
class nsIDOMEvent;
|
||||
|
@ -18,17 +17,19 @@ class nsPIDOMWindow;
|
|||
|
||||
namespace mozilla {
|
||||
class EventChainPreVisitor;
|
||||
|
||||
namespace dom {
|
||||
class MessagePort;
|
||||
}
|
||||
} // namespace mozilla
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
class MessagePort;
|
||||
class RuntimeService;
|
||||
class WorkerPrivate;
|
||||
|
||||
class SharedWorker final : public DOMEventTargetHelper
|
||||
{
|
||||
friend class MessagePort;
|
||||
friend class RuntimeService;
|
||||
|
||||
typedef mozilla::ErrorResult ErrorResult;
|
||||
|
@ -37,7 +38,6 @@ class SharedWorker final : public DOMEventTargetHelper
|
|||
nsRefPtr<WorkerPrivate> mWorkerPrivate;
|
||||
nsRefPtr<MessagePort> mMessagePort;
|
||||
nsTArray<nsCOMPtr<nsIDOMEvent>> mFrozenEvents;
|
||||
uint64_t mSerial;
|
||||
bool mFrozen;
|
||||
|
||||
public:
|
||||
|
@ -46,15 +46,9 @@ public:
|
|||
const nsAString& aScriptURL, const Optional<nsAString>& aName,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<mozilla::dom::workers::MessagePort>
|
||||
MessagePort*
|
||||
Port();
|
||||
|
||||
uint64_t
|
||||
Serial() const
|
||||
{
|
||||
return mSerial;
|
||||
}
|
||||
|
||||
bool
|
||||
IsFrozen() const
|
||||
{
|
||||
|
@ -93,7 +87,8 @@ public:
|
|||
private:
|
||||
// This class can only be created from the RuntimeService.
|
||||
SharedWorker(nsPIDOMWindow* aWindow,
|
||||
WorkerPrivate* aWorkerPrivate);
|
||||
WorkerPrivate* aWorkerPrivate,
|
||||
MessagePort* aMessagePort);
|
||||
|
||||
// This class is reference-counted and will be destroyed from Release().
|
||||
~SharedWorker();
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "mozilla/dom/MessagePort.h"
|
||||
#include "mozilla/dom/MessagePortBinding.h"
|
||||
#include "mozilla/dom/MessagePortList.h"
|
||||
#include "mozilla/dom/PMessagePort.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/PromiseDebugging.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
|
@ -88,7 +89,6 @@
|
|||
#include "nsThreadManager.h"
|
||||
#endif
|
||||
|
||||
#include "MessagePort.h"
|
||||
#include "Navigator.h"
|
||||
#include "Principal.h"
|
||||
#include "RuntimeService.h"
|
||||
|
@ -594,21 +594,15 @@ private:
|
|||
class MessageEventRunnable final : public WorkerRunnable
|
||||
, public StructuredCloneHelper
|
||||
{
|
||||
uint64_t mMessagePortSerial;
|
||||
bool mToMessagePort;
|
||||
|
||||
// This is only used for messages dispatched to a service worker.
|
||||
nsAutoPtr<ServiceWorkerClientInfo> mEventSource;
|
||||
|
||||
public:
|
||||
MessageEventRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
TargetAndBusyBehavior aBehavior,
|
||||
bool aToMessagePort, uint64_t aMessagePortSerial)
|
||||
TargetAndBusyBehavior aBehavior)
|
||||
: WorkerRunnable(aWorkerPrivate, aBehavior)
|
||||
, StructuredCloneHelper(CloningSupported, TransferringSupported,
|
||||
SameProcessDifferentThread)
|
||||
, mMessagePortSerial(aMessagePortSerial)
|
||||
, mToMessagePort(aToMessagePort)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -654,8 +648,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
nsTArray<nsRefPtr<MessagePortBase>> ports;
|
||||
TakeTransferredPorts(ports);
|
||||
nsTArray<nsRefPtr<MessagePort>> ports = TakeTransferredPorts();
|
||||
|
||||
event->SetTrusted(true);
|
||||
event->SetPorts(new MessagePortList(static_cast<dom::Event*>(event.get()),
|
||||
|
@ -671,8 +664,6 @@ private:
|
|||
virtual bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||
{
|
||||
MOZ_ASSERT_IF(mToMessagePort, aWorkerPrivate->IsSharedWorker());
|
||||
|
||||
if (mBehavior == ParentThreadUnchangedBusyCount) {
|
||||
// Don't fire this event if the JS object has been disconnected from the
|
||||
// private object.
|
||||
|
@ -680,13 +671,6 @@ private:
|
|||
return true;
|
||||
}
|
||||
|
||||
if (mToMessagePort) {
|
||||
return
|
||||
aWorkerPrivate->DispatchMessageEventToMessagePort(aCx,
|
||||
mMessagePortSerial,
|
||||
*this);
|
||||
}
|
||||
|
||||
if (aWorkerPrivate->IsFrozen()) {
|
||||
aWorkerPrivate->QueueRunnable(this);
|
||||
return true;
|
||||
|
@ -700,16 +684,6 @@ private:
|
|||
|
||||
MOZ_ASSERT(aWorkerPrivate == GetWorkerPrivateFromContext(aCx));
|
||||
|
||||
if (mToMessagePort) {
|
||||
nsRefPtr<workers::MessagePort> port =
|
||||
aWorkerPrivate->GetMessagePort(mMessagePortSerial);
|
||||
if (!port) {
|
||||
// Must have been closed already.
|
||||
return true;
|
||||
}
|
||||
return DispatchDOMEvent(aCx, aWorkerPrivate, port, false);
|
||||
}
|
||||
|
||||
return DispatchDOMEvent(aCx, aWorkerPrivate, aWorkerPrivate->GlobalScope(),
|
||||
false);
|
||||
}
|
||||
|
@ -1521,18 +1495,19 @@ public:
|
|||
|
||||
class MessagePortRunnable final : public WorkerRunnable
|
||||
{
|
||||
uint64_t mMessagePortSerial;
|
||||
bool mConnect;
|
||||
MessagePortIdentifier mPortIdentifier;
|
||||
|
||||
public:
|
||||
MessagePortRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
uint64_t aMessagePortSerial,
|
||||
bool aConnect)
|
||||
: WorkerRunnable(aWorkerPrivate, aConnect ?
|
||||
WorkerThreadModifyBusyCount :
|
||||
WorkerThreadUnchangedBusyCount),
|
||||
mMessagePortSerial(aMessagePortSerial), mConnect(aConnect)
|
||||
{ }
|
||||
MessagePort* aPort)
|
||||
: WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount)
|
||||
{
|
||||
MOZ_ASSERT(aPort);
|
||||
// In order to move the port from one thread to another one, we have to
|
||||
// close and disentangle it. The output will be a MessagePortIdentifier that
|
||||
// will be used to recreate a new MessagePort on the other thread.
|
||||
aPort->CloneAndDisentangle(mPortIdentifier);
|
||||
}
|
||||
|
||||
private:
|
||||
~MessagePortRunnable()
|
||||
|
@ -1541,12 +1516,7 @@ private:
|
|||
virtual bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||
{
|
||||
if (mConnect) {
|
||||
return aWorkerPrivate->ConnectMessagePort(aCx, mMessagePortSerial);
|
||||
}
|
||||
|
||||
aWorkerPrivate->DisconnectMessagePort(mMessagePortSerial);
|
||||
return true;
|
||||
return aWorkerPrivate->ConnectMessagePort(aCx, mPortIdentifier);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2122,8 +2092,7 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent(
|
|||
mMemoryReportCondVar(mMutex, "WorkerPrivateParent Memory Report CondVar"),
|
||||
mParent(aParent), mScriptURL(aScriptURL),
|
||||
mSharedWorkerName(aSharedWorkerName), mLoadingWorkerScript(false),
|
||||
mBusyCount(0), mMessagePortSerial(0),
|
||||
mParentStatus(Pending), mParentFrozen(false),
|
||||
mBusyCount(0), mParentStatus(Pending), mParentFrozen(false),
|
||||
mIsChromeWorker(aIsChromeWorker), mMainThreadObjectsForgotten(false),
|
||||
mWorkerType(aWorkerType),
|
||||
mCreationTimeStamp(TimeStamp::Now()),
|
||||
|
@ -2487,55 +2456,29 @@ WorkerPrivateParent<Derived>::Freeze(JSContext* aCx, nsPIDOMWindow* aWindow)
|
|||
// Shared workers are only frozen if all of their owning documents are
|
||||
// frozen. It can happen that mSharedWorkers is empty but this thread has
|
||||
// not been unregistered yet.
|
||||
if ((IsSharedWorker() || IsServiceWorker()) && mSharedWorkers.Count()) {
|
||||
if ((IsSharedWorker() || IsServiceWorker()) && !mSharedWorkers.IsEmpty()) {
|
||||
AssertIsOnMainThread();
|
||||
|
||||
struct Closure
|
||||
{
|
||||
nsPIDOMWindow* mWindow;
|
||||
bool mAllFrozen;
|
||||
bool allFrozen = false;
|
||||
|
||||
explicit Closure(nsPIDOMWindow* aWindow)
|
||||
: mWindow(aWindow), mAllFrozen(true)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
// aWindow may be null here.
|
||||
}
|
||||
for (uint32_t i = 0; i < mSharedWorkers.Length(); ++i) {
|
||||
if (aWindow && mSharedWorkers[i]->GetOwner() == aWindow) {
|
||||
// Calling Freeze() may change the refcount, ensure that the worker
|
||||
// outlives this call.
|
||||
nsRefPtr<SharedWorker> kungFuDeathGrip = mSharedWorkers[i];
|
||||
|
||||
static PLDHashOperator
|
||||
Freeze(const uint64_t& aKey,
|
||||
SharedWorker* aSharedWorker,
|
||||
void* aClosure)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aSharedWorker);
|
||||
MOZ_ASSERT(aClosure);
|
||||
|
||||
auto closure = static_cast<Closure*>(aClosure);
|
||||
|
||||
if (closure->mWindow && aSharedWorker->GetOwner() == closure->mWindow) {
|
||||
// Calling Freeze() may change the refcount, ensure that the worker
|
||||
// outlives this call.
|
||||
nsRefPtr<SharedWorker> kungFuDeathGrip = aSharedWorker;
|
||||
|
||||
aSharedWorker->Freeze();
|
||||
} else {
|
||||
MOZ_ASSERT_IF(aSharedWorker->GetOwner() && closure->mWindow,
|
||||
!SameCOMIdentity(aSharedWorker->GetOwner(),
|
||||
closure->mWindow));
|
||||
if (!aSharedWorker->IsFrozen()) {
|
||||
closure->mAllFrozen = false;
|
||||
}
|
||||
mSharedWorkers[i]->Freeze();
|
||||
} else {
|
||||
MOZ_ASSERT_IF(mSharedWorkers[i]->GetOwner() && aWindow,
|
||||
!SameCOMIdentity(mSharedWorkers[i]->GetOwner(),
|
||||
aWindow));
|
||||
if (!mSharedWorkers[i]->IsFrozen()) {
|
||||
allFrozen = false;
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Closure closure(aWindow);
|
||||
|
||||
mSharedWorkers.EnumerateRead(Closure::Freeze, &closure);
|
||||
|
||||
if (!closure.mAllFrozen || mParentFrozen) {
|
||||
if (!allFrozen || mParentFrozen) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -2576,56 +2519,30 @@ WorkerPrivateParent<Derived>::Thaw(JSContext* aCx, nsPIDOMWindow* aWindow)
|
|||
// Shared workers are resumed if any of their owning documents are thawed.
|
||||
// It can happen that mSharedWorkers is empty but this thread has not been
|
||||
// unregistered yet.
|
||||
if ((IsSharedWorker() || IsServiceWorker()) && mSharedWorkers.Count()) {
|
||||
if ((IsSharedWorker() || IsServiceWorker()) && !mSharedWorkers.IsEmpty()) {
|
||||
AssertIsOnMainThread();
|
||||
|
||||
struct Closure
|
||||
{
|
||||
nsPIDOMWindow* mWindow;
|
||||
bool mAnyRunning;
|
||||
bool anyRunning = false;
|
||||
|
||||
explicit Closure(nsPIDOMWindow* aWindow)
|
||||
: mWindow(aWindow), mAnyRunning(false)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
// aWindow may be null here.
|
||||
}
|
||||
for (uint32_t i = 0; i < mSharedWorkers.Length(); ++i) {
|
||||
if (aWindow && mSharedWorkers[i]->GetOwner() == aWindow) {
|
||||
// Calling Thaw() may change the refcount, ensure that the worker
|
||||
// outlives this call.
|
||||
nsRefPtr<SharedWorker> kungFuDeathGrip = mSharedWorkers[i];
|
||||
|
||||
static PLDHashOperator
|
||||
Thaw(const uint64_t& aKey,
|
||||
SharedWorker* aSharedWorker,
|
||||
void* aClosure)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aSharedWorker);
|
||||
MOZ_ASSERT(aClosure);
|
||||
|
||||
auto closure = static_cast<Closure*>(aClosure);
|
||||
|
||||
if (closure->mWindow && aSharedWorker->GetOwner() == closure->mWindow) {
|
||||
// Calling Thaw() may change the refcount, ensure that the worker
|
||||
// outlives this call.
|
||||
nsRefPtr<SharedWorker> kungFuDeathGrip = aSharedWorker;
|
||||
|
||||
aSharedWorker->Thaw();
|
||||
closure->mAnyRunning = true;
|
||||
} else {
|
||||
MOZ_ASSERT_IF(aSharedWorker->GetOwner() && closure->mWindow,
|
||||
!SameCOMIdentity(aSharedWorker->GetOwner(),
|
||||
closure->mWindow));
|
||||
if (!aSharedWorker->IsFrozen()) {
|
||||
closure->mAnyRunning = true;
|
||||
}
|
||||
mSharedWorkers[i]->Thaw();
|
||||
anyRunning = true;
|
||||
} else {
|
||||
MOZ_ASSERT_IF(mSharedWorkers[i]->GetOwner() && aWindow,
|
||||
!SameCOMIdentity(mSharedWorkers[i]->GetOwner(),
|
||||
aWindow));
|
||||
if (!mSharedWorkers[i]->IsFrozen()) {
|
||||
anyRunning = true;
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Closure closure(aWindow);
|
||||
|
||||
mSharedWorkers.EnumerateRead(Closure::Thaw, &closure);
|
||||
|
||||
if (!closure.mAnyRunning || !mParentFrozen) {
|
||||
if (!anyRunning || !mParentFrozen) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -2762,8 +2679,6 @@ WorkerPrivateParent<Derived>::PostMessageInternal(
|
|||
JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
bool aToMessagePort,
|
||||
uint64_t aMessagePortSerial,
|
||||
ServiceWorkerClientInfo* aClientInfo,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
|
@ -2797,8 +2712,7 @@ WorkerPrivateParent<Derived>::PostMessageInternal(
|
|||
|
||||
nsRefPtr<MessageEventRunnable> runnable =
|
||||
new MessageEventRunnable(ParentAsWorkerPrivate(),
|
||||
WorkerRunnable::WorkerThreadModifyBusyCount,
|
||||
aToMessagePort, aMessagePortSerial);
|
||||
WorkerRunnable::WorkerThreadModifyBusyCount);
|
||||
|
||||
runnable->Write(aCx, aMessage, transferable, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
|
@ -2821,88 +2735,7 @@ WorkerPrivateParent<Derived>::PostMessageToServiceWorker(
|
|||
ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
PostMessageInternal(aCx, aMessage, aTransferable, false, 0,
|
||||
aClientInfo.forget(), aRv);
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
void
|
||||
WorkerPrivateParent<Derived>::PostMessageToMessagePort(
|
||||
JSContext* aCx,
|
||||
uint64_t aMessagePortSerial,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
PostMessageInternal(aCx, aMessage, aTransferable, true, aMessagePortSerial,
|
||||
nullptr, aRv);
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
bool
|
||||
WorkerPrivateParent<Derived>::DispatchMessageEventToMessagePort(
|
||||
JSContext* aCx, uint64_t aMessagePortSerial,
|
||||
StructuredCloneHelper& aHelper)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
SharedWorker* sharedWorker;
|
||||
if (!mSharedWorkers.Get(aMessagePortSerial, &sharedWorker)) {
|
||||
// SharedWorker has already been unregistered?
|
||||
return true;
|
||||
}
|
||||
|
||||
nsRefPtr<MessagePort> port = sharedWorker->Port();
|
||||
NS_ASSERTION(port, "SharedWorkers always have a port!");
|
||||
|
||||
if (port->IsClosed()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> parent = do_QueryInterface(port->GetParentObject());
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReporting(port->GetParentObject()))) {
|
||||
return false;
|
||||
}
|
||||
JSContext* cx = jsapi.cx();
|
||||
|
||||
ErrorResult rv;
|
||||
JS::Rooted<JS::Value> data(cx);
|
||||
aHelper.Read(parent, cx, &data, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
xpc::Throw(cx, rv.StealNSResult());
|
||||
return false;
|
||||
}
|
||||
|
||||
nsRefPtr<MessageEvent> event = new MessageEvent(port, nullptr, nullptr);
|
||||
rv = event->InitMessageEvent(NS_LITERAL_STRING("message"), false, false, data,
|
||||
EmptyString(), EmptyString(), nullptr);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
xpc::Throw(cx, rv.StealNSResult());
|
||||
return false;
|
||||
}
|
||||
|
||||
nsTArray<nsRefPtr<MessagePortBase>> ports;
|
||||
aHelper.TakeTransferredPorts(ports);
|
||||
|
||||
event->SetTrusted(true);
|
||||
event->SetPorts(new MessagePortList(port, ports));
|
||||
|
||||
nsCOMPtr<nsIDOMEvent> domEvent;
|
||||
CallQueryInterface(event.get(), getter_AddRefs(domEvent));
|
||||
NS_ASSERTION(domEvent, "This should never fail!");
|
||||
|
||||
bool ignored;
|
||||
rv = port->DispatchEvent(domEvent, &ignored);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
xpc::Throw(cx, rv.StealNSResult());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
PostMessageInternal(aCx, aMessage, aTransferable, aClientInfo.forget(), aRv);
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
|
@ -3090,27 +2923,27 @@ WorkerPrivate::OfflineStatusChangeEventInternal(JSContext* aCx, bool aIsOffline)
|
|||
template <class Derived>
|
||||
bool
|
||||
WorkerPrivateParent<Derived>::RegisterSharedWorker(JSContext* aCx,
|
||||
SharedWorker* aSharedWorker)
|
||||
SharedWorker* aSharedWorker,
|
||||
MessagePort* aPort)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aSharedWorker);
|
||||
MOZ_ASSERT(IsSharedWorker() || IsServiceWorker());
|
||||
MOZ_ASSERT(!mSharedWorkers.Get(aSharedWorker->Serial()));
|
||||
MOZ_ASSERT(!mSharedWorkers.Contains(aSharedWorker));
|
||||
|
||||
if (IsSharedWorker()) {
|
||||
nsRefPtr<MessagePortRunnable> runnable =
|
||||
new MessagePortRunnable(ParentAsWorkerPrivate(), aSharedWorker->Serial(),
|
||||
true);
|
||||
new MessagePortRunnable(ParentAsWorkerPrivate(), aPort);
|
||||
if (!runnable->Dispatch(aCx)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
mSharedWorkers.Put(aSharedWorker->Serial(), aSharedWorker);
|
||||
mSharedWorkers.AppendElement(aSharedWorker);
|
||||
|
||||
// If there were other SharedWorker objects attached to this worker then they
|
||||
// may all have been frozen and this worker would need to be thawed.
|
||||
if (mSharedWorkers.Count() > 1 && !Thaw(aCx, nullptr)) {
|
||||
if (mSharedWorkers.Length() > 1 && !Thaw(aCx, nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3126,21 +2959,14 @@ WorkerPrivateParent<Derived>::UnregisterSharedWorker(
|
|||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aSharedWorker);
|
||||
MOZ_ASSERT(IsSharedWorker() || IsServiceWorker());
|
||||
MOZ_ASSERT(mSharedWorkers.Get(aSharedWorker->Serial()));
|
||||
MOZ_ASSERT(mSharedWorkers.Contains(aSharedWorker));
|
||||
|
||||
nsRefPtr<MessagePortRunnable> runnable =
|
||||
new MessagePortRunnable(ParentAsWorkerPrivate(), aSharedWorker->Serial(),
|
||||
false);
|
||||
if (!runnable->Dispatch(aCx)) {
|
||||
JS_ReportPendingException(aCx);
|
||||
}
|
||||
|
||||
mSharedWorkers.Remove(aSharedWorker->Serial());
|
||||
mSharedWorkers.RemoveElement(aSharedWorker);
|
||||
|
||||
// If there are still SharedWorker objects attached to this worker then they
|
||||
// may all be frozen and this worker would need to be frozen. Otherwise,
|
||||
// if that was the last SharedWorker then it's time to cancel this worker.
|
||||
if (mSharedWorkers.Count()) {
|
||||
if (!mSharedWorkers.IsEmpty()) {
|
||||
if (!Freeze(aCx, nullptr)) {
|
||||
JS_ReportPendingException(aCx);
|
||||
}
|
||||
|
@ -3278,29 +3104,13 @@ WorkerPrivateParent<Derived>::GetAllSharedWorkers(
|
|||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(IsSharedWorker() || IsServiceWorker());
|
||||
|
||||
struct Helper
|
||||
{
|
||||
static PLDHashOperator
|
||||
Collect(const uint64_t& aKey,
|
||||
SharedWorker* aSharedWorker,
|
||||
void* aClosure)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aSharedWorker);
|
||||
MOZ_ASSERT(aClosure);
|
||||
|
||||
auto array = static_cast<nsTArray<nsRefPtr<SharedWorker>>*>(aClosure);
|
||||
array->AppendElement(aSharedWorker);
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
};
|
||||
|
||||
if (!aSharedWorkers.IsEmpty()) {
|
||||
aSharedWorkers.Clear();
|
||||
}
|
||||
|
||||
mSharedWorkers.EnumerateRead(Helper::Collect, &aSharedWorkers);
|
||||
for (uint32_t i = 0; i < mSharedWorkers.Length(); ++i) {
|
||||
aSharedWorkers.AppendElement(mSharedWorkers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
|
@ -3312,47 +3122,19 @@ WorkerPrivateParent<Derived>::CloseSharedWorkersForWindow(
|
|||
MOZ_ASSERT(IsSharedWorker() || IsServiceWorker());
|
||||
MOZ_ASSERT(aWindow);
|
||||
|
||||
struct Closure
|
||||
{
|
||||
nsPIDOMWindow* mWindow;
|
||||
nsAutoTArray<nsRefPtr<SharedWorker>, 10> mSharedWorkers;
|
||||
nsAutoTArray<nsRefPtr<SharedWorker>, 10> sharedWorkers;
|
||||
|
||||
explicit Closure(nsPIDOMWindow* aWindow)
|
||||
: mWindow(aWindow)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aWindow);
|
||||
for (uint32_t i = 0; i < mSharedWorkers.Length(); ++i) {
|
||||
if (mSharedWorkers[i]->GetOwner() == aWindow) {
|
||||
sharedWorkers.AppendElement(mSharedWorkers[i]);
|
||||
} else {
|
||||
MOZ_ASSERT(!SameCOMIdentity(mSharedWorkers[i]->GetOwner(),
|
||||
aWindow));
|
||||
}
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
Collect(const uint64_t& aKey,
|
||||
SharedWorker* aSharedWorker,
|
||||
void* aClosure)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aSharedWorker);
|
||||
MOZ_ASSERT(aClosure);
|
||||
|
||||
auto closure = static_cast<Closure*>(aClosure);
|
||||
MOZ_ASSERT(closure->mWindow);
|
||||
|
||||
if (aSharedWorker->GetOwner() == closure->mWindow) {
|
||||
closure->mSharedWorkers.AppendElement(aSharedWorker);
|
||||
} else {
|
||||
MOZ_ASSERT(!SameCOMIdentity(aSharedWorker->GetOwner(),
|
||||
closure->mWindow));
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
};
|
||||
|
||||
Closure closure(aWindow);
|
||||
|
||||
mSharedWorkers.EnumerateRead(Closure::Collect, &closure);
|
||||
|
||||
for (uint32_t index = 0; index < closure.mSharedWorkers.Length(); index++) {
|
||||
closure.mSharedWorkers[index]->Close();
|
||||
for (uint32_t index = 0; index < sharedWorkers.Length(); index++) {
|
||||
sharedWorkers[index]->Close();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4588,9 +4370,6 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
|
|||
}
|
||||
}
|
||||
|
||||
// Clear away our MessagePorts.
|
||||
mWorkerPorts.Clear();
|
||||
|
||||
// Unroot the globals
|
||||
mScope = nullptr;
|
||||
mDebuggerScope = nullptr;
|
||||
|
@ -5528,8 +5307,6 @@ WorkerPrivate::PostMessageToParentInternal(
|
|||
JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
bool aToMessagePort,
|
||||
uint64_t aMessagePortSerial,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnWorkerThread();
|
||||
|
@ -5554,8 +5331,7 @@ WorkerPrivate::PostMessageToParentInternal(
|
|||
|
||||
nsRefPtr<MessageEventRunnable> runnable =
|
||||
new MessageEventRunnable(this,
|
||||
WorkerRunnable::ParentThreadUnchangedBusyCount,
|
||||
aToMessagePort, aMessagePortSerial);
|
||||
WorkerRunnable::ParentThreadUnchangedBusyCount);
|
||||
|
||||
runnable->Write(aCx, aMessage, transferable, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
|
@ -5567,26 +5343,6 @@ WorkerPrivate::PostMessageToParentInternal(
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
WorkerPrivate::PostMessageToParentMessagePort(
|
||||
JSContext* aCx,
|
||||
uint64_t aMessagePortSerial,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnWorkerThread();
|
||||
|
||||
if (!mWorkerPorts.GetWeak(aMessagePortSerial)) {
|
||||
// This port has been closed from the main thread. There's no point in
|
||||
// sending this message so just bail.
|
||||
return;
|
||||
}
|
||||
|
||||
PostMessageToParentInternal(aCx, aMessage, aTransferable, true,
|
||||
aMessagePortSerial, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
WorkerPrivate::EnterDebuggerEventLoop()
|
||||
{
|
||||
|
@ -6444,19 +6200,23 @@ WorkerPrivate::EndCTypesCall()
|
|||
}
|
||||
|
||||
bool
|
||||
WorkerPrivate::ConnectMessagePort(JSContext* aCx, uint64_t aMessagePortSerial)
|
||||
WorkerPrivate::ConnectMessagePort(JSContext* aCx,
|
||||
MessagePortIdentifier& aIdentifier)
|
||||
{
|
||||
AssertIsOnWorkerThread();
|
||||
|
||||
NS_ASSERTION(!mWorkerPorts.GetWeak(aMessagePortSerial),
|
||||
"Already have this port registered!");
|
||||
|
||||
WorkerGlobalScope* globalScope = GlobalScope();
|
||||
|
||||
JS::Rooted<JSObject*> jsGlobal(aCx, globalScope->GetWrapper());
|
||||
MOZ_ASSERT(jsGlobal);
|
||||
|
||||
nsRefPtr<MessagePort> port = new MessagePort(this, aMessagePortSerial);
|
||||
// This MessagePortIdentifier is used to create a new port, still connected
|
||||
// with the other one, but in the worker thread.
|
||||
ErrorResult rv;
|
||||
nsRefPtr<MessagePort> port = MessagePort::Create(nullptr, aIdentifier, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GlobalObject globalObject(aCx, jsGlobal);
|
||||
if (globalObject.Failed()) {
|
||||
|
@ -6468,51 +6228,27 @@ WorkerPrivate::ConnectMessagePort(JSContext* aCx, uint64_t aMessagePortSerial)
|
|||
init.mCancelable = false;
|
||||
init.mSource.SetValue().SetAsMessagePort() = port;
|
||||
|
||||
ErrorResult rv;
|
||||
|
||||
nsRefPtr<MessageEvent> event =
|
||||
MessageEvent::Constructor(globalObject,
|
||||
NS_LITERAL_STRING("connect"), init, rv);
|
||||
|
||||
event->SetTrusted(true);
|
||||
|
||||
nsTArray<nsRefPtr<MessagePortBase>> ports;
|
||||
nsTArray<nsRefPtr<MessagePort>> ports;
|
||||
ports.AppendElement(port);
|
||||
|
||||
nsRefPtr<MessagePortList> portList =
|
||||
new MessagePortList(static_cast<nsIDOMEventTarget*>(globalScope), ports);
|
||||
event->SetPorts(portList);
|
||||
|
||||
mWorkerPorts.Put(aMessagePortSerial, port);
|
||||
|
||||
nsCOMPtr<nsIDOMEvent> domEvent = do_QueryObject(event);
|
||||
|
||||
nsEventStatus dummy = nsEventStatus_eIgnore;
|
||||
globalScope->DispatchDOMEvent(nullptr, domEvent, nullptr, &dummy);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
WorkerPrivate::DisconnectMessagePort(uint64_t aMessagePortSerial)
|
||||
{
|
||||
AssertIsOnWorkerThread();
|
||||
|
||||
mWorkerPorts.Remove(aMessagePortSerial);
|
||||
}
|
||||
|
||||
workers::MessagePort*
|
||||
WorkerPrivate::GetMessagePort(uint64_t aMessagePortSerial)
|
||||
{
|
||||
AssertIsOnWorkerThread();
|
||||
|
||||
nsRefPtr<MessagePort> port;
|
||||
if (mWorkerPorts.Get(aMessagePortSerial, getter_AddRefs(port))) {
|
||||
return port;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WorkerGlobalScope*
|
||||
WorkerPrivate::GetOrCreateGlobalScope(JSContext* aCx)
|
||||
{
|
||||
|
|
|
@ -50,6 +50,8 @@ struct RuntimeStats;
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Function;
|
||||
class MessagePort;
|
||||
class MessagePortIdentifier;
|
||||
class StructuredCloneHelper;
|
||||
} // namespace dom
|
||||
namespace ipc {
|
||||
|
@ -64,7 +66,6 @@ class ReportDebuggerErrorRunnable;
|
|||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
class AutoSyncLoopHolder;
|
||||
class MessagePort;
|
||||
class SharedWorker;
|
||||
class ServiceWorkerClientInfo;
|
||||
class WorkerControlRunnable;
|
||||
|
@ -177,10 +178,9 @@ private:
|
|||
|
||||
// Only touched on the parent thread (currently this is always the main
|
||||
// thread as SharedWorkers are always top-level).
|
||||
nsDataHashtable<nsUint64HashKey, SharedWorker*> mSharedWorkers;
|
||||
nsTArray<SharedWorker*> mSharedWorkers;
|
||||
|
||||
uint64_t mBusyCount;
|
||||
uint64_t mMessagePortSerial;
|
||||
Status mParentStatus;
|
||||
bool mParentFrozen;
|
||||
bool mIsChromeWorker;
|
||||
|
@ -226,7 +226,6 @@ private:
|
|||
void
|
||||
PostMessageInternal(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
bool aToMessagePort, uint64_t aMessagePortSerial,
|
||||
ServiceWorkerClientInfo* aClientInfo,
|
||||
ErrorResult& aRv);
|
||||
|
||||
|
@ -328,7 +327,7 @@ public:
|
|||
const Optional<Sequence<JS::Value> >& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
PostMessageInternal(aCx, aMessage, aTransferable, false, 0, nullptr, aRv);
|
||||
PostMessageInternal(aCx, aMessage, aTransferable, nullptr, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -337,19 +336,6 @@ public:
|
|||
nsAutoPtr<ServiceWorkerClientInfo>& aClientInfo,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
PostMessageToMessagePort(JSContext* aCx,
|
||||
uint64_t aMessagePortSerial,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value> >& aTransferable,
|
||||
ErrorResult& aRv);
|
||||
|
||||
bool
|
||||
DispatchMessageEventToMessagePort(
|
||||
JSContext* aCx,
|
||||
uint64_t aMessagePortSerial,
|
||||
StructuredCloneHelper& aHelper);
|
||||
|
||||
void
|
||||
UpdateRuntimeOptions(JSContext* aCx,
|
||||
const JS::RuntimeOptions& aRuntimeOptions);
|
||||
|
@ -379,7 +365,8 @@ public:
|
|||
OfflineStatusChangeEvent(JSContext* aCx, bool aIsOffline);
|
||||
|
||||
bool
|
||||
RegisterSharedWorker(JSContext* aCx, SharedWorker* aSharedWorker);
|
||||
RegisterSharedWorker(JSContext* aCx, SharedWorker* aSharedWorker,
|
||||
MessagePort* aPort);
|
||||
|
||||
void
|
||||
UnregisterSharedWorker(JSContext* aCx, SharedWorker* aSharedWorker);
|
||||
|
@ -758,13 +745,6 @@ public:
|
|||
return mSharedWorkerName;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
NextMessagePortSerial()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
return mMessagePortSerial++;
|
||||
}
|
||||
|
||||
bool
|
||||
IsStorageAllowed() const
|
||||
{
|
||||
|
@ -952,8 +932,6 @@ class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
|
|||
|
||||
nsRefPtr<MemoryReporter> mMemoryReporter;
|
||||
|
||||
nsRefPtrHashtable<nsUint64HashKey, MessagePort> mWorkerPorts;
|
||||
|
||||
// fired on the main thread if the worker script fails to load
|
||||
nsCOMPtr<nsIRunnable> mLoadFailedRunnable;
|
||||
|
||||
|
@ -1076,13 +1054,12 @@ public:
|
|||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
PostMessageToParentInternal(aCx, aMessage, aTransferable, false, 0, aRv);
|
||||
PostMessageToParentInternal(aCx, aMessage, aTransferable, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
PostMessageToParentMessagePort(
|
||||
JSContext* aCx,
|
||||
uint64_t aMessagePortSerial,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
ErrorResult& aRv);
|
||||
|
@ -1239,13 +1216,7 @@ public:
|
|||
}
|
||||
|
||||
bool
|
||||
ConnectMessagePort(JSContext* aCx, uint64_t aMessagePortSerial);
|
||||
|
||||
void
|
||||
DisconnectMessagePort(uint64_t aMessagePortSerial);
|
||||
|
||||
MessagePort*
|
||||
GetMessagePort(uint64_t aMessagePortSerial);
|
||||
ConnectMessagePort(JSContext* aCx, MessagePortIdentifier& aIdentifier);
|
||||
|
||||
WorkerGlobalScope*
|
||||
GetOrCreateGlobalScope(JSContext* aCx);
|
||||
|
@ -1445,8 +1416,6 @@ private:
|
|||
PostMessageToParentInternal(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
bool aToMessagePort,
|
||||
uint64_t aMessagePortSerial,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
|
|
|
@ -29,7 +29,6 @@ EXPORTS.mozilla.dom.workers.bindings += [
|
|||
'DataStoreCursor.h',
|
||||
'FileReaderSync.h',
|
||||
'Location.h',
|
||||
'MessagePort.h',
|
||||
'Navigator.h',
|
||||
'Performance.h',
|
||||
'ServiceWorker.h',
|
||||
|
@ -56,7 +55,6 @@ UNIFIED_SOURCES += [
|
|||
'DataStoreCursor.cpp',
|
||||
'FileReaderSync.cpp',
|
||||
'Location.cpp',
|
||||
'MessagePort.cpp',
|
||||
'Navigator.cpp',
|
||||
'Performance.cpp',
|
||||
'Principal.cpp',
|
||||
|
|
|
@ -110,6 +110,7 @@ support-files =
|
|||
sharedworker_performance_user_timing.js
|
||||
referrer.sjs
|
||||
performance_observer.html
|
||||
sharedWorker_ports.js
|
||||
|
||||
[test_404.html]
|
||||
[test_atob.html]
|
||||
|
@ -221,3 +222,4 @@ skip-if = buildapp == 'b2g' || e10s
|
|||
skip-if = (os == "win") || (os == "mac") || toolkit == 'android' || e10s #bug 798220
|
||||
[test_xhrAbort.html]
|
||||
[test_referrer.html]
|
||||
[test_sharedWorker_ports.html]
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
var port;
|
||||
onconnect = function(evt) {
|
||||
evt.source.postMessage({ type: "connected" });
|
||||
|
||||
if (!port) {
|
||||
port = evt.source;
|
||||
evt.source.onmessage = function(evtFromPort) {
|
||||
port.postMessage({type: "status",
|
||||
test: "Port from the main-thread!" == evtFromPort.data,
|
||||
msg: "The message is coming from the main-thread"});
|
||||
port.postMessage({type: "status",
|
||||
test: (evtFromPort.ports.length == 1),
|
||||
msg: "1 port transferred"});
|
||||
|
||||
evtFromPort.ports[0].onmessage = function(evtFromPort2) {
|
||||
port.postMessage({type: "status",
|
||||
test: (evtFromPort2.data.type == "connected"),
|
||||
msg: "The original message received" });
|
||||
port.postMessage({type: "finish"});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for MessagePort and SharedWorkers</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SpecialPowers.pushPrefEnv({ set: [["dom.workers.sharedWorkers.enabled", true]]},
|
||||
function() {
|
||||
var sw1 = new SharedWorker('sharedWorker_ports.js');
|
||||
sw1.port.onmessage = function(event) {
|
||||
if (event.data.type == "connected") {
|
||||
ok(true, "The SharedWorker is alive.");
|
||||
|
||||
var sw2 = new SharedWorker('sharedWorker_ports.js');
|
||||
sw1.port.postMessage("Port from the main-thread!", [sw2.port]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.data.type == "status") {
|
||||
ok(event.data.test, event.data.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.data.type == "finish") {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
Загрузка…
Ссылка в новой задаче