// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/site_details.h" #include "base/metrics/histogram.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "url/origin.h" #if defined(ENABLE_EXTENSIONS) #include "extensions/browser/extension_registry.h" #include "extensions/common/constants.h" #include "extensions/common/extension.h" #endif using content::BrowserContext; using content::BrowserThread; using content::RenderFrameHost; using content::RenderProcessHost; using content::SiteInstance; using content::WebContents; namespace { bool ShouldIsolate(BrowserContext* browser_context, const IsolationScenario& scenario, const GURL& site) { switch (scenario.policy) { case ISOLATE_NOTHING: return false; case ISOLATE_ALL_SITES: return true; case ISOLATE_HTTPS_SITES: // Note: For estimation purposes "isolate https sites" is really // implemented as "isolate non-http sites". This means that, for example, // the New Tab Page gets counted as two processes under this policy, and // extensions are isolated as well. return !site.SchemeIs(url::kHttpScheme); case ISOLATE_EXTENSIONS: { #if !defined(ENABLE_EXTENSIONS) return false; #else if (!site.SchemeIs(extensions::kExtensionScheme)) return false; extensions::ExtensionRegistry* registry = extensions::ExtensionRegistry::Get(browser_context); const extensions::Extension* extension = registry->enabled_extensions().GetExtensionOrAppByURL(site); return extension && !extension->is_hosted_app(); #endif } } NOTREACHED(); return true; } content::SiteInstance* DeterminePrimarySiteInstance( content::SiteInstance* site_instance, SiteData* site_data) { // Find the BrowsingInstance this WebContents belongs to by iterating over // the "primary" SiteInstances of each BrowsingInstance we've seen so far. for (auto& entry : site_data->browsing_instances) { BrowsingInstanceInfo* browsing_instance = &entry.second; content::SiteInstance* primary_for_browsing_instance = entry.first; if (site_instance->IsRelatedSiteInstance(primary_for_browsing_instance)) { browsing_instance->site_instances.insert(site_instance); return primary_for_browsing_instance; } } // Add |instance| as the "primary" SiteInstance of a new BrowsingInstance. BrowsingInstanceInfo* browsing_instance = &site_data->browsing_instances[site_instance]; browsing_instance->site_instances.insert(site_instance); return site_instance; } } // namespace ScenarioBrowsingInstanceInfo::ScenarioBrowsingInstanceInfo() {} ScenarioBrowsingInstanceInfo::ScenarioBrowsingInstanceInfo( const ScenarioBrowsingInstanceInfo& other) = default; ScenarioBrowsingInstanceInfo::~ScenarioBrowsingInstanceInfo() {} BrowsingInstanceInfo::BrowsingInstanceInfo() {} BrowsingInstanceInfo::BrowsingInstanceInfo(const BrowsingInstanceInfo& other) = default; BrowsingInstanceInfo::~BrowsingInstanceInfo() {} IsolationScenario::IsolationScenario() {} IsolationScenario::IsolationScenario(const IsolationScenario& other) = default; IsolationScenario::~IsolationScenario() {} SiteData::SiteData() { for (int i = 0; i <= ISOLATION_SCENARIO_LAST; i++) scenarios[i].policy = static_cast(i); } SiteData::SiteData(const SiteData& other) = default; SiteData::~SiteData() {} SiteDetails::SiteDetails() {} SiteDetails::~SiteDetails() {} void SiteDetails::CollectSiteInfo(WebContents* contents, SiteData* site_data) { DCHECK_CURRENTLY_ON(BrowserThread::UI); BrowserContext* context = contents->GetBrowserContext(); // The primary should be the same for the whole tab. SiteInstance* primary = DeterminePrimarySiteInstance(contents->GetSiteInstance(), site_data); BrowsingInstanceInfo* browsing_instance = &site_data->browsing_instances[primary]; for (RenderFrameHost* frame : contents->GetAllFrames()) { // Ensure that we add the frame's SiteInstance to |site_instances|. DCHECK(frame->GetSiteInstance()->IsRelatedSiteInstance(primary)); browsing_instance->site_instances.insert(frame->GetSiteInstance()); browsing_instance->proxy_count += frame->GetProxyCount(); if (frame->GetParent()) { if (frame->GetSiteInstance() != frame->GetParent()->GetSiteInstance()) site_data->out_of_process_frames++; } } // Now keep track of how many sites we have in this BrowsingInstance (and // overall), including sites in iframes. for (IsolationScenario& scenario : site_data->scenarios) { std::map frame_urls; for (RenderFrameHost* frame : contents->GetAllFrames()) { // Determine the site from the frame's origin, with a fallback to the // frame's URL. In cases like