diff --git a/dom/push/test/test_unregister.html b/dom/push/test/test_unregister.html index 6ce0b18cb2f6..c528f32e92ea 100644 --- a/dom/push/test/test_unregister.html +++ b/dom/push/test/test_unregister.html @@ -10,6 +10,7 @@ http://creativecommons.org/licenses/publicdomain/ Test for Bug 1170817 + @@ -24,65 +25,54 @@ http://creativecommons.org/licenses/publicdomain/ diff --git a/dom/workers/ServiceWorkerUnregisterJob.cpp b/dom/workers/ServiceWorkerUnregisterJob.cpp index 839e4250ca38..98b47d7dac0e 100644 --- a/dom/workers/ServiceWorkerUnregisterJob.cpp +++ b/dom/workers/ServiceWorkerUnregisterJob.cpp @@ -6,10 +6,44 @@ #include "ServiceWorkerUnregisterJob.h" +#include "nsIPushService.h" + namespace mozilla { namespace dom { namespace workers { +class ServiceWorkerUnregisterJob::PushUnsubscribeCallback final : + public nsIUnsubscribeResultCallback +{ +public: + NS_DECL_ISUPPORTS + + explicit PushUnsubscribeCallback(ServiceWorkerUnregisterJob* aJob) + : mJob(aJob) + { + AssertIsOnMainThread(); + } + + NS_IMETHODIMP + OnUnsubscribe(nsresult aStatus, bool) override + { + // Warn if unsubscribing fails, but don't prevent the worker from + // unregistering. + Unused << NS_WARN_IF(NS_FAILED(aStatus)); + mJob->Unregister(); + return NS_OK; + } + +private: + ~PushUnsubscribeCallback() + { + } + + RefPtr mJob; +}; + +NS_IMPL_ISUPPORTS(ServiceWorkerUnregisterJob::PushUnsubscribeCallback, + nsIUnsubscribeResultCallback) ServiceWorkerUnregisterJob::ServiceWorkerUnregisterJob(nsIPrincipal* aPrincipal, const nsACString& aScope, @@ -41,6 +75,35 @@ ServiceWorkerUnregisterJob::AsyncExecute() return; } + // Push API, section 5: "When a service worker registration is unregistered, + // any associated push subscription must be deactivated." To ensure the + // service worker registration isn't cleared as we're unregistering, we + // unsubscribe first. + nsCOMPtr pushService = + do_GetService("@mozilla.org/push/Service;1"); + if (NS_WARN_IF(!pushService)) { + Unregister(); + return; + } + nsCOMPtr unsubscribeCallback = + new PushUnsubscribeCallback(this); + nsresult rv = pushService->Unsubscribe(NS_ConvertUTF8toUTF16(mScope), + mPrincipal, unsubscribeCallback); + if (NS_WARN_IF(NS_FAILED(rv))) { + Unregister(); + } +} + +void +ServiceWorkerUnregisterJob::Unregister() +{ + AssertIsOnMainThread(); + + if (Canceled()) { + Finish(NS_ERROR_DOM_ABORT_ERR); + return; + } + // Step 1 of the Unregister algorithm requires checking that the // client origin matches the scope's origin. We perform this in // registration->update() method directly since we don't have that diff --git a/dom/workers/ServiceWorkerUnregisterJob.h b/dom/workers/ServiceWorkerUnregisterJob.h index 04a675c1195e..976f15a2cc64 100644 --- a/dom/workers/ServiceWorkerUnregisterJob.h +++ b/dom/workers/ServiceWorkerUnregisterJob.h @@ -24,11 +24,16 @@ public: GetResult() const; private: + class PushUnsubscribeCallback; + virtual ~ServiceWorkerUnregisterJob(); virtual void AsyncExecute() override; + void + Unregister(); + bool mResult; bool mSendToParent; };