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 debug builds, observe the RenderProcessHost destruction, to check |
| 661 // that it is 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 #ifndef NDEBUG |
| 706 host->RemoveObserver(this); |
| 707 DCHECK(!HasProcess(host)); |
| 708 #endif |
| 709 } |
| 710 |
| 711 #ifndef NDEBUG |
| 712 // Used in debug builds to ensure that RenderProcessHost don't persist in the |
| 713 // map after they've been destroyed. |
| 714 bool HasProcess(RenderProcessHost* process) { |
| 715 for (auto iter : map_) { |
| 716 std::map<ProcessID, Count>& counts_per_process = iter.second; |
| 717 for (auto iter_process : counts_per_process) { |
| 718 if (iter_process.first == process->GetID()) |
| 719 return true; |
| 720 } |
| 721 } |
| 722 return false; |
| 723 } |
| 724 #endif |
| 725 |
| 726 using ProcessID = int; |
| 727 using Count = int; |
| 728 using CountPerProcessPerSiteMap = std::map<GURL, std::map<ProcessID, Count>>; |
| 729 CountPerProcessPerSiteMap map_; |
| 730 }; |
| 731 |
632 } // namespace | 732 } // namespace |
633 | 733 |
634 RendererMainThreadFactoryFunction g_renderer_main_thread_factory = NULL; | 734 RendererMainThreadFactoryFunction g_renderer_main_thread_factory = NULL; |
635 | 735 |
636 base::MessageLoop* g_in_process_thread; | 736 base::MessageLoop* g_in_process_thread; |
637 | 737 |
638 // Stores the maximum number of renderer processes the content module can | 738 // Stores the maximum number of renderer processes the content module can |
639 // create. | 739 // create. |
640 static size_t g_max_renderer_count_override = 0; | 740 static size_t g_max_renderer_count_override = 0; |
641 | 741 |
(...skipping 1099 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1741 DCHECK_GT(audio_stream_count_, 0); | 1841 DCHECK_GT(audio_stream_count_, 0); |
1742 --audio_stream_count_; | 1842 --audio_stream_count_; |
1743 UpdateProcessPriority(); | 1843 UpdateProcessPriority(); |
1744 } | 1844 } |
1745 | 1845 |
1746 void RenderProcessHostImpl::set_render_process_host_factory( | 1846 void RenderProcessHostImpl::set_render_process_host_factory( |
1747 const RenderProcessHostFactory* rph_factory) { | 1847 const RenderProcessHostFactory* rph_factory) { |
1748 g_render_process_host_factory_ = rph_factory; | 1848 g_render_process_host_factory_ = rph_factory; |
1749 } | 1849 } |
1750 | 1850 |
| 1851 // static |
| 1852 void RenderProcessHostImpl::AddFrameWithSite( |
| 1853 BrowserContext* browser_context, |
| 1854 RenderProcessHost* render_process_host, |
| 1855 const GURL& site_url) { |
| 1856 if (site_url.is_empty()) |
| 1857 return; |
| 1858 |
| 1859 SiteProcessCountTracker* tracker = static_cast<SiteProcessCountTracker*>( |
| 1860 browser_context->GetUserData(kCommittedSiteProcessCountTrackerKey)); |
| 1861 if (!tracker) { |
| 1862 tracker = new SiteProcessCountTracker(); |
| 1863 browser_context->SetUserData(kCommittedSiteProcessCountTrackerKey, |
| 1864 base::WrapUnique(tracker)); |
| 1865 } |
| 1866 tracker->IncrementSiteProcessCount(site_url, render_process_host->GetID()); |
| 1867 } |
| 1868 |
| 1869 // static |
| 1870 void RenderProcessHostImpl::RemoveFrameWithSite( |
| 1871 BrowserContext* browser_context, |
| 1872 RenderProcessHost* render_process_host, |
| 1873 const GURL& site_url) { |
| 1874 if (site_url.is_empty()) |
| 1875 return; |
| 1876 |
| 1877 SiteProcessCountTracker* tracker = static_cast<SiteProcessCountTracker*>( |
| 1878 browser_context->GetUserData(kCommittedSiteProcessCountTrackerKey)); |
| 1879 if (!tracker) { |
| 1880 tracker = new SiteProcessCountTracker(); |
| 1881 browser_context->SetUserData(kCommittedSiteProcessCountTrackerKey, |
| 1882 base::WrapUnique(tracker)); |
| 1883 } |
| 1884 tracker->DecrementSiteProcessCount(site_url, render_process_host->GetID()); |
| 1885 } |
| 1886 |
| 1887 // static |
| 1888 void RenderProcessHostImpl::AddExpectedNavigationToSite( |
| 1889 BrowserContext* browser_context, |
| 1890 RenderProcessHost* render_process_host, |
| 1891 const GURL& site_url) { |
| 1892 if (site_url.is_empty()) |
| 1893 return; |
| 1894 |
| 1895 SiteProcessCountTracker* tracker = static_cast<SiteProcessCountTracker*>( |
| 1896 browser_context->GetUserData(kPendingSiteProcessCountTrackerKey)); |
| 1897 if (!tracker) { |
| 1898 tracker = new SiteProcessCountTracker(); |
| 1899 browser_context->SetUserData(kPendingSiteProcessCountTrackerKey, |
| 1900 base::WrapUnique(tracker)); |
| 1901 } |
| 1902 tracker->IncrementSiteProcessCount(site_url, render_process_host->GetID()); |
| 1903 } |
| 1904 |
| 1905 // static |
| 1906 void RenderProcessHostImpl::RemoveExpectedNavigationToSite( |
| 1907 BrowserContext* browser_context, |
| 1908 RenderProcessHost* render_process_host, |
| 1909 const GURL& site_url) { |
| 1910 if (site_url.is_empty()) |
| 1911 return; |
| 1912 |
| 1913 SiteProcessCountTracker* tracker = static_cast<SiteProcessCountTracker*>( |
| 1914 browser_context->GetUserData(kPendingSiteProcessCountTrackerKey)); |
| 1915 if (!tracker) { |
| 1916 tracker = new SiteProcessCountTracker(); |
| 1917 browser_context->SetUserData(kPendingSiteProcessCountTrackerKey, |
| 1918 base::WrapUnique(tracker)); |
| 1919 } |
| 1920 tracker->DecrementSiteProcessCount(site_url, render_process_host->GetID()); |
| 1921 } |
| 1922 |
1751 bool RenderProcessHostImpl::IsForGuestsOnly() const { | 1923 bool RenderProcessHostImpl::IsForGuestsOnly() const { |
1752 return is_for_guests_only_; | 1924 return is_for_guests_only_; |
1753 } | 1925 } |
1754 | 1926 |
1755 StoragePartition* RenderProcessHostImpl::GetStoragePartition() const { | 1927 StoragePartition* RenderProcessHostImpl::GetStoragePartition() const { |
1756 return storage_partition_impl_; | 1928 return storage_partition_impl_; |
1757 } | 1929 } |
1758 | 1930 |
1759 static void AppendCompositorCommandLineFlags(base::CommandLine* command_line) { | 1931 static void AppendCompositorCommandLineFlags(base::CommandLine* command_line) { |
1760 command_line->AppendSwitchASCII( | 1932 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. | 3039 // First, attempt to reuse an existing RenderProcessHost if necessary. |
2868 switch (process_reuse_policy) { | 3040 switch (process_reuse_policy) { |
2869 case SiteInstanceImpl::ProcessReusePolicy::PROCESS_PER_SITE: | 3041 case SiteInstanceImpl::ProcessReusePolicy::PROCESS_PER_SITE: |
2870 render_process_host = GetProcessHostForSite(browser_context, site_url); | 3042 render_process_host = GetProcessHostForSite(browser_context, site_url); |
2871 break; | 3043 break; |
2872 case SiteInstanceImpl::ProcessReusePolicy::USE_DEFAULT_SUBFRAME_PROCESS: | 3044 case SiteInstanceImpl::ProcessReusePolicy::USE_DEFAULT_SUBFRAME_PROCESS: |
2873 DCHECK(SiteIsolationPolicy::IsTopDocumentIsolationEnabled()); | 3045 DCHECK(SiteIsolationPolicy::IsTopDocumentIsolationEnabled()); |
2874 render_process_host = GetDefaultSubframeProcessHost( | 3046 render_process_host = GetDefaultSubframeProcessHost( |
2875 browser_context, site_instance, is_for_guests_only); | 3047 browser_context, site_instance, is_for_guests_only); |
2876 break; | 3048 break; |
| 3049 case SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE: |
| 3050 render_process_host = |
| 3051 FindReusableProcessHostForSite(browser_context, site_url); |
| 3052 break; |
2877 default: | 3053 default: |
2878 break; | 3054 break; |
2879 } | 3055 } |
2880 | 3056 |
2881 // If not (or if none found), see if we should reuse an existing process. | 3057 // If not (or if none found), see if we should reuse an existing process. |
2882 if (!render_process_host && | 3058 if (!render_process_host && |
2883 ShouldTryToUseExistingProcessHost(browser_context, site_url)) { | 3059 ShouldTryToUseExistingProcessHost(browser_context, site_url)) { |
2884 render_process_host = GetExistingProcessHost(browser_context, site_url); | 3060 render_process_host = GetExistingProcessHost(browser_context, site_url); |
2885 } | 3061 } |
2886 | 3062 |
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3259 browser_context->GetUserData(&kDefaultSubframeProcessHostHolderKey)); | 3435 browser_context->GetUserData(&kDefaultSubframeProcessHostHolderKey)); |
3260 if (!holder) { | 3436 if (!holder) { |
3261 holder = new DefaultSubframeProcessHostHolder(browser_context); | 3437 holder = new DefaultSubframeProcessHostHolder(browser_context); |
3262 browser_context->SetUserData(kDefaultSubframeProcessHostHolderKey, | 3438 browser_context->SetUserData(kDefaultSubframeProcessHostHolderKey, |
3263 base::WrapUnique(holder)); | 3439 base::WrapUnique(holder)); |
3264 } | 3440 } |
3265 | 3441 |
3266 return holder->GetProcessHost(site_instance, is_for_guests_only); | 3442 return holder->GetProcessHost(site_instance, is_for_guests_only); |
3267 } | 3443 } |
3268 | 3444 |
| 3445 // static |
| 3446 RenderProcessHost* RenderProcessHostImpl::FindReusableProcessHostForSite( |
| 3447 BrowserContext* browser_context, |
| 3448 const GURL& site_url) { |
| 3449 if (site_url.is_empty()) |
| 3450 return nullptr; |
| 3451 |
| 3452 std::set<RenderProcessHost*> eligible_foreground_hosts; |
| 3453 std::set<RenderProcessHost*> eligible_background_hosts; |
| 3454 |
| 3455 // First, add the RenderProcessHosts expecting a navigation to |site_url| to |
| 3456 // the list of eligible RenderProcessHosts. |
| 3457 SiteProcessCountTracker* pending_tracker = |
| 3458 static_cast<SiteProcessCountTracker*>( |
| 3459 browser_context->GetUserData(kPendingSiteProcessCountTrackerKey)); |
| 3460 if (pending_tracker) { |
| 3461 pending_tracker->FindRenderProcessesForSite( |
| 3462 site_url, &eligible_foreground_hosts, &eligible_background_hosts); |
| 3463 } |
| 3464 |
| 3465 if (eligible_foreground_hosts.empty()) { |
| 3466 // If needed, add the RenderProcessHosts hosting a frame for |site_url| to |
| 3467 // the list of eligible RenderProcessHosts. |
| 3468 SiteProcessCountTracker* committed_tracker = |
| 3469 static_cast<SiteProcessCountTracker*>( |
| 3470 browser_context->GetUserData(kCommittedSiteProcessCountTrackerKey)); |
| 3471 if (committed_tracker) { |
| 3472 committed_tracker->FindRenderProcessesForSite( |
| 3473 site_url, &eligible_foreground_hosts, &eligible_background_hosts); |
| 3474 } |
| 3475 } |
| 3476 |
| 3477 if (!eligible_foreground_hosts.empty()) { |
| 3478 int index = base::RandInt(0, eligible_foreground_hosts.size() - 1); |
| 3479 auto iterator = eligible_foreground_hosts.begin(); |
| 3480 for (int i = 0; i < index; ++i) |
| 3481 ++iterator; |
| 3482 return (*iterator); |
| 3483 } |
| 3484 |
| 3485 if (!eligible_background_hosts.empty()) { |
| 3486 int index = base::RandInt(0, eligible_background_hosts.size() - 1); |
| 3487 auto iterator = eligible_background_hosts.begin(); |
| 3488 for (int i = 0; i < index; ++i) |
| 3489 ++iterator; |
| 3490 return (*iterator); |
| 3491 } |
| 3492 |
| 3493 return nullptr; |
| 3494 } |
| 3495 |
3269 #if BUILDFLAG(ENABLE_WEBRTC) | 3496 #if BUILDFLAG(ENABLE_WEBRTC) |
3270 void RenderProcessHostImpl::OnRegisterAecDumpConsumer(int id) { | 3497 void RenderProcessHostImpl::OnRegisterAecDumpConsumer(int id) { |
3271 BrowserThread::PostTask( | 3498 BrowserThread::PostTask( |
3272 BrowserThread::UI, FROM_HERE, | 3499 BrowserThread::UI, FROM_HERE, |
3273 base::Bind(&RenderProcessHostImpl::RegisterAecDumpConsumerOnUIThread, | 3500 base::Bind(&RenderProcessHostImpl::RegisterAecDumpConsumerOnUIThread, |
3274 weak_factory_.GetWeakPtr(), id)); | 3501 weak_factory_.GetWeakPtr(), id)); |
3275 } | 3502 } |
3276 | 3503 |
3277 void RenderProcessHostImpl::OnUnregisterAecDumpConsumer(int id) { | 3504 void RenderProcessHostImpl::OnUnregisterAecDumpConsumer(int id) { |
3278 BrowserThread::PostTask( | 3505 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; | 3576 LOG(ERROR) << "Terminating render process for bad Mojo message: " << error; |
3350 | 3577 |
3351 // The ReceivedBadMessage call below will trigger a DumpWithoutCrashing. | 3578 // The ReceivedBadMessage call below will trigger a DumpWithoutCrashing. |
3352 // Capture the error message in a crash key value. | 3579 // Capture the error message in a crash key value. |
3353 base::debug::ScopedCrashKey error_key_value("mojo-message-error", error); | 3580 base::debug::ScopedCrashKey error_key_value("mojo-message-error", error); |
3354 bad_message::ReceivedBadMessage(render_process_id, | 3581 bad_message::ReceivedBadMessage(render_process_id, |
3355 bad_message::RPH_MOJO_PROCESS_ERROR); | 3582 bad_message::RPH_MOJO_PROCESS_ERROR); |
3356 } | 3583 } |
3357 | 3584 |
3358 } // namespace content | 3585 } // namespace content |
OLD | NEW |