summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authornick <nick@chromium.org>2015-08-12 17:04:02 -0700
committerCommit bot <commit-bot@chromium.org>2015-08-13 00:04:43 +0000
commit8c3895b7d1343989606e29cffca8a82f1f3f4ec6 (patch)
treed2fea2333d999ae30c921ef4065a1aa32f5ac7d9 /chrome
parent01780b3cebecf652aa7d7cf41c781ba77d73aff8 (diff)
downloadchromium_src-8c3895b7d1343989606e29cffca8a82f1f3f4ec6.zip
chromium_src-8c3895b7d1343989606e29cffca8a82f1f3f4ec6.tar.gz
chromium_src-8c3895b7d1343989606e29cffca8a82f1f3f4ec6.tar.bz2
[Re-land of https://codereview.chromium.org/126492300]
Introduce cross_site_iframe_factory.html, and use it to test the site isolation code in MemoryMetricsDetails under chrome/. [ See crbug.com/515672 for a screenshot ] /cross_site_iframe_factory.html?a(b(c, d)) gives you a simple three-level, four-site iframe test. The trick it uses, is that the query parameter is parsed and passed recursively to children, so the first level is: <iframe src="b.com:1234/cross_site_iframe_factory.html?b(c(),d())"> Which then contains the two leaf iframes: <iframe src="c.com:1234/cross_site_iframe_factory.html?c()"> <iframe src="d.com:1234/cross_site_iframe_factory.html?d()"> To to cut down on noise. ".com" is automatically affixed to the hostname if a TLD isn't present. As a convenience, the page supports local preview if loaded via file:// URI. file:// URIs are technically cross-origin, although --site-per-process doesn't isolate them today. Each site has a random (but consistent) background color as a visual aid. The page contains some crude layout logic to make sure the outer levels are big enough to fit the inner levels. The parsing logic is in tree_parser_util.js, which has unittests. MetricsMemoryDetailsBrowserTest.TestSiteIsolation is a new test that uses the above facility to creates a bunch of complex iframe cases, and tests that our process-counting UMA stats are as expected. BUG=515672 CQ_INCLUDE_TRYBOTS=tryserver.chromium.mac:mac_chromium_10.6_rel_ng;tryserver.chromium.win:win_chromium_vista_rel_ng TBR=jam@chromium.org Review URL: https://codereview.chromium.org/1264923002 Cr-Commit-Position: refs/heads/master@{#342447} Review URL: https://codereview.chromium.org/1288433002 Cr-Commit-Position: refs/heads/master@{#343132}
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/site_details_browsertest.cc263
-rw-r--r--chrome/chrome_tests.gypi1
2 files changed, 264 insertions, 0 deletions
diff --git a/chrome/browser/site_details_browsertest.cc b/chrome/browser/site_details_browsertest.cc
new file mode 100644
index 0000000..b84be4c
--- /dev/null
+++ b/chrome/browser/site_details_browsertest.cc
@@ -0,0 +1,263 @@
+// 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 "base/bind_helpers.h"
+#include "base/message_loop/message_loop.h"
+#include "base/path_service.h"
+#include "base/test/histogram_tester.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/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_utils.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"
+
+using base::Bucket;
+using testing::ContainerEq;
+using testing::ElementsAre;
+
+namespace {
+
+class TestMemoryDetails : public MetricsMemoryDetails {
+ public:
+ TestMemoryDetails()
+ : MetricsMemoryDetails(base::Bind(&base::DoNothing), nullptr) {}
+
+ void StartFetchAndWait() {
+ uma_.reset(new base::HistogramTester());
+ StartFetch(FROM_CHROME_ONLY);
+ content::RunMessageLoop();
+ }
+
+ // Returns a HistogramTester which observed the most recent call to
+ // StartFetchAndWait().
+ base::HistogramTester* uma() { return uma_.get(); }
+
+ private:
+ ~TestMemoryDetails() override {}
+
+ void OnDetailsAvailable() override {
+ MetricsMemoryDetails::OnDetailsAvailable();
+ // Exit the loop initiated by StartFetchAndWait().
+ base::MessageLoop::current()->Quit();
+ }
+
+ scoped_ptr<base::HistogramTester> uma_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestMemoryDetails);
+};
+
+} // namespace
+
+class SiteDetailsBrowserTest : public InProcessBrowserTest {
+ public:
+ SiteDetailsBrowserTest() {}
+ ~SiteDetailsBrowserTest() override {}
+
+ void SetUpOnMainThread() override {
+ 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()->InitializeAndWaitUntilReady());
+ }
+
+ private:
+ 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.
+IN_PROC_BROWSER_TEST_F(SiteDetailsBrowserTest, ManyCrossSiteIframes) {
+ // 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_THAT(
+ details->uma()->GetAllSamples("SiteIsolation.BrowsingInstanceCount"),
+ ElementsAre(Bucket(1, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.CurrentRendererProcessCount"),
+ ElementsAre(Bucket(1, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateAllSitesProcessCountEstimate"),
+ ElementsAre(Bucket(9, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateAllSitesProcessCountLowerBound"),
+ ElementsAre(Bucket(9, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateAllSitesProcessCountNoLimit"),
+ ElementsAre(Bucket(9, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateHttpsSitesProcessCountEstimate"),
+ ElementsAre(Bucket(1, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateHttpsSitesProcessCountLowerBound"),
+ ElementsAre(Bucket(1, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateHttpsSitesProcessCountNoLimit"),
+ ElementsAre(Bucket(1, 1)));
+
+ // 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_THAT(
+ details->uma()->GetAllSamples("SiteIsolation.BrowsingInstanceCount"),
+ ElementsAre(Bucket(1, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.CurrentRendererProcessCount"),
+ ElementsAre(Bucket(1, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateAllSitesProcessCountEstimate"),
+ ElementsAre(Bucket(7, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateAllSitesProcessCountLowerBound"),
+ ElementsAre(Bucket(7, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateAllSitesProcessCountNoLimit"),
+ ElementsAre(Bucket(7, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateHttpsSitesProcessCountEstimate"),
+ ElementsAre(Bucket(1, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateHttpsSitesProcessCountLowerBound"),
+ ElementsAre(Bucket(1, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateHttpsSitesProcessCountNoLimit"),
+ ElementsAre(Bucket(1, 1)));
+
+ // 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_THAT(
+ details->uma()->GetAllSamples("SiteIsolation.BrowsingInstanceCount"),
+ ElementsAre(Bucket(2, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.CurrentRendererProcessCount"),
+ ElementsAre(Bucket(2, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateAllSitesProcessCountEstimate"),
+ ElementsAre(Bucket(11, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateAllSitesProcessCountLowerBound"),
+ ElementsAre(Bucket(11, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateAllSitesProcessCountNoLimit"),
+ ElementsAre(Bucket(11, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateHttpsSitesProcessCountEstimate"),
+ ElementsAre(Bucket(2, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateHttpsSitesProcessCountLowerBound"),
+ ElementsAre(Bucket(1, 1))); // TODO(nick): This should be 2.
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateHttpsSitesProcessCountNoLimit"),
+ ElementsAre(Bucket(2, 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"),
+ ElementsAre(Bucket(3, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.CurrentRendererProcessCount"),
+ ElementsAre(Bucket(3, 1)));
+ // Could be 11 if subframe processes were reused across BrowsingInstances.
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateAllSitesProcessCountEstimate"),
+ ElementsAre(Bucket(15, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateAllSitesProcessCountLowerBound"),
+ ElementsAre(Bucket(11, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateAllSitesProcessCountNoLimit"),
+ ElementsAre(Bucket(15, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateHttpsSitesProcessCountEstimate"),
+ ElementsAre(Bucket(3, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateHttpsSitesProcessCountLowerBound"),
+ ElementsAre(Bucket(1, 1))); // TODO(nick): This should be 3.
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateHttpsSitesProcessCountNoLimit"),
+ ElementsAre(Bucket(3, 1)));
+
+ // Do a window.open() to obtain a fourth tab in the same BrowsingInstance as
+ // the third tab. The new page uses 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 result, since 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"),
+ ElementsAre(Bucket(3, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.CurrentRendererProcessCount"),
+ ElementsAre(Bucket(3, 1)));
+ // Could be 11 if subframe processes were reused across BrowsingInstances.
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateAllSitesProcessCountEstimate"),
+ ElementsAre(Bucket(16, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateAllSitesProcessCountLowerBound"),
+ ElementsAre(Bucket(12, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateAllSitesProcessCountNoLimit"),
+ ElementsAre(Bucket(16, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateHttpsSitesProcessCountEstimate"),
+ ElementsAre(Bucket(3, 1)));
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateHttpsSitesProcessCountLowerBound"),
+ ElementsAre(Bucket(1, 1))); // TODO(nick): This should be 3.
+ EXPECT_THAT(details->uma()->GetAllSamples(
+ "SiteIsolation.IsolateHttpsSitesProcessCountNoLimit"),
+ ElementsAre(Bucket(3, 1)));
+}
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index ec0d930..39c28d6 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -400,6 +400,7 @@
'browser/sessions/session_restore_browsertest.cc',
'browser/sessions/session_restore_browsertest_chromeos.cc',
'browser/sessions/tab_restore_browsertest.cc',
+ 'browser/site_details_browsertest.cc',
'browser/spellchecker/spellcheck_service_browsertest.cc',
'browser/ssl/captive_portal_blocking_page_browsertest.cc',
'browser/ssl/certificate_reporting_test_utils.cc',