Chromium Code Reviews| 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 |