Bug 1160527 - Patch 1 - Support PushEvent.waitUntil(). r=baku.

This commit is contained in:
Nikhil Marathe 2015-06-02 14:52:49 -07:00
parent 65dbcc75c2
commit 365efe4a1f

View File

@ -284,7 +284,7 @@ private:
nsRefPtr<ServiceWorkerManagerChild> mActor;
};
} // Anonymous namespace
} // anonymous namespace
NS_IMPL_ISUPPORTS0(ServiceWorkerJob)
NS_IMPL_ISUPPORTS0(ServiceWorkerRegistrationInfo)
@ -1587,6 +1587,74 @@ ServiceWorkerManager::AppendPendingOperation(nsIRunnable* aRunnable)
}
}
namespace {
// Just holds a ref to a ServiceWorker until the Promise is fulfilled.
class KeepAliveHandler final : public PromiseNativeHandler
{
nsMainThreadPtrHandle<ServiceWorker> mServiceWorker;
virtual ~KeepAliveHandler()
{}
public:
explicit KeepAliveHandler(const nsMainThreadPtrHandle<ServiceWorker>& aServiceWorker)
: mServiceWorker(aServiceWorker)
{}
void
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{
#ifdef DEBUG
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
workerPrivate->AssertIsOnWorkerThread();
#endif
}
void
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{
#ifdef DEBUG
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
workerPrivate->AssertIsOnWorkerThread();
#endif
}
};
// Returns a Promise if the event was successfully dispatched and no exceptions
// were raised, otherwise returns null.
already_AddRefed<Promise>
DispatchExtendableEventOnWorkerScope(JSContext* aCx,
WorkerGlobalScope* aWorkerScope,
ExtendableEvent* aEvent)
{
MOZ_ASSERT(aWorkerScope);
MOZ_ASSERT(aEvent);
nsCOMPtr<nsIGlobalObject> sgo = aWorkerScope;
WidgetEvent* internalEvent = aEvent->GetInternalNSEvent();
ErrorResult result;
result = aWorkerScope->DispatchDOMEvent(nullptr, aEvent, nullptr, nullptr);
if (result.Failed() || internalEvent->mFlags.mExceptionHasBeenRisen) {
return nullptr;
}
nsRefPtr<Promise> waitUntilPromise = aEvent->GetPromise();
if (!waitUntilPromise) {
ErrorResult result;
waitUntilPromise =
Promise::Resolve(sgo, aCx, JS::UndefinedHandleValue, result);
if (NS_WARN_IF(result.Failed())) {
return nullptr;
}
}
MOZ_ASSERT(waitUntilPromise);
return waitUntilPromise.forget();
}
}; // anonymous namespace
/*
* Used to handle ExtendableEvent::waitUntil() and proceed with
* installation/activation.
@ -1674,23 +1742,12 @@ LifecycleEventWorkerRunnable::DispatchLifecycleEvent(JSContext* aCx, WorkerPriva
event->SetTrusted(true);
nsRefPtr<Promise> waitUntilPromise;
ErrorResult result;
result = target->DispatchDOMEvent(nullptr, event, nullptr, nullptr);
nsCOMPtr<nsIGlobalObject> sgo = aWorkerPrivate->GlobalScope();
WidgetEvent* internalEvent = event->GetInternalNSEvent();
if (!result.Failed() && !internalEvent->mFlags.mExceptionHasBeenRisen) {
waitUntilPromise = event->GetPromise();
if (!waitUntilPromise) {
ErrorResult result;
waitUntilPromise =
Promise::Resolve(sgo, aCx, JS::UndefinedHandleValue, result);
if (NS_WARN_IF(result.Failed())) {
return true;
}
}
nsRefPtr<Promise> waitUntilPromise =
DispatchExtendableEventOnWorkerScope(aCx, aWorkerPrivate->GlobalScope(), event);
if (waitUntilPromise) {
nsRefPtr<LifecycleEventPromiseHandler> handler =
new LifecycleEventPromiseHandler(mTask, mServiceWorker, false /* activateImmediately */);
waitUntilPromise->AppendNativeHandler(handler);
} else {
// Continue with a canceled install.
// Although the spec has different routines to deal with popping stuff
@ -1699,12 +1756,8 @@ LifecycleEventWorkerRunnable::DispatchLifecycleEvent(JSContext* aCx, WorkerPriva
nsRefPtr<ContinueLifecycleRunnable> r =
new ContinueLifecycleRunnable(mTask, false /* success */, false /* activate immediately */);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(r)));
return true;
}
nsRefPtr<LifecycleEventPromiseHandler> handler =
new LifecycleEventPromiseHandler(mTask, mServiceWorker, false /* activateImmediately */);
waitUntilPromise->AppendNativeHandler(handler);
return true;
}
@ -2091,8 +2144,13 @@ public:
event->SetTrusted(true);
event->PostInit(mServiceWorker);
nsRefPtr<EventTarget> target = do_QueryObject(aWorkerPrivate->GlobalScope());
target->DispatchDOMEvent(nullptr, event, nullptr, nullptr);
nsRefPtr<Promise> waitUntilPromise =
DispatchExtendableEventOnWorkerScope(aCx, aWorkerPrivate->GlobalScope(), event);
if (waitUntilPromise) {
nsRefPtr<KeepAliveHandler> handler = new KeepAliveHandler(mServiceWorker);
waitUntilPromise->AppendNativeHandler(handler);
}
return true;
}
};