Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(310)

Side by Side Diff: content/browser/isolated_origin_browsertest.cc

Issue 2831683002: Introduce support for origins that require process isolation. (Closed)
Patch Set: Charlie's comments (round 3) Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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.
4
5 #include "base/command_line.h"
6 #include "content/browser/child_process_security_policy_impl.h"
7 #include "content/browser/web_contents/web_contents_impl.h"
8 #include "content/public/browser/render_process_host.h"
9 #include "content/public/common/content_switches.h"
10 #include "content/public/test/browser_test_utils.h"
11 #include "content/public/test/content_browser_test.h"
12 #include "content/public/test/content_browser_test_utils.h"
13 #include "content/public/test/test_frame_navigation_observer.h"
14 #include "content/public/test/test_navigation_observer.h"
15 #include "content/public/test/test_utils.h"
16 #include "content/shell/browser/shell.h"
17 #include "content/test/content_browser_test_utils_internal.h"
18 #include "net/dns/mock_host_resolver.h"
19 #include "net/test/embedded_test_server/embedded_test_server.h"
20 #include "url/gurl.h"
21
22 namespace content {
23
24 class IsolatedOriginTest : public ContentBrowserTest {
25 public:
26 IsolatedOriginTest() {}
27 ~IsolatedOriginTest() override {}
28
29 void SetUpCommandLine(base::CommandLine* command_line) override {
30 ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
31
32 std::string origin_list =
33 embedded_test_server()->GetURL("isolated.foo.com", "/").spec() + "," +
34 embedded_test_server()->GetURL("isolated.bar.com", "/").spec();
35 command_line->AppendSwitchASCII(switches::kIsolateOrigins, origin_list);
36 }
37
38 void SetUpOnMainThread() override {
39 host_resolver()->AddRule("*", "127.0.0.1");
40 embedded_test_server()->StartAcceptingConnections();
41 }
42
43 WebContentsImpl* web_contents() const {
44 return static_cast<WebContentsImpl*>(shell()->web_contents());
45 }
46 };
47
48 // Check that navigating a main frame from an non-isolated origin to an
49 // isolated origin and vice versa swaps processes and uses a new SiteInstance,
50 // both for browser-initiated and renderer-initiated navigations.
51 IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, MainFrameNavigation) {
52 GURL unisolated_url(
53 embedded_test_server()->GetURL("www.foo.com", "/title1.html"));
54 GURL isolated_url(
55 embedded_test_server()->GetURL("isolated.foo.com", "/title2.html"));
56
57 EXPECT_TRUE(NavigateToURL(shell(), unisolated_url));
58
59 // Open a same-site popup to keep the www.foo.com process alive.
60 Shell* popup = OpenPopup(shell(), GURL(url::kAboutBlankURL), "foo");
61 SiteInstance* unisolated_instance =
62 popup->web_contents()->GetMainFrame()->GetSiteInstance();
63 RenderProcessHost* unisolated_process =
64 popup->web_contents()->GetMainFrame()->GetProcess();
65
66 // Perform a browser-initiated navigation to an isolated origin and ensure
67 // that this ends up in a new process and SiteInstance for isolated.foo.com.
68 EXPECT_TRUE(NavigateToURL(shell(), isolated_url));
69
70 scoped_refptr<SiteInstance> isolated_instance =
71 web_contents()->GetSiteInstance();
72 EXPECT_NE(isolated_instance, unisolated_instance);
73 EXPECT_NE(web_contents()->GetMainFrame()->GetProcess(), unisolated_process);
74
75 // The site URL for isolated.foo.com should be the full origin rather than
76 // scheme and eTLD+1.
77 EXPECT_EQ(isolated_url.GetOrigin(), isolated_instance->GetSiteURL());
78
79 // Now perform a renderer-initiated navigation to an unisolated origin,
80 // www.foo.com. This should end up in the |popup|'s process.
81 {
82 TestNavigationObserver observer(web_contents());
83 EXPECT_TRUE(ExecuteScript(
84 web_contents(), "location.href = '" + unisolated_url.spec() + "'"));
85 observer.Wait();
86 }
87
88 EXPECT_EQ(unisolated_instance, web_contents()->GetSiteInstance());
89 EXPECT_EQ(unisolated_process, web_contents()->GetMainFrame()->GetProcess());
90
91 // Go to isolated.foo.com again, this time with a renderer-initiated
92 // navigation from the unisolated www.foo.com.
93 {
94 TestNavigationObserver observer(web_contents());
95 EXPECT_TRUE(ExecuteScript(web_contents(),
96 "location.href = '" + isolated_url.spec() + "'"));
97 observer.Wait();
98 }
99
100 EXPECT_EQ(isolated_instance, web_contents()->GetSiteInstance());
101 EXPECT_NE(unisolated_process, web_contents()->GetMainFrame()->GetProcess());
102
103 // Go back to www.foo.com: this should end up in the unisolated process.
104 {
105 TestNavigationObserver back_observer(web_contents());
106 web_contents()->GetController().GoBack();
107 back_observer.Wait();
108 }
109
110 EXPECT_EQ(unisolated_instance, web_contents()->GetSiteInstance());
111 EXPECT_EQ(unisolated_process, web_contents()->GetMainFrame()->GetProcess());
112
113 // Go back again. This should go to isolated.foo.com in an isolated process.
114 {
115 TestNavigationObserver back_observer(web_contents());
116 web_contents()->GetController().GoBack();
117 back_observer.Wait();
118 }
119
120 EXPECT_EQ(isolated_instance, web_contents()->GetSiteInstance());
121 EXPECT_NE(unisolated_process, web_contents()->GetMainFrame()->GetProcess());
122
123 // Do a renderer-initiated navigation from isolated.foo.com to another
124 // isolated origin and ensure there is a different isolated process.
125 GURL second_isolated_url(
126 embedded_test_server()->GetURL("isolated.bar.com", "/title3.html"));
127 {
128 TestNavigationObserver observer(web_contents());
129 EXPECT_TRUE(
130 ExecuteScript(web_contents(),
131 "location.href = '" + second_isolated_url.spec() + "'"));
132 observer.Wait();
133 }
134
135 EXPECT_EQ(second_isolated_url.GetOrigin(),
136 web_contents()->GetSiteInstance()->GetSiteURL());
137 EXPECT_NE(isolated_instance, web_contents()->GetSiteInstance());
138 EXPECT_NE(unisolated_instance, web_contents()->GetSiteInstance());
139 }
140
141 // Check that opening a popup for an isolated origin puts it into a new process
142 // and its own SiteInstance.
143 IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, Popup) {
144 GURL unisolated_url(
145 embedded_test_server()->GetURL("foo.com", "/title1.html"));
146 GURL isolated_url(
147 embedded_test_server()->GetURL("isolated.foo.com", "/title2.html"));
148
149 EXPECT_TRUE(NavigateToURL(shell(), unisolated_url));
150
151 // Open a popup to a URL with an isolated origin and ensure that there was a
152 // process swap.
153 Shell* popup = OpenPopup(shell(), isolated_url, "foo");
154
155 EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
156 popup->web_contents()->GetSiteInstance());
157
158 // The popup's site URL should match the full isolated origin.
159 EXPECT_EQ(isolated_url.GetOrigin(),
160 popup->web_contents()->GetSiteInstance()->GetSiteURL());
161
162 // Now open a second popup from an isolated origin to a URL with an
163 // unisolated origin and ensure that there was another process swap.
164 Shell* popup2 = OpenPopup(popup, unisolated_url, "bar");
165 EXPECT_EQ(shell()->web_contents()->GetSiteInstance(),
166 popup2->web_contents()->GetSiteInstance());
167 EXPECT_NE(popup->web_contents()->GetSiteInstance(),
168 popup2->web_contents()->GetSiteInstance());
169 }
170
171 // Check that navigating a subframe to an isolated origin puts the subframe
172 // into an OOPIF and its own SiteInstance. Also check that the isolated
173 // frame's subframes also end up in correct SiteInstance.
174 IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, Subframe) {
175 GURL top_url(
176 embedded_test_server()->GetURL("www.foo.com", "/page_with_iframe.html"));
177 EXPECT_TRUE(NavigateToURL(shell(), top_url));
178
179 GURL isolated_url(embedded_test_server()->GetURL("isolated.foo.com",
180 "/page_with_iframe.html"));
181
182 FrameTreeNode* root = web_contents()->GetFrameTree()->root();
183 FrameTreeNode* child = root->child_at(0);
184
185 NavigateIframeToURL(web_contents(), "test_iframe", isolated_url);
186 EXPECT_EQ(child->current_url(), isolated_url);
187
188 // Verify that the child frame is an OOPIF with a different SiteInstance.
189 EXPECT_NE(web_contents()->GetSiteInstance(),
190 child->current_frame_host()->GetSiteInstance());
191 EXPECT_TRUE(child->current_frame_host()->IsCrossProcessSubframe());
192 EXPECT_EQ(isolated_url.GetOrigin(),
193 child->current_frame_host()->GetSiteInstance()->GetSiteURL());
194
195 // Verify that the isolated frame's subframe (which starts out at a relative
196 // path) is kept in the isolated parent's SiteInstance.
197 FrameTreeNode* grandchild = child->child_at(0);
198 EXPECT_EQ(child->current_frame_host()->GetSiteInstance(),
199 grandchild->current_frame_host()->GetSiteInstance());
200
201 // Navigating the grandchild to www.foo.com should put it into the top
202 // frame's SiteInstance.
203 GURL non_isolated_url(
204 embedded_test_server()->GetURL("www.foo.com", "/title3.html"));
205 TestFrameNavigationObserver observer(grandchild);
206 EXPECT_TRUE(ExecuteScript(
207 grandchild, "location.href = '" + non_isolated_url.spec() + "';"));
208 observer.Wait();
209 EXPECT_EQ(non_isolated_url, grandchild->current_url());
210
211 EXPECT_EQ(root->current_frame_host()->GetSiteInstance(),
212 grandchild->current_frame_host()->GetSiteInstance());
213 EXPECT_NE(child->current_frame_host()->GetSiteInstance(),
214 grandchild->current_frame_host()->GetSiteInstance());
215 }
216
217 // Check that when an non-isolated origin foo.com embeds a subframe from an
218 // isolated origin, which then navigates to a non-isolated origin bar.com,
219 // bar.com goes back to the main frame's SiteInstance. See
220 // https://crbug.com/711006.
221 IN_PROC_BROWSER_TEST_F(IsolatedOriginTest,
222 NoOOPIFWhenIsolatedOriginNavigatesToNonIsolatedOrigin) {
223 if (AreAllSitesIsolatedForTesting())
224 return;
225
226 GURL top_url(
227 embedded_test_server()->GetURL("www.foo.com", "/page_with_iframe.html"));
228 EXPECT_TRUE(NavigateToURL(shell(), top_url));
229
230 FrameTreeNode* root = web_contents()->GetFrameTree()->root();
231 FrameTreeNode* child = root->child_at(0);
232
233 GURL isolated_url(embedded_test_server()->GetURL("isolated.foo.com",
234 "/page_with_iframe.html"));
235
236 NavigateIframeToURL(web_contents(), "test_iframe", isolated_url);
237 EXPECT_EQ(isolated_url, child->current_url());
238
239 // Verify that the child frame is an OOPIF with a different SiteInstance.
240 EXPECT_NE(web_contents()->GetSiteInstance(),
241 child->current_frame_host()->GetSiteInstance());
242 EXPECT_TRUE(child->current_frame_host()->IsCrossProcessSubframe());
243 EXPECT_EQ(isolated_url.GetOrigin(),
244 child->current_frame_host()->GetSiteInstance()->GetSiteURL());
245
246 // Navigate the child frame cross-site, but to a non-isolated origin. When
247 // not in --site-per-process, this should bring the subframe back into the
248 // main frame's SiteInstance.
249 GURL bar_url(embedded_test_server()->GetURL("bar.com", "/title1.html"));
250 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
251 EXPECT_FALSE(policy->IsIsolatedOrigin(url::Origin(bar_url)));
252 NavigateIframeToURL(web_contents(), "test_iframe", bar_url);
253 EXPECT_EQ(web_contents()->GetSiteInstance(),
254 child->current_frame_host()->GetSiteInstance());
255 EXPECT_FALSE(child->current_frame_host()->IsCrossProcessSubframe());
256 }
257
258 // Check that isolated origins can access cookies. This requires cookie checks
259 // on the IO thread to be aware of isolated origins.
260 IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, Cookies) {
261 GURL isolated_url(
262 embedded_test_server()->GetURL("isolated.foo.com", "/title2.html"));
263 EXPECT_TRUE(NavigateToURL(shell(), isolated_url));
264
265 EXPECT_TRUE(ExecuteScript(web_contents(), "document.cookie = 'foo=bar';"));
266
267 std::string cookie;
268 EXPECT_TRUE(ExecuteScriptAndExtractString(
269 web_contents(), "window.domAutomationController.send(document.cookie);",
270 &cookie));
271 EXPECT_EQ("foo=bar", cookie);
272 }
273
274 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/child_process_security_policy_unittest.cc ('k') | content/browser/renderer_host/render_process_host_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698