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 |