Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / content / child / site_isolation_stats_gatherer_browsertest.cc
blob8b61caebc935f0ff1205d616280c2e3ec2980705
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 "base/command_line.h"
6 #include "base/strings/pattern.h"
7 #include "base/strings/string_util.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/test/histogram_tester.h"
10 #include "content/public/common/content_switches.h"
11 #include "content/public/common/resource_type.h"
12 #include "content/public/test/browser_test_utils.h"
13 #include "content/public/test/content_browser_test.h"
14 #include "content/public/test/content_browser_test_utils.h"
15 #include "content/shell/browser/shell.h"
16 #include "net/test/spawned_test_server/spawned_test_server.h"
18 namespace content {
20 // These tests simulate exploited renderer processes, which can fetch arbitrary
21 // resources from other websites, not constrained by the Same Origin Policy. We
22 // are trying to verify that the renderer cannot fetch any cross-site document
23 // responses even when the Same Origin Policy is turned off inside the renderer.
24 class SiteIsolationStatsGathererBrowserTest : public ContentBrowserTest {
25 public:
26 SiteIsolationStatsGathererBrowserTest() {}
27 ~SiteIsolationStatsGathererBrowserTest() override {}
29 void SetUpCommandLine(base::CommandLine* command_line) override {
30 ASSERT_TRUE(test_server()->Start());
31 // Add a host resolver rule to map all outgoing requests to the test server.
32 // This allows us to use "real" hostnames in URLs, which we can use to
33 // create arbitrary SiteInstances.
34 command_line->AppendSwitchASCII(
35 switches::kHostResolverRules,
36 "MAP * " + test_server()->host_port_pair().ToString() +
37 ",EXCLUDE localhost");
39 // Since we assume exploited renderer process, it can bypass the same origin
40 // policy at will. Simulate that by passing the disable-web-security flag.
41 command_line->AppendSwitch(switches::kDisableWebSecurity);
44 void InspectHistograms(const base::HistogramTester& histograms,
45 bool should_be_blocked,
46 const std::string& resource_name) {
47 std::string bucket;
48 int mime_type = 0; // Hardcoded because histogram enums mustn't change.
49 if (base::MatchPattern(resource_name, "*.html")) {
50 bucket = "HTML";
51 mime_type = 0;
52 } else if (base::MatchPattern(resource_name, "*.xml")) {
53 bucket = "XML";
54 mime_type = 1;
55 } else if (base::MatchPattern(resource_name, "*.json")) {
56 bucket = "JSON";
57 mime_type = 2;
58 } else if (base::MatchPattern(resource_name, "*.txt")) {
59 bucket = "Plain";
60 mime_type = 3;
61 if (base::MatchPattern(resource_name, "json*")) {
62 bucket += ".JSON";
63 } else if (base::MatchPattern(resource_name, "html*")) {
64 bucket += ".HTML";
65 } else if (base::MatchPattern(resource_name, "xml*")) {
66 bucket += ".XML";
68 } else {
69 FAIL();
71 FetchHistogramsFromChildProcesses();
73 // A few histograms are incremented unconditionally.
74 histograms.ExpectUniqueSample("SiteIsolation.AllResponses", 1, 1);
75 histograms.ExpectTotalCount("SiteIsolation.XSD.DataLength", 1);
76 histograms.ExpectUniqueSample("SiteIsolation.XSD.MimeType", mime_type, 1);
78 // Inspect the appropriate conditionally-incremented histogram[s].
79 std::set<std::string> expected_metrics;
80 std::string base_metric = "SiteIsolation.XSD." + bucket;
81 base_metric += should_be_blocked ? ".Blocked" : ".NotBlocked";
82 expected_metrics.insert(base_metric);
83 if (should_be_blocked) {
84 expected_metrics.insert(base_metric + ".RenderableStatusCode");
85 } else if (base::MatchPattern(resource_name, "*js.*")) {
86 expected_metrics.insert(base_metric + ".MaybeJS");
89 for (std::string metric : expected_metrics) {
90 if (base::MatchPattern(metric, "*.RenderableStatusCode")) {
91 histograms.ExpectUniqueSample(metric, RESOURCE_TYPE_XHR, 1);
92 } else {
93 histograms.ExpectUniqueSample(metric, 1, 1);
97 // Make sure no other conditionally-incremented histograms were touched.
98 const char* all_metrics[] = {
99 "SiteIsolation.XSD.HTML.Blocked",
100 "SiteIsolation.XSD.HTML.Blocked.NonRenderableStatusCode",
101 "SiteIsolation.XSD.HTML.Blocked.RenderableStatusCode",
102 "SiteIsolation.XSD.HTML.NoSniffBlocked",
103 "SiteIsolation.XSD.HTML.NoSniffBlocked.NonRenderableStatusCode",
104 "SiteIsolation.XSD.HTML.NoSniffBlocked.RenderableStatusCode",
105 "SiteIsolation.XSD.HTML.NotBlocked",
106 "SiteIsolation.XSD.HTML.NotBlocked.MaybeJS",
107 "SiteIsolation.XSD.JSON.Blocked",
108 "SiteIsolation.XSD.JSON.Blocked.NonRenderableStatusCode",
109 "SiteIsolation.XSD.JSON.Blocked.RenderableStatusCode",
110 "SiteIsolation.XSD.JSON.NoSniffBlocked",
111 "SiteIsolation.XSD.JSON.NoSniffBlocked.NonRenderableStatusCode",
112 "SiteIsolation.XSD.JSON.NoSniffBlocked.RenderableStatusCode",
113 "SiteIsolation.XSD.JSON.NotBlocked",
114 "SiteIsolation.XSD.JSON.NotBlocked.MaybeJS",
115 "SiteIsolation.XSD.Plain.HTML.Blocked",
116 "SiteIsolation.XSD.Plain.HTML.Blocked.NonRenderableStatusCode",
117 "SiteIsolation.XSD.Plain.HTML.Blocked.RenderableStatusCode",
118 "SiteIsolation.XSD.Plain.JSON.Blocked",
119 "SiteIsolation.XSD.Plain.JSON.Blocked.NonRenderableStatusCode",
120 "SiteIsolation.XSD.Plain.JSON.Blocked.RenderableStatusCode",
121 "SiteIsolation.XSD.Plain.NoSniffBlocked",
122 "SiteIsolation.XSD.Plain.NoSniffBlocked.NonRenderableStatusCode",
123 "SiteIsolation.XSD.Plain.NoSniffBlocked.RenderableStatusCode",
124 "SiteIsolation.XSD.Plain.NotBlocked",
125 "SiteIsolation.XSD.Plain.NotBlocked.MaybeJS",
126 "SiteIsolation.XSD.Plain.XML.Blocked",
127 "SiteIsolation.XSD.Plain.XML.Blocked.NonRenderableStatusCode",
128 "SiteIsolation.XSD.Plain.XML.Blocked.RenderableStatusCode",
129 "SiteIsolation.XSD.XML.Blocked",
130 "SiteIsolation.XSD.XML.Blocked.NonRenderableStatusCode",
131 "SiteIsolation.XSD.XML.Blocked.RenderableStatusCode",
132 "SiteIsolation.XSD.XML.NoSniffBlocked",
133 "SiteIsolation.XSD.XML.NoSniffBlocked.NonRenderableStatusCode",
134 "SiteIsolation.XSD.XML.NoSniffBlocked.RenderableStatusCode",
135 "SiteIsolation.XSD.XML.NotBlocked",
136 "SiteIsolation.XSD.XML.NotBlocked.MaybeJS"};
138 for (const char* metric : all_metrics) {
139 if (!expected_metrics.count(metric)) {
140 histograms.ExpectTotalCount(metric, 0);
145 private:
146 DISALLOW_COPY_AND_ASSIGN(SiteIsolationStatsGathererBrowserTest);
149 // TODO(dsjang): we cannot run these tests on Android since SetUpCommandLine()
150 // is executed before the I/O thread is created on Android. After this bug
151 // (crbug.com/278425) is resolved, we can enable this test case on Android.
152 #if defined(OS_ANDROID)
153 #define MAYBE_CrossSiteDocumentBlockingForMimeType \
154 DISABLED_CrossSiteDocumentBlockingForMimeType
155 #else
156 #define MAYBE_CrossSiteDocumentBlockingForMimeType \
157 CrossSiteDocumentBlockingForMimeType
158 #endif
160 IN_PROC_BROWSER_TEST_F(SiteIsolationStatsGathererBrowserTest,
161 MAYBE_CrossSiteDocumentBlockingForMimeType) {
162 // Load a page that issues illegal cross-site document requests to bar.com.
163 // The page uses XHR to request HTML/XML/JSON documents from bar.com, and
164 // inspects if any of them were successfully received. Currently, on illegal
165 // access, the XHR requests should succeed, but the UMA histograms should
166 // record that they would have been blocked. This test is only possible since
167 // we run the browser without the same origin policy.
168 GURL foo("http://foo.com/files/cross_site_document_request.html");
170 NavigateToURL(shell(), foo);
172 // Flush out existing histogram activity.
173 FetchHistogramsFromChildProcesses();
175 // The following are files under content/test/data/site_isolation. All
176 // should be disallowed for cross site XHR under the document blocking policy.
177 const char* blocked_resources[] = {
178 "comment_valid.html",
179 "html.txt",
180 "html4_dtd.html",
181 "html4_dtd.txt",
182 "html5_dtd.html",
183 "html5_dtd.txt",
184 "json.txt",
185 "valid.html",
186 "valid.json",
187 "valid.xml",
188 "xml.txt",
191 for (const char* resource : blocked_resources) {
192 SCOPED_TRACE(base::StringPrintf("... while testing page: %s", resource));
193 base::HistogramTester histograms;
195 bool was_blocked;
196 ASSERT_TRUE(ExecuteScriptAndExtractBool(
197 shell()->web_contents(),
198 base::StringPrintf("sendRequest(\"%s\");", resource), &was_blocked));
199 ASSERT_FALSE(was_blocked);
201 InspectHistograms(histograms, true, resource);
204 // These files should be allowed for XHR under the document blocking policy.
205 const char* allowed_resources[] = {"js.html",
206 "comment_js.html",
207 "js.xml",
208 "js.json",
209 "js.txt",
210 "img.html",
211 "img.xml",
212 "img.json",
213 "img.txt",
214 "comment_js.html"};
215 for (const char* resource : allowed_resources) {
216 SCOPED_TRACE(base::StringPrintf("... while testing page: %s", resource));
217 base::HistogramTester histograms;
219 bool was_blocked;
220 ASSERT_TRUE(ExecuteScriptAndExtractBool(
221 shell()->web_contents(),
222 base::StringPrintf("sendRequest(\"%s\");", resource), &was_blocked));
223 ASSERT_FALSE(was_blocked);
225 InspectHistograms(histograms, false, resource);
229 // TODO(dsjang): we cannot run these tests on Android since SetUpCommandLine()
230 // is executed before the I/O thread is created on Android. After this bug
231 // (crbug.com/278425) is resolved, we can enable this test case on Android.
232 #if defined(OS_ANDROID)
233 #define MAYBE_CrossSiteDocumentBlockingForDifferentTargets \
234 DISABLED_CrossSiteDocumentBlockingForDifferentTargets
235 #else
236 #define MAYBE_CrossSiteDocumentBlockingForDifferentTargets \
237 CrossSiteDocumentBlockingForDifferentTargets
238 #endif
240 IN_PROC_BROWSER_TEST_F(SiteIsolationStatsGathererBrowserTest,
241 MAYBE_CrossSiteDocumentBlockingForDifferentTargets) {
242 // This webpage loads a cross-site HTML page in different targets such as
243 // <img>,<link>,<embed>, etc. Since the requested document is blocked, and one
244 // character string (' ') is returned instead, this tests that the renderer
245 // does not crash even when it receives a response body which is " ", whose
246 // length is different from what's described in "content-length" for such
247 // different targets.
249 // TODO(nick): Split up these cases, and add positive assertions here about
250 // what actually happens in these various resource-block cases.
251 GURL foo("http://foo.com/files/cross_site_document_request_target.html");
252 NavigateToURL(shell(), foo);
255 } // namespace content