| 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 |