Bug 1263304 - Move Service Worker MessageEvent dispatching code to ServiceWorkerPrivate. r=bkelly

This refactoring makes it easier to modify the behaviour of lifetime
extensions by having a single call path for all extendable events.
This commit is contained in:
Catalin Badea 2016-11-21 02:14:53 +00:00
Родитель d513b931e0
Коммит 4d1930cd13
3 изменённых файлов: 119 добавлений и 151 удалений

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

@ -7,6 +7,7 @@
#include "ServiceWorkerPrivate.h"
#include "ServiceWorkerManager.h"
#include "ServiceWorkerWindowClient.h"
#include "nsContentUtils.h"
#include "nsIHttpChannelInternal.h"
#include "nsIHttpHeaderVisitor.h"
@ -104,64 +105,6 @@ ServiceWorkerPrivate::~ServiceWorkerPrivate()
namespace {
class MessageWaitUntilHandler final : public PromiseNativeHandler
{
nsMainThreadPtrHandle<nsISupports> mKeepAliveToken;
~MessageWaitUntilHandler()
{
}
public:
explicit MessageWaitUntilHandler(const nsMainThreadPtrHandle<nsISupports>& aKeepAliveToken)
: mKeepAliveToken(aKeepAliveToken)
{
MOZ_ASSERT(mKeepAliveToken);
}
void
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{
mKeepAliveToken = nullptr;
}
void
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{
mKeepAliveToken = nullptr;
}
NS_DECL_THREADSAFE_ISUPPORTS
};
NS_IMPL_ISUPPORTS0(MessageWaitUntilHandler)
} // anonymous namespace
nsresult
ServiceWorkerPrivate::SendMessageEvent(JSContext* aCx,
JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value>>& aTransferable,
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo)
{
ErrorResult rv(SpawnWorkerIfNeeded(MessageEvent, nullptr));
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
nsMainThreadPtrHandle<nsISupports> token(
new nsMainThreadPtrHolder<nsISupports>(CreateEventKeepAliveToken()));
RefPtr<PromiseNativeHandler> handler = new MessageWaitUntilHandler(token);
mWorkerPrivate->PostMessageToServiceWorker(aCx, aMessage, aTransferable,
Move(aClientInfo), handler,
rv);
return rv.StealNSResult();
}
namespace {
class CheckScriptEvaluationWithCallback final : public WorkerRunnable
{
nsMainThreadPtrHandle<KeepAliveToken> mKeepAliveToken;
@ -473,6 +416,112 @@ public:
}
};
class SendMesssageEventRunnable final : public ExtendableEventWorkerRunnable
, public StructuredCloneHolder
{
UniquePtr<ServiceWorkerClientInfo> mEventSource;
public:
SendMesssageEventRunnable(WorkerPrivate* aWorkerPrivate,
KeepAliveToken* aKeepAliveToken,
UniquePtr<ServiceWorkerClientInfo>&& aEventSource)
: ExtendableEventWorkerRunnable(aWorkerPrivate, aKeepAliveToken)
, StructuredCloneHolder(CloningSupported, TransferringSupported,
StructuredCloneScope::SameProcessDifferentThread)
, mEventSource(Move(aEventSource))
{
AssertIsOnMainThread();
MOZ_ASSERT(mEventSource);
}
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
{
JS::Rooted<JS::Value> messageData(aCx);
nsCOMPtr<nsIGlobalObject> sgo = aWorkerPrivate->GlobalScope();
ErrorResult rv;
Read(sgo, aCx, &messageData, rv);
if (NS_WARN_IF(rv.Failed())) {
return true;
}
Sequence<OwningNonNull<MessagePort>> ports;
if (!TakeTransferredPortsAsSequence(ports)) {
return true;
}
RefPtr<ServiceWorkerClient> client = new ServiceWorkerWindowClient(sgo,
*mEventSource);
RootedDictionary<ExtendableMessageEventInit> init(aCx);
init.mBubbles = false;
init.mCancelable = false;
init.mData = messageData;
init.mPorts = ports;
init.mSource.SetValue().SetAsClient() = client;
RefPtr<EventTarget> target = aWorkerPrivate->GlobalScope();
RefPtr<ExtendableMessageEvent> extendableEvent =
ExtendableMessageEvent::Constructor(target, NS_LITERAL_STRING("message"),
init, rv);
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
return false;
}
extendableEvent->SetTrusted(true);
return DispatchExtendableEventOnWorkerScope(aCx, aWorkerPrivate->GlobalScope(),
extendableEvent, nullptr);
}
};
} // anonymous namespace
nsresult
ServiceWorkerPrivate::SendMessageEvent(JSContext* aCx,
JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value>>& aTransferable,
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo)
{
AssertIsOnMainThread();
ErrorResult rv(SpawnWorkerIfNeeded(MessageEvent, nullptr));
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedHandleValue);
if (aTransferable.WasPassed()) {
const Sequence<JS::Value>& value = aTransferable.Value();
JS::HandleValueArray elements =
JS::HandleValueArray::fromMarkedLocation(value.Length(), value.Elements());
JSObject* array = JS_NewArrayObject(aCx, elements);
if (!array) {
return NS_ERROR_OUT_OF_MEMORY;
}
transferable.setObject(*array);
}
RefPtr<KeepAliveToken> token = CreateEventKeepAliveToken();
RefPtr<SendMesssageEventRunnable> runnable =
new SendMesssageEventRunnable(mWorkerPrivate, token, Move(aClientInfo));
runnable->Write(aCx, aMessage, transferable, JS::CloneDataPolicy(), rv);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
if (!runnable->Dispatch()) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
namespace {
// Handle functional event
// 9.9.7 If the time difference in seconds calculated by the current time minus
// registration's last update check time is greater than 86400, invoke Soft Update

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

@ -105,7 +105,6 @@
#include "ScriptLoader.h"
#include "ServiceWorkerEvents.h"
#include "ServiceWorkerManager.h"
#include "ServiceWorkerWindowClient.h"
#include "SharedWorker.h"
#include "WorkerDebuggerManager.h"
#include "WorkerHolder.h"
@ -609,11 +608,6 @@ private:
class MessageEventRunnable final : public WorkerRunnable
, public StructuredCloneHolder
{
// This is only used for messages dispatched to a service worker.
UniquePtr<ServiceWorkerClientInfo> mEventSource;
RefPtr<PromiseNativeHandler> mHandler;
public:
MessageEventRunnable(WorkerPrivate* aWorkerPrivate,
TargetAndBusyBehavior aBehavior)
@ -623,14 +617,6 @@ public:
{
}
void
SetServiceWorkerData(UniquePtr<ServiceWorkerClientInfo>&& aSource,
PromiseNativeHandler* aHandler)
{
mEventSource = Move(aSource);
mHandler = aHandler;
}
bool
DispatchDOMEvent(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
DOMEventTargetHelper* aTarget, bool aIsMainThread)
@ -690,63 +676,23 @@ public:
}
nsCOMPtr<nsIDOMEvent> domEvent;
RefPtr<ExtendableMessageEvent> extendableEvent;
// For messages dispatched to service worker, use ExtendableMessageEvent
// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#extendablemessage-event-section
if (mEventSource) {
RefPtr<ServiceWorkerClient> client =
new ServiceWorkerWindowClient(aTarget, *mEventSource);
RootedDictionary<ExtendableMessageEventInit> init(aCx);
init.mBubbles = false;
init.mCancelable = false;
init.mData = messageData;
init.mPorts = ports;
init.mSource.SetValue().SetAsClient() = client;
ErrorResult rv;
extendableEvent = ExtendableMessageEvent::Constructor(
aTarget, NS_LITERAL_STRING("message"), init, rv);
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
return false;
}
domEvent = do_QueryObject(extendableEvent);
} else {
RefPtr<MessageEvent> event = new MessageEvent(aTarget, nullptr, nullptr);
event->InitMessageEvent(nullptr,
NS_LITERAL_STRING("message"),
false /* non-bubbling */,
false /* cancelable */,
messageData,
EmptyString(),
EmptyString(),
nullptr,
ports);
domEvent = do_QueryObject(event);
}
RefPtr<MessageEvent> event = new MessageEvent(aTarget, nullptr, nullptr);
event->InitMessageEvent(nullptr,
NS_LITERAL_STRING("message"),
false /* non-bubbling */,
false /* cancelable */,
messageData,
EmptyString(),
EmptyString(),
nullptr,
ports);
domEvent = do_QueryObject(event);
domEvent->SetTrusted(true);
nsEventStatus dummy = nsEventStatus_eIgnore;
aTarget->DispatchDOMEvent(nullptr, domEvent, nullptr, &dummy);
if (extendableEvent && mHandler) {
RefPtr<Promise> waitUntilPromise = extendableEvent->GetPromise();
if (!waitUntilPromise) {
waitUntilPromise = Promise::Resolve(parent, aCx,
JS::UndefinedHandleValue, rv);
MOZ_RELEASE_ASSERT(!rv.Failed());
}
MOZ_ASSERT(waitUntilPromise);
waitUntilPromise->AppendNativeHandler(mHandler);
}
return true;
}
@ -2977,8 +2923,6 @@ WorkerPrivateParent<Derived>::PostMessageInternal(
JSContext* aCx,
JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value>>& aTransferable,
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
PromiseNativeHandler* aHandler,
ErrorResult& aRv)
{
AssertIsOnParentThread();
@ -3040,8 +2984,6 @@ WorkerPrivateParent<Derived>::PostMessageInternal(
return;
}
runnable->SetServiceWorkerData(Move(aClientInfo), aHandler);
if (!runnable->Dispatch()) {
aRv.Throw(NS_ERROR_FAILURE);
}
@ -3054,21 +2996,7 @@ WorkerPrivateParent<Derived>::PostMessage(
const Optional<Sequence<JS::Value>>& aTransferable,
ErrorResult& aRv)
{
PostMessageInternal(aCx, aMessage, aTransferable, nullptr, nullptr, aRv);
}
template <class Derived>
void
WorkerPrivateParent<Derived>::PostMessageToServiceWorker(
JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value>>& aTransferable,
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
PromiseNativeHandler* aHandler,
ErrorResult& aRv)
{
AssertIsOnMainThread();
PostMessageInternal(aCx, aMessage, aTransferable, Move(aClientInfo),
aHandler, aRv);
PostMessageInternal(aCx, aMessage, aTransferable, aRv);
}
template <class Derived>

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

@ -252,8 +252,6 @@ private:
void
PostMessageInternal(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value>>& aTransferable,
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
PromiseNativeHandler* aHandler,
ErrorResult& aRv);
nsresult
@ -367,13 +365,6 @@ public:
const Optional<Sequence<JS::Value>>& aTransferable,
ErrorResult& aRv);
void
PostMessageToServiceWorker(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value>>& aTransferable,
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
PromiseNativeHandler* aHandler,
ErrorResult& aRv);
void
UpdateContextOptions(const JS::ContextOptions& aContextOptions);