Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(854)

Side by Side Diff: content/browser/worker_host/worker_service_impl.cc

Issue 22314003: NavigationController prototype Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: NavController prototype - chrome side Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 375 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 iter != pending_shared_workers_.end(); ) { 386 iter != pending_shared_workers_.end(); ) {
387 iter->worker_document_set()->Remove(filter, document_id); 387 iter->worker_document_set()->Remove(filter, document_id);
388 if (iter->worker_document_set()->IsEmpty()) { 388 if (iter->worker_document_set()->IsEmpty()) {
389 iter = pending_shared_workers_.erase(iter); 389 iter = pending_shared_workers_.erase(iter);
390 } else { 390 } else {
391 ++iter; 391 ++iter;
392 } 392 }
393 } 393 }
394 } 394 }
395 395
396 int WorkerServiceImpl::CreateAndStartEmbeddedWorker(
397 ResourceContext* resource_context,
398 const WorkerStoragePartition& partition,
399 const GURL& url,
400 const std::string& raw_handler_source,
401 int64 associated_appcache_id) {
402 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
403 // Generate a unique route id for the browser-worker communication that's
404 // unique among all worker processes. That way when the worker process sends
405 // a wrapped IPC message through us, we know which WorkerProcessHost to give
406 // it to.
407 int worker_route_id = next_worker_route_id();
408 WorkerProcessHost::WorkerInstance instance(
409 url,
410 string16(),
411 worker_route_id,
412 0,
413 0, // associated_appcache_id,
414 resource_context,
415 partition);
416 instance.is_embedded_worker_ = true;
417 CreateWorkerFromInstance(instance);
418 SendToEmbeddedWorker(
419 worker_route_id,
420 new WorkerMsg_StartEmbeddedWorkerContext(
421 worker_route_id, url, raw_handler_source));
422 return worker_route_id;
423 }
424
425 namespace {
426 // Helper to get the WPH for a given embedded worker id.
427 WorkerProcessHost* FindEmbeddedWorkerProcessHost(int worker_route_id) {
428 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) {
429 const WorkerProcessHost::Instances& instances = (*iter)->instances();
430 for (WorkerProcessHost::Instances::const_iterator i = instances.begin();
431 i != instances.end(); ++i) {
432 if (i->is_embedded_worker_ && i->worker_route_id() == worker_route_id) {
433 return *iter;
434 }
435 }
436 }
437 return NULL;
438 }
439 } // namespace
440
441 bool WorkerServiceImpl::SendToEmbeddedWorker(
442 int worker_route_id, IPC::Message* message) {
443 WorkerProcessHost* host = FindEmbeddedWorkerProcessHost(worker_route_id);
444 if (!host) {
445 delete message;
446 return false;
447 }
448 return host->Send(message);
449 }
450
451 void WorkerServiceImpl::TerminateEmbeddedWorker(int worker_route_id) {
452 WorkerProcessHost* host = FindEmbeddedWorkerProcessHost(worker_route_id);
453 if (!host)
454 return;
455 host->TerminateWorker(worker_route_id);
456 }
457
396 bool WorkerServiceImpl::CreateWorkerFromInstance( 458 bool WorkerServiceImpl::CreateWorkerFromInstance(
397 WorkerProcessHost::WorkerInstance instance) { 459 WorkerProcessHost::WorkerInstance instance) {
398 if (!CanCreateWorkerProcess(instance)) { 460 if (!instance.is_embedded_worker_) {
399 queued_workers_.push_back(instance); 461 if (!CanCreateWorkerProcess(instance)) {
400 return true; 462 queued_workers_.push_back(instance);
463 return true;
464 }
465
466 // Check to see if this shared worker is already running (two pages may have
467 // tried to start up the worker simultaneously).
468 // See if a worker with this name already exists.
469 WorkerProcessHost::WorkerInstance* existing_instance =
470 FindSharedWorkerInstance(
471 instance.url(), instance.name(), instance.partition(),
472 instance.resource_context());
473 WorkerProcessHost::WorkerInstance::FilterInfo filter_info =
474 instance.GetFilter();
475 // If this worker is already running, no need to create a new copy. Just
476 // inform the caller that the worker has been created.
477 if (existing_instance) {
478 // Walk the worker's filter list to see if this client is listed. If not,
479 // then it means that the worker started by the client already exited so
480 // we should not attach to this new one (http://crbug.com/29243).
481 if (!existing_instance->HasFilter(filter_info.first, filter_info.second))
482 return false;
483 filter_info.first->Send(new ViewMsg_WorkerCreated(filter_info.second));
484 return true;
485 }
486
487 // Look to see if there's a pending instance.
488 WorkerProcessHost::WorkerInstance* pending = FindPendingInstance(
489 instance.url(), instance.name(), instance.partition(),
490 instance.resource_context());
491 // If there's no instance *and* no pending instance (or there is a pending
492 // instance but it does not contain our filter info), then it means the
493 // worker started up and exited already. Log a warning because this should
494 // be a very rare occurrence and is probably a bug, but it *can* happen so
495 // handle it gracefully.
496 if (!pending ||
497 !pending->HasFilter(filter_info.first, filter_info.second)) {
498 DLOG(WARNING) << "Pending worker already exited";
499 return false;
500 }
501
502 // Assign the accumulated document set and filter list for this pending
503 // worker to the new instance.
504 DCHECK(!pending->worker_document_set()->IsEmpty());
505 instance.ShareDocumentSet(*pending);
506 for (WorkerProcessHost::WorkerInstance::FilterList::const_iterator i =
507 pending->filters().begin();
508 i != pending->filters().end(); ++i) {
509 instance.AddFilter(i->first, i->second);
510 }
511 RemovePendingInstances(instance.url(), instance.name(),
512 instance.partition(), instance.resource_context());
513
514 // Remove any queued instances of this worker and copy over the filter to
515 // this instance.
516 for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin();
517 iter != queued_workers_.end();) {
518 if (iter->Matches(instance.url(), instance.name(),
519 instance.partition(), instance.resource_context())) {
520 DCHECK(iter->NumFilters() == 1);
521 WorkerProcessHost::WorkerInstance::FilterInfo filter_info =
522 iter->GetFilter();
523 instance.AddFilter(filter_info.first, filter_info.second);
524 iter = queued_workers_.erase(iter);
525 } else {
526 ++iter;
527 }
528 }
529 DCHECK_EQ(instance.filters().begin()->first->render_process_id(),
530 instance.parent_process_id());
401 } 531 }
402 532
403 // Check to see if this shared worker is already running (two pages may have
404 // tried to start up the worker simultaneously).
405 // See if a worker with this name already exists.
406 WorkerProcessHost::WorkerInstance* existing_instance =
407 FindSharedWorkerInstance(
408 instance.url(), instance.name(), instance.partition(),
409 instance.resource_context());
410 WorkerProcessHost::WorkerInstance::FilterInfo filter_info =
411 instance.GetFilter();
412 // If this worker is already running, no need to create a new copy. Just
413 // inform the caller that the worker has been created.
414 if (existing_instance) {
415 // Walk the worker's filter list to see if this client is listed. If not,
416 // then it means that the worker started by the client already exited so
417 // we should not attach to this new one (http://crbug.com/29243).
418 if (!existing_instance->HasFilter(filter_info.first, filter_info.second))
419 return false;
420 filter_info.first->Send(new ViewMsg_WorkerCreated(filter_info.second));
421 return true;
422 }
423
424 // Look to see if there's a pending instance.
425 WorkerProcessHost::WorkerInstance* pending = FindPendingInstance(
426 instance.url(), instance.name(), instance.partition(),
427 instance.resource_context());
428 // If there's no instance *and* no pending instance (or there is a pending
429 // instance but it does not contain our filter info), then it means the
430 // worker started up and exited already. Log a warning because this should
431 // be a very rare occurrence and is probably a bug, but it *can* happen so
432 // handle it gracefully.
433 if (!pending ||
434 !pending->HasFilter(filter_info.first, filter_info.second)) {
435 DLOG(WARNING) << "Pending worker already exited";
436 return false;
437 }
438
439 // Assign the accumulated document set and filter list for this pending
440 // worker to the new instance.
441 DCHECK(!pending->worker_document_set()->IsEmpty());
442 instance.ShareDocumentSet(*pending);
443 for (WorkerProcessHost::WorkerInstance::FilterList::const_iterator i =
444 pending->filters().begin();
445 i != pending->filters().end(); ++i) {
446 instance.AddFilter(i->first, i->second);
447 }
448 RemovePendingInstances(instance.url(), instance.name(),
449 instance.partition(), instance.resource_context());
450
451 // Remove any queued instances of this worker and copy over the filter to
452 // this instance.
453 for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin();
454 iter != queued_workers_.end();) {
455 if (iter->Matches(instance.url(), instance.name(),
456 instance.partition(), instance.resource_context())) {
457 DCHECK(iter->NumFilters() == 1);
458 WorkerProcessHost::WorkerInstance::FilterInfo filter_info =
459 iter->GetFilter();
460 instance.AddFilter(filter_info.first, filter_info.second);
461 iter = queued_workers_.erase(iter);
462 } else {
463 ++iter;
464 }
465 }
466
467 WorkerMessageFilter* first_filter = instance.filters().begin()->first;
468 WorkerProcessHost* worker = new WorkerProcessHost( 533 WorkerProcessHost* worker = new WorkerProcessHost(
469 instance.resource_context(), instance.partition()); 534 instance.resource_context(), instance.partition());
470 // TODO(atwilson): This won't work if the message is from a worker process. 535 // TODO(atwilson): This won't work if the message is from a worker process.
471 // We don't support that yet though (this message is only sent from 536 // We don't support that yet though (this message is only sent from
472 // renderers) but when we do, we'll need to add code to pass in the current 537 // renderers) but when we do, we'll need to add code to pass in the current
473 // worker's document set for nested workers. 538 // worker's document set for nested workers.
474 if (!worker->Init(first_filter->render_process_id())) { 539 if (!worker->Init(instance.parent_process_id())) {
475 delete worker; 540 delete worker;
476 return false; 541 return false;
477 } 542 }
478 543
479 worker->CreateWorker(instance); 544 worker->CreateWorker(instance);
480 FOR_EACH_OBSERVER( 545 FOR_EACH_OBSERVER(
481 WorkerServiceObserver, observers_, 546 WorkerServiceObserver, observers_,
482 WorkerCreated(instance.url(), instance.name(), worker->GetData().id, 547 WorkerCreated(instance.url(), instance.name(), worker->GetData().id,
483 instance.worker_route_id())); 548 instance.worker_route_id()));
484 WorkerDevToolsManager::GetInstance()->WorkerCreated(worker, instance); 549 WorkerDevToolsManager::GetInstance()->WorkerCreated(worker, instance);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 } 626 }
562 627
563 bool WorkerServiceImpl::GetRendererForWorker(int worker_process_id, 628 bool WorkerServiceImpl::GetRendererForWorker(int worker_process_id,
564 int* render_process_id, 629 int* render_process_id,
565 int* render_view_id) const { 630 int* render_view_id) const {
566 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { 631 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) {
567 if (iter.GetData().id != worker_process_id) 632 if (iter.GetData().id != worker_process_id)
568 continue; 633 continue;
569 634
570 // This code assumes one worker per process, see function comment in header! 635 // This code assumes one worker per process, see function comment in header!
636 // ^^^ gee, lovely ^^^
571 WorkerProcessHost::Instances::const_iterator first_instance = 637 WorkerProcessHost::Instances::const_iterator first_instance =
572 iter->instances().begin(); 638 iter->instances().begin();
573 if (first_instance == iter->instances().end()) 639 if (first_instance == iter->instances().end())
574 return false; 640 return false;
575 641
576 WorkerDocumentSet::DocumentInfoSet::const_iterator info = 642 WorkerDocumentSet::DocumentInfoSet::const_iterator info =
577 first_instance->worker_document_set()->documents().begin(); 643 first_instance->worker_document_set()->documents().begin();
578 *render_process_id = info->render_process_id(); 644 *render_process_id = info->render_process_id();
579 *render_view_id = info->render_view_id(); 645 *render_view_id = info->render_view_id();
580 return true; 646 return true;
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
709 return instance; 775 return instance;
710 776
711 // No existing pending worker - create a new one. 777 // No existing pending worker - create a new one.
712 WorkerProcessHost::WorkerInstance pending( 778 WorkerProcessHost::WorkerInstance pending(
713 url, true, name, resource_context, partition); 779 url, true, name, resource_context, partition);
714 pending_shared_workers_.push_back(pending); 780 pending_shared_workers_.push_back(pending);
715 return &pending_shared_workers_.back(); 781 return &pending_shared_workers_.back();
716 } 782 }
717 783
718 } // namespace content 784 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/worker_host/worker_service_impl.h ('k') | content/child/appcache/appcache_backend_proxy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698