1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/site_details.h"
7 #include "base/bind_helpers.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/path_service.h"
10 #include "base/test/histogram_tester.h"
11 #include "chrome/browser/metrics/metrics_memory_details.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/tabs/tab_strip_model.h"
14 #include "chrome/test/base/in_process_browser_test.h"
15 #include "chrome/test/base/ui_test_utils.h"
16 #include "content/public/browser/notification_service.h"
17 #include "content/public/test/browser_test_utils.h"
18 #include "content/public/test/test_utils.h"
19 #include "net/dns/mock_host_resolver.h"
20 #include "net/test/embedded_test_server/embedded_test_server.h"
21 #include "testing/gmock/include/gmock/gmock.h"
24 using testing::ContainerEq
;
25 using testing::ElementsAre
;
29 class TestMemoryDetails
: public MetricsMemoryDetails
{
32 : MetricsMemoryDetails(base::Bind(&base::DoNothing
), nullptr) {}
34 void StartFetchAndWait() {
35 uma_
.reset(new base::HistogramTester());
36 StartFetch(FROM_CHROME_ONLY
);
37 content::RunMessageLoop();
40 // Returns a HistogramTester which observed the most recent call to
41 // StartFetchAndWait().
42 base::HistogramTester
* uma() { return uma_
.get(); }
45 ~TestMemoryDetails() override
{}
47 void OnDetailsAvailable() override
{
48 MetricsMemoryDetails::OnDetailsAvailable();
49 // Exit the loop initiated by StartFetchAndWait().
50 base::MessageLoop::current()->Quit();
53 scoped_ptr
<base::HistogramTester
> uma_
;
55 DISALLOW_COPY_AND_ASSIGN(TestMemoryDetails
);
60 class SiteDetailsBrowserTest
: public InProcessBrowserTest
{
62 SiteDetailsBrowserTest() {}
63 ~SiteDetailsBrowserTest() override
{}
65 void SetUpOnMainThread() override
{
66 host_resolver()->AddRule("*", "127.0.0.1");
68 // Add content/test/data so we can use cross_site_iframe_factory.html
69 base::FilePath test_data_dir
;
70 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT
, &test_data_dir
));
71 embedded_test_server()->ServeFilesFromDirectory(
72 test_data_dir
.AppendASCII("content/test/data/"));
73 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
77 DISALLOW_COPY_AND_ASSIGN(SiteDetailsBrowserTest
);
80 // Test the accuracy of SiteDetails process estimation, in the presence of
81 // multiple iframes, navigation, multiple BrowsingInstances, and multiple tabs
82 // in the same BrowsingInstance.
83 IN_PROC_BROWSER_TEST_F(SiteDetailsBrowserTest
, ManyCrossSiteIframes
) {
84 // Page with 14 nested oopifs across 9 sites (a.com through i.com).
85 // None of these are https.
86 GURL abcdefghi_url
= embedded_test_server()->GetURL(
88 "/cross_site_iframe_factory.html?a(b(a(b,c,d,e,f,g,h)),c,d,e,i(f))");
89 ui_test_utils::NavigateToURL(browser(), abcdefghi_url
);
92 scoped_refptr
<TestMemoryDetails
> details
= new TestMemoryDetails();
93 details
->StartFetchAndWait();
96 details
->uma()->GetAllSamples("SiteIsolation.BrowsingInstanceCount"),
97 ElementsAre(Bucket(1, 1)));
98 EXPECT_THAT(details
->uma()->GetAllSamples(
99 "SiteIsolation.CurrentRendererProcessCount"),
100 ElementsAre(Bucket(1, 1)));
101 EXPECT_THAT(details
->uma()->GetAllSamples(
102 "SiteIsolation.IsolateAllSitesProcessCountEstimate"),
103 ElementsAre(Bucket(9, 1)));
104 EXPECT_THAT(details
->uma()->GetAllSamples(
105 "SiteIsolation.IsolateAllSitesProcessCountLowerBound"),
106 ElementsAre(Bucket(9, 1)));
107 EXPECT_THAT(details
->uma()->GetAllSamples(
108 "SiteIsolation.IsolateAllSitesProcessCountNoLimit"),
109 ElementsAre(Bucket(9, 1)));
110 EXPECT_THAT(details
->uma()->GetAllSamples(
111 "SiteIsolation.IsolateHttpsSitesProcessCountEstimate"),
112 ElementsAre(Bucket(1, 1)));
113 EXPECT_THAT(details
->uma()->GetAllSamples(
114 "SiteIsolation.IsolateHttpsSitesProcessCountLowerBound"),
115 ElementsAre(Bucket(1, 1)));
116 EXPECT_THAT(details
->uma()->GetAllSamples(
117 "SiteIsolation.IsolateHttpsSitesProcessCountNoLimit"),
118 ElementsAre(Bucket(1, 1)));
120 // Navigate to a different, disjoint set of 7 sites.
121 GURL pqrstuv_url
= embedded_test_server()->GetURL(
123 "/cross_site_iframe_factory.html?p(q(r),r(s),s(t),t(q),u(u),v(p))");
124 ui_test_utils::NavigateToURL(browser(), pqrstuv_url
);
126 details
= new TestMemoryDetails();
127 details
->StartFetchAndWait();
130 details
->uma()->GetAllSamples("SiteIsolation.BrowsingInstanceCount"),
131 ElementsAre(Bucket(1, 1)));
132 EXPECT_THAT(details
->uma()->GetAllSamples(
133 "SiteIsolation.CurrentRendererProcessCount"),
134 ElementsAre(Bucket(1, 1)));
135 EXPECT_THAT(details
->uma()->GetAllSamples(
136 "SiteIsolation.IsolateAllSitesProcessCountEstimate"),
137 ElementsAre(Bucket(7, 1)));
138 EXPECT_THAT(details
->uma()->GetAllSamples(
139 "SiteIsolation.IsolateAllSitesProcessCountLowerBound"),
140 ElementsAre(Bucket(7, 1)));
141 EXPECT_THAT(details
->uma()->GetAllSamples(
142 "SiteIsolation.IsolateAllSitesProcessCountNoLimit"),
143 ElementsAre(Bucket(7, 1)));
144 EXPECT_THAT(details
->uma()->GetAllSamples(
145 "SiteIsolation.IsolateHttpsSitesProcessCountEstimate"),
146 ElementsAre(Bucket(1, 1)));
147 EXPECT_THAT(details
->uma()->GetAllSamples(
148 "SiteIsolation.IsolateHttpsSitesProcessCountLowerBound"),
149 ElementsAre(Bucket(1, 1)));
150 EXPECT_THAT(details
->uma()->GetAllSamples(
151 "SiteIsolation.IsolateHttpsSitesProcessCountNoLimit"),
152 ElementsAre(Bucket(1, 1)));
154 // Open a second tab (different BrowsingInstance) with 4 sites (a through d).
155 GURL abcd_url
= embedded_test_server()->GetURL(
156 "a.com", "/cross_site_iframe_factory.html?a(b(c(d())))");
157 AddTabAtIndex(1, abcd_url
, ui::PAGE_TRANSITION_TYPED
);
159 details
= new TestMemoryDetails();
160 details
->StartFetchAndWait();
163 details
->uma()->GetAllSamples("SiteIsolation.BrowsingInstanceCount"),
164 ElementsAre(Bucket(2, 1)));
165 EXPECT_THAT(details
->uma()->GetAllSamples(
166 "SiteIsolation.CurrentRendererProcessCount"),
167 ElementsAre(Bucket(2, 1)));
168 EXPECT_THAT(details
->uma()->GetAllSamples(
169 "SiteIsolation.IsolateAllSitesProcessCountEstimate"),
170 ElementsAre(Bucket(11, 1)));
171 EXPECT_THAT(details
->uma()->GetAllSamples(
172 "SiteIsolation.IsolateAllSitesProcessCountLowerBound"),
173 ElementsAre(Bucket(11, 1)));
174 EXPECT_THAT(details
->uma()->GetAllSamples(
175 "SiteIsolation.IsolateAllSitesProcessCountNoLimit"),
176 ElementsAre(Bucket(11, 1)));
177 EXPECT_THAT(details
->uma()->GetAllSamples(
178 "SiteIsolation.IsolateHttpsSitesProcessCountEstimate"),
179 ElementsAre(Bucket(2, 1)));
180 EXPECT_THAT(details
->uma()->GetAllSamples(
181 "SiteIsolation.IsolateHttpsSitesProcessCountLowerBound"),
182 ElementsAre(Bucket(1, 1))); // TODO(nick): This should be 2.
183 EXPECT_THAT(details
->uma()->GetAllSamples(
184 "SiteIsolation.IsolateHttpsSitesProcessCountNoLimit"),
185 ElementsAre(Bucket(2, 1)));
187 // Open a third tab (different BrowsingInstance) with the same 4 sites.
188 AddTabAtIndex(2, abcd_url
, ui::PAGE_TRANSITION_TYPED
);
190 details
= new TestMemoryDetails();
191 details
->StartFetchAndWait();
194 details
->uma()->GetAllSamples("SiteIsolation.BrowsingInstanceCount"),
195 ElementsAre(Bucket(3, 1)));
196 EXPECT_THAT(details
->uma()->GetAllSamples(
197 "SiteIsolation.CurrentRendererProcessCount"),
198 ElementsAre(Bucket(3, 1)));
199 // Could be 11 if subframe processes were reused across BrowsingInstances.
200 EXPECT_THAT(details
->uma()->GetAllSamples(
201 "SiteIsolation.IsolateAllSitesProcessCountEstimate"),
202 ElementsAre(Bucket(15, 1)));
203 EXPECT_THAT(details
->uma()->GetAllSamples(
204 "SiteIsolation.IsolateAllSitesProcessCountLowerBound"),
205 ElementsAre(Bucket(11, 1)));
206 EXPECT_THAT(details
->uma()->GetAllSamples(
207 "SiteIsolation.IsolateAllSitesProcessCountNoLimit"),
208 ElementsAre(Bucket(15, 1)));
209 EXPECT_THAT(details
->uma()->GetAllSamples(
210 "SiteIsolation.IsolateHttpsSitesProcessCountEstimate"),
211 ElementsAre(Bucket(3, 1)));
212 EXPECT_THAT(details
->uma()->GetAllSamples(
213 "SiteIsolation.IsolateHttpsSitesProcessCountLowerBound"),
214 ElementsAre(Bucket(1, 1))); // TODO(nick): This should be 3.
215 EXPECT_THAT(details
->uma()->GetAllSamples(
216 "SiteIsolation.IsolateHttpsSitesProcessCountNoLimit"),
217 ElementsAre(Bucket(3, 1)));
219 // Do a window.open() to obtain a fourth tab in the same BrowsingInstance as
220 // the third tab. The new page uses the same four sites "a-d" as third tab,
221 // plus an additional site "e". The estimated process counts should increase
222 // by one (not five) from the previous result, since the new tab can reuse the
223 // four processes already in the BrowsingInstance.
224 GURL dcbae_url
= embedded_test_server()->GetURL(
225 "a.com", "/cross_site_iframe_factory.html?d(c(b(a(e))))");
226 ui_test_utils::UrlLoadObserver
load_complete(
227 dcbae_url
, content::NotificationService::AllSources());
228 ASSERT_EQ(3, browser()->tab_strip_model()->count());
229 ASSERT_TRUE(content::ExecuteScript(
230 browser()->tab_strip_model()->GetActiveWebContents(),
231 "window.open('" + dcbae_url
.spec() + "');"));
232 ASSERT_EQ(4, browser()->tab_strip_model()->count());
233 load_complete
.Wait();
235 details
= new TestMemoryDetails();
236 details
->StartFetchAndWait();
239 details
->uma()->GetAllSamples("SiteIsolation.BrowsingInstanceCount"),
240 ElementsAre(Bucket(3, 1)));
241 EXPECT_THAT(details
->uma()->GetAllSamples(
242 "SiteIsolation.CurrentRendererProcessCount"),
243 ElementsAre(Bucket(3, 1)));
244 // Could be 11 if subframe processes were reused across BrowsingInstances.
245 EXPECT_THAT(details
->uma()->GetAllSamples(
246 "SiteIsolation.IsolateAllSitesProcessCountEstimate"),
247 ElementsAre(Bucket(16, 1)));
248 EXPECT_THAT(details
->uma()->GetAllSamples(
249 "SiteIsolation.IsolateAllSitesProcessCountLowerBound"),
250 ElementsAre(Bucket(12, 1)));
251 EXPECT_THAT(details
->uma()->GetAllSamples(
252 "SiteIsolation.IsolateAllSitesProcessCountNoLimit"),
253 ElementsAre(Bucket(16, 1)));
254 EXPECT_THAT(details
->uma()->GetAllSamples(
255 "SiteIsolation.IsolateHttpsSitesProcessCountEstimate"),
256 ElementsAre(Bucket(3, 1)));
257 EXPECT_THAT(details
->uma()->GetAllSamples(
258 "SiteIsolation.IsolateHttpsSitesProcessCountLowerBound"),
259 ElementsAre(Bucket(1, 1))); // TODO(nick): This should be 3.
260 EXPECT_THAT(details
->uma()->GetAllSamples(
261 "SiteIsolation.IsolateHttpsSitesProcessCountNoLimit"),
262 ElementsAre(Bucket(3, 1)));