diff options
author | nick <nick@chromium.org> | 2015-08-12 17:04:02 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-08-13 00:04:43 +0000 |
commit | 8c3895b7d1343989606e29cffca8a82f1f3f4ec6 (patch) | |
tree | d2fea2333d999ae30c921ef4065a1aa32f5ac7d9 /chrome | |
parent | 01780b3cebecf652aa7d7cf41c781ba77d73aff8 (diff) | |
download | chromium_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.cc | 263 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 |
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', |