Backed out changeset b2d3c6629a37 (bug 1263304)

This commit is contained in:
Carsten "Tomcat" Book 2016-11-11 10:47:43 +01:00
parent 933a225285
commit e84cb96866
3 changed files with 232 additions and 228 deletions

View File

@ -767,9 +767,9 @@ FetchEvent::RespondWith(JSContext* aCx, Promise& aArg, ErrorResult& aRv)
spec, line, column); spec, line, column);
aArg.AppendNativeHandler(handler); aArg.AppendNativeHandler(handler);
if (!WaitOnPromise(aArg)) { // Append directly to the lifecycle promises array. Don't call WaitUntil()
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); // because that will lead to double-reporting any errors.
} mPromises.AppendElement(&aArg);
} }
void void
@ -910,29 +910,12 @@ ExtendableEvent::ExtendableEvent(EventTarget* aOwner)
{ {
} }
bool
ExtendableEvent::WaitOnPromise(Promise& aPromise)
{
MOZ_ASSERT(mExtensionsHandler);
return mExtensionsHandler->WaitOnPromise(aPromise);
}
void
ExtendableEvent::SetKeepAliveHandler(ExtensionsHandler* aExtensionsHandler)
{
MOZ_ASSERT(!mExtensionsHandler);
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(worker);
worker->AssertIsOnWorkerThread();
mExtensionsHandler = aExtensionsHandler;
}
void void
ExtendableEvent::WaitUntil(JSContext* aCx, Promise& aPromise, ErrorResult& aRv) ExtendableEvent::WaitUntil(JSContext* aCx, Promise& aPromise, ErrorResult& aRv)
{ {
MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(!NS_IsMainThread());
if (!WaitOnPromise(aPromise)) { if (EventPhase() == nsIDOMEvent::NONE) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return; return;
} }
@ -942,6 +925,34 @@ ExtendableEvent::WaitUntil(JSContext* aCx, Promise& aPromise, ErrorResult& aRv)
RefPtr<WaitUntilHandler> handler = RefPtr<WaitUntilHandler> handler =
new WaitUntilHandler(GetCurrentThreadWorkerPrivate(), aCx); new WaitUntilHandler(GetCurrentThreadWorkerPrivate(), aCx);
aPromise.AppendNativeHandler(handler); aPromise.AppendNativeHandler(handler);
mPromises.AppendElement(&aPromise);
}
already_AddRefed<Promise>
ExtendableEvent::GetPromise()
{
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(worker);
worker->AssertIsOnWorkerThread();
nsIGlobalObject* globalObj = worker->GlobalScope();
AutoJSAPI jsapi;
if (!jsapi.Init(globalObj)) {
return nullptr;
}
JSContext* cx = jsapi.cx();
GlobalObject global(cx, globalObj->GetGlobalJSObject());
ErrorResult result;
RefPtr<Promise> p = Promise::All(global, Move(mPromises), result);
if (NS_WARN_IF(result.MaybeSetPendingException(cx))) {
return nullptr;
}
return p.forget();
} }
NS_IMPL_ADDREF_INHERITED(ExtendableEvent, Event) NS_IMPL_ADDREF_INHERITED(ExtendableEvent, Event)
@ -950,6 +961,8 @@ NS_IMPL_RELEASE_INHERITED(ExtendableEvent, Event)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ExtendableEvent) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ExtendableEvent)
NS_INTERFACE_MAP_END_INHERITING(Event) NS_INTERFACE_MAP_END_INHERITING(Event)
NS_IMPL_CYCLE_COLLECTION_INHERITED(ExtendableEvent, Event, mPromises)
namespace { namespace {
nsresult nsresult
ExtractBytesFromUSVString(const nsAString& aStr, nsTArray<uint8_t>& aBytes) ExtractBytesFromUSVString(const nsAString& aStr, nsTArray<uint8_t>& aBytes)

View File

@ -51,36 +51,17 @@ public:
class ExtendableEvent : public Event class ExtendableEvent : public Event
{ {
public:
class ExtensionsHandler {
public:
virtual bool
WaitOnPromise(Promise& aPromise) = 0;
NS_IMETHOD_(MozExternalRefCountType)
AddRef() = 0;
NS_IMETHOD_(MozExternalRefCountType)
Release() = 0;
};
private:
RefPtr<ExtensionsHandler> mExtensionsHandler;
protected: protected:
bool nsTArray<RefPtr<Promise>> mPromises;
WaitOnPromise(Promise& aPromise);
explicit ExtendableEvent(mozilla::dom::EventTarget* aOwner); explicit ExtendableEvent(mozilla::dom::EventTarget* aOwner);
~ExtendableEvent() {} ~ExtendableEvent() {}
public: public:
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ExtendableEvent, Event)
NS_FORWARD_TO_EVENT NS_FORWARD_TO_EVENT
void
SetKeepAliveHandler(ExtensionsHandler* aExtensionsHandler);
virtual JSObject* WrapObjectInternal(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override virtual JSObject* WrapObjectInternal(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override
{ {
return mozilla::dom::ExtendableEventBinding::Wrap(aCx, this, aGivenProto); return mozilla::dom::ExtendableEventBinding::Wrap(aCx, this, aGivenProto);
@ -112,6 +93,9 @@ public:
void void
WaitUntil(JSContext* aCx, Promise& aPromise, ErrorResult& aRv); WaitUntil(JSContext* aCx, Promise& aPromise, ErrorResult& aRv);
already_AddRefed<Promise>
GetPromise();
virtual ExtendableEvent* AsExtendableEvent() override virtual ExtendableEvent* AsExtendableEvent() override
{ {
return this; return this;

View File

@ -181,186 +181,154 @@ ServiceWorkerPrivate::CheckScriptEvaluation(LifeCycleEventCallback* aCallback)
namespace { namespace {
enum ExtendableEventResult { // Holds the worker alive until the waitUntil promise is resolved or
Rejected = 0, // rejected.
Resolved class KeepAliveHandler final
};
class ExtendableEventCallback {
public:
virtual void
FinishedWithResult(ExtendableEventResult aResult) = 0;
NS_IMETHOD_(MozExternalRefCountType)
AddRef() = 0;
NS_IMETHOD_(MozExternalRefCountType)
Release() = 0;
};
class KeepAliveHandler final : public WorkerHolder
, public ExtendableEvent::ExtensionsHandler
, public PromiseNativeHandler
{ {
// This class manages lifetime extensions added by calling WaitUntil() // Use an internal class to listen for the promise resolve/reject
// or RespondWith(). We allow new extensions as long as we still hold // callbacks. This class also registers a feature so that it can
// |mKeepAliveToken|. Once the last promise was settled, we queue a microtask // preemptively cleanup if the service worker is timed out and
// which releases the token and prevents further extensions. By doing this, // terminated.
// we give other pending microtasks a chance to continue adding extensions. class InternalHandler final : public PromiseNativeHandler
, public WorkerHolder
nsMainThreadPtrHandle<KeepAliveToken> mKeepAliveToken;
WorkerPrivate* MOZ_NON_OWNING_REF mWorkerPrivate;
bool mWorkerHolderAdded;
// We start holding a self reference when the first extension promise is
// added. As far as I can tell, the only case where this is useful is when
// we're waiting indefinitely on a promise that's no longer reachable
// and will never be settled.
// The cycle is broken when the last promise was settled or when the
// worker is shutting down.
RefPtr<KeepAliveHandler> mSelfRef;
// Called when the last promise was settled.
RefPtr<ExtendableEventCallback> mCallback;
uint32_t mPendingPromisesCount;
// We don't actually care what values the promises resolve to, only whether
// any of them were rejected.
bool mRejected;
public:
NS_DECL_ISUPPORTS
explicit KeepAliveHandler(const nsMainThreadPtrHandle<KeepAliveToken>& aKeepAliveToken,
ExtendableEventCallback* aCallback)
: mKeepAliveToken(aKeepAliveToken)
, mWorkerPrivate(GetCurrentThreadWorkerPrivate())
, mWorkerHolderAdded(false)
, mCallback(aCallback)
, mPendingPromisesCount(0)
, mRejected(false)
{ {
MOZ_ASSERT(mKeepAliveToken); nsMainThreadPtrHandle<KeepAliveToken> mKeepAliveToken;
MOZ_ASSERT(mWorkerPrivate);
}
bool // Worker thread only
UseWorkerHolder() WorkerPrivate* mWorkerPrivate;
{ RefPtr<Promise> mPromise;
MOZ_ASSERT(mWorkerPrivate); bool mWorkerHolderAdded;
mWorkerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(!mWorkerHolderAdded);
mWorkerHolderAdded = HoldWorker(mWorkerPrivate, Terminating);
return mWorkerHolderAdded;
}
bool ~InternalHandler()
WaitOnPromise(Promise& aPromise) override {
{ MaybeCleanup();
if (!mKeepAliveToken) {
MOZ_ASSERT(!mSelfRef, "We shouldn't be holding a self reference!");
return false;
}
if (!mSelfRef) {
MOZ_ASSERT(!mPendingPromisesCount);
mSelfRef = this;
} }
++mPendingPromisesCount; bool
aPromise.AppendNativeHandler(this); UseWorkerHolder()
{
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(!mWorkerHolderAdded);
mWorkerHolderAdded = HoldWorker(mWorkerPrivate, Terminating);
return mWorkerHolderAdded;
}
return true; void
} MaybeCleanup()
{
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
if (!mPromise) {
return;
}
if (mWorkerHolderAdded) {
ReleaseWorker();
}
mPromise = nullptr;
mKeepAliveToken = nullptr;
}
void void
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{ {
RemovePromise(Resolved); MOZ_ASSERT(mWorkerPrivate);
} mWorkerPrivate->AssertIsOnWorkerThread();
MaybeCleanup();
}
void void
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{ {
RemovePromise(Rejected); MOZ_ASSERT(mWorkerPrivate);
} mWorkerPrivate->AssertIsOnWorkerThread();
MaybeCleanup();
}
bool bool
Notify(Status aStatus) override Notify(Status aStatus) override
{ {
MOZ_ASSERT(mWorkerPrivate); MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread(); mWorkerPrivate->AssertIsOnWorkerThread();
if (aStatus < Terminating) { if (aStatus < Terminating) {
return true;
}
MaybeCleanup();
return true; return true;
} }
MaybeCleanup(); InternalHandler(const nsMainThreadPtrHandle<KeepAliveToken>& aKeepAliveToken,
return true; WorkerPrivate* aWorkerPrivate,
} Promise* aPromise)
: mKeepAliveToken(aKeepAliveToken)
void , mWorkerPrivate(aWorkerPrivate)
MaybeDone() , mPromise(aPromise)
{ , mWorkerHolderAdded(false)
MOZ_ASSERT(mWorkerPrivate); {
mWorkerPrivate->AssertIsOnWorkerThread(); MOZ_ASSERT(mKeepAliveToken);
MOZ_ASSERT(mWorkerPrivate);
if (mPendingPromisesCount) { MOZ_ASSERT(mPromise);
return;
}
if (mCallback) {
mCallback->FinishedWithResult(mRejected ? Rejected : Resolved);
} }
MaybeCleanup(); public:
} static already_AddRefed<InternalHandler>
Create(const nsMainThreadPtrHandle<KeepAliveToken>& aKeepAliveToken,
WorkerPrivate* aWorkerPrivate,
Promise* aPromise)
{
RefPtr<InternalHandler> ref = new InternalHandler(aKeepAliveToken,
aWorkerPrivate,
aPromise);
private: if (NS_WARN_IF(!ref->UseWorkerHolder())) {
~KeepAliveHandler() return nullptr;
{ }
MaybeCleanup();
}
void return ref.forget();
MaybeCleanup()
{
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
if (!mKeepAliveToken) {
return;
}
if (mWorkerHolderAdded) {
ReleaseWorker();
} }
mKeepAliveToken = nullptr; NS_DECL_ISUPPORTS
mSelfRef = nullptr; };
}
void // This is really just a wrapper class to keep the InternalHandler
RemovePromise(ExtendableEventResult aResult) // private. We don't want any code to accidentally call
// Promise::AppendNativeHandler() without also referencing the promise.
// Therefore we force all code through the static CreateAndAttachToPromise()
// and use the private InternalHandler object.
KeepAliveHandler() = delete;
~KeepAliveHandler() = delete;
public:
// Create a private handler object and attach it to the given Promise.
// This will also create a strong ref to the Promise in a ref cycle. The
// ref cycle is broken when the Promise is fulfilled or the worker thread
// is Terminated.
static void
CreateAndAttachToPromise(const nsMainThreadPtrHandle<KeepAliveToken>& aKeepAliveToken,
Promise* aPromise)
{ {
MOZ_ASSERT(mWorkerPrivate); WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
mWorkerPrivate->AssertIsOnWorkerThread(); MOZ_ASSERT(workerPrivate);
MOZ_DIAGNOSTIC_ASSERT(mPendingPromisesCount > 0); workerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(mSelfRef); MOZ_ASSERT(aKeepAliveToken);
MOZ_ASSERT(mKeepAliveToken); MOZ_ASSERT(aPromise);
mRejected |= (aResult == Rejected); // This creates a strong ref to the promise.
RefPtr<InternalHandler> handler = InternalHandler::Create(aKeepAliveToken,
--mPendingPromisesCount; workerPrivate,
if (mPendingPromisesCount) { aPromise);
if (NS_WARN_IF(!handler)) {
return; return;
} }
CycleCollectedJSContext* cx = CycleCollectedJSContext::Get(); // This then creates a strong ref cycle between the promise and the
MOZ_ASSERT(cx); // handler. The cycle is broken when the Promise is fulfilled or
// the worker thread is Terminated.
RefPtr<nsIRunnable> r = NewRunnableMethod(this, &KeepAliveHandler::MaybeDone); aPromise->AppendNativeHandler(handler);
cx->DispatchToMicroTask(r.forget());
} }
}; };
NS_IMPL_ISUPPORTS0(KeepAliveHandler) NS_IMPL_ISUPPORTS0(KeepAliveHandler::InternalHandler)
class RegistrationUpdateRunnable : public Runnable class RegistrationUpdateRunnable : public Runnable
{ {
@ -409,23 +377,13 @@ public:
DispatchExtendableEventOnWorkerScope(JSContext* aCx, DispatchExtendableEventOnWorkerScope(JSContext* aCx,
WorkerGlobalScope* aWorkerScope, WorkerGlobalScope* aWorkerScope,
ExtendableEvent* aEvent, ExtendableEvent* aEvent,
ExtendableEventCallback* aCallback) PromiseNativeHandler* aPromiseHandler)
{ {
MOZ_ASSERT(aWorkerScope); MOZ_ASSERT(aWorkerScope);
MOZ_ASSERT(aEvent); MOZ_ASSERT(aEvent);
nsCOMPtr<nsIGlobalObject> sgo = aWorkerScope; nsCOMPtr<nsIGlobalObject> sgo = aWorkerScope;
WidgetEvent* internalEvent = aEvent->WidgetEventPtr(); WidgetEvent* internalEvent = aEvent->WidgetEventPtr();
RefPtr<KeepAliveHandler> keepAliveHandler =
new KeepAliveHandler(mKeepAliveToken, aCallback);
if (NS_WARN_IF(!keepAliveHandler->UseWorkerHolder())) {
return false;
}
// This must always be set *before* dispatching the event, otherwise
// waitUntil calls will fail.
aEvent->SetKeepAliveHandler(keepAliveHandler);
ErrorResult result; ErrorResult result;
result = aWorkerScope->DispatchDOMEvent(nullptr, aEvent, nullptr, nullptr); result = aWorkerScope->DispatchDOMEvent(nullptr, aEvent, nullptr, nullptr);
if (NS_WARN_IF(result.Failed()) || internalEvent->mFlags.mExceptionWasRaised) { if (NS_WARN_IF(result.Failed()) || internalEvent->mFlags.mExceptionWasRaised) {
@ -433,9 +391,26 @@ public:
return false; return false;
} }
// [[ If es extend lifetime promises is empty, unset es extensions allowed RefPtr<Promise> waitUntilPromise = aEvent->GetPromise();
// flag and abort these steps. ]] if (!waitUntilPromise) {
keepAliveHandler->MaybeDone(); waitUntilPromise =
Promise::Resolve(sgo, aCx, JS::UndefinedHandleValue, result);
MOZ_RELEASE_ASSERT(!result.Failed());
}
MOZ_ASSERT(waitUntilPromise);
// Make sure to append the caller's promise handler before attaching
// our keep alive handler. This can avoid terminating the worker
// before a success result is delivered to the caller in cases where
// the idle timeout has been set to zero. This low timeout value is
// sometimes set in tests.
if (aPromiseHandler) {
waitUntilPromise->AppendNativeHandler(aPromiseHandler);
}
KeepAliveHandler::CreateAndAttachToPromise(mKeepAliveToken,
waitUntilPromise);
return true; return true;
} }
@ -626,7 +601,7 @@ private:
* termination during the execution of life cycle events. It is responsible * termination during the execution of life cycle events. It is responsible
* with advancing the job queue for install/activate tasks. * with advancing the job queue for install/activate tasks.
*/ */
class LifeCycleEventWatcher final : public ExtendableEventCallback, class LifeCycleEventWatcher final : public PromiseNativeHandler,
public WorkerHolder public WorkerHolder
{ {
WorkerPrivate* mWorkerPrivate; WorkerPrivate* mWorkerPrivate;
@ -648,7 +623,7 @@ class LifeCycleEventWatcher final : public ExtendableEventCallback,
} }
public: public:
NS_INLINE_DECL_REFCOUNTING(LifeCycleEventWatcher, override) NS_DECL_ISUPPORTS
LifeCycleEventWatcher(WorkerPrivate* aWorkerPrivate, LifeCycleEventWatcher(WorkerPrivate* aWorkerPrivate,
LifeCycleEventCallback* aCallback) LifeCycleEventCallback* aCallback)
@ -715,11 +690,21 @@ public:
} }
void void
FinishedWithResult(ExtendableEventResult aResult) override ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{ {
MOZ_ASSERT(GetCurrentThreadWorkerPrivate() == mWorkerPrivate); MOZ_ASSERT(GetCurrentThreadWorkerPrivate() == mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread(); mWorkerPrivate->AssertIsOnWorkerThread();
ReportResult(aResult == Resolved);
ReportResult(true);
}
void
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{
MOZ_ASSERT(GetCurrentThreadWorkerPrivate() == mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
ReportResult(false);
// Note, all WaitUntil() rejections are reported to client consoles // Note, all WaitUntil() rejections are reported to client consoles
// by the WaitUntilHandler in ServiceWorkerEvents. This ensures that // by the WaitUntilHandler in ServiceWorkerEvents. This ensures that
@ -728,6 +713,8 @@ public:
} }
}; };
NS_IMPL_ISUPPORTS0(LifeCycleEventWatcher)
bool bool
LifecycleEventWorkerRunnable::DispatchLifecycleEvent(JSContext* aCx, LifecycleEventWorkerRunnable::DispatchLifecycleEvent(JSContext* aCx,
WorkerPrivate* aWorkerPrivate) WorkerPrivate* aWorkerPrivate)
@ -791,7 +778,7 @@ ServiceWorkerPrivate::SendLifeCycleEvent(const nsAString& aEventType,
namespace { namespace {
class PushErrorReporter final : public ExtendableEventCallback class PushErrorReporter final : public PromiseNativeHandler
{ {
WorkerPrivate* mWorkerPrivate; WorkerPrivate* mWorkerPrivate;
nsString mMessageId; nsString mMessageId;
@ -801,7 +788,7 @@ class PushErrorReporter final : public ExtendableEventCallback
} }
public: public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PushErrorReporter, override) NS_DECL_THREADSAFE_ISUPPORTS
PushErrorReporter(WorkerPrivate* aWorkerPrivate, PushErrorReporter(WorkerPrivate* aWorkerPrivate,
const nsAString& aMessageId) const nsAString& aMessageId)
@ -811,12 +798,16 @@ public:
mWorkerPrivate->AssertIsOnWorkerThread(); mWorkerPrivate->AssertIsOnWorkerThread();
} }
void void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
FinishedWithResult(ExtendableEventResult aResult) override
{ {
if (aResult == Rejected) { mWorkerPrivate->AssertIsOnWorkerThread();
Report(nsIPushErrorReporter::DELIVERY_UNHANDLED_REJECTION); mWorkerPrivate = nullptr;
} // Do nothing; we only use this to report errors to the Push service.
}
void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{
Report(nsIPushErrorReporter::DELIVERY_UNHANDLED_REJECTION);
} }
void Report(uint16_t aReason = nsIPushErrorReporter::DELIVERY_INTERNAL_ERROR) void Report(uint16_t aReason = nsIPushErrorReporter::DELIVERY_INTERNAL_ERROR)
@ -848,6 +839,8 @@ public:
} }
}; };
NS_IMPL_ISUPPORTS0(PushErrorReporter)
class SendPushEventRunnable final : public ExtendableFunctionalEventWorkerRunnable class SendPushEventRunnable final : public ExtendableFunctionalEventWorkerRunnable
{ {
nsString mMessageId; nsString mMessageId;
@ -1050,7 +1043,7 @@ private:
RefPtr<AllowWindowInteractionHandler> mHandler; RefPtr<AllowWindowInteractionHandler> mHandler;
}; };
class AllowWindowInteractionHandler final : public ExtendableEventCallback class AllowWindowInteractionHandler final : public PromiseNativeHandler
{ {
friend class ClearWindowAllowedRunnable; friend class ClearWindowAllowedRunnable;
nsCOMPtr<nsITimer> mTimer; nsCOMPtr<nsITimer> mTimer;
@ -1129,7 +1122,7 @@ class AllowWindowInteractionHandler final : public ExtendableEventCallback
} }
public: public:
NS_INLINE_DECL_REFCOUNTING(AllowWindowInteractionHandler, override) NS_DECL_ISUPPORTS
explicit AllowWindowInteractionHandler(WorkerPrivate* aWorkerPrivate) explicit AllowWindowInteractionHandler(WorkerPrivate* aWorkerPrivate)
{ {
@ -1137,13 +1130,22 @@ public:
} }
void void
FinishedWithResult(ExtendableEventResult /* aResult */) override ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{ {
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
ClearWindowAllowed(workerPrivate);
}
void
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
ClearWindowAllowed(workerPrivate); ClearWindowAllowed(workerPrivate);
} }
}; };
NS_IMPL_ISUPPORTS0(AllowWindowInteractionHandler)
bool bool
ClearWindowAllowedRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) ClearWindowAllowedRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{ {
@ -1232,7 +1234,7 @@ public:
new AllowWindowInteractionHandler(aWorkerPrivate); new AllowWindowInteractionHandler(aWorkerPrivate);
if (!DispatchExtendableEventOnWorkerScope(aCx, aWorkerPrivate->GlobalScope(), if (!DispatchExtendableEventOnWorkerScope(aCx, aWorkerPrivate->GlobalScope(),
event, allowWindowInteraction)) { event, allowWindowInteraction)) {
allowWindowInteraction->FinishedWithResult(Rejected); allowWindowInteraction->RejectedCallback(aCx, JS::UndefinedHandleValue);
} }
aWorkerPrivate->GlobalScope()->ConsumeWindowInteraction(); aWorkerPrivate->GlobalScope()->ConsumeWindowInteraction();
@ -1565,10 +1567,9 @@ private:
event->PostInit(mInterceptedChannel, mRegistration, mScriptSpec); event->PostInit(mInterceptedChannel, mRegistration, mScriptSpec);
event->SetTrusted(true); event->SetTrusted(true);
bool rv2 = RefPtr<EventTarget> target = do_QueryObject(aWorkerPrivate->GlobalScope());
DispatchExtendableEventOnWorkerScope(aCx, aWorkerPrivate->GlobalScope(), nsresult rv2 = target->DispatchDOMEvent(nullptr, event, nullptr, nullptr);
event, nullptr); if (NS_WARN_IF(NS_FAILED(rv2)) || !event->WaitToRespond()) {
if (NS_WARN_IF(!rv2) || !event->WaitToRespond()) {
nsCOMPtr<nsIRunnable> runnable; nsCOMPtr<nsIRunnable> runnable;
if (event->DefaultPrevented(aCx)) { if (event->DefaultPrevented(aCx)) {
event->ReportCanceled(); event->ReportCanceled();
@ -1587,6 +1588,12 @@ private:
MOZ_ALWAYS_SUCCEEDS(mWorkerPrivate->DispatchToMainThread(runnable.forget())); MOZ_ALWAYS_SUCCEEDS(mWorkerPrivate->DispatchToMainThread(runnable.forget()));
} }
RefPtr<Promise> waitUntilPromise = event->GetPromise();
if (waitUntilPromise) {
KeepAliveHandler::CreateAndAttachToPromise(mKeepAliveToken,
waitUntilPromise);
}
return true; return true;
} }