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 "ServiceWorkerContainerProxy.h"
8 
9 #include "mozilla/dom/ServiceWorkerContainerParent.h"
10 #include "mozilla/dom/ServiceWorkerManager.h"
11 #include "mozilla/ipc/BackgroundParent.h"
12 #include "mozilla/SchedulerGroup.h"
13 #include "mozilla/ScopeExit.h"
14 
15 namespace mozilla {
16 namespace dom {
17 
18 using mozilla::ipc::AssertIsOnBackgroundThread;
19 
~ServiceWorkerContainerProxy()20 ServiceWorkerContainerProxy::~ServiceWorkerContainerProxy() {
21   // Any thread
22   MOZ_DIAGNOSTIC_ASSERT(!mActor);
23 }
24 
ServiceWorkerContainerProxy(ServiceWorkerContainerParent * aActor)25 ServiceWorkerContainerProxy::ServiceWorkerContainerProxy(
26     ServiceWorkerContainerParent* aActor)
27     : mActor(aActor) {
28   AssertIsOnBackgroundThread();
29   MOZ_DIAGNOSTIC_ASSERT(mActor);
30 
31   // The container does not directly listen for updates, so we don't need
32   // to immediately initialize.  The controllerchange event comes via the
33   // ClientSource associated with the ServiceWorkerContainer's bound global.
34 }
35 
RevokeActor(ServiceWorkerContainerParent * aActor)36 void ServiceWorkerContainerProxy::RevokeActor(
37     ServiceWorkerContainerParent* aActor) {
38   AssertIsOnBackgroundThread();
39   MOZ_DIAGNOSTIC_ASSERT(mActor);
40   MOZ_DIAGNOSTIC_ASSERT(mActor == aActor);
41   mActor = nullptr;
42 }
43 
Register(const ClientInfo & aClientInfo,const nsCString & aScopeURL,const nsCString & aScriptURL,ServiceWorkerUpdateViaCache aUpdateViaCache)44 RefPtr<ServiceWorkerRegistrationPromise> ServiceWorkerContainerProxy::Register(
45     const ClientInfo& aClientInfo, const nsCString& aScopeURL,
46     const nsCString& aScriptURL, ServiceWorkerUpdateViaCache aUpdateViaCache) {
47   AssertIsOnBackgroundThread();
48 
49   RefPtr<ServiceWorkerRegistrationPromise::Private> promise =
50       new ServiceWorkerRegistrationPromise::Private(__func__);
51 
52   nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
53       __func__,
54       [aClientInfo, aScopeURL, aScriptURL, aUpdateViaCache, promise]() mutable {
55         auto scopeExit = MakeScopeExit(
56             [&] { promise->Reject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__); });
57 
58         RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
59         NS_ENSURE_TRUE_VOID(swm);
60 
61         swm->Register(aClientInfo, aScopeURL, aScriptURL, aUpdateViaCache)
62             ->ChainTo(promise.forget(), __func__);
63 
64         scopeExit.release();
65       });
66 
67   MOZ_ALWAYS_SUCCEEDS(
68       SchedulerGroup::Dispatch(TaskCategory::Other, r.forget()));
69 
70   return promise;
71 }
72 
73 RefPtr<ServiceWorkerRegistrationPromise>
GetRegistration(const ClientInfo & aClientInfo,const nsCString & aURL)74 ServiceWorkerContainerProxy::GetRegistration(const ClientInfo& aClientInfo,
75                                              const nsCString& aURL) {
76   AssertIsOnBackgroundThread();
77 
78   RefPtr<ServiceWorkerRegistrationPromise::Private> promise =
79       new ServiceWorkerRegistrationPromise::Private(__func__);
80 
81   nsCOMPtr<nsIRunnable> r =
82       NS_NewRunnableFunction(__func__, [aClientInfo, aURL, promise]() mutable {
83         auto scopeExit = MakeScopeExit(
84             [&] { promise->Reject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__); });
85 
86         RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
87         NS_ENSURE_TRUE_VOID(swm);
88 
89         swm->GetRegistration(aClientInfo, aURL)
90             ->ChainTo(promise.forget(), __func__);
91 
92         scopeExit.release();
93       });
94 
95   MOZ_ALWAYS_SUCCEEDS(
96       SchedulerGroup::Dispatch(TaskCategory::Other, r.forget()));
97 
98   return promise;
99 }
100 
101 RefPtr<ServiceWorkerRegistrationListPromise>
GetRegistrations(const ClientInfo & aClientInfo)102 ServiceWorkerContainerProxy::GetRegistrations(const ClientInfo& aClientInfo) {
103   AssertIsOnBackgroundThread();
104 
105   RefPtr<ServiceWorkerRegistrationListPromise::Private> promise =
106       new ServiceWorkerRegistrationListPromise::Private(__func__);
107 
108   nsCOMPtr<nsIRunnable> r =
109       NS_NewRunnableFunction(__func__, [aClientInfo, promise]() mutable {
110         auto scopeExit = MakeScopeExit(
111             [&] { promise->Reject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__); });
112 
113         RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
114         NS_ENSURE_TRUE_VOID(swm);
115 
116         swm->GetRegistrations(aClientInfo)->ChainTo(promise.forget(), __func__);
117 
118         scopeExit.release();
119       });
120 
121   MOZ_ALWAYS_SUCCEEDS(
122       SchedulerGroup::Dispatch(TaskCategory::Other, r.forget()));
123 
124   return promise;
125 }
126 
GetReady(const ClientInfo & aClientInfo)127 RefPtr<ServiceWorkerRegistrationPromise> ServiceWorkerContainerProxy::GetReady(
128     const ClientInfo& aClientInfo) {
129   AssertIsOnBackgroundThread();
130 
131   RefPtr<ServiceWorkerRegistrationPromise::Private> promise =
132       new ServiceWorkerRegistrationPromise::Private(__func__);
133 
134   nsCOMPtr<nsIRunnable> r =
135       NS_NewRunnableFunction(__func__, [aClientInfo, promise]() mutable {
136         auto scopeExit = MakeScopeExit(
137             [&] { promise->Reject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__); });
138 
139         RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
140         NS_ENSURE_TRUE_VOID(swm);
141 
142         swm->WhenReady(aClientInfo)->ChainTo(promise.forget(), __func__);
143 
144         scopeExit.release();
145       });
146 
147   MOZ_ALWAYS_SUCCEEDS(
148       SchedulerGroup::Dispatch(TaskCategory::Other, r.forget()));
149 
150   return promise;
151 }
152 
153 }  // namespace dom
154 }  // namespace mozilla
155