Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/service_worker/service_worker_version.h" | 5 #include "content/browser/service_worker/service_worker_version.h" |
| 6 | 6 |
| 7 #include "base/stl_util.h" | 7 #include "base/stl_util.h" |
| 8 #include "content/browser/service_worker/embedded_worker_instance.h" | 8 #include "content/browser/service_worker/embedded_worker_instance.h" |
| 9 #include "content/browser/service_worker/embedded_worker_registry.h" | 9 #include "content/browser/service_worker/embedded_worker_registry.h" |
| 10 #include "content/browser/service_worker/service_worker_context_core.h" | 10 #include "content/browser/service_worker/service_worker_context_core.h" |
| 11 #include "content/browser/service_worker/service_worker_registration.h" | 11 #include "content/browser/service_worker/service_worker_registration.h" |
| 12 #include "content/common/service_worker/service_worker_messages.h" | 12 #include "content/common/service_worker/service_worker_messages.h" |
| 13 | 13 |
| 14 namespace content { | 14 namespace content { |
| 15 | 15 |
| 16 typedef ServiceWorkerVersion::StatusCallback StatusCallback; | |
| 17 typedef ServiceWorkerVersion::MessageCallback MessageCallback; | |
| 18 | |
| 16 namespace { | 19 namespace { |
| 17 | 20 |
| 18 void RunSoon(const base::Closure& callback) { | 21 void RunSoon(const base::Closure& callback) { |
| 19 base::MessageLoop::current()->PostTask(FROM_HERE, callback); | 22 if (!callback.is_null()) |
| 23 base::MessageLoop::current()->PostTask(FROM_HERE, callback); | |
| 20 } | 24 } |
| 21 | 25 |
| 22 template <typename CallbackArray, typename Arg> | 26 template <typename CallbackArray, typename Arg> |
| 23 void RunCallbacks(const CallbackArray& callbacks, const Arg& arg) { | 27 void RunCallbacks(const CallbackArray& callbacks, const Arg& arg) { |
| 24 for (typename CallbackArray::const_iterator i = callbacks.begin(); | 28 for (typename CallbackArray::const_iterator i = callbacks.begin(); |
| 25 i != callbacks.end(); ++i) | 29 i != callbacks.end(); ++i) |
| 26 (*i).Run(arg); | 30 (*i).Run(arg); |
| 27 } | 31 } |
| 28 | 32 |
| 33 // A callback adapter to start a |task| after StartWorker. | |
| 34 void RunTaskAfterStartWorker( | |
| 35 base::WeakPtr<ServiceWorkerVersion> version, | |
| 36 const StatusCallback& error_callback, | |
| 37 const base::Closure& task, | |
| 38 ServiceWorkerStatusCode status) { | |
| 39 if (status != SERVICE_WORKER_OK) { | |
| 40 if (!error_callback.is_null()) | |
| 41 error_callback.Run(status); | |
| 42 return; | |
| 43 } | |
| 44 if (version->status() != ServiceWorkerVersion::RUNNING) { | |
| 45 // We've tried to start the worker (and it has succeeded), but | |
| 46 // it looks it's not running yet. | |
| 47 NOTREACHED() << "The worker's not running after successful StartWorker"; | |
| 48 if (!error_callback.is_null()) | |
| 49 error_callback.Run(SERVICE_WORKER_ERROR_START_WORKER_FAILED); | |
| 50 return; | |
| 51 } | |
| 52 task.Run(); | |
| 53 } | |
| 54 | |
| 55 void RunEmptyMessageCallback(const MessageCallback& callback, | |
| 56 ServiceWorkerStatusCode status) { | |
| 57 callback.Run(status, IPC::Message()); | |
| 58 } | |
| 59 | |
| 29 } // namespace | 60 } // namespace |
| 30 | 61 |
| 31 ServiceWorkerVersion::ServiceWorkerVersion( | 62 ServiceWorkerVersion::ServiceWorkerVersion( |
| 32 ServiceWorkerRegistration* registration, | 63 ServiceWorkerRegistration* registration, |
| 33 EmbeddedWorkerRegistry* worker_registry, | 64 EmbeddedWorkerRegistry* worker_registry, |
| 34 int64 version_id) | 65 int64 version_id) |
| 35 : version_id_(version_id), | 66 : version_id_(version_id), |
| 36 is_shutdown_(false), | 67 is_shutdown_(false), |
| 37 registration_(registration) { | 68 registration_(registration), |
| 69 weak_factory_(this) { | |
| 38 if (worker_registry) { | 70 if (worker_registry) { |
| 39 embedded_worker_ = worker_registry->CreateWorker(); | 71 embedded_worker_ = worker_registry->CreateWorker(); |
| 40 embedded_worker_->AddObserver(this); | 72 embedded_worker_->AddObserver(this); |
| 41 } | 73 } |
| 42 } | 74 } |
| 43 | 75 |
| 44 ServiceWorkerVersion::~ServiceWorkerVersion() { DCHECK(is_shutdown_); } | 76 ServiceWorkerVersion::~ServiceWorkerVersion() { DCHECK(is_shutdown_); } |
| 45 | 77 |
| 46 void ServiceWorkerVersion::Shutdown() { | 78 void ServiceWorkerVersion::Shutdown() { |
| 47 is_shutdown_ = true; | 79 is_shutdown_ = true; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 86 if (stop_callbacks_.empty()) { | 118 if (stop_callbacks_.empty()) { |
| 87 ServiceWorkerStatusCode status = embedded_worker_->Stop(); | 119 ServiceWorkerStatusCode status = embedded_worker_->Stop(); |
| 88 if (status != SERVICE_WORKER_OK) { | 120 if (status != SERVICE_WORKER_OK) { |
| 89 RunSoon(base::Bind(callback, status)); | 121 RunSoon(base::Bind(callback, status)); |
| 90 return; | 122 return; |
| 91 } | 123 } |
| 92 } | 124 } |
| 93 stop_callbacks_.push_back(callback); | 125 stop_callbacks_.push_back(callback); |
| 94 } | 126 } |
| 95 | 127 |
| 128 void ServiceWorkerVersion::SendMessage( | |
| 129 const IPC::Message& message, const StatusCallback& callback) { | |
| 130 DCHECK(!is_shutdown_); | |
| 131 DCHECK(embedded_worker_); | |
| 132 if (status() != RUNNING) { | |
| 133 // Schedule calling this method after starting the worker. | |
| 134 StartWorker(base::Bind(&RunTaskAfterStartWorker, | |
| 135 weak_factory_.GetWeakPtr(), callback, | |
| 136 base::Bind(&self::SendMessage, | |
| 137 weak_factory_.GetWeakPtr(), | |
| 138 message, callback))); | |
| 139 return; | |
| 140 } | |
| 141 | |
| 142 ServiceWorkerStatusCode status = embedded_worker_->SendMessage(-1, message); | |
| 143 RunSoon(base::Bind(callback, status)); | |
| 144 } | |
| 145 | |
| 146 void ServiceWorkerVersion::SendMessageAndRegisterCallback( | |
| 147 const IPC::Message& message, const MessageCallback& callback) { | |
| 148 DCHECK(!is_shutdown_); | |
| 149 DCHECK(embedded_worker_); | |
| 150 if (status() != RUNNING) { | |
| 151 // Schedule calling this method after starting the worker. | |
| 152 StartWorker(base::Bind(&RunTaskAfterStartWorker, | |
| 153 weak_factory_.GetWeakPtr(), | |
| 154 base::Bind(&RunEmptyMessageCallback, callback), | |
| 155 base::Bind(&self::SendMessageAndRegisterCallback, | |
| 156 weak_factory_.GetWeakPtr(), | |
| 157 message, callback))); | |
| 158 return; | |
| 159 } | |
| 160 | |
| 161 int request_id = message_callbacks_.Add(new MessageCallback(callback)); | |
| 162 ServiceWorkerStatusCode status = | |
| 163 embedded_worker_->SendMessage(request_id, message); | |
| 164 if (status != SERVICE_WORKER_OK) { | |
| 165 message_callbacks_.Remove(request_id); | |
| 166 RunSoon(base::Bind(callback, status, IPC::Message())); | |
| 167 return; | |
| 168 } | |
| 169 } | |
| 170 | |
| 96 bool ServiceWorkerVersion::DispatchFetchEvent( | 171 bool ServiceWorkerVersion::DispatchFetchEvent( |
| 97 const ServiceWorkerFetchRequest& request) { | 172 const ServiceWorkerFetchRequest& request) { |
| 98 if (status() != RUNNING) | 173 if (status() != RUNNING) |
| 99 return false; | 174 return false; |
| 100 return embedded_worker_->SendMessage( | 175 return embedded_worker_->SendMessage( |
| 101 ServiceWorkerMsg_FetchEvent(request)) == SERVICE_WORKER_OK; | 176 -1, ServiceWorkerMsg_FetchEvent(request)) == SERVICE_WORKER_OK; |
|
jsbell
2014/02/04 23:29:03
Sorry for the late drive-by, but -1 is a magic num
| |
| 102 } | 177 } |
| 103 | 178 |
| 104 void ServiceWorkerVersion::AddProcessToWorker(int process_id) { | 179 void ServiceWorkerVersion::AddProcessToWorker(int process_id) { |
| 105 DCHECK(!is_shutdown_); | 180 DCHECK(!is_shutdown_); |
| 106 embedded_worker_->AddProcessReference(process_id); | 181 embedded_worker_->AddProcessReference(process_id); |
| 107 } | 182 } |
| 108 | 183 |
| 109 void ServiceWorkerVersion::RemoveProcessToWorker(int process_id) { | 184 void ServiceWorkerVersion::RemoveProcessToWorker(int process_id) { |
| 110 embedded_worker_->ReleaseProcessReference(process_id); | 185 embedded_worker_->ReleaseProcessReference(process_id); |
| 111 } | 186 } |
| 112 | 187 |
| 113 void ServiceWorkerVersion::OnStarted() { | 188 void ServiceWorkerVersion::OnStarted() { |
| 114 DCHECK_EQ(RUNNING, status()); | 189 DCHECK_EQ(RUNNING, status()); |
| 115 // Fire all start callbacks. | 190 // Fire all start callbacks. |
| 116 RunCallbacks(start_callbacks_, SERVICE_WORKER_OK); | 191 RunCallbacks(start_callbacks_, SERVICE_WORKER_OK); |
| 117 start_callbacks_.clear(); | 192 start_callbacks_.clear(); |
| 118 } | 193 } |
| 119 | 194 |
| 120 void ServiceWorkerVersion::OnStopped() { | 195 void ServiceWorkerVersion::OnStopped() { |
| 121 DCHECK_EQ(STOPPED, status()); | 196 DCHECK_EQ(STOPPED, status()); |
| 122 // Fire all stop callbacks. | 197 // Fire all stop callbacks. |
| 123 RunCallbacks(stop_callbacks_, SERVICE_WORKER_OK); | 198 RunCallbacks(stop_callbacks_, SERVICE_WORKER_OK); |
| 124 stop_callbacks_.clear(); | 199 stop_callbacks_.clear(); |
| 125 | 200 |
| 126 // If there're any callbacks that were waiting start let them know it's | 201 // Let all start callbacks fail. |
| 127 // failed. | |
| 128 RunCallbacks(start_callbacks_, SERVICE_WORKER_ERROR_START_WORKER_FAILED); | 202 RunCallbacks(start_callbacks_, SERVICE_WORKER_ERROR_START_WORKER_FAILED); |
| 129 start_callbacks_.clear(); | 203 start_callbacks_.clear(); |
| 204 | |
| 205 // Let all message callbacks fail. | |
| 206 // TODO(kinuko): Consider if we want to add queue+resend mechanism here. | |
| 207 IDMap<MessageCallback, IDMapOwnPointer>::iterator iter(&message_callbacks_); | |
| 208 while (!iter.IsAtEnd()) { | |
| 209 iter.GetCurrentValue()->Run(SERVICE_WORKER_ERROR_ABORT, IPC::Message()); | |
| 210 iter.Advance(); | |
| 211 } | |
| 212 message_callbacks_.Clear(); | |
| 130 } | 213 } |
| 131 | 214 |
| 132 void ServiceWorkerVersion::OnMessageReceived(const IPC::Message& message) { | 215 void ServiceWorkerVersion::OnMessageReceived( |
| 133 NOTREACHED(); | 216 int request_id, const IPC::Message& message) { |
| 217 MessageCallback* callback = message_callbacks_.Lookup(request_id); | |
| 218 if (callback) { | |
| 219 callback->Run(SERVICE_WORKER_OK, message); | |
| 220 message_callbacks_.Remove(request_id); | |
| 221 return; | |
| 222 } | |
| 223 NOTREACHED() << "Got unexpected message: " << request_id | |
| 224 << " " << message.type(); | |
| 134 } | 225 } |
| 135 | 226 |
| 136 } // namespace content | 227 } // namespace content |
| OLD | NEW |