| 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_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/resource_context.h" | 14 #include "content/browser/resource_context.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/worker_service_observer.h" | 20 #include "content/public/browser/worker_service_observer.h" |
| 20 #include "content/public/common/content_switches.h" | 21 #include "content/public/common/content_switches.h" |
| 21 #include "content/public/common/process_type.h" | 22 #include "content/public/common/process_type.h" |
| 22 #include "net/base/registry_controlled_domain.h" | 23 #include "net/base/registry_controlled_domain.h" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 // the queued workers, or a renderer has shut down, in which case it doesn't | 78 // the queued workers, or a renderer has shut down, in which case it doesn't |
| 78 // affect anything. We call this function in both scenarios because then we | 79 // affect anything. We call this function in both scenarios because then we |
| 79 // don't have to keep track which filters are from worker processes. | 80 // don't have to keep track which filters are from worker processes. |
| 80 TryStartingQueuedWorker(); | 81 TryStartingQueuedWorker(); |
| 81 } | 82 } |
| 82 | 83 |
| 83 void WorkerServiceImpl::CreateWorker( | 84 void WorkerServiceImpl::CreateWorker( |
| 84 const ViewHostMsg_CreateWorker_Params& params, | 85 const ViewHostMsg_CreateWorker_Params& params, |
| 85 int route_id, | 86 int route_id, |
| 86 WorkerMessageFilter* filter, | 87 WorkerMessageFilter* filter, |
| 87 const content::ResourceContext& resource_context) { | 88 const ResourceContext& resource_context) { |
| 88 // Generate a unique route id for the browser-worker communication that's | 89 // Generate a unique route id for the browser-worker communication that's |
| 89 // unique among all worker processes. That way when the worker process sends | 90 // unique among all worker processes. That way when the worker process sends |
| 90 // a wrapped IPC message through us, we know which WorkerProcessHost to give | 91 // a wrapped IPC message through us, we know which WorkerProcessHost to give |
| 91 // it to. | 92 // it to. |
| 92 WorkerProcessHost::WorkerInstance instance( | 93 WorkerProcessHost::WorkerInstance instance( |
| 93 params.url, | 94 params.url, |
| 94 params.name, | 95 params.name, |
| 95 next_worker_route_id(), | 96 next_worker_route_id(), |
| 96 0, | 97 0, |
| 97 params.script_resource_appcache_id, | 98 params.script_resource_appcache_id, |
| 98 &resource_context); | 99 &resource_context); |
| 99 instance.AddFilter(filter, route_id); | 100 instance.AddFilter(filter, route_id); |
| 100 instance.worker_document_set()->Add( | 101 instance.worker_document_set()->Add( |
| 101 filter, params.document_id, filter->render_process_id(), | 102 filter, params.document_id, filter->render_process_id(), |
| 102 params.render_view_route_id); | 103 params.render_view_route_id); |
| 103 | 104 |
| 104 CreateWorkerFromInstance(instance); | 105 CreateWorkerFromInstance(instance); |
| 105 } | 106 } |
| 106 | 107 |
| 107 void WorkerServiceImpl::LookupSharedWorker( | 108 void WorkerServiceImpl::LookupSharedWorker( |
| 108 const ViewHostMsg_CreateWorker_Params& params, | 109 const ViewHostMsg_CreateWorker_Params& params, |
| 109 int route_id, | 110 int route_id, |
| 110 WorkerMessageFilter* filter, | 111 WorkerMessageFilter* filter, |
| 111 const content::ResourceContext* resource_context, | 112 const ResourceContext* resource_context, |
| 112 bool* exists, | 113 bool* exists, |
| 113 bool* url_mismatch) { | 114 bool* url_mismatch) { |
| 114 *exists = true; | 115 *exists = true; |
| 115 WorkerProcessHost::WorkerInstance* instance = FindSharedWorkerInstance( | 116 WorkerProcessHost::WorkerInstance* instance = FindSharedWorkerInstance( |
| 116 params.url, params.name, resource_context); | 117 params.url, params.name, resource_context); |
| 117 | 118 |
| 118 if (!instance) { | 119 if (!instance) { |
| 119 // If no worker instance currently exists, we need to create a pending | 120 // If no worker instance currently exists, we need to create a pending |
| 120 // instance - this is to make sure that any subsequent lookups passing a | 121 // instance - this is to make sure that any subsequent lookups passing a |
| 121 // mismatched URL get the appropriate url_mismatch error at lookup time. | 122 // mismatched URL get the appropriate url_mismatch error at lookup time. |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 delete worker; | 288 delete worker; |
| 288 return false; | 289 return false; |
| 289 } | 290 } |
| 290 } | 291 } |
| 291 | 292 |
| 292 // TODO(michaeln): As written, test can fail per my earlier comment in | 293 // TODO(michaeln): As written, test can fail per my earlier comment in |
| 293 // this method, but that's a bug. | 294 // this method, but that's a bug. |
| 294 // DCHECK(worker->request_context() == instance.request_context()); | 295 // DCHECK(worker->request_context() == instance.request_context()); |
| 295 | 296 |
| 296 worker->CreateWorker(instance); | 297 worker->CreateWorker(instance); |
| 297 FOR_EACH_OBSERVER(WorkerServiceObserver, observers_, | 298 FOR_EACH_OBSERVER( |
| 298 WorkerCreated(worker, instance)); | 299 WorkerServiceObserver, observers_, |
| 300 WorkerCreated(instance.url(), instance.name(), worker->GetData().id, |
| 301 instance.worker_route_id())); |
| 302 WorkerDevToolsManager::GetInstance()->WorkerCreated(worker, instance); |
| 299 return true; | 303 return true; |
| 300 } | 304 } |
| 301 | 305 |
| 302 WorkerProcessHost* WorkerServiceImpl::GetProcessForDomain(const GURL& url) { | 306 WorkerProcessHost* WorkerServiceImpl::GetProcessForDomain(const GURL& url) { |
| 303 int num_processes = 0; | 307 int num_processes = 0; |
| 304 std::string domain = | 308 std::string domain = |
| 305 net::RegistryControlledDomainService::GetDomainAndRegistry(url); | 309 net::RegistryControlledDomainService::GetDomainAndRegistry(url); |
| 306 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { | 310 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { |
| 307 num_processes++; | 311 num_processes++; |
| 308 for (WorkerProcessHost::Instances::const_iterator instance = | 312 for (WorkerProcessHost::Instances::const_iterator instance = |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 445 if (iter.GetData().id != worker_process_id) | 449 if (iter.GetData().id != worker_process_id) |
| 446 continue; | 450 continue; |
| 447 | 451 |
| 448 WorkerProcessHost::Instances::const_iterator instance = | 452 WorkerProcessHost::Instances::const_iterator instance = |
| 449 iter->instances().begin(); | 453 iter->instances().begin(); |
| 450 return instance == iter->instances().end() ? NULL : &*instance; | 454 return instance == iter->instances().end() ? NULL : &*instance; |
| 451 } | 455 } |
| 452 return NULL; | 456 return NULL; |
| 453 } | 457 } |
| 454 | 458 |
| 459 bool WorkerServiceImpl::TerminateWorker(int process_id, int route_id) { |
| 460 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { |
| 461 if (iter.GetData().id == process_id) { |
| 462 iter->TerminateWorker(route_id); |
| 463 return true; |
| 464 } |
| 465 } |
| 466 return false; |
| 467 } |
| 468 |
| 469 std::vector<WorkerService::WorkerInfo> WorkerServiceImpl::GetWorkers() { |
| 470 std::vector<WorkerService::WorkerInfo> results; |
| 471 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { |
| 472 const WorkerProcessHost::Instances& instances = (*iter)->instances(); |
| 473 for (WorkerProcessHost::Instances::const_iterator i = instances.begin(); |
| 474 i != instances.end(); ++i) { |
| 475 WorkerService::WorkerInfo info; |
| 476 info.url = i->url(); |
| 477 info.name = i->name(); |
| 478 info.route_id = i->worker_route_id(); |
| 479 info.process_id = iter.GetData().id; |
| 480 info.handle = iter.GetData().handle; |
| 481 results.push_back(info); |
| 482 } |
| 483 } |
| 484 return results; |
| 485 } |
| 486 |
| 455 void WorkerServiceImpl::AddObserver(WorkerServiceObserver* observer) { | 487 void WorkerServiceImpl::AddObserver(WorkerServiceObserver* observer) { |
| 456 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 488 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 457 observers_.AddObserver(observer); | 489 observers_.AddObserver(observer); |
| 458 } | 490 } |
| 459 | 491 |
| 460 void WorkerServiceImpl::RemoveObserver(WorkerServiceObserver* observer) { | 492 void WorkerServiceImpl::RemoveObserver(WorkerServiceObserver* observer) { |
| 461 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 493 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 462 observers_.RemoveObserver(observer); | 494 observers_.RemoveObserver(observer); |
| 463 } | 495 } |
| 464 | 496 |
| 465 void WorkerServiceImpl::NotifyWorkerDestroyed( | 497 void WorkerServiceImpl::NotifyWorkerDestroyed( |
| 466 WorkerProcessHost* process, | 498 WorkerProcessHost* process, |
| 467 int worker_route_id) { | 499 int worker_route_id) { |
| 500 WorkerDevToolsManager::GetInstance()->WorkerDestroyed( |
| 501 process, worker_route_id); |
| 468 FOR_EACH_OBSERVER(WorkerServiceObserver, observers_, | 502 FOR_EACH_OBSERVER(WorkerServiceObserver, observers_, |
| 469 WorkerDestroyed(process, worker_route_id)); | 503 WorkerDestroyed(process->GetData().id, worker_route_id)); |
| 470 } | |
| 471 | |
| 472 void WorkerServiceImpl::NotifyWorkerContextStarted(WorkerProcessHost* process, | |
| 473 int worker_route_id) { | |
| 474 FOR_EACH_OBSERVER(WorkerServiceObserver, observers_, | |
| 475 WorkerContextStarted(process, worker_route_id)); | |
| 476 } | 504 } |
| 477 | 505 |
| 478 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindSharedWorkerInstance( | 506 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindSharedWorkerInstance( |
| 479 const GURL& url, | 507 const GURL& url, |
| 480 const string16& name, | 508 const string16& name, |
| 481 const content::ResourceContext* resource_context) { | 509 const ResourceContext* resource_context) { |
| 482 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { | 510 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { |
| 483 for (WorkerProcessHost::Instances::iterator instance_iter = | 511 for (WorkerProcessHost::Instances::iterator instance_iter = |
| 484 iter->mutable_instances().begin(); | 512 iter->mutable_instances().begin(); |
| 485 instance_iter != iter->mutable_instances().end(); | 513 instance_iter != iter->mutable_instances().end(); |
| 486 ++instance_iter) { | 514 ++instance_iter) { |
| 487 if (instance_iter->Matches(url, name, resource_context)) | 515 if (instance_iter->Matches(url, name, resource_context)) |
| 488 return &(*instance_iter); | 516 return &(*instance_iter); |
| 489 } | 517 } |
| 490 } | 518 } |
| 491 return NULL; | 519 return NULL; |
| 492 } | 520 } |
| 493 | 521 |
| 494 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindPendingInstance( | 522 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindPendingInstance( |
| 495 const GURL& url, | 523 const GURL& url, |
| 496 const string16& name, | 524 const string16& name, |
| 497 const content::ResourceContext* resource_context) { | 525 const ResourceContext* resource_context) { |
| 498 // Walk the pending instances looking for a matching pending worker. | 526 // Walk the pending instances looking for a matching pending worker. |
| 499 for (WorkerProcessHost::Instances::iterator iter = | 527 for (WorkerProcessHost::Instances::iterator iter = |
| 500 pending_shared_workers_.begin(); | 528 pending_shared_workers_.begin(); |
| 501 iter != pending_shared_workers_.end(); | 529 iter != pending_shared_workers_.end(); |
| 502 ++iter) { | 530 ++iter) { |
| 503 if (iter->Matches(url, name, resource_context)) { | 531 if (iter->Matches(url, name, resource_context)) { |
| 504 return &(*iter); | 532 return &(*iter); |
| 505 } | 533 } |
| 506 } | 534 } |
| 507 return NULL; | 535 return NULL; |
| 508 } | 536 } |
| 509 | 537 |
| 510 | 538 |
| 511 void WorkerServiceImpl::RemovePendingInstances( | 539 void WorkerServiceImpl::RemovePendingInstances( |
| 512 const GURL& url, | 540 const GURL& url, |
| 513 const string16& name, | 541 const string16& name, |
| 514 const content::ResourceContext* resource_context) { | 542 const ResourceContext* resource_context) { |
| 515 // Walk the pending instances looking for a matching pending worker. | 543 // Walk the pending instances looking for a matching pending worker. |
| 516 for (WorkerProcessHost::Instances::iterator iter = | 544 for (WorkerProcessHost::Instances::iterator iter = |
| 517 pending_shared_workers_.begin(); | 545 pending_shared_workers_.begin(); |
| 518 iter != pending_shared_workers_.end(); ) { | 546 iter != pending_shared_workers_.end(); ) { |
| 519 if (iter->Matches(url, name, resource_context)) { | 547 if (iter->Matches(url, name, resource_context)) { |
| 520 iter = pending_shared_workers_.erase(iter); | 548 iter = pending_shared_workers_.erase(iter); |
| 521 } else { | 549 } else { |
| 522 ++iter; | 550 ++iter; |
| 523 } | 551 } |
| 524 } | 552 } |
| 525 } | 553 } |
| 526 | 554 |
| 527 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::CreatePendingInstance( | 555 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::CreatePendingInstance( |
| 528 const GURL& url, | 556 const GURL& url, |
| 529 const string16& name, | 557 const string16& name, |
| 530 const content::ResourceContext* resource_context) { | 558 const ResourceContext* resource_context) { |
| 531 // Look for an existing pending shared worker. | 559 // Look for an existing pending shared worker. |
| 532 WorkerProcessHost::WorkerInstance* instance = | 560 WorkerProcessHost::WorkerInstance* instance = |
| 533 FindPendingInstance(url, name, resource_context); | 561 FindPendingInstance(url, name, resource_context); |
| 534 if (instance) | 562 if (instance) |
| 535 return instance; | 563 return instance; |
| 536 | 564 |
| 537 // No existing pending worker - create a new one. | 565 // No existing pending worker - create a new one. |
| 538 WorkerProcessHost::WorkerInstance pending(url, true, name, resource_context); | 566 WorkerProcessHost::WorkerInstance pending(url, true, name, resource_context); |
| 539 pending_shared_workers_.push_back(pending); | 567 pending_shared_workers_.push_back(pending); |
| 540 return &pending_shared_workers_.back(); | 568 return &pending_shared_workers_.back(); |
| 541 } | 569 } |
| 542 | 570 |
| 543 } // namespace content | 571 } // namespace content |
| OLD | NEW |