blob: 42e438fb1047fd1bccb45367fad593f923adb9e8 [file] [log] [blame]
// Copyright 2015 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 <stddef.h>
#include <stdint.h>
#include <memory>
#include <utility>
#include <vector>
#include "base/bind_helpers.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/test/histogram_tester.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/metrics/metrics_memory_details.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/metrics/metrics_service.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "extensions/common/switches.h"
#include "extensions/common/value_builder.h"
#include "extensions/test/test_extension_dir.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::Bucket;
using content::WebContents;
using extensions::DictionaryBuilder;
using extensions::Extension;
using extensions::ListBuilder;
using extensions::TestExtensionDir;
using testing::ElementsAre;
using testing::PrintToString;
namespace {
class TestMemoryDetails : public MetricsMemoryDetails {
public:
TestMemoryDetails() : MetricsMemoryDetails(base::DoNothing()) {}
void StartFetchAndWait() {
uma_.reset(new base::HistogramTester());
StartFetch();
content::RunMessageLoop();
}
// Returns a HistogramTester which observed the most recent call to
// StartFetchAndWait().
base::HistogramTester* uma() { return uma_.get(); }
int GetOutOfProcessIframeCount() {
std::vector<Bucket> buckets =
uma_->GetAllSamples("SiteIsolation.OutOfProcessIframes");
CHECK_EQ(1U, buckets.size());
return buckets[0].min;
}
size_t CountPageTitles() {
size_t count = 0;
for (const ProcessMemoryInformation& process : ChromeBrowser()->processes) {
if (process.process_type == content::PROCESS_TYPE_RENDERER) {
count += process.titles.size();
}
}
return count;
}
private:
~TestMemoryDetails() override {}
void OnDetailsAvailable() override {
MetricsMemoryDetails::OnDetailsAvailable();
// Exit the loop initiated by StartFetchAndWait().
base::RunLoop::QuitCurrentWhenIdleDeprecated();
}
std::unique_ptr<base::HistogramTester> uma_;
DISALLOW_COPY_AND_ASSIGN(TestMemoryDetails);
};
IsolationScenarioType GetCurrentPolicy() {
if (content::AreAllSitesIsolatedForTesting())
return ISOLATE_ALL_SITES;
#if BUILDFLAG(ENABLE_EXTENSIONS)
return ISOLATE_EXTENSIONS;
#else
return ISOLATE_NOTHING;
#endif
}
// This matcher takes three other matchers as arguments, and applies one of them
// depending on the current site isolation mode. The first applies if no site
// isolation mode is active; the second applies under --isolate-extensions mode;
// and the third applies under --site-per-process mode.
MATCHER_P3(DependingOnPolicy,
isolate_nothing,
isolate_extensions,
isolate_all_sites,
GetCurrentPolicy() == ISOLATE_NOTHING
? std::string("(with oopifs disabled) ") +
PrintToString(isolate_nothing)
: GetCurrentPolicy() == ISOLATE_EXTENSIONS
? std::string("(under --isolate-extensions) ") +
PrintToString(isolate_extensions)
: std::string("(under --site-per-process) ") +
PrintToString(isolate_all_sites)) {
switch (GetCurrentPolicy()) {
case ISOLATE_NOTHING:
return ExplainMatchResult(isolate_nothing, arg, result_listener);
case ISOLATE_EXTENSIONS:
return ExplainMatchResult(isolate_extensions, arg, result_listener);
case ISOLATE_ALL_SITES:
return ExplainMatchResult(isolate_all_sites, arg, result_listener);
default:
return false;
}
}
// Matcher for base::Bucket objects that allows bucket_min to be a matcher.
MATCHER_P2(Sample,
bucket_min,
count,
std::string("is a Bucket whose count is ") + PrintToString(count) +
std::string(" and whose value is ") +
PrintToString(bucket_min)) {
return ExplainMatchResult(count, arg.count, result_listener) &&
ExplainMatchResult(bucket_min, arg.min, result_listener);
}
// Allow matchers to be pretty-printed when passed to PrintToString() for the
// cases we care about.
template <typename P1, typename P2, typename P3>
void PrintTo(const DependingOnPolicyMatcherP3<P1, P2, P3>& matcher,
std::ostream* os) {
testing::Matcher<int> matcherCast = matcher;
matcherCast.DescribeTo(os);
}
template <typename P1, typename P2>
void PrintTo(const SampleMatcherP2<P1, P2>& matcher, std::ostream* os) {
testing::Matcher<Bucket> matcherCast = matcher;
matcherCast.DescribeTo(os);
}
// Matches a container of histogram samples, for the common case where the
// histogram received just one sample.
#define HasOneSample(x) ElementsAre(Sample(x, 1))
} // namespace
class SiteDetailsBrowserTest : public ExtensionBrowserTest {
public:
SiteDetailsBrowserTest() {}
~SiteDetailsBrowserTest() override {}
void SetUpOnMainThread() override {
ExtensionBrowserTest::SetUpOnMainThread();
host_resolver()->AddRule("*", "127.0.0.1");
// Add content/test/data so we can use cross_site_iframe_factory.html
base::FilePath test_data_dir;
ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &test_data_dir));
embedded_test_server()->ServeFilesFromDirectory(
test_data_dir.AppendASCII("content/test/data/"));
ASSERT_TRUE(embedded_test_server()->Start());
}
// Create and install an extension that has a couple of web-accessible
// resources and, optionally, a background process.
const Extension* CreateExtension(const std::string& name,
bool has_background_process) {
std::unique_ptr<TestExtensionDir> dir(new TestExtensionDir);
DictionaryBuilder manifest;
manifest.Set("name", name)
.Set("version", "1.0")
.Set("manifest_version", 2)
.Set("web_accessible_resources", ListBuilder()
.Append("blank_iframe.html")
.Append("http_iframe.html")
.Append("two_http_iframes.html")
.Build());
if (has_background_process) {
manifest.Set(
"background",
DictionaryBuilder()
.Set("scripts", ListBuilder().Append("script.js").Build())
.Build());
dir->WriteFile(FILE_PATH_LITERAL("script.js"),
"console.log('" + name + " running');");
}
dir->WriteFile(FILE_PATH_LITERAL("blank_iframe.html"),
base::StringPrintf("<html><body>%s, blank iframe:"
" <iframe width=80 height=80></iframe>"
"</body></html>",
name.c_str()));
std::string iframe_url =
embedded_test_server()
->GetURL("w.com", "/cross_site_iframe_factory.html?w")
.spec();
std::string iframe_url2 =
embedded_test_server()
->GetURL("x.com", "/cross_site_iframe_factory.html?x")
.spec();
dir->WriteFile(
FILE_PATH_LITERAL("http_iframe.html"),
base::StringPrintf("<html><body>%s, http:// iframe:"
" <iframe width=80 height=80 src='%s'></iframe>"
"</body></html>",
name.c_str(), iframe_url.c_str()));
dir->WriteFile(FILE_PATH_LITERAL("two_http_iframes.html"),
base::StringPrintf(
"<html><body>%s, two http:// iframes:"
" <iframe width=80 height=80 src='%s'></iframe>"
" <iframe width=80 height=80 src='%s'></iframe>"
"</body></html>",
name.c_str(), iframe_url.c_str(), iframe_url2.c_str()));
dir->WriteManifest(manifest.ToJSON());
const Extension* extension = LoadExtension(dir->UnpackedPath());
EXPECT_TRUE(extension);
temp_dirs_.push_back(std::move(dir));
return extension;
}
const Extension* CreateHostedApp(const std::string& name,
const GURL& app_url) {
std::unique_ptr<TestExtensionDir> dir(new TestExtensionDir);
DictionaryBuilder manifest;
manifest.Set("name", name)
.Set("version", "1.0")
.Set("manifest_version", 2)
.Set(
"app",
DictionaryBuilder()
.Set("urls", ListBuilder().Append(app_url.spec()).Build())
.Set("launch",
DictionaryBuilder().Set("web_url", app_url.spec()).Build())
.Build());
dir->WriteManifest(manifest.ToJSON());
const Extension* extension = LoadExtension(dir->UnpackedPath());
EXPECT_TRUE(extension);
temp_dirs_.push_back(std::move(dir));
return extension;
}
int GetRenderProcessCount() {
return content::RenderProcessHost::GetCurrentRenderProcessCountForTesting();
}
private:
std::vector<std::unique_ptr<TestExtensionDir>> temp_dirs_;
DISALLOW_COPY_AND_ASSIGN(SiteDetailsBrowserTest);
};
// Test the accuracy of SiteDetails process estimation, in the presence of
// multiple iframes, navigation, multiple BrowsingInstances, and multiple tabs
// in the same BrowsingInstance.
//
// Disabled since it's flaky: https://crbug.com/830318.
IN_PROC_BROWSER_TEST_F(SiteDetailsBrowserTest, DISABLED_ManyIframes) {
// Page with 14 nested oopifs across 9 sites (a.com through i.com).
// None of these are https.
GURL abcdefghi_url = embedded_test_server()->GetURL(
"a.com",
"/cross_site_iframe_factory.html?a(b(a(b,c,d,e,f,g,h)),c,d,e,i(f))");
ui_test_utils::NavigateToURL(browser(), abcdefghi_url);
// Get the metrics.
scoped_refptr<TestMemoryDetails> details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_EQ(1U, details->CountPageTitles());
EXPECT_THAT(
details->uma()->GetAllSamples("SiteIsolation.BrowsingInstanceCount"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.CurrentRendererProcessCount"),
HasOneSample(GetRenderProcessCount()));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateNothingProcessCountEstimate"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountEstimate"),
HasOneSample(9));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountLowerBound"),
HasOneSample(9));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountNoLimit"),
HasOneSample(9));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateHttpsSitesProcessCountEstimate"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateHttpsSitesProcessCountLowerBound"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateHttpsSitesProcessCountNoLimit"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountEstimate"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountLowerBound"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountNoLimit"),
HasOneSample(1));
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(1, 1, 9));
EXPECT_THAT(details->GetOutOfProcessIframeCount(),
DependingOnPolicy(0, 0, 14));
EXPECT_THAT(details->uma()->GetAllSamples("SiteIsolation.ProxyCount"),
HasOneSample(DependingOnPolicy(0, 0, 114)));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.ProxyCountPerBrowsingInstance"),
HasOneSample(DependingOnPolicy(0, 0, 114)));
// Navigate to a different, disjoint set of 7 sites.
GURL pqrstuv_url = embedded_test_server()->GetURL(
"p.com",
"/cross_site_iframe_factory.html?p(q(r),r(s),s(t),t(q),u(u),v(p))");
ui_test_utils::NavigateToURL(browser(), pqrstuv_url);
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_EQ(1U, details->CountPageTitles());
EXPECT_THAT(
details->uma()->GetAllSamples("SiteIsolation.BrowsingInstanceCount"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.CurrentRendererProcessCount"),
HasOneSample(GetRenderProcessCount()));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateNothingProcessCountEstimate"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountEstimate"),
HasOneSample(7));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountLowerBound"),
HasOneSample(7));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountNoLimit"),
HasOneSample(7));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateHttpsSitesProcessCountEstimate"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateHttpsSitesProcessCountLowerBound"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateHttpsSitesProcessCountNoLimit"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountEstimate"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountLowerBound"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountNoLimit"),
HasOneSample(1));
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(1, 1, 7));
EXPECT_THAT(details->GetOutOfProcessIframeCount(),
DependingOnPolicy(0, 0, 11));
EXPECT_THAT(details->uma()->GetAllSamples("SiteIsolation.ProxyCount"),
HasOneSample(DependingOnPolicy(0, 0, 68)));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.ProxyCountPerBrowsingInstance"),
HasOneSample(DependingOnPolicy(0, 0, 68)));
// Open a second tab (different BrowsingInstance) with 4 sites (a through d).
GURL abcd_url = embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b(c(d())))");
AddTabAtIndex(1, abcd_url, ui::PAGE_TRANSITION_TYPED);
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_EQ(2U, details->CountPageTitles());
EXPECT_THAT(
details->uma()->GetAllSamples("SiteIsolation.BrowsingInstanceCount"),
HasOneSample(2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.CurrentRendererProcessCount"),
HasOneSample(GetRenderProcessCount()));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateNothingProcessCountEstimate"),
HasOneSample(2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountEstimate"),
HasOneSample(11));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountLowerBound"),
HasOneSample(11));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountNoLimit"),
HasOneSample(11));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateHttpsSitesProcessCountEstimate"),
HasOneSample(2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateHttpsSitesProcessCountLowerBound"),
HasOneSample(1)); // TODO(nick): This should be 2.
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateHttpsSitesProcessCountNoLimit"),
HasOneSample(2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountEstimate"),
HasOneSample(2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountLowerBound"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountNoLimit"),
HasOneSample(2));
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(2, 2, 11));
EXPECT_THAT(details->GetOutOfProcessIframeCount(),
DependingOnPolicy(0, 0, 14));
EXPECT_THAT(details->uma()->GetAllSamples("SiteIsolation.ProxyCount"),
HasOneSample(DependingOnPolicy(0, 0, 81)));
EXPECT_THAT(
details->uma()->GetAllSamples(
"SiteIsolation.ProxyCountPerBrowsingInstance"),
DependingOnPolicy(ElementsAre(Bucket(0, 2)), ElementsAre(Bucket(0, 2)),
ElementsAre(Bucket(12, 1), Bucket(68, 1))));
// Open a third tab (different BrowsingInstance) with the same 4 sites.
AddTabAtIndex(2, abcd_url, ui::PAGE_TRANSITION_TYPED);
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(
details->uma()->GetAllSamples("SiteIsolation.BrowsingInstanceCount"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.CurrentRendererProcessCount"),
HasOneSample(GetRenderProcessCount()));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateNothingProcessCountEstimate"),
HasOneSample(3));
// Could be 11 if subframe processes were reused across BrowsingInstances.
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountEstimate"),
HasOneSample(15));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountLowerBound"),
HasOneSample(11));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountNoLimit"),
HasOneSample(15));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateHttpsSitesProcessCountEstimate"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateHttpsSitesProcessCountLowerBound"),
HasOneSample(1)); // TODO(nick): This should be 3.
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateHttpsSitesProcessCountNoLimit"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountEstimate"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountLowerBound"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountNoLimit"),
HasOneSample(3));
// For --site-per-process, the total process count will be 12 instead of 15,
// because the third tab's subframes (b, c, d) will reuse matching subframe
// processes from the second tab (across BrowsingInstances). This subframe
// process consolidation was added as part of https://crbug.com/512560. Note
// that the a.com main frame in tab 3 won't reuse tab 2's main frame process,
// so this is still one process higher than the lower bound.
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(3, 3, 12));
EXPECT_THAT(details->GetOutOfProcessIframeCount(),
DependingOnPolicy(0, 0, 17));
EXPECT_THAT(details->uma()->GetAllSamples("SiteIsolation.ProxyCount"),
HasOneSample(DependingOnPolicy(0, 0, 96)));
EXPECT_THAT(
details->uma()->GetAllSamples(
"SiteIsolation.ProxyCountPerBrowsingInstance"),
DependingOnPolicy(ElementsAre(Bucket(0, 3)), ElementsAre(Bucket(0, 3)),
ElementsAre(Bucket(12, 2), Bucket(68, 1))));
// From the third tab, window.open() a fourth tab in the same
// BrowsingInstance, to a page using the same four sites "a-d" as third tab,
// plus an additional site "e". The estimated process counts should increase
// by one (not five) from the previous scenario, as the new tab can reuse the
// four processes already in the BrowsingInstance.
GURL dcbae_url = embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?d(c(b(a(e))))");
ui_test_utils::UrlLoadObserver load_complete(
dcbae_url, content::NotificationService::AllSources());
ASSERT_EQ(3, browser()->tab_strip_model()->count());
ASSERT_TRUE(content::ExecuteScript(
browser()->tab_strip_model()->GetActiveWebContents(),
"window.open('" + dcbae_url.spec() + "');"));
ASSERT_EQ(4, browser()->tab_strip_model()->count());
load_complete.Wait();
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(
details->uma()->GetAllSamples("SiteIsolation.BrowsingInstanceCount"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.CurrentRendererProcessCount"),
HasOneSample(GetRenderProcessCount()));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateNothingProcessCountEstimate"),
HasOneSample(3));
// Could be 11 if subframe processes were reused across BrowsingInstances.
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountEstimate"),
HasOneSample(16));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountLowerBound"),
HasOneSample(12));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountNoLimit"),
HasOneSample(16));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateHttpsSitesProcessCountEstimate"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateHttpsSitesProcessCountLowerBound"),
HasOneSample(1)); // TODO(nick): This should be 3.
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateHttpsSitesProcessCountNoLimit"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountEstimate"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountLowerBound"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountNoLimit"),
HasOneSample(3));
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(3, 3, 13));
EXPECT_THAT(details->GetOutOfProcessIframeCount(),
DependingOnPolicy(0, 0, 21));
EXPECT_THAT(details->uma()->GetAllSamples("SiteIsolation.ProxyCount"),
HasOneSample(DependingOnPolicy(0, 0, 114)));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.ProxyCountPerBrowsingInstance"),
DependingOnPolicy(
ElementsAre(Bucket(0, 3)), ElementsAre(Bucket(0, 3)),
ElementsAre(Bucket(12, 1), Bucket(29, 1), Bucket(68, 1))));
}
// Flaky on Windows and Mac. crbug.com/671891
#if defined(OS_WIN) || defined(OS_MACOSX)
#define MAYBE_IsolateExtensions DISABLED_IsolateExtensions
#else
#define MAYBE_IsolateExtensions IsolateExtensions
#endif
IN_PROC_BROWSER_TEST_F(SiteDetailsBrowserTest, MAYBE_IsolateExtensions) {
// We start on "about:blank", which should be credited with a process in this
// case.
scoped_refptr<TestMemoryDetails> details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.CurrentRendererProcessCount"),
HasOneSample(GetRenderProcessCount()));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateNothingProcessCountEstimate"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountEstimate"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountLowerBound"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountNoLimit"),
HasOneSample(1));
EXPECT_THAT(GetRenderProcessCount(), 1);
EXPECT_EQ(0, details->GetOutOfProcessIframeCount());
// Install one script-injecting extension with background page, and an
// extension with web accessible resources.
const Extension* extension1 = CreateExtension("Extension One", true);
const Extension* extension2 = CreateExtension("Extension Two", false);
// Open two a.com tabs (with cross site http iframes). IsolateExtensions mode
// should have no effect so far, since there are no frames straddling the
// extension/web boundary.
GURL tab1_url = embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b,c)");
ui_test_utils::NavigateToURL(browser(), tab1_url);
WebContents* tab1 = browser()->tab_strip_model()->GetWebContentsAt(0);
GURL tab2_url = embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(d,e)");
AddTabAtIndex(1, tab2_url, ui::PAGE_TRANSITION_TYPED);
WebContents* tab2 = browser()->tab_strip_model()->GetWebContentsAt(1);
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.CurrentRendererProcessCount"),
HasOneSample(GetRenderProcessCount()));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateNothingProcessCountEstimate"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountEstimate"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountLowerBound"),
HasOneSample(2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountNoLimit"),
HasOneSample(3));
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(3, 3, 7));
EXPECT_THAT(details->GetOutOfProcessIframeCount(),
DependingOnPolicy(0, 0, 4));
// Test that "one process per extension" applies even when web content has an
// extension iframe.
// Tab1 navigates its first iframe to a resource of extension1. This shouldn't
// result in a new extension process (it should share with extension1's
// background page).
content::NavigateIframeToURL(
tab1, "child-0", extension1->GetResourceURL("/blank_iframe.html"));
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.CurrentRendererProcessCount"),
HasOneSample(GetRenderProcessCount()));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateNothingProcessCountEstimate"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountEstimate"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountLowerBound"),
HasOneSample(2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountNoLimit"),
HasOneSample(3));
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(3, 3, 6));
EXPECT_THAT(details->GetOutOfProcessIframeCount(),
DependingOnPolicy(0, 1, 4));
// Tab2 navigates its first iframe to a resource of extension1. This also
// shouldn't result in a new extension process (it should share with the
// background page and the other iframe).
content::NavigateIframeToURL(
tab2, "child-0", extension1->GetResourceURL("/blank_iframe.html"));
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.CurrentRendererProcessCount"),
HasOneSample(GetRenderProcessCount()));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateNothingProcessCountEstimate"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountEstimate"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountLowerBound"),
HasOneSample(2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountNoLimit"),
HasOneSample(3));
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(3, 3, 5));
EXPECT_THAT(details->GetOutOfProcessIframeCount(),
DependingOnPolicy(0, 2, 4));
// Tab1 navigates its second iframe to a resource of extension2. This SHOULD
// result in a new process since extension2 had no existing process.
content::NavigateIframeToURL(
tab1, "child-1", extension2->GetResourceURL("/blank_iframe.html"));
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.CurrentRendererProcessCount"),
HasOneSample(GetRenderProcessCount()));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateNothingProcessCountEstimate"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountEstimate"),
HasOneSample(4));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountLowerBound"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountNoLimit"),
HasOneSample(4));
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(3, 4, 5));
EXPECT_THAT(details->GetOutOfProcessIframeCount(),
DependingOnPolicy(0, 3, 4));
// Tab2 navigates its second iframe to a resource of extension2. This should
// share the existing extension2 process.
content::NavigateIframeToURL(
tab2, "child-1", extension2->GetResourceURL("/blank_iframe.html"));
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.CurrentRendererProcessCount"),
HasOneSample(GetRenderProcessCount()));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateNothingProcessCountEstimate"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountEstimate"),
HasOneSample(4));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountLowerBound"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountNoLimit"),
HasOneSample(4));
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(3, 4, 4));
EXPECT_THAT(details->GetOutOfProcessIframeCount(),
DependingOnPolicy(0, 4, 4));
// Install extension3 (identical config to extension2)
const Extension* extension3 = CreateExtension("Extension Three", false);
// Navigate Tab2 to a top-level page from extension3. There are four processes
// now: one for tab1's main frame, and one for each of the extensions:
// extension1 has a process because it has a background page; extension2 is
// used as an iframe in tab1, and extension3 is the top-level frame in tab2.
ui_test_utils::NavigateToURL(browser(),
extension3->GetResourceURL("blank_iframe.html"));
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.CurrentRendererProcessCount"),
HasOneSample(GetRenderProcessCount()));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateNothingProcessCountEstimate"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountEstimate"),
HasOneSample(4));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountLowerBound"),
HasOneSample(4));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountNoLimit"),
HasOneSample(4));
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(3, 4, 4));
EXPECT_THAT(details->GetOutOfProcessIframeCount(),
DependingOnPolicy(0, 2, 2));
// Navigate tab2 to a different extension3 page containing a web iframe. The
// iframe should get its own process. The lower bound number indicates that,
// in theory, the iframe could share a process with tab1's main frame.
ui_test_utils::NavigateToURL(browser(),
extension3->GetResourceURL("http_iframe.html"));
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.CurrentRendererProcessCount"),
HasOneSample(GetRenderProcessCount()));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateNothingProcessCountEstimate"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountEstimate"),
HasOneSample(5));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountLowerBound"),
HasOneSample(4));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountNoLimit"),
HasOneSample(5));
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(3, 5, 5));
EXPECT_THAT(details->GetOutOfProcessIframeCount(),
DependingOnPolicy(0, 3, 3));
// Navigate tab1 to an extension3 page with an extension3 iframe. There should
// be three processes estimated by IsolateExtensions: one for extension3, one
// for extension1's background page, and one for the web iframe in tab2.
browser()->tab_strip_model()->ActivateTabAt(0, true);
ui_test_utils::NavigateToURL(browser(),
extension3->GetResourceURL("blank_iframe.html"));
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.CurrentRendererProcessCount"),
HasOneSample(GetRenderProcessCount()));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateNothingProcessCountEstimate"),
HasOneSample(2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountEstimate"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountLowerBound"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountNoLimit"),
HasOneSample(3));
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(2, 3, 3));
EXPECT_THAT(details->GetOutOfProcessIframeCount(),
DependingOnPolicy(0, 1, 1));
// Now navigate tab1 to an extension3 page with a web iframe. This could share
// a process with tab2's iframe (the LowerBound number), or it could get its
// own process (the Estimate number).
ui_test_utils::NavigateToURL(browser(),
extension3->GetResourceURL("http_iframe.html"));
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.CurrentRendererProcessCount"),
HasOneSample(GetRenderProcessCount()));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateNothingProcessCountEstimate"),
HasOneSample(2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountEstimate"),
HasOneSample(4));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountLowerBound"),
HasOneSample(3));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountNoLimit"),
HasOneSample(4));
// As part of https://crbug.com/512560, subframes that require a dedicated
// process started reusing existing processes when possible, so under
// --site-per-process, tab1's web iframe will share the process with tab2's
// web iframe, since they have the same site. This won't affect
// --isolate-extensions, because the web iframe's site won't require a
// dedicated process in that mode. Hence, with site-per-process, there should
// be three total renderer processes: one for the two web iframes, one for
// extension3, and one for extension 1's background page. With only
// --isolate-extensions, there should be four total renderer processes, as
// each web iframe will go into its own process.
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(2, 4, 3));
EXPECT_THAT(details->GetOutOfProcessIframeCount(),
DependingOnPolicy(0, 2, 2));
}
// Exercises accounting in the case where an extension has two different-site
// web iframes.
IN_PROC_BROWSER_TEST_F(SiteDetailsBrowserTest, ExtensionWithTwoWebIframes) {
scoped_refptr<TestMemoryDetails> details = new TestMemoryDetails();
details->StartFetchAndWait();
// Install one script-injecting extension with background page, and an
// extension with web accessible resources.
const Extension* extension = CreateExtension("Test Extension", false);
ui_test_utils::NavigateToURL(
browser(), extension->GetResourceURL("/two_http_iframes.html"));
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.CurrentRendererProcessCount"),
HasOneSample(GetRenderProcessCount()));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateNothingProcessCountEstimate"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountEstimate"),
HasOneSample(2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountLowerBound"),
HasOneSample(2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountNoLimit"),
HasOneSample(2));
// TODO(nick): https://crbug.com/512560 Make the number below agree with the
// estimates above, which assume consolidation of subframe processes.
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(1, 3, 3));
EXPECT_THAT(details->GetOutOfProcessIframeCount(),
DependingOnPolicy(0, 2, 2));
}
// Verifies that --isolate-extensions doesn't isolate hosted apps.
//
// Disabled since it's flaky: https://crbug.com/830318.
IN_PROC_BROWSER_TEST_F(SiteDetailsBrowserTest,
DISABLED_IsolateExtensionsHostedApps) {
GURL app_with_web_iframe_url = embedded_test_server()->GetURL(
"app.org", "/cross_site_iframe_factory.html?app.org(b.com)");
GURL app_in_web_iframe_url = embedded_test_server()->GetURL(
"b.com", "/cross_site_iframe_factory.html?b.com(app.org)");
// No hosted app is installed: app.org just behaves like a normal domain.
ui_test_utils::NavigateToURL(browser(), app_with_web_iframe_url);
scoped_refptr<TestMemoryDetails> details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.CurrentRendererProcessCount"),
HasOneSample(GetRenderProcessCount()));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateNothingProcessCountEstimate"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountEstimate"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountLowerBound"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountNoLimit"),
HasOneSample(1));
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(1, 1, 2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountEstimate"),
HasOneSample(2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountLowerBound"),
HasOneSample(2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountNoLimit"),
HasOneSample(2));
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(1, 1, 2));
EXPECT_THAT(details->GetOutOfProcessIframeCount(),
DependingOnPolicy(0, 0, 1));
ui_test_utils::NavigateToURL(browser(), app_in_web_iframe_url);
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.CurrentRendererProcessCount"),
HasOneSample(GetRenderProcessCount()));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateNothingProcessCountEstimate"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountEstimate"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountLowerBound"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountNoLimit"),
HasOneSample(1));
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(1, 1, 2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountEstimate"),
HasOneSample(2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountLowerBound"),
HasOneSample(2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountNoLimit"),
HasOneSample(2));
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(1, 1, 2));
EXPECT_THAT(details->GetOutOfProcessIframeCount(),
DependingOnPolicy(0, 0, 1));
// Now install app.org as a hosted app.
CreateHostedApp("App", GURL("http://app.org"));
// Reload the same two pages, and verify that the hosted app still is not
// isolated by --isolate-extensions, but is isolated by --site-per-process.
ui_test_utils::NavigateToURL(browser(), app_with_web_iframe_url);
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.CurrentRendererProcessCount"),
HasOneSample(GetRenderProcessCount()));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateNothingProcessCountEstimate"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountEstimate"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountLowerBound"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountNoLimit"),
HasOneSample(1));
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(1, 1, 2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountEstimate"),
HasOneSample(2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountLowerBound"),
HasOneSample(2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountNoLimit"),
HasOneSample(2));
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(1, 1, 2));
EXPECT_THAT(details->GetOutOfProcessIframeCount(),
DependingOnPolicy(0, 0, 1));
ui_test_utils::NavigateToURL(browser(), app_in_web_iframe_url);
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.CurrentRendererProcessCount"),
HasOneSample(GetRenderProcessCount()));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateNothingProcessCountEstimate"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountEstimate"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountLowerBound"),
HasOneSample(1));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateExtensionsProcessCountNoLimit"),
HasOneSample(1));
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(1, 1, 2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountEstimate"),
HasOneSample(2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountLowerBound"),
HasOneSample(2));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.IsolateAllSitesProcessCountNoLimit"),
HasOneSample(2));
EXPECT_THAT(GetRenderProcessCount(), DependingOnPolicy(1, 1, 2));
EXPECT_THAT(details->GetOutOfProcessIframeCount(),
DependingOnPolicy(0, 0, 1));
}
// Verifies that the UMA counter for SiteInstances in a BrowsingInstance is
// correct when using tabs with web pages.
IN_PROC_BROWSER_TEST_F(SiteDetailsBrowserTest,
VerifySiteInstanceCountInBrowsingInstance) {
// Page with 14 nested oopifs across 9 sites (a.com through i.com).
GURL abcdefghi_url = embedded_test_server()->GetURL(
"a.com",
"/cross_site_iframe_factory.html?a(b(a(b,c,d,e,f,g,h)),c,d,e,i(f))");
ui_test_utils::NavigateToURL(browser(), abcdefghi_url);
// Get the metrics.
scoped_refptr<TestMemoryDetails> details = new TestMemoryDetails();
details->StartFetchAndWait();
// Since there are no extensions involved, the results in the default case
// and extensions::IsIsolateExtensionsEnabled() are the same.
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.SiteInstancesPerBrowsingInstance"),
HasOneSample(DependingOnPolicy(1, 1, 9)));
EXPECT_THAT(details->uma()->GetAllSamples("SiteIsolation.ProxyCount"),
HasOneSample(DependingOnPolicy(0, 0, 114)));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.ProxyCountPerBrowsingInstance"),
HasOneSample(DependingOnPolicy(0, 0, 114)));
// Open another tab through window.open(), which will be in the same
// BrowsingInstance.
GURL dcbae_url = embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?d(c(b(j(k))))");
ui_test_utils::UrlLoadObserver load_complete(
dcbae_url, content::NotificationService::AllSources());
ASSERT_EQ(1, browser()->tab_strip_model()->count());
ASSERT_TRUE(content::ExecuteScript(
browser()->tab_strip_model()->GetActiveWebContents(),
"window.open('" + dcbae_url.spec() + "');"));
ASSERT_EQ(2, browser()->tab_strip_model()->count());
load_complete.Wait();
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.SiteInstancesPerBrowsingInstance"),
HasOneSample(DependingOnPolicy(1, 1, 11)));
EXPECT_THAT(details->uma()->GetAllSamples("SiteIsolation.ProxyCount"),
HasOneSample(DependingOnPolicy(0, 0, 160)));
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.ProxyCountPerBrowsingInstance"),
HasOneSample(DependingOnPolicy(0, 0, 160)));
// Open a tab, which will be in a different BrowsingInstance.
GURL abcd_url = embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b(c(d())))");
AddTabAtIndex(1, abcd_url, ui::PAGE_TRANSITION_TYPED);
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(
details->uma()->GetAllSamples(
"SiteIsolation.SiteInstancesPerBrowsingInstance"),
DependingOnPolicy(ElementsAre(Sample(1, 2)), ElementsAre(Sample(1, 2)),
ElementsAre(Sample(4, 1), Sample(11, 1))));
EXPECT_THAT(details->uma()->GetAllSamples("SiteIsolation.ProxyCount"),
HasOneSample(DependingOnPolicy(0, 0, 160)));
EXPECT_THAT(
details->uma()->GetAllSamples(
"SiteIsolation.ProxyCountPerBrowsingInstance"),
DependingOnPolicy(ElementsAre(Sample(0, 2)), ElementsAre(Sample(0, 2)),
ElementsAre(Sample(12, 1), Sample(160, 1))));
}
// Verifies that the UMA counter for SiteInstances in a BrowsingInstance is
// correct when extensions and web pages are mixed together.
//
// Disabled since it's flaky: https://crbug.com/830318.
IN_PROC_BROWSER_TEST_F(
SiteDetailsBrowserTest,
DISABLED_VerifySiteInstanceCountInBrowsingInstanceWithExtensions) {
// Open two a.com tabs (with cross site http iframes). IsolateExtensions mode
// should have no effect so far, since there are no frames straddling the
// extension/web boundary.
GURL tab_url = embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b,c,d(e))");
ui_test_utils::NavigateToURL(browser(), tab_url);
WebContents* tab = browser()->tab_strip_model()->GetWebContentsAt(0);
scoped_refptr<TestMemoryDetails> details = new TestMemoryDetails();
details->StartFetchAndWait();
// Since there are no extensions loaded yet, the results in the default case
// and extensions::IsIsolateExtensionsEnabled() are the same.
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.SiteInstancesPerBrowsingInstance"),
HasOneSample(DependingOnPolicy(1, 1, 5)));
// Load an extension without a background page, which will avoid creating a
// BrowsingInstance for it.
const Extension* extension1 = CreateExtension("Extension One", false);
// Navigate the tab's first iframe to a resource of the extension. The
// extension iframe will be put in the same BrowsingInstance as it is part
// of the frame tree.
content::NavigateIframeToURL(
tab, "child-0", extension1->GetResourceURL("/blank_iframe.html"));
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.SiteInstancesPerBrowsingInstance"),
HasOneSample(DependingOnPolicy(1, 2, 5)));
// Now load an extension with a background page. This will result in a
// BrowsingInstance for the background page.
const Extension* extension2 = CreateExtension("Extension Two", true);
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.SiteInstancesPerBrowsingInstance"),
DependingOnPolicy(ElementsAre(Bucket(1, 2)),
ElementsAre(Bucket(1, 1), Bucket(2, 1)),
ElementsAre(Bucket(1, 1), Bucket(5, 1))));
// Navigate the second iframe of the tab to the second extension. It should
// stay in the same BrowsingInstance as the page.
content::NavigateIframeToURL(
tab, "child-1", extension2->GetResourceURL("/blank_iframe.html"));
details = new TestMemoryDetails();
details->StartFetchAndWait();
EXPECT_THAT(details->uma()->GetAllSamples(
"SiteIsolation.SiteInstancesPerBrowsingInstance"),
DependingOnPolicy(ElementsAre(Bucket(1, 2)),
ElementsAre(Bucket(1, 1), Bucket(3, 1)),
ElementsAre(Bucket(1, 1), Bucket(5, 1))));
}