Cast: Skip receiver log messages with time delta that can't be encoded.
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_register_job.cc
blobd706968780570336023cf3aeae48d8c1bfb551fa
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_register_job.h"
7 #include <vector>
9 #include "base/message_loop/message_loop.h"
10 #include "content/browser/service_worker/service_worker_job_coordinator.h"
11 #include "content/browser/service_worker/service_worker_registration.h"
12 #include "url/gurl.h"
14 namespace content {
16 static void RunSoon(const base::Closure& closure) {
17 base::MessageLoop::current()->PostTask(FROM_HERE, closure);
20 ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
21 ServiceWorkerStorage* storage,
22 EmbeddedWorkerRegistry* worker_registry,
23 ServiceWorkerJobCoordinator* coordinator,
24 const GURL& pattern,
25 const GURL& script_url,
26 RegistrationType type)
27 : storage_(storage),
28 worker_registry_(worker_registry),
29 coordinator_(coordinator),
30 pattern_(pattern),
31 script_url_(script_url),
32 type_(type),
33 weak_factory_(this) {}
35 ServiceWorkerRegisterJob::~ServiceWorkerRegisterJob() {}
37 void ServiceWorkerRegisterJob::AddCallback(const RegistrationCallback& callback,
38 int process_id) {
39 // if we've created a pending version, associate source_provider it with
40 // that, otherwise queue it up
41 callbacks_.push_back(callback);
42 DCHECK(process_id != -1);
43 if (pending_version_) {
44 pending_version_->AddProcessToWorker(process_id);
45 } else {
46 pending_process_ids_.push_back(process_id);
50 void ServiceWorkerRegisterJob::Start() {
51 if (type_ == REGISTER)
52 StartRegister();
53 else
54 StartUnregister();
57 bool ServiceWorkerRegisterJob::Equals(ServiceWorkerRegisterJob* job) {
58 return job->type_ == type_ &&
59 (type_ == ServiceWorkerRegisterJob::UNREGISTER ||
60 job->script_url_ == script_url_);
63 void ServiceWorkerRegisterJob::StartRegister() {
64 // Set up a chain of callbacks, in reverse order. Each of these
65 // callbacks may be called asynchronously by the previous callback.
66 StatusCallback finish_registration(base::Bind(
67 &ServiceWorkerRegisterJob::Complete, weak_factory_.GetWeakPtr()));
69 StatusCallback start_worker(
70 base::Bind(&ServiceWorkerRegisterJob::StartWorkerAndContinue,
71 weak_factory_.GetWeakPtr(),
72 finish_registration));
74 StatusCallback register_new(
75 base::Bind(&ServiceWorkerRegisterJob::RegisterPatternAndContinue,
76 weak_factory_.GetWeakPtr(),
77 start_worker));
79 ServiceWorkerStorage::FindRegistrationCallback unregister_old(
80 base::Bind(&ServiceWorkerRegisterJob::UnregisterPatternAndContinue,
81 weak_factory_.GetWeakPtr(),
82 register_new));
84 storage_->FindRegistrationForPattern(pattern_, unregister_old);
87 void ServiceWorkerRegisterJob::StartUnregister() {
88 // Set up a chain of callbacks, in reverse order. Each of these
89 // callbacks may be called asynchronously by the previous callback.
90 StatusCallback finish_unregistration(
91 base::Bind(&ServiceWorkerRegisterJob::Complete,
92 weak_factory_.GetWeakPtr()));
94 ServiceWorkerStorage::FindRegistrationCallback unregister(
95 base::Bind(&ServiceWorkerRegisterJob::UnregisterPatternAndContinue,
96 weak_factory_.GetWeakPtr(),
97 finish_unregistration));
99 storage_->FindRegistrationForPattern(pattern_, unregister);
102 void ServiceWorkerRegisterJob::StartWorkerAndContinue(
103 const StatusCallback& callback,
104 ServiceWorkerStatusCode status) {
105 DCHECK(registration_);
106 if (registration_->active_version()) {
107 // We have an active version, so we can complete immediately, even
108 // if the service worker isn't running.
109 callback.Run(SERVICE_WORKER_OK);
110 return;
113 pending_version_ = new ServiceWorkerVersion(
114 registration_, worker_registry_, registration_->next_version_id());
115 for (std::vector<int>::const_iterator it = pending_process_ids_.begin();
116 it != pending_process_ids_.end();
117 ++it)
118 pending_version_->AddProcessToWorker(*it);
120 // The callback to watch "installation" actually fires as soon as
121 // the worker is up and running, just before the install event is
122 // dispatched. The job will continue to run even though the main
123 // callback has executed.
124 pending_version_->StartWorker(callback);
126 // TODO(alecflett): Don't set the active version until just before
127 // the activate event is dispatched.
128 registration_->set_active_version(pending_version_);
131 void ServiceWorkerRegisterJob::RegisterPatternAndContinue(
132 const StatusCallback& callback,
133 ServiceWorkerStatusCode previous_status) {
134 if (previous_status == SERVICE_WORKER_ERROR_EXISTS) {
135 // Registration already exists, call to the next step.
136 RunSoon(base::Bind(callback, SERVICE_WORKER_OK));
137 return;
140 if (previous_status != SERVICE_WORKER_OK) {
141 // Failure case.
142 registration_ = NULL;
143 Complete(previous_status);
144 return;
147 DCHECK(!registration_);
148 registration_ = new ServiceWorkerRegistration(pattern_, script_url_,
149 storage_->NewRegistrationId());
150 storage_->StoreRegistration(registration_.get(), callback);
153 void ServiceWorkerRegisterJob::UnregisterPatternAndContinue(
154 const StatusCallback& callback,
155 ServiceWorkerStatusCode previous_status,
156 const scoped_refptr<ServiceWorkerRegistration>& previous_registration) {
157 if (previous_status == SERVICE_WORKER_OK &&
158 (type_ == UNREGISTER ||
159 previous_registration->script_url() != script_url_)) {
160 // It's unregister, or we have conflicting registration.
161 // Unregister it and continue to the next step.
162 previous_registration->Shutdown();
163 storage_->DeleteRegistration(pattern_, callback);
164 return;
167 if (previous_status == SERVICE_WORKER_ERROR_NOT_FOUND) {
168 // The previous registration does not exist, which is ok.
169 RunSoon(base::Bind(callback, SERVICE_WORKER_OK));
170 return;
173 if (previous_status == SERVICE_WORKER_OK) {
174 // We have an existing registration.
175 registration_ = previous_registration;
176 RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_EXISTS));
177 return;
180 RunSoon(base::Bind(callback, previous_status));
183 void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status) {
184 for (std::vector<RegistrationCallback>::iterator it = callbacks_.begin();
185 it != callbacks_.end();
186 ++it) {
187 it->Run(status, registration_);
189 coordinator_->FinishJob(pattern_, this);
192 } // namespace content