OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/worker_host/worker_service.h" | 5 #include "content/browser/worker_host/worker_service.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
77 const ViewHostMsg_CreateWorker_Params& params, | 77 const ViewHostMsg_CreateWorker_Params& params, |
78 int route_id, | 78 int route_id, |
79 WorkerMessageFilter* filter, | 79 WorkerMessageFilter* filter, |
80 const content::ResourceContext& resource_context) { | 80 const content::ResourceContext& resource_context) { |
81 // Generate a unique route id for the browser-worker communication that's | 81 // Generate a unique route id for the browser-worker communication that's |
82 // unique among all worker processes. That way when the worker process sends | 82 // unique among all worker processes. That way when the worker process sends |
83 // a wrapped IPC message through us, we know which WorkerProcessHost to give | 83 // a wrapped IPC message through us, we know which WorkerProcessHost to give |
84 // it to. | 84 // it to. |
85 WorkerProcessHost::WorkerInstance instance( | 85 WorkerProcessHost::WorkerInstance instance( |
86 params.url, | 86 params.url, |
87 params.is_shared, | |
88 params.name, | 87 params.name, |
89 next_worker_route_id(), | 88 next_worker_route_id(), |
90 params.is_shared ? 0 : filter->render_process_id(), | 89 0, |
91 params.is_shared ? 0 : params.parent_appcache_host_id, | 90 params.script_resource_appcache_id, |
92 params.is_shared ? params.script_resource_appcache_id : 0, | |
93 &resource_context); | 91 &resource_context); |
94 instance.AddFilter(filter, route_id); | 92 instance.AddFilter(filter, route_id); |
95 instance.worker_document_set()->Add( | 93 instance.worker_document_set()->Add( |
96 filter, params.document_id, filter->render_process_id(), | 94 filter, params.document_id, filter->render_process_id(), |
97 params.render_view_route_id); | 95 params.render_view_route_id); |
98 | 96 |
99 CreateWorkerFromInstance(instance); | 97 CreateWorkerFromInstance(instance); |
100 } | 98 } |
101 | 99 |
102 void WorkerService::LookupSharedWorker( | 100 void WorkerService::LookupSharedWorker( |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
134 // TODO(atwilson): This won't work if the message is from a worker process. | 132 // TODO(atwilson): This won't work if the message is from a worker process. |
135 // We don't support that yet though (this message is only sent from | 133 // We don't support that yet though (this message is only sent from |
136 // renderers) but when we do, we'll need to add code to pass in the current | 134 // renderers) but when we do, we'll need to add code to pass in the current |
137 // worker's document set for nested workers. | 135 // worker's document set for nested workers. |
138 instance->worker_document_set()->Add( | 136 instance->worker_document_set()->Add( |
139 filter, params.document_id, filter->render_process_id(), | 137 filter, params.document_id, filter->render_process_id(), |
140 params.render_view_route_id); | 138 params.render_view_route_id); |
141 } | 139 } |
142 } | 140 } |
143 | 141 |
144 void WorkerService::CancelCreateDedicatedWorker( | 142 void WorkerService::CancelCreateDedicatedWorker( |
jam
2011/10/26 22:25:38
i guess this is second round?
| |
145 int route_id, | 143 int route_id, |
146 WorkerMessageFilter* filter) { | 144 WorkerMessageFilter* filter) { |
147 for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin(); | |
148 i != queued_workers_.end(); ++i) { | |
149 if (i->HasFilter(filter, route_id)) { | |
150 DCHECK(!i->shared()); | |
151 queued_workers_.erase(i); | |
152 return; | |
153 } | |
154 } | |
155 | 145 |
156 // There could be a race condition where the WebWorkerProxy told us to cancel | 146 NOTREACHED(); |
157 // the worker right as we sent it a message say it's been created. Look at | |
158 // the running workers. | |
159 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); | |
160 !iter.Done(); ++iter) { | |
161 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | |
162 for (WorkerProcessHost::Instances::const_iterator instance = | |
163 worker->instances().begin(); | |
164 instance != worker->instances().end(); ++instance) { | |
165 if (instance->HasFilter(filter, route_id)) { | |
166 // Fake a worker destroyed message so that WorkerProcessHost cleans up | |
167 // properly. | |
168 WorkerMsg_TerminateWorkerContext message(route_id); | |
169 ForwardToWorker(message, filter); | |
170 return; | |
171 } | |
172 } | |
173 } | |
174 | |
175 DCHECK(false) << "Couldn't find worker to cancel"; | |
176 } | 147 } |
177 | 148 |
178 void WorkerService::ForwardToWorker(const IPC::Message& message, | 149 void WorkerService::ForwardToWorker(const IPC::Message& message, |
179 WorkerMessageFilter* filter) { | 150 WorkerMessageFilter* filter) { |
180 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); | 151 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); |
181 !iter.Done(); ++iter) { | 152 !iter.Done(); ++iter) { |
182 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 153 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |
183 if (worker->FilterMessage(message, filter)) | 154 if (worker->FilterMessage(message, filter)) |
184 return; | 155 return; |
185 } | 156 } |
186 | 157 |
187 // TODO(jabdelmalek): tell filter that callee is gone | 158 // TODO(jabdelmalek): tell filter that callee is gone |
188 } | 159 } |
189 | 160 |
190 void WorkerService::DocumentDetached(unsigned long long document_id, | 161 void WorkerService::DocumentDetached(unsigned long long document_id, |
191 WorkerMessageFilter* filter) { | 162 WorkerMessageFilter* filter) { |
192 // Any associated shared workers can be shut down. | 163 // Any associated shared workers can be shut down. |
193 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); | 164 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); |
194 !iter.Done(); ++iter) { | 165 !iter.Done(); ++iter) { |
195 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 166 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |
196 worker->DocumentDetached(filter, document_id); | 167 worker->DocumentDetached(filter, document_id); |
197 } | 168 } |
198 | 169 |
199 // Remove any queued shared workers for this document. | 170 // Remove any queued shared workers for this document. |
200 for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin(); | 171 for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin(); |
201 iter != queued_workers_.end();) { | 172 iter != queued_workers_.end();) { |
202 if (iter->shared()) { | 173 |
203 iter->worker_document_set()->Remove(filter, document_id); | 174 iter->worker_document_set()->Remove(filter, document_id); |
204 if (iter->worker_document_set()->IsEmpty()) { | 175 if (iter->worker_document_set()->IsEmpty()) { |
205 iter = queued_workers_.erase(iter); | 176 iter = queued_workers_.erase(iter); |
206 continue; | 177 continue; |
207 } | |
208 } | 178 } |
209 ++iter; | 179 ++iter; |
210 } | 180 } |
211 | 181 |
212 // Remove the document from any pending shared workers. | 182 // Remove the document from any pending shared workers. |
213 for (WorkerProcessHost::Instances::iterator iter = | 183 for (WorkerProcessHost::Instances::iterator iter = |
214 pending_shared_workers_.begin(); | 184 pending_shared_workers_.begin(); |
215 iter != pending_shared_workers_.end(); ) { | 185 iter != pending_shared_workers_.end(); ) { |
216 iter->worker_document_set()->Remove(filter, document_id); | 186 iter->worker_document_set()->Remove(filter, document_id); |
217 if (iter->worker_document_set()->IsEmpty()) { | 187 if (iter->worker_document_set()->IsEmpty()) { |
(...skipping 19 matching lines...) Expand all Loading... | |
237 worker = GetProcessForDomain(instance.url()); | 207 worker = GetProcessForDomain(instance.url()); |
238 } else { // One process per worker. | 208 } else { // One process per worker. |
239 if (!CanCreateWorkerProcess(instance)) { | 209 if (!CanCreateWorkerProcess(instance)) { |
240 queued_workers_.push_back(instance); | 210 queued_workers_.push_back(instance); |
241 return true; | 211 return true; |
242 } | 212 } |
243 } | 213 } |
244 | 214 |
245 // Check to see if this shared worker is already running (two pages may have | 215 // Check to see if this shared worker is already running (two pages may have |
246 // tried to start up the worker simultaneously). | 216 // tried to start up the worker simultaneously). |
247 if (instance.shared()) { | 217 // See if a worker with this name already exists. |
248 // See if a worker with this name already exists. | 218 WorkerProcessHost::WorkerInstance* existing_instance = |
249 WorkerProcessHost::WorkerInstance* existing_instance = | 219 FindSharedWorkerInstance( |
250 FindSharedWorkerInstance( | 220 instance.url(), instance.name(), instance.resource_context()); |
251 instance.url(), instance.name(), instance.resource_context()); | 221 WorkerProcessHost::WorkerInstance::FilterInfo filter_info = |
252 WorkerProcessHost::WorkerInstance::FilterInfo filter_info = | 222 instance.GetFilter(); |
253 instance.GetFilter(); | 223 // If this worker is already running, no need to create a new copy. Just |
254 // If this worker is already running, no need to create a new copy. Just | 224 // inform the caller that the worker has been created. |
255 // inform the caller that the worker has been created. | 225 if (existing_instance) { |
256 if (existing_instance) { | 226 // Walk the worker's filter list to see if this client is listed. If not, |
257 // Walk the worker's filter list to see if this client is listed. If not, | 227 // then it means that the worker started by the client already exited so |
258 // then it means that the worker started by the client already exited so | 228 // we should not attach to this new one (http://crbug.com/29243). |
259 // we should not attach to this new one (http://crbug.com/29243). | 229 if (!existing_instance->HasFilter(filter_info.first, filter_info.second)) |
260 if (!existing_instance->HasFilter(filter_info.first, filter_info.second)) | 230 return false; |
261 return false; | 231 filter_info.first->Send(new ViewMsg_WorkerCreated(filter_info.second)); |
262 filter_info.first->Send(new ViewMsg_WorkerCreated(filter_info.second)); | 232 return true; |
263 return true; | 233 } |
264 } | |
265 | 234 |
266 // Look to see if there's a pending instance. | 235 // Look to see if there's a pending instance. |
267 WorkerProcessHost::WorkerInstance* pending = FindPendingInstance( | 236 WorkerProcessHost::WorkerInstance* pending = FindPendingInstance( |
268 instance.url(), instance.name(), instance.resource_context()); | 237 instance.url(), instance.name(), instance.resource_context()); |
269 // If there's no instance *and* no pending instance (or there is a pending | 238 // If there's no instance *and* no pending instance (or there is a pending |
270 // instance but it does not contain our filter info), then it means the | 239 // instance but it does not contain our filter info), then it means the |
271 // worker started up and exited already. Log a warning because this should | 240 // worker started up and exited already. Log a warning because this should |
272 // be a very rare occurrence and is probably a bug, but it *can* happen so | 241 // be a very rare occurrence and is probably a bug, but it *can* happen so |
273 // handle it gracefully. | 242 // handle it gracefully. |
274 if (!pending || | 243 if (!pending || |
275 !pending->HasFilter(filter_info.first, filter_info.second)) { | 244 !pending->HasFilter(filter_info.first, filter_info.second)) { |
276 DLOG(WARNING) << "Pending worker already exited"; | 245 DLOG(WARNING) << "Pending worker already exited"; |
277 return false; | 246 return false; |
278 } | 247 } |
279 | 248 |
280 // Assign the accumulated document set and filter list for this pending | 249 // Assign the accumulated document set and filter list for this pending |
281 // worker to the new instance. | 250 // worker to the new instance. |
282 DCHECK(!pending->worker_document_set()->IsEmpty()); | 251 DCHECK(!pending->worker_document_set()->IsEmpty()); |
283 instance.ShareDocumentSet(*pending); | 252 instance.ShareDocumentSet(*pending); |
284 for (WorkerProcessHost::WorkerInstance::FilterList::const_iterator i = | 253 for (WorkerProcessHost::WorkerInstance::FilterList::const_iterator i = |
285 pending->filters().begin(); | 254 pending->filters().begin(); |
286 i != pending->filters().end(); ++i) { | 255 i != pending->filters().end(); ++i) { |
287 instance.AddFilter(i->first, i->second); | 256 instance.AddFilter(i->first, i->second); |
288 } | 257 } |
289 RemovePendingInstances( | 258 RemovePendingInstances( |
290 instance.url(), instance.name(), instance.resource_context()); | 259 instance.url(), instance.name(), instance.resource_context()); |
291 | 260 |
292 // Remove any queued instances of this worker and copy over the filter to | 261 // Remove any queued instances of this worker and copy over the filter to |
293 // this instance. | 262 // this instance. |
294 for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin(); | 263 for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin(); |
295 iter != queued_workers_.end();) { | 264 iter != queued_workers_.end();) { |
296 if (iter->Matches(instance.url(), instance.name(), | 265 if (iter->Matches(instance.url(), instance.name(), |
297 instance.resource_context())) { | 266 instance.resource_context())) { |
298 DCHECK(iter->NumFilters() == 1); | 267 DCHECK(iter->NumFilters() == 1); |
299 WorkerProcessHost::WorkerInstance::FilterInfo filter_info = | 268 WorkerProcessHost::WorkerInstance::FilterInfo filter_info = |
300 iter->GetFilter(); | 269 iter->GetFilter(); |
301 instance.AddFilter(filter_info.first, filter_info.second); | 270 instance.AddFilter(filter_info.first, filter_info.second); |
302 iter = queued_workers_.erase(iter); | 271 iter = queued_workers_.erase(iter); |
303 } else { | 272 } else { |
304 ++iter; | 273 ++iter; |
305 } | |
306 } | 274 } |
307 } | 275 } |
308 | 276 |
309 if (!worker) { | 277 if (!worker) { |
310 WorkerMessageFilter* first_filter = instance.filters().begin()->first; | 278 WorkerMessageFilter* first_filter = instance.filters().begin()->first; |
311 worker = new WorkerProcessHost( | 279 worker = new WorkerProcessHost( |
312 instance.resource_context(), | 280 instance.resource_context(), |
313 first_filter->resource_dispatcher_host()); | 281 first_filter->resource_dispatcher_host()); |
314 // TODO(atwilson): This won't work if the message is from a worker process. | 282 // TODO(atwilson): This won't work if the message is from a worker process. |
315 // We don't support that yet though (this message is only sent from | 283 // We don't support that yet though (this message is only sent from |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
579 WorkerProcessHost::WorkerInstance* instance = | 547 WorkerProcessHost::WorkerInstance* instance = |
580 FindPendingInstance(url, name, resource_context); | 548 FindPendingInstance(url, name, resource_context); |
581 if (instance) | 549 if (instance) |
582 return instance; | 550 return instance; |
583 | 551 |
584 // No existing pending worker - create a new one. | 552 // No existing pending worker - create a new one. |
585 WorkerProcessHost::WorkerInstance pending(url, true, name, resource_context); | 553 WorkerProcessHost::WorkerInstance pending(url, true, name, resource_context); |
586 pending_shared_workers_.push_back(pending); | 554 pending_shared_workers_.push_back(pending); |
587 return &pending_shared_workers_.back(); | 555 return &pending_shared_workers_.back(); |
588 } | 556 } |
OLD | NEW |