1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "ServiceWorkerUnregisterJob.h"
8
9 #include "nsIPushService.h"
10
11 namespace mozilla {
12 namespace dom {
13
14 class ServiceWorkerUnregisterJob::PushUnsubscribeCallback final
15 : public nsIUnsubscribeResultCallback {
16 public:
17 NS_DECL_ISUPPORTS
18
PushUnsubscribeCallback(ServiceWorkerUnregisterJob * aJob)19 explicit PushUnsubscribeCallback(ServiceWorkerUnregisterJob* aJob)
20 : mJob(aJob) {
21 MOZ_ASSERT(NS_IsMainThread());
22 }
23
24 NS_IMETHOD
OnUnsubscribe(nsresult aStatus,bool)25 OnUnsubscribe(nsresult aStatus, bool) override {
26 // Warn if unsubscribing fails, but don't prevent the worker from
27 // unregistering.
28 Unused << NS_WARN_IF(NS_FAILED(aStatus));
29 mJob->Unregister();
30 return NS_OK;
31 }
32
33 private:
~PushUnsubscribeCallback()34 ~PushUnsubscribeCallback() {}
35
36 RefPtr<ServiceWorkerUnregisterJob> mJob;
37 };
38
NS_IMPL_ISUPPORTS(ServiceWorkerUnregisterJob::PushUnsubscribeCallback,nsIUnsubscribeResultCallback)39 NS_IMPL_ISUPPORTS(ServiceWorkerUnregisterJob::PushUnsubscribeCallback,
40 nsIUnsubscribeResultCallback)
41
42 ServiceWorkerUnregisterJob::ServiceWorkerUnregisterJob(nsIPrincipal* aPrincipal,
43 const nsACString& aScope,
44 bool aSendToParent)
45 : ServiceWorkerJob(Type::Unregister, aPrincipal, aScope, EmptyCString()),
46 mResult(false),
47 mSendToParent(aSendToParent) {}
48
GetResult() const49 bool ServiceWorkerUnregisterJob::GetResult() const {
50 MOZ_ASSERT(NS_IsMainThread());
51 return mResult;
52 }
53
~ServiceWorkerUnregisterJob()54 ServiceWorkerUnregisterJob::~ServiceWorkerUnregisterJob() {}
55
AsyncExecute()56 void ServiceWorkerUnregisterJob::AsyncExecute() {
57 MOZ_ASSERT(NS_IsMainThread());
58
59 if (Canceled()) {
60 Finish(NS_ERROR_DOM_ABORT_ERR);
61 return;
62 }
63
64 // Push API, section 5: "When a service worker registration is unregistered,
65 // any associated push subscription must be deactivated." To ensure the
66 // service worker registration isn't cleared as we're unregistering, we
67 // unsubscribe first.
68 nsCOMPtr<nsIPushService> pushService =
69 do_GetService("@mozilla.org/push/Service;1");
70 if (NS_WARN_IF(!pushService)) {
71 Unregister();
72 return;
73 }
74 nsCOMPtr<nsIUnsubscribeResultCallback> unsubscribeCallback =
75 new PushUnsubscribeCallback(this);
76 nsresult rv = pushService->Unsubscribe(NS_ConvertUTF8toUTF16(mScope),
77 mPrincipal, unsubscribeCallback);
78 if (NS_WARN_IF(NS_FAILED(rv))) {
79 Unregister();
80 }
81 }
82
Unregister()83 void ServiceWorkerUnregisterJob::Unregister() {
84 MOZ_ASSERT(NS_IsMainThread());
85
86 RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
87 if (Canceled() || !swm) {
88 Finish(NS_ERROR_DOM_ABORT_ERR);
89 return;
90 }
91
92 // Step 1 of the Unregister algorithm requires checking that the
93 // client origin matches the scope's origin. We perform this in
94 // registration->update() method directly since we don't have that
95 // client information available here.
96
97 // "Let registration be the result of running [[Get Registration]]
98 // algorithm passing scope as the argument."
99 RefPtr<ServiceWorkerRegistrationInfo> registration =
100 swm->GetRegistration(mPrincipal, mScope);
101 if (!registration) {
102 // "If registration is null, then, resolve promise with false."
103 Finish(NS_OK);
104 return;
105 }
106
107 // Note, we send the message to remove the registration from disk now even
108 // though we may only set the pending uninstall flag below. This is
109 // necessary to ensure the registration is removed if the controlled
110 // clients are closed by shutting down the browser. If the registration
111 // is resurrected by clearing pending uninstall then it should be saved
112 // to disk again.
113 if (mSendToParent && !registration->IsPendingUninstall()) {
114 swm->MaybeSendUnregister(mPrincipal, mScope);
115 }
116
117 // "Set registration's uninstalling flag."
118 registration->SetPendingUninstall();
119
120 // "Resolve promise with true"
121 mResult = true;
122 InvokeResultCallbacks(NS_OK);
123
124 // "If no service worker client is using registration..."
125 if (!registration->IsControllingClients() && registration->IsIdle()) {
126 // "Invoke [[Clear Registration]]..."
127 swm->RemoveRegistration(registration);
128 }
129
130 Finish(NS_OK);
131 }
132
133 } // namespace dom
134 } // namespace mozilla
135