Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_registration.cc
blobd2b58339912e744b17a2b40f6d240395a3670311
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/service_worker/service_worker_registration.h"
7 #include "content/browser/service_worker/service_worker_context_core.h"
8 #include "content/browser/service_worker/service_worker_info.h"
9 #include "content/browser/service_worker/service_worker_register_job.h"
10 #include "content/browser/service_worker/service_worker_utils.h"
11 #include "content/public/browser/browser_thread.h"
13 namespace content {
15 namespace {
17 ServiceWorkerVersionInfo GetVersionInfo(ServiceWorkerVersion* version) {
18 if (!version)
19 return ServiceWorkerVersionInfo();
20 return version->GetInfo();
23 } // namespace
25 ServiceWorkerRegistration::ServiceWorkerRegistration(
26 const GURL& pattern,
27 int64 registration_id,
28 base::WeakPtr<ServiceWorkerContextCore> context)
29 : pattern_(pattern),
30 registration_id_(registration_id),
31 is_deleted_(false),
32 is_uninstalling_(false),
33 is_uninstalled_(false),
34 should_activate_when_ready_(false),
35 resources_total_size_bytes_(0),
36 context_(context) {
37 DCHECK_CURRENTLY_ON(BrowserThread::IO);
38 DCHECK(context_);
39 context_->AddLiveRegistration(this);
42 ServiceWorkerRegistration::~ServiceWorkerRegistration() {
43 DCHECK_CURRENTLY_ON(BrowserThread::IO);
44 DCHECK(!listeners_.might_have_observers());
45 if (context_)
46 context_->RemoveLiveRegistration(registration_id_);
47 if (active_version())
48 active_version()->RemoveListener(this);
51 ServiceWorkerVersion* ServiceWorkerRegistration::GetNewestVersion() const {
52 if (installing_version())
53 return installing_version();
54 if (waiting_version())
55 return waiting_version();
56 return active_version();
59 void ServiceWorkerRegistration::AddListener(Listener* listener) {
60 listeners_.AddObserver(listener);
63 void ServiceWorkerRegistration::RemoveListener(Listener* listener) {
64 listeners_.RemoveObserver(listener);
67 void ServiceWorkerRegistration::NotifyRegistrationFailed() {
68 FOR_EACH_OBSERVER(Listener, listeners_, OnRegistrationFailed(this));
71 void ServiceWorkerRegistration::NotifyUpdateFound() {
72 FOR_EACH_OBSERVER(Listener, listeners_, OnUpdateFound(this));
75 ServiceWorkerRegistrationInfo ServiceWorkerRegistration::GetInfo() {
76 DCHECK_CURRENTLY_ON(BrowserThread::IO);
77 return ServiceWorkerRegistrationInfo(
78 pattern(), registration_id_,
79 is_deleted_ ? ServiceWorkerRegistrationInfo::IS_DELETED
80 : ServiceWorkerRegistrationInfo::IS_NOT_DELETED,
81 GetVersionInfo(active_version_.get()),
82 GetVersionInfo(waiting_version_.get()),
83 GetVersionInfo(installing_version_.get()), resources_total_size_bytes_);
86 void ServiceWorkerRegistration::SetActiveVersion(
87 ServiceWorkerVersion* version) {
88 should_activate_when_ready_ = false;
89 SetVersionInternal(version, &active_version_,
90 ChangedVersionAttributesMask::ACTIVE_VERSION);
93 void ServiceWorkerRegistration::SetWaitingVersion(
94 ServiceWorkerVersion* version) {
95 should_activate_when_ready_ = false;
96 SetVersionInternal(version, &waiting_version_,
97 ChangedVersionAttributesMask::WAITING_VERSION);
100 void ServiceWorkerRegistration::SetInstallingVersion(
101 ServiceWorkerVersion* version) {
102 SetVersionInternal(version, &installing_version_,
103 ChangedVersionAttributesMask::INSTALLING_VERSION);
106 void ServiceWorkerRegistration::UnsetVersion(ServiceWorkerVersion* version) {
107 if (!version)
108 return;
109 ChangedVersionAttributesMask mask;
110 UnsetVersionInternal(version, &mask);
111 if (mask.changed()) {
112 ServiceWorkerRegistrationInfo info = GetInfo();
113 FOR_EACH_OBSERVER(Listener, listeners_,
114 OnVersionAttributesChanged(this, mask, info));
118 void ServiceWorkerRegistration::SetVersionInternal(
119 ServiceWorkerVersion* version,
120 scoped_refptr<ServiceWorkerVersion>* data_member,
121 int change_flag) {
122 if (version == data_member->get())
123 return;
124 scoped_refptr<ServiceWorkerVersion> protect(version);
125 ChangedVersionAttributesMask mask;
126 if (version)
127 UnsetVersionInternal(version, &mask);
128 if (*data_member && *data_member == active_version_)
129 active_version_->RemoveListener(this);
130 *data_member = version;
131 if (active_version_.get() && active_version_.get() == version)
132 active_version_->AddListener(this);
133 mask.add(change_flag);
134 ServiceWorkerRegistrationInfo info = GetInfo();
135 FOR_EACH_OBSERVER(Listener, listeners_,
136 OnVersionAttributesChanged(this, mask, info));
139 void ServiceWorkerRegistration::UnsetVersionInternal(
140 ServiceWorkerVersion* version,
141 ChangedVersionAttributesMask* mask) {
142 DCHECK(version);
143 if (installing_version_.get() == version) {
144 installing_version_ = NULL;
145 mask->add(ChangedVersionAttributesMask::INSTALLING_VERSION);
146 } else if (waiting_version_.get() == version) {
147 waiting_version_ = NULL;
148 mask->add(ChangedVersionAttributesMask::WAITING_VERSION);
149 } else if (active_version_.get() == version) {
150 active_version_->RemoveListener(this);
151 active_version_ = NULL;
152 mask->add(ChangedVersionAttributesMask::ACTIVE_VERSION);
156 void ServiceWorkerRegistration::ActivateWaitingVersionWhenReady() {
157 DCHECK(waiting_version());
158 should_activate_when_ready_ = true;
160 if (!active_version() || !active_version()->HasControllee() ||
161 waiting_version()->skip_waiting())
162 ActivateWaitingVersion();
165 void ServiceWorkerRegistration::ClaimClients() {
166 DCHECK(context_);
167 DCHECK(active_version());
169 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it =
170 context_->GetProviderHostIterator();
171 !it->IsAtEnd(); it->Advance()) {
172 ServiceWorkerProviderHost* host = it->GetProviderHost();
173 if (host->IsHostToRunningServiceWorker())
174 continue;
175 if (host->controlling_version() == active_version())
176 continue;
177 if (host->MatchRegistration() == this)
178 host->ClaimedByRegistration(this);
182 void ServiceWorkerRegistration::ClearWhenReady() {
183 DCHECK(context_);
184 if (is_uninstalling_)
185 return;
186 is_uninstalling_ = true;
188 context_->storage()->NotifyUninstallingRegistration(this);
189 context_->storage()->DeleteRegistration(
190 id(),
191 pattern().GetOrigin(),
192 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
194 if (!active_version() || !active_version()->HasControllee())
195 Clear();
198 void ServiceWorkerRegistration::AbortPendingClear(
199 const StatusCallback& callback) {
200 DCHECK(context_);
201 if (!is_uninstalling()) {
202 callback.Run(SERVICE_WORKER_OK);
203 return;
205 is_uninstalling_ = false;
206 context_->storage()->NotifyDoneUninstallingRegistration(this);
208 scoped_refptr<ServiceWorkerVersion> most_recent_version =
209 waiting_version() ? waiting_version() : active_version();
210 DCHECK(most_recent_version.get());
211 context_->storage()->NotifyInstallingRegistration(this);
212 context_->storage()->StoreRegistration(
213 this,
214 most_recent_version.get(),
215 base::Bind(&ServiceWorkerRegistration::OnRestoreFinished,
216 this,
217 callback,
218 most_recent_version));
221 void ServiceWorkerRegistration::GetUserData(
222 const std::string& key,
223 const GetUserDataCallback& callback) {
224 DCHECK(context_);
225 context_->storage()->GetUserData(registration_id_, key, callback);
228 void ServiceWorkerRegistration::StoreUserData(
229 const std::string& key,
230 const std::string& data,
231 const StatusCallback& callback) {
232 DCHECK(context_);
233 context_->storage()->StoreUserData(
234 registration_id_, pattern().GetOrigin(), key, data, callback);
237 void ServiceWorkerRegistration::ClearUserData(
238 const std::string& key,
239 const StatusCallback& callback) {
240 DCHECK(context_);
241 context_->storage()->ClearUserData(registration_id_, key, callback);
244 void ServiceWorkerRegistration::OnNoControllees(ServiceWorkerVersion* version) {
245 DCHECK_EQ(active_version(), version);
246 if (is_uninstalling_)
247 Clear();
248 else if (should_activate_when_ready_)
249 ActivateWaitingVersion();
250 is_uninstalling_ = false;
251 should_activate_when_ready_ = false;
254 void ServiceWorkerRegistration::ActivateWaitingVersion() {
255 DCHECK(context_);
256 DCHECK(waiting_version());
257 DCHECK(should_activate_when_ready_);
258 should_activate_when_ready_ = false;
259 scoped_refptr<ServiceWorkerVersion> activating_version = waiting_version();
260 scoped_refptr<ServiceWorkerVersion> exiting_version = active_version();
262 if (activating_version->is_redundant())
263 return; // Activation is no longer relevant.
265 // "5. If exitingWorker is not null,
266 if (exiting_version.get()) {
267 // TODO(michaeln): should wait for events to be complete
268 // "1. Wait for exitingWorker to finish handling any in-progress requests."
269 // "2. Terminate exitingWorker."
270 exiting_version->StopWorker(
271 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
272 // "3. Run the [[UpdateState]] algorithm passing exitingWorker and
273 // "redundant" as the arguments."
274 exiting_version->SetStatus(ServiceWorkerVersion::REDUNDANT);
277 // "6. Set serviceWorkerRegistration.activeWorker to activatingWorker."
278 // "7. Set serviceWorkerRegistration.waitingWorker to null."
279 SetActiveVersion(activating_version.get());
281 // "8. Run the [[UpdateState]] algorithm passing registration.activeWorker and
282 // "activating" as arguments."
283 activating_version->SetStatus(ServiceWorkerVersion::ACTIVATING);
284 // "9. Fire a simple event named controllerchange..."
285 if (activating_version->skip_waiting())
286 FOR_EACH_OBSERVER(Listener, listeners_, OnSkippedWaiting(this));
288 // "10. Queue a task to fire an event named activate..."
289 activating_version->DispatchActivateEvent(
290 base::Bind(&ServiceWorkerRegistration::OnActivateEventFinished,
291 this, activating_version));
294 void ServiceWorkerRegistration::OnActivateEventFinished(
295 ServiceWorkerVersion* activating_version,
296 ServiceWorkerStatusCode status) {
297 if (!context_ || activating_version != active_version())
298 return;
299 // "If activateFailed is true, then:..."
300 if (status != SERVICE_WORKER_OK) {
301 // "Set registration's active worker to null." (The spec's step order may
302 // differ. It's OK because the other steps queue a task.)
303 UnsetVersion(activating_version);
305 // "Run the Update State algorithm passing registration's active worker and
306 // 'redundant' as the arguments."
307 activating_version->SetStatus(ServiceWorkerVersion::REDUNDANT);
309 // "For each service worker client client whose active worker is
310 // registration's active worker..." set the active worker to null.
311 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it =
312 context_->GetProviderHostIterator();
313 !it->IsAtEnd(); it->Advance()) {
314 ServiceWorkerProviderHost* host = it->GetProviderHost();
315 if (host->controlling_version() == activating_version)
316 host->NotifyControllerActivationFailed();
319 activating_version->Doom();
320 if (!waiting_version()) {
321 // Delete the records from the db.
322 context_->storage()->DeleteRegistration(
323 id(), pattern().GetOrigin(),
324 base::Bind(&ServiceWorkerRegistration::OnDeleteFinished, this));
325 // But not from memory if there is a version in the pipeline.
326 if (installing_version()) {
327 is_deleted_ = false;
328 } else {
329 is_uninstalled_ = true;
330 FOR_EACH_OBSERVER(Listener, listeners_, OnRegistrationFailed(this));
333 return;
336 // "Run the Update State algorithm passing registration's active worker and
337 // 'activated' as the arguments."
338 activating_version->SetStatus(ServiceWorkerVersion::ACTIVATED);
339 if (context_) {
340 context_->storage()->UpdateToActiveState(
341 this,
342 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
346 void ServiceWorkerRegistration::OnDeleteFinished(
347 ServiceWorkerStatusCode status) {
348 // Intentionally empty completion callback, used to prevent
349 // |this| from being deleted until the storage method completes.
352 void ServiceWorkerRegistration::Clear() {
353 is_uninstalling_ = false;
354 is_uninstalled_ = true;
355 if (context_)
356 context_->storage()->NotifyDoneUninstallingRegistration(this);
358 ChangedVersionAttributesMask mask;
359 if (installing_version_.get()) {
360 installing_version_->Doom();
361 installing_version_ = NULL;
362 mask.add(ChangedVersionAttributesMask::INSTALLING_VERSION);
364 if (waiting_version_.get()) {
365 waiting_version_->Doom();
366 waiting_version_ = NULL;
367 mask.add(ChangedVersionAttributesMask::WAITING_VERSION);
369 if (active_version_.get()) {
370 active_version_->Doom();
371 active_version_->RemoveListener(this);
372 active_version_ = NULL;
373 mask.add(ChangedVersionAttributesMask::ACTIVE_VERSION);
375 if (mask.changed()) {
376 ServiceWorkerRegistrationInfo info = GetInfo();
377 FOR_EACH_OBSERVER(Listener, listeners_,
378 OnVersionAttributesChanged(this, mask, info));
381 FOR_EACH_OBSERVER(
382 Listener, listeners_, OnRegistrationFinishedUninstalling(this));
385 void ServiceWorkerRegistration::OnRestoreFinished(
386 const StatusCallback& callback,
387 scoped_refptr<ServiceWorkerVersion> version,
388 ServiceWorkerStatusCode status) {
389 if (!context_) {
390 callback.Run(SERVICE_WORKER_ERROR_ABORT);
391 return;
393 context_->storage()->NotifyDoneInstallingRegistration(
394 this, version.get(), status);
395 callback.Run(status);
398 } // namespace content