зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
d513b931e0
Коммит
4d1930cd13
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче