OLD | NEW |
---|---|
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 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 // Represents the browser side of the browser <--> renderer communication | 5 // Represents the browser side of the browser <--> renderer communication |
6 // channel. There will be one RenderProcessHost per renderer process. | 6 // channel. There will be one RenderProcessHost per renderer process. |
7 | 7 |
8 #include "content/browser/renderer_host/render_process_host_impl.h" | 8 #include "content/browser/renderer_host/render_process_host_impl.h" |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
456 void Release(int old_route_id) { | 456 void Release(int old_route_id) { |
457 session_storage_namespaces_awaiting_close_->erase(old_route_id); | 457 session_storage_namespaces_awaiting_close_->erase(old_route_id); |
458 } | 458 } |
459 | 459 |
460 private: | 460 private: |
461 std::unique_ptr<std::map<int, SessionStorageNamespaceMap>> | 461 std::unique_ptr<std::map<int, SessionStorageNamespaceMap>> |
462 session_storage_namespaces_awaiting_close_; | 462 session_storage_namespaces_awaiting_close_; |
463 DISALLOW_COPY_AND_ASSIGN(SessionStorageHolder); | 463 DISALLOW_COPY_AND_ASSIGN(SessionStorageHolder); |
464 }; | 464 }; |
465 | 465 |
466 // This class manages spare RenderProcessHosts. | |
467 // | |
468 // There is a singleton instance of this class which manages a single spare | |
469 // renderer (g_spare_render_process_host_manager, below). This class | |
470 // encapsulates the implementation of | |
471 // RenderProcessHost::WarmupSpareRenderProcessHost() | |
472 // | |
473 // RenderProcessHostImpl should call | |
474 // SpareRenderProcessHostManager::MaybeTakeSpareRenderProcessHost when creating | |
475 // a new RPH. In this implementation, the spare renderer is bound to a | |
476 // BrowserContext and its default StoragePartition. If | |
477 // MaybeTakeSpareRenderProcessHost is called with a BrowserContext and | |
478 // StoragePartition that does not match, the spare renderer is discarded. In | |
479 // particular, only the default StoragePartition will be able to use a spare | |
480 // renderer. The spare renderer will also not be used as a guest renderer | |
481 // (is_for_guests_ == true). | |
482 // | |
483 // It is safe to call WarmupSpareRenderProcessHost multiple times, although if | |
484 // called in a context where the spare renderer is not likely to be used | |
485 // performance may suffer due to the unnecessary RPH creation. | |
486 class SpareRenderProcessHostManager : public RenderProcessHostObserver { | |
487 public: | |
488 SpareRenderProcessHostManager() {} | |
489 | |
490 void WarmupSpareRenderProcessHost(BrowserContext* browser_context) { | |
491 StoragePartitionImpl* current_partition = | |
492 static_cast<StoragePartitionImpl*>( | |
493 BrowserContext::GetStoragePartition(browser_context, nullptr)); | |
494 | |
495 if (spare_render_process_host_ && | |
496 matching_browser_context_ == browser_context && | |
497 matching_storage_partition_ == current_partition) | |
498 return; // Nothing to warm up. | |
499 | |
500 CleanupSpareRenderProcessHost(); | |
501 | |
502 // Don't create a spare renderer if we're running a single renderer or if | |
503 // we've got too many processes. See also ShouldTryToUseExistingProcessHost | |
504 // in this file. | |
505 if (RenderProcessHost::run_renderer_in_process() || | |
506 g_all_hosts.Get().size() >= | |
507 RenderProcessHostImpl::GetMaxRendererProcessCount()) | |
508 return; | |
509 | |
510 matching_browser_context_ = browser_context; | |
511 matching_storage_partition_ = current_partition; | |
512 | |
513 spare_render_process_host_ = RenderProcessHostImpl::CreateRenderProcessHost( | |
514 browser_context, current_partition, false /* is_for_guests_only */); | |
515 spare_render_process_host_->AddObserver(this); | |
516 spare_render_process_host_->Init(); | |
517 } | |
518 | |
519 RenderProcessHost* MaybeTakeSpareRenderProcessHost( | |
520 const BrowserContext* browser_context, | |
521 const StoragePartition* partition, | |
522 bool is_for_guests_only) { | |
523 if (!spare_render_process_host_ || | |
524 browser_context != matching_browser_context_ || | |
525 partition != matching_storage_partition_ || is_for_guests_only) { | |
526 // As a new RenderProcessHost will almost certainly be created, we cleanup | |
527 // the non-matching one so as not to waste resources. | |
528 CleanupSpareRenderProcessHost(); | |
529 return nullptr; | |
530 } | |
531 | |
532 RenderProcessHost* rph = spare_render_process_host_; | |
533 DropSpareRenderProcessHost(spare_render_process_host_); | |
534 return rph; | |
535 } | |
536 | |
537 void OnStoragePartitionShutdown(StoragePartition* partition) { | |
538 if (partition == matching_storage_partition_) | |
539 CleanupSpareRenderProcessHost(); | |
540 } | |
541 | |
542 RenderProcessHost* spare_render_process_host() { | |
543 return spare_render_process_host_; | |
544 } | |
545 | |
546 private: | |
547 // RenderProcessHostObserver | |
548 void RenderProcessWillExit(RenderProcessHost* host) override { | |
549 DropSpareRenderProcessHost(host); | |
550 } | |
551 | |
552 void RenderProcessExited(RenderProcessHost* host, | |
553 base::TerminationStatus unused_status, | |
554 int unused_exit_code) override { | |
555 DropSpareRenderProcessHost(host); | |
556 } | |
557 | |
558 void RenderProcessHostDestroyed(RenderProcessHost* host) override { | |
559 DropSpareRenderProcessHost(host); | |
560 } | |
561 | |
562 void CleanupSpareRenderProcessHost() { | |
563 if (spare_render_process_host_) { | |
564 spare_render_process_host_->Cleanup(); | |
565 DropSpareRenderProcessHost(spare_render_process_host_); | |
566 } | |
567 } | |
568 | |
569 // Remove |host| as a possible spare renderer. Does not shut it down cleanly; | |
570 // the assumption is that the host was shutdown somewhere else and has | |
571 // notifying the SpareRenderProcessHostManager. | |
572 void DropSpareRenderProcessHost(RenderProcessHost* host) { | |
573 if (host && host == spare_render_process_host_) { | |
Charlie Reis
2017/06/28 22:31:35
nit: Let's make the null pointer check be on spare
mattcary
2017/06/29 12:57:09
Done.
| |
574 spare_render_process_host_->RemoveObserver(this); | |
575 spare_render_process_host_ = nullptr; | |
576 } | |
577 } | |
578 | |
579 // This is a bare pointer, because RenderProcessHost manages the lifetime of | |
580 // all its instances; see g_all_hosts, above. | |
581 RenderProcessHost* spare_render_process_host_; | |
582 | |
583 // Used only to check if a creation request matches the spare, and not | |
584 // accessed. | |
585 const BrowserContext* matching_browser_context_ = nullptr; | |
586 const StoragePartition* matching_storage_partition_ = nullptr; | |
587 | |
588 DISALLOW_COPY_AND_ASSIGN(SpareRenderProcessHostManager); | |
589 }; | |
590 | |
591 base::LazyInstance<SpareRenderProcessHostManager>::Leaky | |
592 g_spare_render_process_host_manager = LAZY_INSTANCE_INITIALIZER; | |
593 | |
466 const void* const kDefaultSubframeProcessHostHolderKey = | 594 const void* const kDefaultSubframeProcessHostHolderKey = |
467 &kDefaultSubframeProcessHostHolderKey; | 595 &kDefaultSubframeProcessHostHolderKey; |
468 | 596 |
469 class DefaultSubframeProcessHostHolder : public base::SupportsUserData::Data, | 597 class DefaultSubframeProcessHostHolder : public base::SupportsUserData::Data, |
470 public RenderProcessHostObserver { | 598 public RenderProcessHostObserver { |
471 public: | 599 public: |
472 explicit DefaultSubframeProcessHostHolder(BrowserContext* browser_context) | 600 explicit DefaultSubframeProcessHostHolder(BrowserContext* browser_context) |
473 : browser_context_(browser_context) {} | 601 : browser_context_(browser_context) {} |
474 ~DefaultSubframeProcessHostHolder() override {} | 602 ~DefaultSubframeProcessHostHolder() override {} |
475 | 603 |
476 // Gets the correct render process to use for this SiteInstance. | 604 // Gets the correct render process to use for this SiteInstance. |
477 RenderProcessHost* GetProcessHost(SiteInstance* site_instance, | 605 RenderProcessHost* GetProcessHost(SiteInstance* site_instance, |
478 bool is_for_guests_only) { | 606 bool is_for_guests_only) { |
479 StoragePartition* default_partition = | 607 StoragePartition* default_partition = |
480 BrowserContext::GetDefaultStoragePartition(browser_context_); | 608 BrowserContext::GetDefaultStoragePartition(browser_context_); |
481 StoragePartition* partition = | 609 StoragePartition* partition = |
482 BrowserContext::GetStoragePartition(browser_context_, site_instance); | 610 BrowserContext::GetStoragePartition(browser_context_, site_instance); |
483 | 611 |
484 // Is this the default storage partition? If it isn't, then just give it its | 612 // Is this the default storage partition? If it isn't, then just give it its |
485 // own non-shared process. | 613 // own non-shared process. |
486 if (partition != default_partition || is_for_guests_only) { | 614 if (partition != default_partition || is_for_guests_only) { |
487 RenderProcessHostImpl* host = new RenderProcessHostImpl( | 615 RenderProcessHost* host = RenderProcessHostImpl::CreateRenderProcessHost( |
488 browser_context_, static_cast<StoragePartitionImpl*>(partition), | 616 browser_context_, static_cast<StoragePartitionImpl*>(partition), |
489 is_for_guests_only); | 617 is_for_guests_only); |
490 host->SetIsNeverSuitableForReuse(); | 618 host->SetIsNeverSuitableForReuse(); |
491 return host; | 619 return host; |
492 } | 620 } |
493 | 621 |
494 // If we already have a shared host for the default storage partition, use | 622 // If we already have a shared host for the default storage partition, use |
495 // it. | 623 // it. |
496 if (host_) | 624 if (host_) |
497 return host_; | 625 return host_; |
498 | 626 |
499 host_ = new RenderProcessHostImpl( | 627 // Before creating a new process, try to take a spare renderer. |
628 host_ = | |
629 g_spare_render_process_host_manager.Get() | |
630 .MaybeTakeSpareRenderProcessHost(browser_context_, partition, | |
631 false /* is for guests only */); | |
632 | |
633 host_ = RenderProcessHostImpl::CreateRenderProcessHost( | |
500 browser_context_, static_cast<StoragePartitionImpl*>(partition), | 634 browser_context_, static_cast<StoragePartitionImpl*>(partition), |
501 false /* for guests only */); | 635 false /* for guests only */); |
502 host_->SetIsNeverSuitableForReuse(); | 636 host_->SetIsNeverSuitableForReuse(); |
503 host_->AddObserver(this); | 637 host_->AddObserver(this); |
504 | 638 |
505 return host_; | 639 return host_; |
506 } | 640 } |
507 | 641 |
508 // Implementation of RenderProcessHostObserver. | 642 // Implementation of RenderProcessHostObserver. |
509 void RenderProcessHostDestroyed(RenderProcessHost* host) override { | 643 void RenderProcessHostDestroyed(RenderProcessHost* host) override { |
510 DCHECK_EQ(host_, host); | 644 DCHECK_EQ(host_, host); |
511 host_->RemoveObserver(this); | 645 host_->RemoveObserver(this); |
512 host_ = nullptr; | 646 host_ = nullptr; |
513 } | 647 } |
514 | 648 |
515 private: | 649 private: |
516 BrowserContext* browser_context_; | 650 BrowserContext* browser_context_; |
517 | 651 |
518 // The default subframe render process used for the default storage partition | 652 // The default subframe render process used for the default storage partition |
519 // of this BrowserContext. | 653 // of this BrowserContext. |
520 RenderProcessHostImpl* host_ = nullptr; | 654 RenderProcessHost* host_ = nullptr; |
521 }; | 655 }; |
522 | 656 |
523 void CreateMemoryCoordinatorHandle( | 657 void CreateMemoryCoordinatorHandle( |
524 int render_process_id, | 658 int render_process_id, |
525 const service_manager::BindSourceInfo& source_info, | 659 const service_manager::BindSourceInfo& source_info, |
526 mojom::MemoryCoordinatorHandleRequest request) { | 660 mojom::MemoryCoordinatorHandleRequest request) { |
527 MemoryCoordinatorImpl::GetInstance()->CreateHandle(render_process_id, | 661 MemoryCoordinatorImpl::GetInstance()->CreateHandle(render_process_id, |
528 std::move(request)); | 662 std::move(request)); |
529 } | 663 } |
530 | 664 |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
908 max_count = std::min(max_count, kMaxRendererProcessCount); | 1042 max_count = std::min(max_count, kMaxRendererProcessCount); |
909 } | 1043 } |
910 return max_count; | 1044 return max_count; |
911 } | 1045 } |
912 | 1046 |
913 // static | 1047 // static |
914 void RenderProcessHost::SetMaxRendererProcessCount(size_t count) { | 1048 void RenderProcessHost::SetMaxRendererProcessCount(size_t count) { |
915 g_max_renderer_count_override = count; | 1049 g_max_renderer_count_override = count; |
916 } | 1050 } |
917 | 1051 |
1052 // static | |
1053 RenderProcessHost* RenderProcessHostImpl::CreateRenderProcessHost( | |
1054 BrowserContext* browser_context, | |
1055 StoragePartitionImpl* storage_partition_impl, | |
1056 bool is_for_guests_only) { | |
1057 if (g_render_process_host_factory_) { | |
1058 return g_render_process_host_factory_->CreateRenderProcessHost( | |
1059 browser_context); | |
1060 } | |
1061 | |
1062 return new RenderProcessHostImpl(browser_context, storage_partition_impl, | |
1063 is_for_guests_only); | |
1064 } | |
1065 | |
918 RenderProcessHostImpl::RenderProcessHostImpl( | 1066 RenderProcessHostImpl::RenderProcessHostImpl( |
919 BrowserContext* browser_context, | 1067 BrowserContext* browser_context, |
920 StoragePartitionImpl* storage_partition_impl, | 1068 StoragePartitionImpl* storage_partition_impl, |
921 bool is_for_guests_only) | 1069 bool is_for_guests_only) |
922 : fast_shutdown_started_(false), | 1070 : fast_shutdown_started_(false), |
923 deleting_soon_(false), | 1071 deleting_soon_(false), |
924 #ifndef NDEBUG | 1072 #ifndef NDEBUG |
925 is_self_deleted_(false), | 1073 is_self_deleted_(false), |
926 #endif | 1074 #endif |
927 pending_views_(0), | 1075 pending_views_(0), |
(...skipping 1051 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1979 SiteProcessCountTracker* tracker = static_cast<SiteProcessCountTracker*>( | 2127 SiteProcessCountTracker* tracker = static_cast<SiteProcessCountTracker*>( |
1980 browser_context->GetUserData(kPendingSiteProcessCountTrackerKey)); | 2128 browser_context->GetUserData(kPendingSiteProcessCountTrackerKey)); |
1981 if (!tracker) { | 2129 if (!tracker) { |
1982 tracker = new SiteProcessCountTracker(); | 2130 tracker = new SiteProcessCountTracker(); |
1983 browser_context->SetUserData(kPendingSiteProcessCountTrackerKey, | 2131 browser_context->SetUserData(kPendingSiteProcessCountTrackerKey, |
1984 base::WrapUnique(tracker)); | 2132 base::WrapUnique(tracker)); |
1985 } | 2133 } |
1986 tracker->DecrementSiteProcessCount(site_url, render_process_host->GetID()); | 2134 tracker->DecrementSiteProcessCount(site_url, render_process_host->GetID()); |
1987 } | 2135 } |
1988 | 2136 |
2137 // static | |
2138 void RenderProcessHostImpl::OnStoragePartitionShutdown( | |
2139 StoragePartition* partition) { | |
2140 g_spare_render_process_host_manager.Get().OnStoragePartitionShutdown( | |
2141 partition); | |
2142 } | |
2143 | |
2144 // static | |
2145 RenderProcessHost* | |
2146 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting() { | |
2147 return g_spare_render_process_host_manager.Get().spare_render_process_host(); | |
2148 } | |
2149 | |
1989 bool RenderProcessHostImpl::IsForGuestsOnly() const { | 2150 bool RenderProcessHostImpl::IsForGuestsOnly() const { |
1990 return is_for_guests_only_; | 2151 return is_for_guests_only_; |
1991 } | 2152 } |
1992 | 2153 |
1993 StoragePartition* RenderProcessHostImpl::GetStoragePartition() const { | 2154 StoragePartition* RenderProcessHostImpl::GetStoragePartition() const { |
1994 return storage_partition_impl_; | 2155 return storage_partition_impl_; |
1995 } | 2156 } |
1996 | 2157 |
1997 static void AppendCompositorCommandLineFlags(base::CommandLine* command_line) { | 2158 static void AppendCompositorCommandLineFlags(base::CommandLine* command_line) { |
1998 command_line->AppendSwitchASCII( | 2159 command_line->AppendSwitchASCII( |
(...skipping 919 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2918 host->GetID()) != | 3079 host->GetID()) != |
2919 WebUIControllerFactoryRegistry::GetInstance()->UseWebUIBindingsForURL( | 3080 WebUIControllerFactoryRegistry::GetInstance()->UseWebUIBindingsForURL( |
2920 browser_context, site_url)) { | 3081 browser_context, site_url)) { |
2921 return false; | 3082 return false; |
2922 } | 3083 } |
2923 | 3084 |
2924 return GetContentClient()->browser()->IsSuitableHost(host, site_url); | 3085 return GetContentClient()->browser()->IsSuitableHost(host, site_url); |
2925 } | 3086 } |
2926 | 3087 |
2927 // static | 3088 // static |
3089 void RenderProcessHost::WarmupSpareRenderProcessHost( | |
3090 content::BrowserContext* browser_context) { | |
3091 g_spare_render_process_host_manager.Get().WarmupSpareRenderProcessHost( | |
3092 browser_context); | |
3093 } | |
3094 | |
3095 // static | |
2928 bool RenderProcessHost::run_renderer_in_process() { | 3096 bool RenderProcessHost::run_renderer_in_process() { |
2929 return g_run_renderer_in_process_; | 3097 return g_run_renderer_in_process_; |
2930 } | 3098 } |
2931 | 3099 |
2932 // static | 3100 // static |
2933 void RenderProcessHost::SetRunRendererInProcess(bool value) { | 3101 void RenderProcessHost::SetRunRendererInProcess(bool value) { |
2934 g_run_renderer_in_process_ = value; | 3102 g_run_renderer_in_process_ = value; |
2935 | 3103 |
2936 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | 3104 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
2937 if (value) { | 3105 if (value) { |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3116 default: | 3284 default: |
3117 break; | 3285 break; |
3118 } | 3286 } |
3119 | 3287 |
3120 // If not (or if none found), see if we should reuse an existing process. | 3288 // If not (or if none found), see if we should reuse an existing process. |
3121 if (!render_process_host && | 3289 if (!render_process_host && |
3122 ShouldTryToUseExistingProcessHost(browser_context, site_url)) { | 3290 ShouldTryToUseExistingProcessHost(browser_context, site_url)) { |
3123 render_process_host = GetExistingProcessHost(browser_context, site_url); | 3291 render_process_host = GetExistingProcessHost(browser_context, site_url); |
3124 } | 3292 } |
3125 | 3293 |
3294 // Before creating a new process, try to use a spare process if one is found. | |
3295 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>( | |
3296 BrowserContext::GetStoragePartition(browser_context, site_instance)); | |
3297 if (!render_process_host) { | |
3298 render_process_host = | |
3299 g_spare_render_process_host_manager.Get() | |
3300 .MaybeTakeSpareRenderProcessHost(browser_context, partition, | |
3301 is_for_guests_only); | |
3302 } | |
3303 | |
3126 // Otherwise (or if that fails), create a new one. | 3304 // Otherwise (or if that fails), create a new one. |
3127 if (!render_process_host) { | 3305 if (!render_process_host) { |
3128 if (g_render_process_host_factory_) { | 3306 render_process_host = |
3129 render_process_host = | 3307 CreateRenderProcessHost(browser_context, partition, is_for_guests_only); |
3130 g_render_process_host_factory_->CreateRenderProcessHost( | |
3131 browser_context); | |
3132 } else { | |
3133 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>( | |
3134 BrowserContext::GetStoragePartition(browser_context, site_instance)); | |
3135 render_process_host = new RenderProcessHostImpl( | |
3136 browser_context, partition, is_for_guests_only); | |
3137 } | |
3138 } | 3308 } |
3309 | |
3310 DCHECK(render_process_host); | |
3139 return render_process_host; | 3311 return render_process_host; |
3140 } | 3312 } |
3141 | 3313 |
3142 void RenderProcessHostImpl::CreateSharedRendererHistogramAllocator() { | 3314 void RenderProcessHostImpl::CreateSharedRendererHistogramAllocator() { |
3143 // Create a persistent memory segment for renderer histograms only if | 3315 // Create a persistent memory segment for renderer histograms only if |
3144 // they're active in the browser. | 3316 // they're active in the browser. |
3145 if (!base::GlobalHistogramAllocator::Get()) | 3317 if (!base::GlobalHistogramAllocator::Get()) |
3146 return; | 3318 return; |
3147 | 3319 |
3148 // Get handle to the renderer process. Stop if there is none. | 3320 // Get handle to the renderer process. Stop if there is none. |
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3635 LOG(ERROR) << "Terminating render process for bad Mojo message: " << error; | 3807 LOG(ERROR) << "Terminating render process for bad Mojo message: " << error; |
3636 | 3808 |
3637 // The ReceivedBadMessage call below will trigger a DumpWithoutCrashing. | 3809 // The ReceivedBadMessage call below will trigger a DumpWithoutCrashing. |
3638 // Capture the error message in a crash key value. | 3810 // Capture the error message in a crash key value. |
3639 base::debug::ScopedCrashKey error_key_value("mojo-message-error", error); | 3811 base::debug::ScopedCrashKey error_key_value("mojo-message-error", error); |
3640 bad_message::ReceivedBadMessage(render_process_id, | 3812 bad_message::ReceivedBadMessage(render_process_id, |
3641 bad_message::RPH_MOJO_PROCESS_ERROR); | 3813 bad_message::RPH_MOJO_PROCESS_ERROR); |
3642 } | 3814 } |
3643 | 3815 |
3644 } // namespace content | 3816 } // namespace content |
OLD | NEW |