Bug 1853814 [wpt PR 42017] - LoAF: Expose script URL for promise resolvers, a=testonly
[gecko.git] / dom / serviceworkers / ServiceWorkerUnregisterJob.cpp
blob5cf61e2a93c24688166d9c59e4b2d5e0df45eb33
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/. */
7 #include "ServiceWorkerUnregisterJob.h"
9 #include "mozilla/Unused.h"
10 #include "nsIPushService.h"
11 #include "nsServiceManagerUtils.h"
12 #include "nsThreadUtils.h"
13 #include "ServiceWorkerManager.h"
15 namespace mozilla::dom {
17 class ServiceWorkerUnregisterJob::PushUnsubscribeCallback final
18 : public nsIUnsubscribeResultCallback {
19 public:
20 NS_DECL_ISUPPORTS
22 explicit PushUnsubscribeCallback(ServiceWorkerUnregisterJob* aJob)
23 : mJob(aJob) {
24 MOZ_ASSERT(NS_IsMainThread());
27 NS_IMETHOD
28 OnUnsubscribe(nsresult aStatus, bool) override {
29 // Warn if unsubscribing fails, but don't prevent the worker from
30 // unregistering.
31 Unused << NS_WARN_IF(NS_FAILED(aStatus));
32 mJob->Unregister();
33 return NS_OK;
36 private:
37 ~PushUnsubscribeCallback() = default;
39 RefPtr<ServiceWorkerUnregisterJob> mJob;
42 NS_IMPL_ISUPPORTS(ServiceWorkerUnregisterJob::PushUnsubscribeCallback,
43 nsIUnsubscribeResultCallback)
45 ServiceWorkerUnregisterJob::ServiceWorkerUnregisterJob(nsIPrincipal* aPrincipal,
46 const nsACString& aScope)
47 : ServiceWorkerJob(Type::Unregister, aPrincipal, aScope, ""_ns),
48 mResult(false) {}
50 bool ServiceWorkerUnregisterJob::GetResult() const {
51 MOZ_ASSERT(NS_IsMainThread());
52 return mResult;
55 ServiceWorkerUnregisterJob::~ServiceWorkerUnregisterJob() = default;
57 void ServiceWorkerUnregisterJob::AsyncExecute() {
58 MOZ_ASSERT(NS_IsMainThread());
60 if (Canceled()) {
61 Finish(NS_ERROR_DOM_ABORT_ERR);
62 return;
65 // Push API, section 5: "When a service worker registration is unregistered,
66 // any associated push subscription must be deactivated." To ensure the
67 // service worker registration isn't cleared as we're unregistering, we
68 // unsubscribe first.
69 nsCOMPtr<nsIPushService> pushService =
70 do_GetService("@mozilla.org/push/Service;1");
71 if (NS_WARN_IF(!pushService)) {
72 Unregister();
73 return;
75 nsCOMPtr<nsIUnsubscribeResultCallback> unsubscribeCallback =
76 new PushUnsubscribeCallback(this);
77 nsresult rv = pushService->Unsubscribe(NS_ConvertUTF8toUTF16(mScope),
78 mPrincipal, unsubscribeCallback);
79 if (NS_WARN_IF(NS_FAILED(rv))) {
80 Unregister();
84 void ServiceWorkerUnregisterJob::Unregister() {
85 MOZ_ASSERT(NS_IsMainThread());
87 RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
88 if (Canceled() || !swm) {
89 Finish(NS_ERROR_DOM_ABORT_ERR);
90 return;
93 // Step 1 of the Unregister algorithm requires checking that the
94 // client origin matches the scope's origin. We perform this in
95 // registration->update() method directly since we don't have that
96 // client information available here.
98 // "Let registration be the result of running [[Get Registration]]
99 // algorithm passing scope as the argument."
100 RefPtr<ServiceWorkerRegistrationInfo> registration =
101 swm->GetRegistration(mPrincipal, mScope);
102 if (!registration) {
103 // "If registration is null, then, resolve promise with false."
104 Finish(NS_OK);
105 return;
108 // Note, we send the message to remove the registration from disk now. This is
109 // necessary to ensure the registration is removed if the controlled
110 // clients are closed by shutting down the browser.
111 swm->MaybeSendUnregister(mPrincipal, mScope);
113 swm->EvictFromBFCache(registration);
115 // "Remove scope to registration map[job's scope url]."
116 swm->RemoveRegistration(registration);
117 MOZ_ASSERT(registration->IsUnregistered());
119 // "Resolve promise with true"
120 mResult = true;
121 InvokeResultCallbacks(NS_OK);
123 // "Invoke Try Clear Registration with registration"
124 if (!registration->IsControllingClients()) {
125 if (registration->IsIdle()) {
126 registration->Clear();
127 } else {
128 registration->ClearWhenIdle();
132 Finish(NS_OK);
135 } // namespace mozilla::dom