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 611 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
622 delete this; | 622 delete this; |
623 } | 623 } |
624 | 624 |
625 RenderProcessHost* render_process_host_; | 625 RenderProcessHost* render_process_host_; |
626 base::OnceClosure task_; | 626 base::OnceClosure task_; |
627 base::WeakPtrFactory<RenderProcessHostIsReadyObserver> weak_factory_; | 627 base::WeakPtrFactory<RenderProcessHostIsReadyObserver> weak_factory_; |
628 | 628 |
629 DISALLOW_COPY_AND_ASSIGN(RenderProcessHostIsReadyObserver); | 629 DISALLOW_COPY_AND_ASSIGN(RenderProcessHostIsReadyObserver); |
630 }; | 630 }; |
631 | 631 |
632 // The following class is used to track the sites each RenderProcessHost is | |
633 // hosting frames for and expecting navigations to. There are two of them per | |
634 // BrowserContext: one for frames and one for navigations. | |
635 // | |
636 // For each site, the SiteProcessCountTracker keeps a map of counts per | |
637 // RenderProcessHost, which represents the number of frames/navigations | |
638 // for this site that are associated with the RenderProcessHost. This allows to | |
639 // quickly lookup a list of RenderProcessHost that can be used by a particular | |
640 // SiteInstance. On the other hand, it does not allow to quickly lookup which | |
641 // sites are hosted by a RenderProcessHost. This class is meant to help reusing | |
642 // RenderProcessHosts among SiteInstances, not to perform security checks for a | |
643 // RenderProcessHost. | |
644 const void* const kCommittedSiteProcessCountTrackerKey = | |
645 "CommittedSiteProcessCountTrackerKey"; | |
646 const void* const kPendingSiteProcessCountTrackerKey = | |
647 "PendingSiteProcessCountTrackerKey"; | |
648 class SiteProcessCountTracker : public base::SupportsUserData::Data, | |
649 public RenderProcessHostObserver { | |
650 public: | |
651 SiteProcessCountTracker() {} | |
652 ~SiteProcessCountTracker() override { DCHECK(map_.empty()); } | |
653 | |
654 void IncrementSiteProcessCount(const GURL& site_url, | |
655 int render_process_host_id) { | |
656 std::map<ProcessID, Count>& counts_per_process = map_[site_url]; | |
657 ++counts_per_process[render_process_host_id]; | |
658 | |
659 #ifndef NDEBUG | |
660 // In tests, observer the RenderProcessHost destrcution, to check that it is | |
Charlie Reis
2017/05/24 17:18:37
nit: s/tests/debug builds/
nit: observe
nit: destr
clamy
2017/05/24 18:03:04
Done.
| |
661 // properly removed from the map. | |
662 RenderProcessHost* host = RenderProcessHost::FromID(render_process_host_id); | |
663 if (!HasProcess(host)) | |
664 host->AddObserver(this); | |
665 #endif | |
666 } | |
667 | |
668 void DecrementSiteProcessCount(const GURL& site_url, | |
669 int render_process_host_id) { | |
670 auto result = map_.find(site_url); | |
671 DCHECK(result != map_.end()); | |
672 std::map<ProcessID, Count>& counts_per_process = result->second; | |
673 | |
674 --counts_per_process[render_process_host_id]; | |
675 DCHECK(counts_per_process[render_process_host_id] >= 0); | |
676 | |
677 if (counts_per_process[render_process_host_id] == 0) | |
678 counts_per_process.erase(render_process_host_id); | |
679 | |
680 if (counts_per_process.empty()) | |
681 map_.erase(site_url); | |
682 } | |
683 | |
684 void FindRenderProcessesForSite( | |
685 const GURL& site_url, | |
686 std::set<RenderProcessHost*>* foreground_processes, | |
687 std::set<RenderProcessHost*>* background_processes) { | |
688 auto result = map_.find(site_url); | |
689 if (result == map_.end()) | |
690 return; | |
691 | |
692 std::map<ProcessID, Count>& counts_per_process = result->second; | |
693 for (auto iter : counts_per_process) { | |
694 RenderProcessHost* host = RenderProcessHost::FromID(iter.first); | |
695 DCHECK(host); | |
696 if (host->VisibleWidgetCount()) | |
697 foreground_processes->insert(host); | |
698 else | |
699 background_processes->insert(host); | |
700 } | |
701 } | |
702 | |
703 private: | |
704 void RenderProcessHostDestroyed(RenderProcessHost* host) override { | |
705 host->RemoveObserver(this); | |
Charlie Reis
2017/05/24 17:18:37
Shouldn't this be within the ifndef as well? We o
clamy
2017/05/24 18:03:04
Done.
| |
706 #ifndef NDEBUG | |
707 DCHECK(!HasProcess(host)); | |
708 #endif | |
709 } | |
710 | |
711 // Used in tests to ensure that RenderProcessHost don't persist in the map | |
Charlie Reis
2017/05/24 17:18:37
nit: s/tests/debug builds/
clamy
2017/05/24 18:03:04
Done.
| |
712 // after they've been destroyed. | |
713 bool HasProcess(RenderProcessHost* process) { | |
Charlie Reis
2017/05/24 17:18:37
I'd include this in the ifndef as well, given the
clamy
2017/05/24 18:03:04
Done.
| |
714 for (auto iter : map_) { | |
715 std::map<ProcessID, Count>& counts_per_process = iter.second; | |
716 for (auto iter_process : counts_per_process) { | |
717 if (iter_process.first == process->GetID()) | |
718 return true; | |
719 } | |
720 } | |
721 return false; | |
722 } | |
723 | |
724 using ProcessID = int; | |
725 using Count = int; | |
726 using CountPerProcessPerSiteMap = std::map<GURL, std::map<ProcessID, Count>>; | |
727 CountPerProcessPerSiteMap map_; | |
728 }; | |
729 | |
632 } // namespace | 730 } // namespace |
633 | 731 |
634 RendererMainThreadFactoryFunction g_renderer_main_thread_factory = NULL; | 732 RendererMainThreadFactoryFunction g_renderer_main_thread_factory = NULL; |
635 | 733 |
636 base::MessageLoop* g_in_process_thread; | 734 base::MessageLoop* g_in_process_thread; |
637 | 735 |
638 // Stores the maximum number of renderer processes the content module can | 736 // Stores the maximum number of renderer processes the content module can |
639 // create. | 737 // create. |
640 static size_t g_max_renderer_count_override = 0; | 738 static size_t g_max_renderer_count_override = 0; |
641 | 739 |
(...skipping 1099 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1741 DCHECK_GT(audio_stream_count_, 0); | 1839 DCHECK_GT(audio_stream_count_, 0); |
1742 --audio_stream_count_; | 1840 --audio_stream_count_; |
1743 UpdateProcessPriority(); | 1841 UpdateProcessPriority(); |
1744 } | 1842 } |
1745 | 1843 |
1746 void RenderProcessHostImpl::set_render_process_host_factory( | 1844 void RenderProcessHostImpl::set_render_process_host_factory( |
1747 const RenderProcessHostFactory* rph_factory) { | 1845 const RenderProcessHostFactory* rph_factory) { |
1748 g_render_process_host_factory_ = rph_factory; | 1846 g_render_process_host_factory_ = rph_factory; |
1749 } | 1847 } |
1750 | 1848 |
1849 // static | |
1850 void RenderProcessHostImpl::AddFrameWithSite( | |
1851 BrowserContext* browser_context, | |
1852 RenderProcessHost* render_process_host, | |
1853 const GURL& site_url) { | |
1854 if (site_url.is_empty()) | |
1855 return; | |
1856 | |
1857 SiteProcessCountTracker* tracker = static_cast<SiteProcessCountTracker*>( | |
1858 browser_context->GetUserData(kCommittedSiteProcessCountTrackerKey)); | |
1859 if (!tracker) { | |
1860 tracker = new SiteProcessCountTracker(); | |
1861 browser_context->SetUserData(kCommittedSiteProcessCountTrackerKey, | |
1862 base::WrapUnique(tracker)); | |
1863 } | |
1864 tracker->IncrementSiteProcessCount(site_url, render_process_host->GetID()); | |
1865 } | |
1866 | |
1867 // static | |
1868 void RenderProcessHostImpl::RemoveFrameWithSite( | |
1869 BrowserContext* browser_context, | |
1870 RenderProcessHost* render_process_host, | |
1871 const GURL& site_url) { | |
1872 if (site_url.is_empty()) | |
1873 return; | |
1874 | |
1875 SiteProcessCountTracker* tracker = static_cast<SiteProcessCountTracker*>( | |
1876 browser_context->GetUserData(kCommittedSiteProcessCountTrackerKey)); | |
1877 if (!tracker) { | |
1878 tracker = new SiteProcessCountTracker(); | |
1879 browser_context->SetUserData(kCommittedSiteProcessCountTrackerKey, | |
1880 base::WrapUnique(tracker)); | |
1881 } | |
1882 tracker->DecrementSiteProcessCount(site_url, render_process_host->GetID()); | |
1883 } | |
1884 | |
1885 // static | |
1886 void RenderProcessHostImpl::AddExpectedNavigationToSite( | |
1887 BrowserContext* browser_context, | |
1888 RenderProcessHost* render_process_host, | |
1889 const GURL& site_url) { | |
1890 if (site_url.is_empty()) | |
1891 return; | |
1892 | |
1893 SiteProcessCountTracker* tracker = static_cast<SiteProcessCountTracker*>( | |
1894 browser_context->GetUserData(kPendingSiteProcessCountTrackerKey)); | |
1895 if (!tracker) { | |
1896 tracker = new SiteProcessCountTracker(); | |
1897 browser_context->SetUserData(kPendingSiteProcessCountTrackerKey, | |
1898 base::WrapUnique(tracker)); | |
1899 } | |
1900 tracker->IncrementSiteProcessCount(site_url, render_process_host->GetID()); | |
1901 } | |
1902 | |
1903 // static | |
1904 void RenderProcessHostImpl::RemoveExpectedNavigationToSite( | |
1905 BrowserContext* browser_context, | |
1906 RenderProcessHost* render_process_host, | |
1907 const GURL& site_url) { | |
1908 if (site_url.is_empty()) | |
1909 return; | |
1910 | |
1911 SiteProcessCountTracker* tracker = static_cast<SiteProcessCountTracker*>( | |
1912 browser_context->GetUserData(kPendingSiteProcessCountTrackerKey)); | |
1913 if (!tracker) { | |
1914 tracker = new SiteProcessCountTracker(); | |
1915 browser_context->SetUserData(kPendingSiteProcessCountTrackerKey, | |
1916 base::WrapUnique(tracker)); | |
1917 } | |
1918 tracker->DecrementSiteProcessCount(site_url, render_process_host->GetID()); | |
1919 } | |
1920 | |
1751 bool RenderProcessHostImpl::IsForGuestsOnly() const { | 1921 bool RenderProcessHostImpl::IsForGuestsOnly() const { |
1752 return is_for_guests_only_; | 1922 return is_for_guests_only_; |
1753 } | 1923 } |
1754 | 1924 |
1755 StoragePartition* RenderProcessHostImpl::GetStoragePartition() const { | 1925 StoragePartition* RenderProcessHostImpl::GetStoragePartition() const { |
1756 return storage_partition_impl_; | 1926 return storage_partition_impl_; |
1757 } | 1927 } |
1758 | 1928 |
1759 static void AppendCompositorCommandLineFlags(base::CommandLine* command_line) { | 1929 static void AppendCompositorCommandLineFlags(base::CommandLine* command_line) { |
1760 command_line->AppendSwitchASCII( | 1930 command_line->AppendSwitchASCII( |
(...skipping 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2867 // First, attempt to reuse an existing RenderProcessHost if necessary. | 3037 // First, attempt to reuse an existing RenderProcessHost if necessary. |
2868 switch (process_reuse_policy) { | 3038 switch (process_reuse_policy) { |
2869 case SiteInstanceImpl::ProcessReusePolicy::PROCESS_PER_SITE: | 3039 case SiteInstanceImpl::ProcessReusePolicy::PROCESS_PER_SITE: |
2870 render_process_host = GetProcessHostForSite(browser_context, site_url); | 3040 render_process_host = GetProcessHostForSite(browser_context, site_url); |
2871 break; | 3041 break; |
2872 case SiteInstanceImpl::ProcessReusePolicy::USE_DEFAULT_SUBFRAME_PROCESS: | 3042 case SiteInstanceImpl::ProcessReusePolicy::USE_DEFAULT_SUBFRAME_PROCESS: |
2873 DCHECK(SiteIsolationPolicy::IsTopDocumentIsolationEnabled()); | 3043 DCHECK(SiteIsolationPolicy::IsTopDocumentIsolationEnabled()); |
2874 render_process_host = GetDefaultSubframeProcessHost( | 3044 render_process_host = GetDefaultSubframeProcessHost( |
2875 browser_context, site_instance, is_for_guests_only); | 3045 browser_context, site_instance, is_for_guests_only); |
2876 break; | 3046 break; |
3047 case SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE: | |
3048 render_process_host = | |
3049 FindReusableProcessHostForSite(browser_context, site_url); | |
3050 break; | |
2877 default: | 3051 default: |
2878 break; | 3052 break; |
2879 } | 3053 } |
2880 | 3054 |
2881 // If not (or if none found), see if we should reuse an existing process. | 3055 // If not (or if none found), see if we should reuse an existing process. |
2882 if (!render_process_host && | 3056 if (!render_process_host && |
2883 ShouldTryToUseExistingProcessHost(browser_context, site_url)) { | 3057 ShouldTryToUseExistingProcessHost(browser_context, site_url)) { |
2884 render_process_host = GetExistingProcessHost(browser_context, site_url); | 3058 render_process_host = GetExistingProcessHost(browser_context, site_url); |
2885 } | 3059 } |
2886 | 3060 |
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3259 browser_context->GetUserData(&kDefaultSubframeProcessHostHolderKey)); | 3433 browser_context->GetUserData(&kDefaultSubframeProcessHostHolderKey)); |
3260 if (!holder) { | 3434 if (!holder) { |
3261 holder = new DefaultSubframeProcessHostHolder(browser_context); | 3435 holder = new DefaultSubframeProcessHostHolder(browser_context); |
3262 browser_context->SetUserData(kDefaultSubframeProcessHostHolderKey, | 3436 browser_context->SetUserData(kDefaultSubframeProcessHostHolderKey, |
3263 base::WrapUnique(holder)); | 3437 base::WrapUnique(holder)); |
3264 } | 3438 } |
3265 | 3439 |
3266 return holder->GetProcessHost(site_instance, is_for_guests_only); | 3440 return holder->GetProcessHost(site_instance, is_for_guests_only); |
3267 } | 3441 } |
3268 | 3442 |
3443 // static | |
3444 RenderProcessHost* RenderProcessHostImpl::FindReusableProcessHostForSite( | |
3445 BrowserContext* browser_context, | |
3446 const GURL& site_url) { | |
3447 if (site_url.is_empty()) | |
3448 return nullptr; | |
3449 | |
3450 std::set<RenderProcessHost*> eligible_foreground_hosts; | |
3451 std::set<RenderProcessHost*> eligible_background_hosts; | |
3452 | |
3453 // First, add the RenderProcessHosts expecting a navigation to |site_url| to | |
3454 // the list of eligible RenderProcessHosts. | |
3455 SiteProcessCountTracker* pending_tracker = | |
3456 static_cast<SiteProcessCountTracker*>( | |
3457 browser_context->GetUserData(kPendingSiteProcessCountTrackerKey)); | |
3458 if (pending_tracker) { | |
3459 pending_tracker->FindRenderProcessesForSite( | |
3460 site_url, &eligible_foreground_hosts, &eligible_background_hosts); | |
3461 } | |
3462 | |
3463 if (eligible_foreground_hosts.empty()) { | |
3464 // If needed, add the RenderProcessHosts hosting a frame for |site_url| to | |
3465 // the list of eligible RenderProcessHosts. | |
3466 SiteProcessCountTracker* committed_tracker = | |
3467 static_cast<SiteProcessCountTracker*>( | |
3468 browser_context->GetUserData(kCommittedSiteProcessCountTrackerKey)); | |
3469 if (committed_tracker) { | |
3470 committed_tracker->FindRenderProcessesForSite( | |
3471 site_url, &eligible_foreground_hosts, &eligible_background_hosts); | |
3472 } | |
3473 } | |
3474 | |
3475 if (!eligible_foreground_hosts.empty()) { | |
3476 int index = base::RandInt(0, eligible_foreground_hosts.size() - 1); | |
3477 auto iterator = eligible_foreground_hosts.begin(); | |
3478 for (int i = 0; i < index; ++i) | |
3479 ++iterator; | |
3480 return (*iterator); | |
3481 } | |
3482 | |
3483 if (!eligible_background_hosts.empty()) { | |
3484 int index = base::RandInt(0, eligible_background_hosts.size() - 1); | |
3485 auto iterator = eligible_background_hosts.begin(); | |
3486 for (int i = 0; i < index; ++i) | |
3487 ++iterator; | |
3488 return (*iterator); | |
3489 } | |
3490 | |
3491 return nullptr; | |
3492 } | |
3493 | |
3269 #if BUILDFLAG(ENABLE_WEBRTC) | 3494 #if BUILDFLAG(ENABLE_WEBRTC) |
3270 void RenderProcessHostImpl::OnRegisterAecDumpConsumer(int id) { | 3495 void RenderProcessHostImpl::OnRegisterAecDumpConsumer(int id) { |
3271 BrowserThread::PostTask( | 3496 BrowserThread::PostTask( |
3272 BrowserThread::UI, FROM_HERE, | 3497 BrowserThread::UI, FROM_HERE, |
3273 base::Bind(&RenderProcessHostImpl::RegisterAecDumpConsumerOnUIThread, | 3498 base::Bind(&RenderProcessHostImpl::RegisterAecDumpConsumerOnUIThread, |
3274 weak_factory_.GetWeakPtr(), id)); | 3499 weak_factory_.GetWeakPtr(), id)); |
3275 } | 3500 } |
3276 | 3501 |
3277 void RenderProcessHostImpl::OnUnregisterAecDumpConsumer(int id) { | 3502 void RenderProcessHostImpl::OnUnregisterAecDumpConsumer(int id) { |
3278 BrowserThread::PostTask( | 3503 BrowserThread::PostTask( |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3349 LOG(ERROR) << "Terminating render process for bad Mojo message: " << error; | 3574 LOG(ERROR) << "Terminating render process for bad Mojo message: " << error; |
3350 | 3575 |
3351 // The ReceivedBadMessage call below will trigger a DumpWithoutCrashing. | 3576 // The ReceivedBadMessage call below will trigger a DumpWithoutCrashing. |
3352 // Capture the error message in a crash key value. | 3577 // Capture the error message in a crash key value. |
3353 base::debug::ScopedCrashKey error_key_value("mojo-message-error", error); | 3578 base::debug::ScopedCrashKey error_key_value("mojo-message-error", error); |
3354 bad_message::ReceivedBadMessage(render_process_id, | 3579 bad_message::ReceivedBadMessage(render_process_id, |
3355 bad_message::RPH_MOJO_PROCESS_ERROR); | 3580 bad_message::RPH_MOJO_PROCESS_ERROR); |
3356 } | 3581 } |
3357 | 3582 |
3358 } // namespace content | 3583 } // namespace content |
OLD | NEW |