OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_impl.h" | 5 #include "content/browser/worker_host/worker_service_impl.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" |
11 #include "base/sys_info.h" | 11 #include "base/sys_info.h" |
12 #include "base/threading/thread.h" | 12 #include "base/threading/thread.h" |
13 #include "content/browser/debugger/worker_devtools_manager.h" | 13 #include "content/browser/debugger/worker_devtools_manager.h" |
| 14 #include "content/browser/storage_partition_impl.h" |
14 #include "content/browser/worker_host/worker_message_filter.h" | 15 #include "content/browser/worker_host/worker_message_filter.h" |
15 #include "content/browser/worker_host/worker_process_host.h" | 16 #include "content/browser/worker_host/worker_process_host.h" |
16 #include "content/common/view_messages.h" | 17 #include "content/common/view_messages.h" |
17 #include "content/common/worker_messages.h" | 18 #include "content/common/worker_messages.h" |
18 #include "content/public/browser/child_process_data.h" | 19 #include "content/public/browser/child_process_data.h" |
19 #include "content/public/browser/resource_context.h" | 20 #include "content/public/browser/resource_context.h" |
20 #include "content/public/browser/worker_service_observer.h" | 21 #include "content/public/browser/worker_service_observer.h" |
21 #include "content/public/common/content_switches.h" | 22 #include "content/public/common/content_switches.h" |
22 #include "content/public/common/process_type.h" | 23 #include "content/public/common/process_type.h" |
23 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | 24 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 // the queued workers, or a renderer has shut down, in which case it doesn't | 90 // the queued workers, or a renderer has shut down, in which case it doesn't |
90 // affect anything. We call this function in both scenarios because then we | 91 // affect anything. We call this function in both scenarios because then we |
91 // don't have to keep track which filters are from worker processes. | 92 // don't have to keep track which filters are from worker processes. |
92 TryStartingQueuedWorker(); | 93 TryStartingQueuedWorker(); |
93 } | 94 } |
94 | 95 |
95 void WorkerServiceImpl::CreateWorker( | 96 void WorkerServiceImpl::CreateWorker( |
96 const ViewHostMsg_CreateWorker_Params& params, | 97 const ViewHostMsg_CreateWorker_Params& params, |
97 int route_id, | 98 int route_id, |
98 WorkerMessageFilter* filter, | 99 WorkerMessageFilter* filter, |
99 ResourceContext* resource_context) { | 100 ResourceContext* resource_context, |
| 101 StoragePartitionImpl* storage_partition) { |
100 // Generate a unique route id for the browser-worker communication that's | 102 // Generate a unique route id for the browser-worker communication that's |
101 // unique among all worker processes. That way when the worker process sends | 103 // unique among all worker processes. That way when the worker process sends |
102 // a wrapped IPC message through us, we know which WorkerProcessHost to give | 104 // a wrapped IPC message through us, we know which WorkerProcessHost to give |
103 // it to. | 105 // it to. |
104 WorkerProcessHost::WorkerInstance instance( | 106 WorkerProcessHost::WorkerInstance instance( |
105 params.url, | 107 params.url, |
106 params.name, | 108 params.name, |
107 next_worker_route_id(), | 109 next_worker_route_id(), |
108 0, | 110 0, |
109 params.script_resource_appcache_id, | 111 params.script_resource_appcache_id, |
110 resource_context); | 112 resource_context, |
| 113 storage_partition); |
111 instance.AddFilter(filter, route_id); | 114 instance.AddFilter(filter, route_id); |
112 instance.worker_document_set()->Add( | 115 instance.worker_document_set()->Add( |
113 filter, params.document_id, filter->render_process_id(), | 116 filter, params.document_id, filter->render_process_id(), |
114 params.render_view_route_id); | 117 params.render_view_route_id); |
115 | 118 |
116 CreateWorkerFromInstance(instance); | 119 CreateWorkerFromInstance(instance); |
117 } | 120 } |
118 | 121 |
119 void WorkerServiceImpl::LookupSharedWorker( | 122 void WorkerServiceImpl::LookupSharedWorker( |
120 const ViewHostMsg_CreateWorker_Params& params, | 123 const ViewHostMsg_CreateWorker_Params& params, |
121 int route_id, | 124 int route_id, |
122 WorkerMessageFilter* filter, | 125 WorkerMessageFilter* filter, |
123 ResourceContext* resource_context, | 126 ResourceContext* resource_context, |
| 127 StoragePartitionImpl* storage_partition, |
124 bool* exists, | 128 bool* exists, |
125 bool* url_mismatch) { | 129 bool* url_mismatch) { |
126 *exists = true; | 130 *exists = true; |
127 WorkerProcessHost::WorkerInstance* instance = FindSharedWorkerInstance( | 131 WorkerProcessHost::WorkerInstance* instance = FindSharedWorkerInstance( |
128 params.url, params.name, resource_context); | 132 params.url, params.name, resource_context, storage_partition); |
129 | 133 |
130 if (!instance) { | 134 if (!instance) { |
131 // If no worker instance currently exists, we need to create a pending | 135 // If no worker instance currently exists, we need to create a pending |
132 // instance - this is to make sure that any subsequent lookups passing a | 136 // instance - this is to make sure that any subsequent lookups passing a |
133 // mismatched URL get the appropriate url_mismatch error at lookup time. | 137 // mismatched URL get the appropriate url_mismatch error at lookup time. |
134 // Having named shared workers was a Really Bad Idea due to details like | 138 // Having named shared workers was a Really Bad Idea due to details like |
135 // this. | 139 // this. |
136 instance = CreatePendingInstance(params.url, params.name, resource_context); | 140 instance = CreatePendingInstance(params.url, params.name, resource_context, |
| 141 storage_partition); |
137 *exists = false; | 142 *exists = false; |
138 } | 143 } |
139 | 144 |
140 // Make sure the passed-in instance matches the URL - if not, return an | 145 // Make sure the passed-in instance matches the URL - if not, return an |
141 // error. | 146 // error. |
142 if (params.url != instance->url()) { | 147 if (params.url != instance->url()) { |
143 *url_mismatch = true; | 148 *url_mismatch = true; |
144 *exists = false; | 149 *exists = false; |
145 } else { | 150 } else { |
146 *url_mismatch = false; | 151 *url_mismatch = false; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 queued_workers_.push_back(instance); | 229 queued_workers_.push_back(instance); |
225 return true; | 230 return true; |
226 } | 231 } |
227 } | 232 } |
228 | 233 |
229 // Check to see if this shared worker is already running (two pages may have | 234 // Check to see if this shared worker is already running (two pages may have |
230 // tried to start up the worker simultaneously). | 235 // tried to start up the worker simultaneously). |
231 // See if a worker with this name already exists. | 236 // See if a worker with this name already exists. |
232 WorkerProcessHost::WorkerInstance* existing_instance = | 237 WorkerProcessHost::WorkerInstance* existing_instance = |
233 FindSharedWorkerInstance( | 238 FindSharedWorkerInstance( |
234 instance.url(), instance.name(), instance.resource_context()); | 239 instance.url(), instance.name(), instance.resource_context(), |
| 240 instance.storage_partition()); |
235 WorkerProcessHost::WorkerInstance::FilterInfo filter_info = | 241 WorkerProcessHost::WorkerInstance::FilterInfo filter_info = |
236 instance.GetFilter(); | 242 instance.GetFilter(); |
237 // If this worker is already running, no need to create a new copy. Just | 243 // If this worker is already running, no need to create a new copy. Just |
238 // inform the caller that the worker has been created. | 244 // inform the caller that the worker has been created. |
239 if (existing_instance) { | 245 if (existing_instance) { |
240 // Walk the worker's filter list to see if this client is listed. If not, | 246 // Walk the worker's filter list to see if this client is listed. If not, |
241 // then it means that the worker started by the client already exited so | 247 // then it means that the worker started by the client already exited so |
242 // we should not attach to this new one (http://crbug.com/29243). | 248 // we should not attach to this new one (http://crbug.com/29243). |
243 if (!existing_instance->HasFilter(filter_info.first, filter_info.second)) | 249 if (!existing_instance->HasFilter(filter_info.first, filter_info.second)) |
244 return false; | 250 return false; |
245 filter_info.first->Send(new ViewMsg_WorkerCreated(filter_info.second)); | 251 filter_info.first->Send(new ViewMsg_WorkerCreated(filter_info.second)); |
246 return true; | 252 return true; |
247 } | 253 } |
248 | 254 |
249 // Look to see if there's a pending instance. | 255 // Look to see if there's a pending instance. |
250 WorkerProcessHost::WorkerInstance* pending = FindPendingInstance( | 256 WorkerProcessHost::WorkerInstance* pending = FindPendingInstance( |
251 instance.url(), instance.name(), instance.resource_context()); | 257 instance.url(), instance.name(), instance.resource_context(), |
| 258 instance.storage_partition()); |
252 // If there's no instance *and* no pending instance (or there is a pending | 259 // If there's no instance *and* no pending instance (or there is a pending |
253 // instance but it does not contain our filter info), then it means the | 260 // instance but it does not contain our filter info), then it means the |
254 // worker started up and exited already. Log a warning because this should | 261 // worker started up and exited already. Log a warning because this should |
255 // be a very rare occurrence and is probably a bug, but it *can* happen so | 262 // be a very rare occurrence and is probably a bug, but it *can* happen so |
256 // handle it gracefully. | 263 // handle it gracefully. |
257 if (!pending || | 264 if (!pending || |
258 !pending->HasFilter(filter_info.first, filter_info.second)) { | 265 !pending->HasFilter(filter_info.first, filter_info.second)) { |
259 DLOG(WARNING) << "Pending worker already exited"; | 266 DLOG(WARNING) << "Pending worker already exited"; |
260 return false; | 267 return false; |
261 } | 268 } |
262 | 269 |
263 // Assign the accumulated document set and filter list for this pending | 270 // Assign the accumulated document set and filter list for this pending |
264 // worker to the new instance. | 271 // worker to the new instance. |
265 DCHECK(!pending->worker_document_set()->IsEmpty()); | 272 DCHECK(!pending->worker_document_set()->IsEmpty()); |
266 instance.ShareDocumentSet(*pending); | 273 instance.ShareDocumentSet(*pending); |
267 for (WorkerProcessHost::WorkerInstance::FilterList::const_iterator i = | 274 for (WorkerProcessHost::WorkerInstance::FilterList::const_iterator i = |
268 pending->filters().begin(); | 275 pending->filters().begin(); |
269 i != pending->filters().end(); ++i) { | 276 i != pending->filters().end(); ++i) { |
270 instance.AddFilter(i->first, i->second); | 277 instance.AddFilter(i->first, i->second); |
271 } | 278 } |
272 RemovePendingInstances( | 279 RemovePendingInstances( |
273 instance.url(), instance.name(), instance.resource_context()); | 280 instance.url(), instance.name(), instance.resource_context(), |
| 281 instance.storage_partition()); |
274 | 282 |
275 // Remove any queued instances of this worker and copy over the filter to | 283 // Remove any queued instances of this worker and copy over the filter to |
276 // this instance. | 284 // this instance. |
277 for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin(); | 285 for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin(); |
278 iter != queued_workers_.end();) { | 286 iter != queued_workers_.end();) { |
279 if (iter->Matches(instance.url(), instance.name(), | 287 if (iter->Matches(instance.url(), instance.name(), |
280 instance.resource_context())) { | 288 instance.resource_context(), |
| 289 instance.storage_partition())) { |
281 DCHECK(iter->NumFilters() == 1); | 290 DCHECK(iter->NumFilters() == 1); |
282 WorkerProcessHost::WorkerInstance::FilterInfo filter_info = | 291 WorkerProcessHost::WorkerInstance::FilterInfo filter_info = |
283 iter->GetFilter(); | 292 iter->GetFilter(); |
284 instance.AddFilter(filter_info.first, filter_info.second); | 293 instance.AddFilter(filter_info.first, filter_info.second); |
285 iter = queued_workers_.erase(iter); | 294 iter = queued_workers_.erase(iter); |
286 } else { | 295 } else { |
287 ++iter; | 296 ++iter; |
288 } | 297 } |
289 } | 298 } |
290 | 299 |
291 if (!worker) { | 300 if (!worker) { |
292 WorkerMessageFilter* first_filter = instance.filters().begin()->first; | 301 WorkerMessageFilter* first_filter = instance.filters().begin()->first; |
293 worker = new WorkerProcessHost(instance.resource_context()); | 302 worker = new WorkerProcessHost(instance.resource_context(), |
| 303 instance.storage_partition()); |
294 // TODO(atwilson): This won't work if the message is from a worker process. | 304 // TODO(atwilson): This won't work if the message is from a worker process. |
295 // We don't support that yet though (this message is only sent from | 305 // We don't support that yet though (this message is only sent from |
296 // renderers) but when we do, we'll need to add code to pass in the current | 306 // renderers) but when we do, we'll need to add code to pass in the current |
297 // worker's document set for nested workers. | 307 // worker's document set for nested workers. |
298 if (!worker->Init(first_filter->render_process_id())) { | 308 if (!worker->Init(first_filter->render_process_id())) { |
299 delete worker; | 309 delete worker; |
300 return false; | 310 return false; |
301 } | 311 } |
302 } | 312 } |
303 | 313 |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 int worker_route_id) { | 520 int worker_route_id) { |
511 WorkerDevToolsManager::GetInstance()->WorkerDestroyed( | 521 WorkerDevToolsManager::GetInstance()->WorkerDestroyed( |
512 process, worker_route_id); | 522 process, worker_route_id); |
513 FOR_EACH_OBSERVER(WorkerServiceObserver, observers_, | 523 FOR_EACH_OBSERVER(WorkerServiceObserver, observers_, |
514 WorkerDestroyed(process->GetData().id, worker_route_id)); | 524 WorkerDestroyed(process->GetData().id, worker_route_id)); |
515 } | 525 } |
516 | 526 |
517 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindSharedWorkerInstance( | 527 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindSharedWorkerInstance( |
518 const GURL& url, | 528 const GURL& url, |
519 const string16& name, | 529 const string16& name, |
520 ResourceContext* resource_context) { | 530 ResourceContext* resource_context, |
| 531 StoragePartitionImpl* storage_partition) { |
521 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { | 532 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { |
522 for (WorkerProcessHost::Instances::iterator instance_iter = | 533 for (WorkerProcessHost::Instances::iterator instance_iter = |
523 iter->mutable_instances().begin(); | 534 iter->mutable_instances().begin(); |
524 instance_iter != iter->mutable_instances().end(); | 535 instance_iter != iter->mutable_instances().end(); |
525 ++instance_iter) { | 536 ++instance_iter) { |
526 if (instance_iter->Matches(url, name, resource_context)) | 537 if (instance_iter->Matches(url, name, resource_context, |
| 538 storage_partition)) |
527 return &(*instance_iter); | 539 return &(*instance_iter); |
528 } | 540 } |
529 } | 541 } |
530 return NULL; | 542 return NULL; |
531 } | 543 } |
532 | 544 |
533 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindPendingInstance( | 545 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindPendingInstance( |
534 const GURL& url, | 546 const GURL& url, |
535 const string16& name, | 547 const string16& name, |
536 ResourceContext* resource_context) { | 548 ResourceContext* resource_context, |
| 549 StoragePartitionImpl* storage_partition) { |
537 // Walk the pending instances looking for a matching pending worker. | 550 // Walk the pending instances looking for a matching pending worker. |
538 for (WorkerProcessHost::Instances::iterator iter = | 551 for (WorkerProcessHost::Instances::iterator iter = |
539 pending_shared_workers_.begin(); | 552 pending_shared_workers_.begin(); |
540 iter != pending_shared_workers_.end(); | 553 iter != pending_shared_workers_.end(); |
541 ++iter) { | 554 ++iter) { |
542 if (iter->Matches(url, name, resource_context)) { | 555 if (iter->Matches(url, name, resource_context, storage_partition)) { |
543 return &(*iter); | 556 return &(*iter); |
544 } | 557 } |
545 } | 558 } |
546 return NULL; | 559 return NULL; |
547 } | 560 } |
548 | 561 |
549 | 562 |
550 void WorkerServiceImpl::RemovePendingInstances( | 563 void WorkerServiceImpl::RemovePendingInstances( |
551 const GURL& url, | 564 const GURL& url, |
552 const string16& name, | 565 const string16& name, |
553 ResourceContext* resource_context) { | 566 ResourceContext* resource_context, |
| 567 StoragePartitionImpl* storage_partition) { |
554 // Walk the pending instances looking for a matching pending worker. | 568 // Walk the pending instances looking for a matching pending worker. |
555 for (WorkerProcessHost::Instances::iterator iter = | 569 for (WorkerProcessHost::Instances::iterator iter = |
556 pending_shared_workers_.begin(); | 570 pending_shared_workers_.begin(); |
557 iter != pending_shared_workers_.end(); ) { | 571 iter != pending_shared_workers_.end(); ) { |
558 if (iter->Matches(url, name, resource_context)) { | 572 if (iter->Matches(url, name, resource_context, storage_partition)) { |
559 iter = pending_shared_workers_.erase(iter); | 573 iter = pending_shared_workers_.erase(iter); |
560 } else { | 574 } else { |
561 ++iter; | 575 ++iter; |
562 } | 576 } |
563 } | 577 } |
564 } | 578 } |
565 | 579 |
566 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::CreatePendingInstance( | 580 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::CreatePendingInstance( |
567 const GURL& url, | 581 const GURL& url, |
568 const string16& name, | 582 const string16& name, |
569 ResourceContext* resource_context) { | 583 ResourceContext* resource_context, |
| 584 StoragePartitionImpl* storage_partition) { |
570 // Look for an existing pending shared worker. | 585 // Look for an existing pending shared worker. |
571 WorkerProcessHost::WorkerInstance* instance = | 586 WorkerProcessHost::WorkerInstance* instance = |
572 FindPendingInstance(url, name, resource_context); | 587 FindPendingInstance(url, name, resource_context, storage_partition); |
573 if (instance) | 588 if (instance) |
574 return instance; | 589 return instance; |
575 | 590 |
576 // No existing pending worker - create a new one. | 591 // No existing pending worker - create a new one. |
577 WorkerProcessHost::WorkerInstance pending(url, true, name, resource_context); | 592 WorkerProcessHost::WorkerInstance pending( |
| 593 url, true, name, resource_context, storage_partition); |
578 pending_shared_workers_.push_back(pending); | 594 pending_shared_workers_.push_back(pending); |
579 return &pending_shared_workers_.back(); | 595 return &pending_shared_workers_.back(); |
580 } | 596 } |
581 | 597 |
582 } // namespace content | 598 } // namespace content |
OLD | NEW |