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

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

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

Powered by Google App Engine
This is Rietveld 408576698