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 |