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" |
(...skipping 78 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 | 89 // 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 | 90 // 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. | 91 // don't have to keep track which filters are from worker processes. |
92 TryStartingQueuedWorker(); | 92 TryStartingQueuedWorker(); |
93 } | 93 } |
94 | 94 |
95 void WorkerServiceImpl::CreateWorker( | 95 void WorkerServiceImpl::CreateWorker( |
96 const ViewHostMsg_CreateWorker_Params& params, | 96 const ViewHostMsg_CreateWorker_Params& params, |
97 int route_id, | 97 int route_id, |
98 WorkerMessageFilter* filter, | 98 WorkerMessageFilter* filter, |
99 ResourceContext* resource_context) { | 99 ResourceContext* resource_context, |
| 100 const WorkerStoragePartition& partition) { |
| 101 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
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 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 const WorkerStoragePartition& 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, partition, resource_context); |
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, |
| 141 resource_context, 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.partition(), |
| 240 instance.resource_context()); |
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.partition(), |
| 258 instance.resource_context()); |
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(instance.url(), instance.name(), |
273 instance.url(), instance.name(), instance.resource_context()); | 280 instance.partition(), instance.resource_context()); |
274 | 281 |
275 // Remove any queued instances of this worker and copy over the filter to | 282 // Remove any queued instances of this worker and copy over the filter to |
276 // this instance. | 283 // this instance. |
277 for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin(); | 284 for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin(); |
278 iter != queued_workers_.end();) { | 285 iter != queued_workers_.end();) { |
279 if (iter->Matches(instance.url(), instance.name(), | 286 if (iter->Matches(instance.url(), instance.name(), |
280 instance.resource_context())) { | 287 instance.partition(), instance.resource_context())) { |
281 DCHECK(iter->NumFilters() == 1); | 288 DCHECK(iter->NumFilters() == 1); |
282 WorkerProcessHost::WorkerInstance::FilterInfo filter_info = | 289 WorkerProcessHost::WorkerInstance::FilterInfo filter_info = |
283 iter->GetFilter(); | 290 iter->GetFilter(); |
284 instance.AddFilter(filter_info.first, filter_info.second); | 291 instance.AddFilter(filter_info.first, filter_info.second); |
285 iter = queued_workers_.erase(iter); | 292 iter = queued_workers_.erase(iter); |
286 } else { | 293 } else { |
287 ++iter; | 294 ++iter; |
288 } | 295 } |
289 } | 296 } |
290 | 297 |
291 if (!worker) { | 298 if (!worker) { |
292 WorkerMessageFilter* first_filter = instance.filters().begin()->first; | 299 WorkerMessageFilter* first_filter = instance.filters().begin()->first; |
293 worker = new WorkerProcessHost(instance.resource_context()); | 300 worker = new WorkerProcessHost(instance.resource_context(), |
| 301 instance.partition()); |
294 // TODO(atwilson): This won't work if the message is from a worker process. | 302 // 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 | 303 // 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 | 304 // renderers) but when we do, we'll need to add code to pass in the current |
297 // worker's document set for nested workers. | 305 // worker's document set for nested workers. |
298 if (!worker->Init(first_filter->render_process_id())) { | 306 if (!worker->Init(first_filter->render_process_id())) { |
299 delete worker; | 307 delete worker; |
300 return false; | 308 return false; |
301 } | 309 } |
302 } | 310 } |
303 | 311 |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 int worker_route_id) { | 518 int worker_route_id) { |
511 WorkerDevToolsManager::GetInstance()->WorkerDestroyed( | 519 WorkerDevToolsManager::GetInstance()->WorkerDestroyed( |
512 process, worker_route_id); | 520 process, worker_route_id); |
513 FOR_EACH_OBSERVER(WorkerServiceObserver, observers_, | 521 FOR_EACH_OBSERVER(WorkerServiceObserver, observers_, |
514 WorkerDestroyed(process->GetData().id, worker_route_id)); | 522 WorkerDestroyed(process->GetData().id, worker_route_id)); |
515 } | 523 } |
516 | 524 |
517 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindSharedWorkerInstance( | 525 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindSharedWorkerInstance( |
518 const GURL& url, | 526 const GURL& url, |
519 const string16& name, | 527 const string16& name, |
| 528 const WorkerStoragePartition& partition, |
520 ResourceContext* resource_context) { | 529 ResourceContext* resource_context) { |
521 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { | 530 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { |
522 for (WorkerProcessHost::Instances::iterator instance_iter = | 531 for (WorkerProcessHost::Instances::iterator instance_iter = |
523 iter->mutable_instances().begin(); | 532 iter->mutable_instances().begin(); |
524 instance_iter != iter->mutable_instances().end(); | 533 instance_iter != iter->mutable_instances().end(); |
525 ++instance_iter) { | 534 ++instance_iter) { |
526 if (instance_iter->Matches(url, name, resource_context)) | 535 if (instance_iter->Matches(url, name, partition, resource_context)) |
527 return &(*instance_iter); | 536 return &(*instance_iter); |
528 } | 537 } |
529 } | 538 } |
530 return NULL; | 539 return NULL; |
531 } | 540 } |
532 | 541 |
533 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindPendingInstance( | 542 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindPendingInstance( |
534 const GURL& url, | 543 const GURL& url, |
535 const string16& name, | 544 const string16& name, |
| 545 const WorkerStoragePartition& partition, |
536 ResourceContext* resource_context) { | 546 ResourceContext* resource_context) { |
537 // Walk the pending instances looking for a matching pending worker. | 547 // Walk the pending instances looking for a matching pending worker. |
538 for (WorkerProcessHost::Instances::iterator iter = | 548 for (WorkerProcessHost::Instances::iterator iter = |
539 pending_shared_workers_.begin(); | 549 pending_shared_workers_.begin(); |
540 iter != pending_shared_workers_.end(); | 550 iter != pending_shared_workers_.end(); |
541 ++iter) { | 551 ++iter) { |
542 if (iter->Matches(url, name, resource_context)) { | 552 if (iter->Matches(url, name, partition, resource_context)) |
543 return &(*iter); | 553 return &(*iter); |
544 } | |
545 } | 554 } |
546 return NULL; | 555 return NULL; |
547 } | 556 } |
548 | 557 |
549 | 558 |
550 void WorkerServiceImpl::RemovePendingInstances( | 559 void WorkerServiceImpl::RemovePendingInstances( |
551 const GURL& url, | 560 const GURL& url, |
552 const string16& name, | 561 const string16& name, |
| 562 const WorkerStoragePartition& partition, |
553 ResourceContext* resource_context) { | 563 ResourceContext* resource_context) { |
554 // Walk the pending instances looking for a matching pending worker. | 564 // Walk the pending instances looking for a matching pending worker. |
555 for (WorkerProcessHost::Instances::iterator iter = | 565 for (WorkerProcessHost::Instances::iterator iter = |
556 pending_shared_workers_.begin(); | 566 pending_shared_workers_.begin(); |
557 iter != pending_shared_workers_.end(); ) { | 567 iter != pending_shared_workers_.end(); ) { |
558 if (iter->Matches(url, name, resource_context)) { | 568 if (iter->Matches(url, name, partition, resource_context)) { |
559 iter = pending_shared_workers_.erase(iter); | 569 iter = pending_shared_workers_.erase(iter); |
560 } else { | 570 } else { |
561 ++iter; | 571 ++iter; |
562 } | 572 } |
563 } | 573 } |
564 } | 574 } |
565 | 575 |
566 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::CreatePendingInstance( | 576 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::CreatePendingInstance( |
567 const GURL& url, | 577 const GURL& url, |
568 const string16& name, | 578 const string16& name, |
569 ResourceContext* resource_context) { | 579 ResourceContext* resource_context, |
| 580 const WorkerStoragePartition& partition) { |
570 // Look for an existing pending shared worker. | 581 // Look for an existing pending shared worker. |
571 WorkerProcessHost::WorkerInstance* instance = | 582 WorkerProcessHost::WorkerInstance* instance = |
572 FindPendingInstance(url, name, resource_context); | 583 FindPendingInstance(url, name, partition, resource_context); |
573 if (instance) | 584 if (instance) |
574 return instance; | 585 return instance; |
575 | 586 |
576 // No existing pending worker - create a new one. | 587 // No existing pending worker - create a new one. |
577 WorkerProcessHost::WorkerInstance pending(url, true, name, resource_context); | 588 WorkerProcessHost::WorkerInstance pending( |
| 589 url, true, name, resource_context, partition); |
578 pending_shared_workers_.push_back(pending); | 590 pending_shared_workers_.push_back(pending); |
579 return &pending_shared_workers_.back(); | 591 return &pending_shared_workers_.back(); |
580 } | 592 } |
581 | 593 |
582 } // namespace content | 594 } // namespace content |
OLD | NEW |