Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / content / browser / frame_host / render_frame_host_manager_browsertest.cc
blob9de16f8e9c0be905594f840c66bddc33e4f83358
1 // Copyright 2013 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 <set>
7 #include "base/command_line.h"
8 #include "base/json/json_reader.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/path_service.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/values.h"
13 #include "content/browser/child_process_security_policy_impl.h"
14 #include "content/browser/renderer_host/render_view_host_impl.h"
15 #include "content/browser/site_instance_impl.h"
16 #include "content/browser/web_contents/web_contents_impl.h"
17 #include "content/browser/webui/web_ui_impl.h"
18 #include "content/common/content_constants_internal.h"
19 #include "content/public/browser/navigation_controller.h"
20 #include "content/public/browser/navigation_entry.h"
21 #include "content/public/browser/render_process_host.h"
22 #include "content/public/browser/web_contents.h"
23 #include "content/public/browser/web_contents_observer.h"
24 #include "content/public/common/bindings_policy.h"
25 #include "content/public/common/content_switches.h"
26 #include "content/public/common/file_chooser_file_info.h"
27 #include "content/public/common/file_chooser_params.h"
28 #include "content/public/common/page_state.h"
29 #include "content/public/common/url_constants.h"
30 #include "content/public/test/browser_test_utils.h"
31 #include "content/public/test/content_browser_test.h"
32 #include "content/public/test/content_browser_test_utils.h"
33 #include "content/public/test/test_navigation_observer.h"
34 #include "content/public/test/test_utils.h"
35 #include "content/shell/browser/shell.h"
36 #include "net/base/net_util.h"
37 #include "net/dns/mock_host_resolver.h"
38 #include "net/test/spawned_test_server/spawned_test_server.h"
40 using base::ASCIIToUTF16;
42 namespace content {
44 namespace {
46 const char kOpenUrlViaClickTargetFunc[] =
47 "(function(url) {\n"
48 " var lnk = document.createElement(\"a\");\n"
49 " lnk.href = url;\n"
50 " lnk.target = \"_blank\";\n"
51 " document.body.appendChild(lnk);\n"
52 " lnk.click();\n"
53 "})";
55 // Adds a link with given url and target=_blank, and clicks on it.
56 void OpenUrlViaClickTarget(const internal::ToRenderFrameHost& adapter,
57 const GURL& url) {
58 EXPECT_TRUE(ExecuteScript(adapter,
59 std::string(kOpenUrlViaClickTargetFunc) + "(\"" + url.spec() + "\");"));
62 } // anonymous namespace
64 class RenderFrameHostManagerTest : public ContentBrowserTest {
65 public:
66 RenderFrameHostManagerTest() : foo_com_("foo.com") {
67 replace_host_.SetHostStr(foo_com_);
70 static bool GetFilePathWithHostAndPortReplacement(
71 const std::string& original_file_path,
72 const net::HostPortPair& host_port_pair,
73 std::string* replacement_path) {
74 std::vector<net::SpawnedTestServer::StringPair> replacement_text;
75 replacement_text.push_back(
76 make_pair("REPLACE_WITH_HOST_AND_PORT", host_port_pair.ToString()));
77 return net::SpawnedTestServer::GetFilePathWithReplacements(
78 original_file_path, replacement_text, replacement_path);
81 void StartServer() {
82 // Support multiple sites on the test server.
83 host_resolver()->AddRule("*", "127.0.0.1");
84 ASSERT_TRUE(test_server()->Start());
86 foo_host_port_ = test_server()->host_port_pair();
87 foo_host_port_.set_host(foo_com_);
90 // Returns a URL on foo.com with the given path.
91 GURL GetCrossSiteURL(const std::string& path) {
92 GURL cross_site_url(test_server()->GetURL(path));
93 return cross_site_url.ReplaceComponents(replace_host_);
96 protected:
97 std::string foo_com_;
98 GURL::Replacements replace_host_;
99 net::HostPortPair foo_host_port_;
102 // Web pages should not have script access to the swapped out page.
103 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, NoScriptAccessAfterSwapOut) {
104 StartServer();
106 // Load a page with links that open in a new window.
107 std::string replacement_path;
108 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
109 "files/click-noreferrer-links.html",
110 foo_host_port_,
111 &replacement_path));
112 NavigateToURL(shell(), test_server()->GetURL(replacement_path));
114 // Get the original SiteInstance for later comparison.
115 scoped_refptr<SiteInstance> orig_site_instance(
116 shell()->web_contents()->GetSiteInstance());
117 EXPECT_TRUE(orig_site_instance.get() != NULL);
119 // Open a same-site link in a new window.
120 ShellAddedObserver new_shell_observer;
121 bool success = false;
122 EXPECT_TRUE(ExecuteScriptAndExtractBool(
123 shell()->web_contents(),
124 "window.domAutomationController.send(clickSameSiteTargetedLink());",
125 &success));
126 EXPECT_TRUE(success);
127 Shell* new_shell = new_shell_observer.GetShell();
129 // Wait for the navigation in the new window to finish, if it hasn't.
130 WaitForLoadStop(new_shell->web_contents());
131 EXPECT_EQ("/files/navigate_opener.html",
132 new_shell->web_contents()->GetLastCommittedURL().path());
134 // Should have the same SiteInstance.
135 EXPECT_EQ(orig_site_instance, new_shell->web_contents()->GetSiteInstance());
137 // We should have access to the opened window's location.
138 success = false;
139 EXPECT_TRUE(ExecuteScriptAndExtractBool(
140 shell()->web_contents(),
141 "window.domAutomationController.send(testScriptAccessToWindow());",
142 &success));
143 EXPECT_TRUE(success);
145 // Now navigate the new window to a different site.
146 NavigateToURL(new_shell, GetCrossSiteURL("files/title1.html"));
147 scoped_refptr<SiteInstance> new_site_instance(
148 new_shell->web_contents()->GetSiteInstance());
149 EXPECT_NE(orig_site_instance, new_site_instance);
151 // We should no longer have script access to the opened window's location.
152 success = false;
153 EXPECT_TRUE(ExecuteScriptAndExtractBool(
154 shell()->web_contents(),
155 "window.domAutomationController.send(testScriptAccessToWindow());",
156 &success));
157 EXPECT_FALSE(success);
159 // We now navigate the window to an about:blank page.
160 success = false;
161 EXPECT_TRUE(ExecuteScriptAndExtractBool(
162 shell()->web_contents(),
163 "window.domAutomationController.send(clickBlankTargetedLink());",
164 &success));
165 EXPECT_TRUE(success);
167 // Wait for the navigation in the new window to finish.
168 WaitForLoadStop(new_shell->web_contents());
169 GURL blank_url(url::kAboutBlankURL);
170 EXPECT_EQ(blank_url,
171 new_shell->web_contents()->GetLastCommittedURL());
172 EXPECT_EQ(orig_site_instance, new_shell->web_contents()->GetSiteInstance());
174 // We should have access to the opened window's location.
175 success = false;
176 EXPECT_TRUE(ExecuteScriptAndExtractBool(
177 shell()->web_contents(),
178 "window.domAutomationController.send(testScriptAccessToWindow());",
179 &success));
180 EXPECT_TRUE(success);
183 // Test for crbug.com/24447. Following a cross-site link with rel=noreferrer
184 // and target=_blank should create a new SiteInstance.
185 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
186 SwapProcessWithRelNoreferrerAndTargetBlank) {
187 StartServer();
189 // Load a page with links that open in a new window.
190 std::string replacement_path;
191 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
192 "files/click-noreferrer-links.html",
193 foo_host_port_,
194 &replacement_path));
195 NavigateToURL(shell(), test_server()->GetURL(replacement_path));
197 // Get the original SiteInstance for later comparison.
198 scoped_refptr<SiteInstance> orig_site_instance(
199 shell()->web_contents()->GetSiteInstance());
200 EXPECT_TRUE(orig_site_instance.get() != NULL);
202 // Test clicking a rel=noreferrer + target=blank link.
203 ShellAddedObserver new_shell_observer;
204 bool success = false;
205 EXPECT_TRUE(ExecuteScriptAndExtractBool(
206 shell()->web_contents(),
207 "window.domAutomationController.send(clickNoRefTargetBlankLink());",
208 &success));
209 EXPECT_TRUE(success);
211 // Wait for the window to open.
212 Shell* new_shell = new_shell_observer.GetShell();
214 EXPECT_EQ("/files/title2.html",
215 new_shell->web_contents()->GetVisibleURL().path());
217 // Wait for the cross-site transition in the new tab to finish.
218 WaitForLoadStop(new_shell->web_contents());
219 WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
220 new_shell->web_contents());
221 EXPECT_FALSE(web_contents->GetRenderManagerForTesting()->
222 pending_render_view_host());
224 // Should have a new SiteInstance.
225 scoped_refptr<SiteInstance> noref_blank_site_instance(
226 new_shell->web_contents()->GetSiteInstance());
227 EXPECT_NE(orig_site_instance, noref_blank_site_instance);
230 // As of crbug.com/69267, we create a new BrowsingInstance (and SiteInstance)
231 // for rel=noreferrer links in new windows, even to same site pages and named
232 // targets.
233 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
234 SwapProcessWithSameSiteRelNoreferrer) {
235 StartServer();
237 // Load a page with links that open in a new window.
238 std::string replacement_path;
239 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
240 "files/click-noreferrer-links.html",
241 foo_host_port_,
242 &replacement_path));
243 NavigateToURL(shell(), test_server()->GetURL(replacement_path));
245 // Get the original SiteInstance for later comparison.
246 scoped_refptr<SiteInstance> orig_site_instance(
247 shell()->web_contents()->GetSiteInstance());
248 EXPECT_TRUE(orig_site_instance.get() != NULL);
250 // Test clicking a same-site rel=noreferrer + target=foo link.
251 ShellAddedObserver new_shell_observer;
252 bool success = false;
253 EXPECT_TRUE(ExecuteScriptAndExtractBool(
254 shell()->web_contents(),
255 "window.domAutomationController.send(clickSameSiteNoRefTargetedLink());",
256 &success));
257 EXPECT_TRUE(success);
259 // Wait for the window to open.
260 Shell* new_shell = new_shell_observer.GetShell();
262 // Opens in new window.
263 EXPECT_EQ("/files/title2.html",
264 new_shell->web_contents()->GetVisibleURL().path());
266 // Wait for the cross-site transition in the new tab to finish.
267 WaitForLoadStop(new_shell->web_contents());
268 WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
269 new_shell->web_contents());
270 EXPECT_FALSE(web_contents->GetRenderManagerForTesting()->
271 pending_render_view_host());
273 // Should have a new SiteInstance (in a new BrowsingInstance).
274 scoped_refptr<SiteInstance> noref_blank_site_instance(
275 new_shell->web_contents()->GetSiteInstance());
276 EXPECT_NE(orig_site_instance, noref_blank_site_instance);
279 // Test for crbug.com/24447. Following a cross-site link with just
280 // target=_blank should not create a new SiteInstance, unless we
281 // are running in --site-per-process mode.
282 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
283 DontSwapProcessWithOnlyTargetBlank) {
284 StartServer();
286 // Load a page with links that open in a new window.
287 std::string replacement_path;
288 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
289 "files/click-noreferrer-links.html",
290 foo_host_port_,
291 &replacement_path));
292 EXPECT_TRUE(NavigateToURL(shell(), test_server()->GetURL(replacement_path)));
294 // Get the original SiteInstance for later comparison.
295 scoped_refptr<SiteInstance> orig_site_instance(
296 shell()->web_contents()->GetSiteInstance());
297 EXPECT_TRUE(orig_site_instance.get() != NULL);
299 // Test clicking a target=blank link.
300 ShellAddedObserver new_shell_observer;
301 bool success = false;
302 EXPECT_TRUE(ExecuteScriptAndExtractBool(
303 shell()->web_contents(),
304 "window.domAutomationController.send(clickTargetBlankLink());",
305 &success));
306 EXPECT_TRUE(success);
308 // Wait for the window to open.
309 Shell* new_shell = new_shell_observer.GetShell();
311 // Wait for the cross-site transition in the new tab to finish.
312 EXPECT_TRUE(WaitForLoadStop(new_shell->web_contents()));
313 EXPECT_EQ("/files/title2.html",
314 new_shell->web_contents()->GetLastCommittedURL().path());
316 // Should have the same SiteInstance unless we're in site-per-process mode.
317 scoped_refptr<SiteInstance> blank_site_instance(
318 new_shell->web_contents()->GetSiteInstance());
319 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
320 switches::kSitePerProcess))
321 EXPECT_EQ(orig_site_instance, blank_site_instance);
322 else
323 EXPECT_NE(orig_site_instance, blank_site_instance);
326 // Test for crbug.com/24447. Following a cross-site link with rel=noreferrer
327 // and no target=_blank should not create a new SiteInstance.
328 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
329 DontSwapProcessWithOnlyRelNoreferrer) {
330 StartServer();
332 // Load a page with links that open in a new window.
333 std::string replacement_path;
334 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
335 "files/click-noreferrer-links.html",
336 foo_host_port_,
337 &replacement_path));
338 NavigateToURL(shell(), test_server()->GetURL(replacement_path));
340 // Get the original SiteInstance for later comparison.
341 scoped_refptr<SiteInstance> orig_site_instance(
342 shell()->web_contents()->GetSiteInstance());
343 EXPECT_TRUE(orig_site_instance.get() != NULL);
345 // Test clicking a rel=noreferrer link.
346 bool success = false;
347 EXPECT_TRUE(ExecuteScriptAndExtractBool(
348 shell()->web_contents(),
349 "window.domAutomationController.send(clickNoRefLink());",
350 &success));
351 EXPECT_TRUE(success);
353 // Wait for the cross-site transition in the current tab to finish.
354 WaitForLoadStop(shell()->web_contents());
356 // Opens in same window.
357 EXPECT_EQ(1u, Shell::windows().size());
358 EXPECT_EQ("/files/title2.html",
359 shell()->web_contents()->GetLastCommittedURL().path());
361 // Should have the same SiteInstance unless we're in site-per-process mode.
362 scoped_refptr<SiteInstance> noref_site_instance(
363 shell()->web_contents()->GetSiteInstance());
364 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
365 switches::kSitePerProcess))
366 EXPECT_EQ(orig_site_instance, noref_site_instance);
367 else
368 EXPECT_NE(orig_site_instance, noref_site_instance);
371 // Test for crbug.com/116192. Targeted links should still work after the
372 // named target window has swapped processes.
373 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
374 AllowTargetedNavigationsAfterSwap) {
375 StartServer();
377 // Load a page with links that open in a new window.
378 std::string replacement_path;
379 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
380 "files/click-noreferrer-links.html",
381 foo_host_port_,
382 &replacement_path));
383 NavigateToURL(shell(), test_server()->GetURL(replacement_path));
385 // Get the original SiteInstance for later comparison.
386 scoped_refptr<SiteInstance> orig_site_instance(
387 shell()->web_contents()->GetSiteInstance());
388 EXPECT_TRUE(orig_site_instance.get() != NULL);
390 // Test clicking a target=foo link.
391 ShellAddedObserver new_shell_observer;
392 bool success = false;
393 EXPECT_TRUE(ExecuteScriptAndExtractBool(
394 shell()->web_contents(),
395 "window.domAutomationController.send(clickSameSiteTargetedLink());",
396 &success));
397 EXPECT_TRUE(success);
398 Shell* new_shell = new_shell_observer.GetShell();
400 // Wait for the navigation in the new tab to finish, if it hasn't.
401 WaitForLoadStop(new_shell->web_contents());
402 EXPECT_EQ("/files/navigate_opener.html",
403 new_shell->web_contents()->GetLastCommittedURL().path());
405 // Should have the same SiteInstance.
406 scoped_refptr<SiteInstance> blank_site_instance(
407 new_shell->web_contents()->GetSiteInstance());
408 EXPECT_EQ(orig_site_instance, blank_site_instance);
410 // Now navigate the new tab to a different site.
411 GURL cross_site_url(GetCrossSiteURL("files/title1.html"));
412 NavigateToURL(new_shell, cross_site_url);
413 scoped_refptr<SiteInstance> new_site_instance(
414 new_shell->web_contents()->GetSiteInstance());
415 EXPECT_NE(orig_site_instance, new_site_instance);
417 // Clicking the original link in the first tab should cause us to swap back.
418 TestNavigationObserver navigation_observer(new_shell->web_contents());
419 EXPECT_TRUE(ExecuteScriptAndExtractBool(
420 shell()->web_contents(),
421 "window.domAutomationController.send(clickSameSiteTargetedLink());",
422 &success));
423 EXPECT_TRUE(success);
424 navigation_observer.Wait();
426 // Should have swapped back and shown the new window again.
427 scoped_refptr<SiteInstance> revisit_site_instance(
428 new_shell->web_contents()->GetSiteInstance());
429 EXPECT_EQ(orig_site_instance, revisit_site_instance);
431 // If it navigates away to another process, the original window should
432 // still be able to close it (using a cross-process close message).
433 NavigateToURL(new_shell, cross_site_url);
434 EXPECT_EQ(new_site_instance.get(),
435 new_shell->web_contents()->GetSiteInstance());
436 WebContentsDestroyedWatcher close_watcher(new_shell->web_contents());
437 EXPECT_TRUE(ExecuteScriptAndExtractBool(
438 shell()->web_contents(),
439 "window.domAutomationController.send(testCloseWindow());",
440 &success));
441 EXPECT_TRUE(success);
442 close_watcher.Wait();
445 // Test that setting the opener to null in a window affects cross-process
446 // navigations, including those to existing entries. http://crbug.com/156669.
447 // This test crashes under ThreadSanitizer, http://crbug.com/356758.
448 #if defined(THREAD_SANITIZER)
449 #define MAYBE_DisownOpener DISABLED_DisownOpener
450 #else
451 #define MAYBE_DisownOpener DisownOpener
452 #endif
453 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, MAYBE_DisownOpener) {
454 StartServer();
456 // Load a page with links that open in a new window.
457 std::string replacement_path;
458 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
459 "files/click-noreferrer-links.html",
460 foo_host_port_,
461 &replacement_path));
462 NavigateToURL(shell(), test_server()->GetURL(replacement_path));
464 // Get the original SiteInstance for later comparison.
465 scoped_refptr<SiteInstance> orig_site_instance(
466 shell()->web_contents()->GetSiteInstance());
467 EXPECT_TRUE(orig_site_instance.get() != NULL);
469 // Test clicking a target=_blank link.
470 ShellAddedObserver new_shell_observer;
471 bool success = false;
472 EXPECT_TRUE(ExecuteScriptAndExtractBool(
473 shell()->web_contents(),
474 "window.domAutomationController.send(clickSameSiteTargetBlankLink());",
475 &success));
476 EXPECT_TRUE(success);
477 Shell* new_shell = new_shell_observer.GetShell();
478 EXPECT_TRUE(new_shell->web_contents()->HasOpener());
480 // Wait for the navigation in the new tab to finish, if it hasn't.
481 WaitForLoadStop(new_shell->web_contents());
482 EXPECT_EQ("/files/title2.html",
483 new_shell->web_contents()->GetLastCommittedURL().path());
485 // Should have the same SiteInstance.
486 scoped_refptr<SiteInstance> blank_site_instance(
487 new_shell->web_contents()->GetSiteInstance());
488 EXPECT_EQ(orig_site_instance, blank_site_instance);
490 // Now navigate the new tab to a different site.
491 NavigateToURL(new_shell, GetCrossSiteURL("files/title1.html"));
492 scoped_refptr<SiteInstance> new_site_instance(
493 new_shell->web_contents()->GetSiteInstance());
494 EXPECT_NE(orig_site_instance, new_site_instance);
495 EXPECT_TRUE(new_shell->web_contents()->HasOpener());
497 // Now disown the opener.
498 EXPECT_TRUE(ExecuteScript(new_shell->web_contents(),
499 "window.opener = null;"));
500 EXPECT_FALSE(new_shell->web_contents()->HasOpener());
502 // Go back and ensure the opener is still null.
504 TestNavigationObserver back_nav_load_observer(new_shell->web_contents());
505 new_shell->web_contents()->GetController().GoBack();
506 back_nav_load_observer.Wait();
508 success = false;
509 EXPECT_TRUE(ExecuteScriptAndExtractBool(
510 new_shell->web_contents(),
511 "window.domAutomationController.send(window.opener == null);",
512 &success));
513 EXPECT_TRUE(success);
514 EXPECT_FALSE(new_shell->web_contents()->HasOpener());
516 // Now navigate forward again (creating a new process) and check opener.
517 NavigateToURL(new_shell, GetCrossSiteURL("files/title1.html"));
518 success = false;
519 EXPECT_TRUE(ExecuteScriptAndExtractBool(
520 new_shell->web_contents(),
521 "window.domAutomationController.send(window.opener == null);",
522 &success));
523 EXPECT_TRUE(success);
524 EXPECT_FALSE(new_shell->web_contents()->HasOpener());
527 // Test that subframes can disown their openers. http://crbug.com/225528.
528 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, DisownSubframeOpener) {
529 const GURL frame_url("data:text/html,<iframe name=\"foo\"></iframe>");
530 NavigateToURL(shell(), frame_url);
532 // Give the frame an opener using window.open.
533 EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
534 "window.open('about:blank','foo');"));
536 // Now disown the frame's opener. Shouldn't crash.
537 EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
538 "window.frames[0].opener = null;"));
541 // Test for crbug.com/99202. PostMessage calls should still work after
542 // navigating the source and target windows to different sites.
543 // Specifically:
544 // 1) Create 3 windows (opener, "foo", and _blank) and send "foo" cross-process.
545 // 2) Fail to post a message from "foo" to opener with the wrong target origin.
546 // 3) Post a message from "foo" to opener, which replies back to "foo".
547 // 4) Post a message from _blank to "foo".
548 // 5) Post a message from "foo" to a subframe of opener, which replies back.
549 // 6) Post a message from _blank to a subframe of "foo".
550 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
551 SupportCrossProcessPostMessage) {
552 StartServer();
554 // Load a page with links that open in a new window.
555 std::string replacement_path;
556 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
557 "files/click-noreferrer-links.html",
558 foo_host_port_,
559 &replacement_path));
560 NavigateToURL(shell(), test_server()->GetURL(replacement_path));
562 // Get the original SiteInstance and RVHM for later comparison.
563 WebContents* opener_contents = shell()->web_contents();
564 scoped_refptr<SiteInstance> orig_site_instance(
565 opener_contents->GetSiteInstance());
566 EXPECT_TRUE(orig_site_instance.get() != NULL);
567 RenderFrameHostManager* opener_manager = static_cast<WebContentsImpl*>(
568 opener_contents)->GetRenderManagerForTesting();
570 // 1) Open two more windows, one named. These initially have openers but no
571 // reference to each other. We will later post a message between them.
573 // First, a named target=foo window.
574 ShellAddedObserver new_shell_observer;
575 bool success = false;
576 EXPECT_TRUE(ExecuteScriptAndExtractBool(
577 opener_contents,
578 "window.domAutomationController.send(clickSameSiteTargetedLink());",
579 &success));
580 EXPECT_TRUE(success);
581 Shell* new_shell = new_shell_observer.GetShell();
583 // Wait for the navigation in the new window to finish, if it hasn't, then
584 // send it to post_message.html on a different site.
585 WebContents* foo_contents = new_shell->web_contents();
586 WaitForLoadStop(foo_contents);
587 EXPECT_EQ("/files/navigate_opener.html",
588 foo_contents->GetLastCommittedURL().path());
589 NavigateToURL(new_shell, GetCrossSiteURL("files/post_message.html"));
590 scoped_refptr<SiteInstance> foo_site_instance(
591 foo_contents->GetSiteInstance());
592 EXPECT_NE(orig_site_instance, foo_site_instance);
594 // Second, a target=_blank window.
595 ShellAddedObserver new_shell_observer2;
596 EXPECT_TRUE(ExecuteScriptAndExtractBool(
597 shell()->web_contents(),
598 "window.domAutomationController.send(clickSameSiteTargetBlankLink());",
599 &success));
600 EXPECT_TRUE(success);
602 // Wait for the navigation in the new window to finish, if it hasn't, then
603 // send it to post_message.html on the original site.
604 Shell* new_shell2 = new_shell_observer2.GetShell();
605 WebContents* new_contents = new_shell2->web_contents();
606 WaitForLoadStop(new_contents);
607 EXPECT_EQ("/files/title2.html", new_contents->GetLastCommittedURL().path());
608 NavigateToURL(new_shell2, test_server()->GetURL("files/post_message.html"));
609 EXPECT_EQ(orig_site_instance.get(), new_contents->GetSiteInstance());
610 RenderFrameHostManager* new_manager =
611 static_cast<WebContentsImpl*>(new_contents)->GetRenderManagerForTesting();
613 // We now have three windows. The opener should have a swapped out RVH
614 // for the new SiteInstance, but the _blank window should not.
615 EXPECT_EQ(3u, Shell::windows().size());
616 EXPECT_TRUE(
617 opener_manager->GetSwappedOutRenderViewHost(foo_site_instance.get()));
618 EXPECT_FALSE(
619 new_manager->GetSwappedOutRenderViewHost(foo_site_instance.get()));
621 // 2) Fail to post a message from the foo window to the opener if the target
622 // origin is wrong. We won't see an error, but we can check for the right
623 // number of received messages below.
624 EXPECT_TRUE(ExecuteScriptAndExtractBool(
625 foo_contents,
626 "window.domAutomationController.send(postToOpener('msg',"
627 " 'http://google.com'));",
628 &success));
629 EXPECT_TRUE(success);
630 ASSERT_FALSE(
631 opener_manager->GetSwappedOutRenderViewHost(orig_site_instance.get()));
633 // 3) Post a message from the foo window to the opener. The opener will
634 // reply, causing the foo window to update its own title.
635 base::string16 expected_title = ASCIIToUTF16("msg");
636 TitleWatcher title_watcher(foo_contents, expected_title);
637 EXPECT_TRUE(ExecuteScriptAndExtractBool(
638 foo_contents,
639 "window.domAutomationController.send(postToOpener('msg','*'));",
640 &success));
641 EXPECT_TRUE(success);
642 ASSERT_FALSE(
643 opener_manager->GetSwappedOutRenderViewHost(orig_site_instance.get()));
644 ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
646 // We should have received only 1 message in the opener and "foo" tabs,
647 // and updated the title.
648 int opener_received_messages = 0;
649 EXPECT_TRUE(ExecuteScriptAndExtractInt(
650 opener_contents,
651 "window.domAutomationController.send(window.receivedMessages);",
652 &opener_received_messages));
653 int foo_received_messages = 0;
654 EXPECT_TRUE(ExecuteScriptAndExtractInt(
655 foo_contents,
656 "window.domAutomationController.send(window.receivedMessages);",
657 &foo_received_messages));
658 EXPECT_EQ(1, foo_received_messages);
659 EXPECT_EQ(1, opener_received_messages);
660 EXPECT_EQ(ASCIIToUTF16("msg"), foo_contents->GetTitle());
662 // 4) Now post a message from the _blank window to the foo window. The
663 // foo window will update its title and will not reply.
664 expected_title = ASCIIToUTF16("msg2");
665 TitleWatcher title_watcher2(foo_contents, expected_title);
666 EXPECT_TRUE(ExecuteScriptAndExtractBool(
667 new_contents,
668 "window.domAutomationController.send(postToFoo('msg2'));",
669 &success));
670 EXPECT_TRUE(success);
671 ASSERT_EQ(expected_title, title_watcher2.WaitAndGetTitle());
673 // This postMessage should have created a swapped out RVH for the new
674 // SiteInstance in the target=_blank window.
675 EXPECT_TRUE(
676 new_manager->GetSwappedOutRenderViewHost(foo_site_instance.get()));
678 // TODO(nasko): Test subframe targeting of postMessage once
679 // http://crbug.com/153701 is fixed.
682 // Test for crbug.com/278336. MessagePorts should work cross-process. I.e.,
683 // messages which contain Transferables and get intercepted by
684 // RenderViewImpl::willCheckAndDispatchMessageEvent (because the RenderView is
685 // swapped out) should work.
686 // Specifically:
687 // 1) Create 2 windows (opener and "foo") and send "foo" cross-process.
688 // 2) Post a message containing a message port from opener to "foo".
689 // 3) Post a message from "foo" back to opener via the passed message port.
690 // The test will be enabled when the feature implementation lands.
691 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
692 SupportCrossProcessPostMessageWithMessagePort) {
693 StartServer();
695 // Load a page with links that open in a new window.
696 std::string replacement_path;
697 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
698 "files/click-noreferrer-links.html",
699 foo_host_port_,
700 &replacement_path));
701 NavigateToURL(shell(), test_server()->GetURL(replacement_path));
703 // Get the original SiteInstance and RVHM for later comparison.
704 WebContents* opener_contents = shell()->web_contents();
705 scoped_refptr<SiteInstance> orig_site_instance(
706 opener_contents->GetSiteInstance());
707 EXPECT_TRUE(orig_site_instance.get() != NULL);
708 RenderFrameHostManager* opener_manager = static_cast<WebContentsImpl*>(
709 opener_contents)->GetRenderManagerForTesting();
711 // 1) Open a named target=foo window. We will later post a message between the
712 // opener and the new window.
713 ShellAddedObserver new_shell_observer;
714 bool success = false;
715 EXPECT_TRUE(ExecuteScriptAndExtractBool(
716 opener_contents,
717 "window.domAutomationController.send(clickSameSiteTargetedLink());",
718 &success));
719 EXPECT_TRUE(success);
720 Shell* new_shell = new_shell_observer.GetShell();
722 // Wait for the navigation in the new window to finish, if it hasn't, then
723 // send it to post_message.html on a different site.
724 WebContents* foo_contents = new_shell->web_contents();
725 WaitForLoadStop(foo_contents);
726 EXPECT_EQ("/files/navigate_opener.html",
727 foo_contents->GetLastCommittedURL().path());
728 NavigateToURL(new_shell, GetCrossSiteURL("files/post_message.html"));
729 scoped_refptr<SiteInstance> foo_site_instance(
730 foo_contents->GetSiteInstance());
731 EXPECT_NE(orig_site_instance, foo_site_instance);
733 // We now have two windows. The opener should have a swapped out RVH
734 // for the new SiteInstance.
735 EXPECT_EQ(2u, Shell::windows().size());
736 EXPECT_TRUE(
737 opener_manager->GetSwappedOutRenderViewHost(foo_site_instance.get()));
739 // 2) Post a message containing a MessagePort from opener to the the foo
740 // window. The foo window will reply via the passed port, causing the opener
741 // to update its own title.
742 base::string16 expected_title = ASCIIToUTF16("msg-back-via-port");
743 TitleWatcher title_observer(opener_contents, expected_title);
744 EXPECT_TRUE(ExecuteScriptAndExtractBool(
745 opener_contents,
746 "window.domAutomationController.send(postWithPortToFoo());",
747 &success));
748 EXPECT_TRUE(success);
749 ASSERT_FALSE(
750 opener_manager->GetSwappedOutRenderViewHost(orig_site_instance.get()));
751 ASSERT_EQ(expected_title, title_observer.WaitAndGetTitle());
753 // Check message counts.
754 int opener_received_messages_via_port = 0;
755 EXPECT_TRUE(ExecuteScriptAndExtractInt(
756 opener_contents,
757 "window.domAutomationController.send(window.receivedMessagesViaPort);",
758 &opener_received_messages_via_port));
759 int foo_received_messages = 0;
760 EXPECT_TRUE(ExecuteScriptAndExtractInt(
761 foo_contents,
762 "window.domAutomationController.send(window.receivedMessages);",
763 &foo_received_messages));
764 int foo_received_messages_with_port = 0;
765 EXPECT_TRUE(ExecuteScriptAndExtractInt(
766 foo_contents,
767 "window.domAutomationController.send(window.receivedMessagesWithPort);",
768 &foo_received_messages_with_port));
769 EXPECT_EQ(1, foo_received_messages);
770 EXPECT_EQ(1, foo_received_messages_with_port);
771 EXPECT_EQ(1, opener_received_messages_via_port);
772 EXPECT_EQ(ASCIIToUTF16("msg-with-port"), foo_contents->GetTitle());
773 EXPECT_EQ(ASCIIToUTF16("msg-back-via-port"), opener_contents->GetTitle());
776 // Test for crbug.com/116192. Navigations to a window's opener should
777 // still work after a process swap.
778 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
779 AllowTargetedNavigationsInOpenerAfterSwap) {
780 StartServer();
782 // Load a page with links that open in a new window.
783 std::string replacement_path;
784 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
785 "files/click-noreferrer-links.html",
786 foo_host_port_,
787 &replacement_path));
788 NavigateToURL(shell(), test_server()->GetURL(replacement_path));
790 // Get the original tab and SiteInstance for later comparison.
791 WebContents* orig_contents = shell()->web_contents();
792 scoped_refptr<SiteInstance> orig_site_instance(
793 orig_contents->GetSiteInstance());
794 EXPECT_TRUE(orig_site_instance.get() != NULL);
796 // Test clicking a target=foo link.
797 ShellAddedObserver new_shell_observer;
798 bool success = false;
799 EXPECT_TRUE(ExecuteScriptAndExtractBool(
800 orig_contents,
801 "window.domAutomationController.send(clickSameSiteTargetedLink());",
802 &success));
803 EXPECT_TRUE(success);
804 Shell* new_shell = new_shell_observer.GetShell();
806 // Wait for the navigation in the new window to finish, if it hasn't.
807 WaitForLoadStop(new_shell->web_contents());
808 EXPECT_EQ("/files/navigate_opener.html",
809 new_shell->web_contents()->GetLastCommittedURL().path());
811 // Should have the same SiteInstance.
812 scoped_refptr<SiteInstance> blank_site_instance(
813 new_shell->web_contents()->GetSiteInstance());
814 EXPECT_EQ(orig_site_instance, blank_site_instance);
816 // Now navigate the original (opener) tab to a different site.
817 NavigateToURL(shell(), GetCrossSiteURL("files/title1.html"));
818 scoped_refptr<SiteInstance> new_site_instance(
819 shell()->web_contents()->GetSiteInstance());
820 EXPECT_NE(orig_site_instance, new_site_instance);
822 // The opened tab should be able to navigate the opener back to its process.
823 TestNavigationObserver navigation_observer(orig_contents);
824 EXPECT_TRUE(ExecuteScriptAndExtractBool(
825 new_shell->web_contents(),
826 "window.domAutomationController.send(navigateOpener());",
827 &success));
828 EXPECT_TRUE(success);
829 navigation_observer.Wait();
831 // Should have swapped back into this process.
832 scoped_refptr<SiteInstance> revisit_site_instance(
833 shell()->web_contents()->GetSiteInstance());
834 EXPECT_EQ(orig_site_instance, revisit_site_instance);
837 // Test that subframes do not crash when sending a postMessage to the top frame
838 // from an unload handler while the top frame is being swapped out as part of
839 // navigating cross-process. https://crbug.com/475651.
840 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
841 PostMessageFromSubframeUnloadHandler) {
842 StartServer();
844 GURL frame_url(test_server()->GetURL("files/post_message.html"));
845 GURL main_url("data:text/html,<iframe name='foo' src='" + frame_url.spec() +
846 "'></iframe>");
847 EXPECT_TRUE(NavigateToURL(shell(), main_url));
849 // Get the original SiteInstance for later comparison.
850 scoped_refptr<SiteInstance> orig_site_instance(
851 shell()->web_contents()->GetSiteInstance());
852 EXPECT_NE(nullptr, orig_site_instance.get());
854 // It is safe to obtain the root frame tree node here, as it doesn't change.
855 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
856 ->GetFrameTree()
857 ->root();
858 ASSERT_EQ(1U, root->child_count());
859 EXPECT_EQ(frame_url, root->child_at(0)->current_url());
861 // Register an unload handler that sends a postMessage to the top frame.
862 EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(),
863 "registerUnload();"));
865 // Navigate the top frame cross-site. This will cause the top frame to be
866 // swapped out and run unload handlers, and the original renderer process
867 // should then terminate since it's not rendering any other frames.
868 RenderProcessHostWatcher exit_observer(
869 root->current_frame_host()->GetProcess(),
870 RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION);
871 EXPECT_TRUE(NavigateToURL(shell(), GetCrossSiteURL("files/title1.html")));
872 scoped_refptr<SiteInstance> new_site_instance(
873 shell()->web_contents()->GetSiteInstance());
874 EXPECT_NE(orig_site_instance, new_site_instance);
876 // Ensure that the original renderer process exited cleanly without crashing.
877 exit_observer.Wait();
878 EXPECT_EQ(true, exit_observer.did_exit_normally());
881 // Test that opening a new window in the same SiteInstance and then navigating
882 // both windows to a different SiteInstance allows the first process to exit.
883 // See http://crbug.com/126333.
884 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
885 ProcessExitWithSwappedOutViews) {
886 StartServer();
888 // Load a page with links that open in a new window.
889 std::string replacement_path;
890 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
891 "files/click-noreferrer-links.html",
892 foo_host_port_,
893 &replacement_path));
894 NavigateToURL(shell(), test_server()->GetURL(replacement_path));
896 // Get the original SiteInstance for later comparison.
897 scoped_refptr<SiteInstance> orig_site_instance(
898 shell()->web_contents()->GetSiteInstance());
899 EXPECT_TRUE(orig_site_instance.get() != NULL);
901 // Test clicking a target=foo link.
902 ShellAddedObserver new_shell_observer;
903 bool success = false;
904 EXPECT_TRUE(ExecuteScriptAndExtractBool(
905 shell()->web_contents(),
906 "window.domAutomationController.send(clickSameSiteTargetedLink());",
907 &success));
908 EXPECT_TRUE(success);
909 Shell* new_shell = new_shell_observer.GetShell();
911 // Wait for the navigation in the new window to finish, if it hasn't.
912 WaitForLoadStop(new_shell->web_contents());
913 EXPECT_EQ("/files/navigate_opener.html",
914 new_shell->web_contents()->GetLastCommittedURL().path());
916 // Should have the same SiteInstance.
917 scoped_refptr<SiteInstance> opened_site_instance(
918 new_shell->web_contents()->GetSiteInstance());
919 EXPECT_EQ(orig_site_instance, opened_site_instance);
921 // Now navigate the opened window to a different site.
922 NavigateToURL(new_shell, GetCrossSiteURL("files/title1.html"));
923 scoped_refptr<SiteInstance> new_site_instance(
924 new_shell->web_contents()->GetSiteInstance());
925 EXPECT_NE(orig_site_instance, new_site_instance);
927 // The original process should still be alive, since it is still used in the
928 // first window.
929 RenderProcessHost* orig_process = orig_site_instance->GetProcess();
930 EXPECT_TRUE(orig_process->HasConnection());
932 // Navigate the first window to a different site as well. The original
933 // process should exit, since all of its views are now swapped out.
934 RenderProcessHostWatcher exit_observer(
935 orig_process,
936 RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION);
937 NavigateToURL(shell(), GetCrossSiteURL("files/title1.html"));
938 exit_observer.Wait();
939 scoped_refptr<SiteInstance> new_site_instance2(
940 shell()->web_contents()->GetSiteInstance());
941 EXPECT_EQ(new_site_instance, new_site_instance2);
944 // Test for crbug.com/76666. A cross-site navigation that fails with a 204
945 // error should not make us ignore future renderer-initiated navigations.
946 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, ClickLinkAfter204Error) {
947 StartServer();
949 // Get the original SiteInstance for later comparison.
950 scoped_refptr<SiteInstance> orig_site_instance(
951 shell()->web_contents()->GetSiteInstance());
952 EXPECT_TRUE(orig_site_instance.get() != NULL);
954 // Load a cross-site page that fails with a 204 error.
955 EXPECT_TRUE(NavigateToURLAndExpectNoCommit(shell(),
956 GetCrossSiteURL("nocontent")));
958 // We should still be looking at the normal page. Because we started from a
959 // blank new tab, the typed URL will still be visible until the user clears it
960 // manually. The last committed URL will be the previous page.
961 scoped_refptr<SiteInstance> post_nav_site_instance(
962 shell()->web_contents()->GetSiteInstance());
963 EXPECT_EQ(orig_site_instance, post_nav_site_instance);
964 EXPECT_EQ("/nocontent",
965 shell()->web_contents()->GetVisibleURL().path());
966 EXPECT_FALSE(
967 shell()->web_contents()->GetController().GetLastCommittedEntry());
969 // Renderer-initiated navigations should work.
970 base::string16 expected_title = ASCIIToUTF16("Title Of Awesomeness");
971 TitleWatcher title_watcher(shell()->web_contents(), expected_title);
972 GURL url = test_server()->GetURL("files/title2.html");
973 EXPECT_TRUE(ExecuteScript(
974 shell()->web_contents(),
975 base::StringPrintf("location.href = '%s'", url.spec().c_str())));
976 ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
978 // Opens in same tab.
979 EXPECT_EQ(1u, Shell::windows().size());
980 EXPECT_EQ("/files/title2.html",
981 shell()->web_contents()->GetLastCommittedURL().path());
983 // Should have the same SiteInstance.
984 scoped_refptr<SiteInstance> new_site_instance(
985 shell()->web_contents()->GetSiteInstance());
986 EXPECT_EQ(orig_site_instance, new_site_instance);
989 // Test for crbug.com/9682. We should show the URL for a pending renderer-
990 // initiated navigation in a new tab, until the content of the initial
991 // about:blank page is modified by another window. At that point, we should
992 // revert to showing about:blank to prevent a URL spoof.
993 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, ShowLoadingURLUntilSpoof) {
994 ASSERT_TRUE(test_server()->Start());
996 // Load a page that can open a URL that won't commit in a new window.
997 NavigateToURL(
998 shell(), test_server()->GetURL("files/click-nocontent-link.html"));
999 WebContents* orig_contents = shell()->web_contents();
1001 // Click a /nocontent link that opens in a new window but never commits.
1002 ShellAddedObserver new_shell_observer;
1003 bool success = false;
1004 EXPECT_TRUE(ExecuteScriptAndExtractBool(
1005 orig_contents,
1006 "window.domAutomationController.send(clickNoContentTargetedLink());",
1007 &success));
1008 EXPECT_TRUE(success);
1010 // Wait for the window to open.
1011 Shell* new_shell = new_shell_observer.GetShell();
1013 // Ensure the destination URL is visible, because it is considered the
1014 // initial navigation.
1015 WebContents* contents = new_shell->web_contents();
1016 EXPECT_TRUE(contents->GetController().IsInitialNavigation());
1017 EXPECT_EQ("/nocontent",
1018 contents->GetController().GetVisibleEntry()->GetURL().path());
1020 // Now modify the contents of the new window from the opener. This will also
1021 // modify the title of the document to give us something to listen for.
1022 base::string16 expected_title = ASCIIToUTF16("Modified Title");
1023 TitleWatcher title_watcher(contents, expected_title);
1024 success = false;
1025 EXPECT_TRUE(ExecuteScriptAndExtractBool(
1026 orig_contents,
1027 "window.domAutomationController.send(modifyNewWindow());",
1028 &success));
1029 EXPECT_TRUE(success);
1030 ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
1032 // At this point, we should no longer be showing the destination URL.
1033 // The visible entry should be null, resulting in about:blank in the address
1034 // bar.
1035 EXPECT_FALSE(contents->GetController().GetVisibleEntry());
1038 // Test for crbug.com/9682. We should not show the URL for a pending renderer-
1039 // initiated navigation in a new tab if it is not the initial navigation. In
1040 // this case, the renderer will not notify us of a modification, so we cannot
1041 // show the pending URL without allowing a spoof.
1042 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
1043 DontShowLoadingURLIfNotInitialNav) {
1044 ASSERT_TRUE(test_server()->Start());
1046 // Load a page that can open a URL that won't commit in a new window.
1047 NavigateToURL(
1048 shell(), test_server()->GetURL("files/click-nocontent-link.html"));
1049 WebContents* orig_contents = shell()->web_contents();
1051 // Click a /nocontent link that opens in a new window but never commits.
1052 // By using an onclick handler that first creates the window, the slow
1053 // navigation is not considered an initial navigation.
1054 ShellAddedObserver new_shell_observer;
1055 bool success = false;
1056 EXPECT_TRUE(ExecuteScriptAndExtractBool(
1057 orig_contents,
1058 "window.domAutomationController.send("
1059 "clickNoContentScriptedTargetedLink());",
1060 &success));
1061 EXPECT_TRUE(success);
1063 // Wait for the window to open.
1064 Shell* new_shell = new_shell_observer.GetShell();
1066 // Ensure the destination URL is not visible, because it is not the initial
1067 // navigation.
1068 WebContents* contents = new_shell->web_contents();
1069 EXPECT_FALSE(contents->GetController().IsInitialNavigation());
1070 EXPECT_FALSE(contents->GetController().GetVisibleEntry());
1073 // Crashes under ThreadSanitizer, http://crbug.com/356758.
1074 #if defined(THREAD_SANITIZER)
1075 #define MAYBE_BackForwardNotStale DISABLED_BackForwardNotStale
1076 #else
1077 #define MAYBE_BackForwardNotStale BackForwardNotStale
1078 #endif
1079 // Test for http://crbug.com/93427. Ensure that cross-site navigations
1080 // do not cause back/forward navigations to be considered stale by the
1081 // renderer.
1082 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, MAYBE_BackForwardNotStale) {
1083 StartServer();
1084 NavigateToURL(shell(), GURL(url::kAboutBlankURL));
1086 // Visit a page on first site.
1087 NavigateToURL(shell(), test_server()->GetURL("files/title1.html"));
1089 // Visit three pages on second site.
1090 NavigateToURL(shell(), GetCrossSiteURL("files/title1.html"));
1091 NavigateToURL(shell(), GetCrossSiteURL("files/title2.html"));
1092 NavigateToURL(shell(), GetCrossSiteURL("files/title3.html"));
1094 // History is now [blank, A1, B1, B2, *B3].
1095 WebContents* contents = shell()->web_contents();
1096 EXPECT_EQ(5, contents->GetController().GetEntryCount());
1098 // Open another window in same process to keep this process alive.
1099 Shell* new_shell = CreateBrowser();
1100 NavigateToURL(new_shell, GetCrossSiteURL("files/title1.html"));
1102 // Go back three times to first site.
1104 TestNavigationObserver back_nav_load_observer(shell()->web_contents());
1105 shell()->web_contents()->GetController().GoBack();
1106 back_nav_load_observer.Wait();
1109 TestNavigationObserver back_nav_load_observer(shell()->web_contents());
1110 shell()->web_contents()->GetController().GoBack();
1111 back_nav_load_observer.Wait();
1114 TestNavigationObserver back_nav_load_observer(shell()->web_contents());
1115 shell()->web_contents()->GetController().GoBack();
1116 back_nav_load_observer.Wait();
1119 // Now go forward twice to B2. Shouldn't be left spinning.
1121 TestNavigationObserver forward_nav_load_observer(shell()->web_contents());
1122 shell()->web_contents()->GetController().GoForward();
1123 forward_nav_load_observer.Wait();
1126 TestNavigationObserver forward_nav_load_observer(shell()->web_contents());
1127 shell()->web_contents()->GetController().GoForward();
1128 forward_nav_load_observer.Wait();
1131 // Go back twice to first site.
1133 TestNavigationObserver back_nav_load_observer(shell()->web_contents());
1134 shell()->web_contents()->GetController().GoBack();
1135 back_nav_load_observer.Wait();
1138 TestNavigationObserver back_nav_load_observer(shell()->web_contents());
1139 shell()->web_contents()->GetController().GoBack();
1140 back_nav_load_observer.Wait();
1143 // Now go forward directly to B3. Shouldn't be left spinning.
1145 TestNavigationObserver forward_nav_load_observer(shell()->web_contents());
1146 shell()->web_contents()->GetController().GoToIndex(4);
1147 forward_nav_load_observer.Wait();
1151 // Test for http://crbug.com/130016.
1152 // Swapping out a render view should update its visiblity state.
1153 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
1154 SwappedOutViewHasCorrectVisibilityState) {
1155 StartServer();
1157 // Load a page with links that open in a new window.
1158 std::string replacement_path;
1159 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
1160 "files/click-noreferrer-links.html",
1161 foo_host_port_,
1162 &replacement_path));
1163 NavigateToURL(shell(), test_server()->GetURL(replacement_path));
1165 // Open a same-site link in a new widnow.
1166 ShellAddedObserver new_shell_observer;
1167 bool success = false;
1168 EXPECT_TRUE(ExecuteScriptAndExtractBool(
1169 shell()->web_contents(),
1170 "window.domAutomationController.send(clickSameSiteTargetedLink());",
1171 &success));
1172 EXPECT_TRUE(success);
1173 Shell* new_shell = new_shell_observer.GetShell();
1175 // Wait for the navigation in the new tab to finish, if it hasn't.
1176 WaitForLoadStop(new_shell->web_contents());
1177 EXPECT_EQ("/files/navigate_opener.html",
1178 new_shell->web_contents()->GetLastCommittedURL().path());
1180 RenderViewHost* rvh = new_shell->web_contents()->GetRenderViewHost();
1182 EXPECT_TRUE(ExecuteScriptAndExtractBool(
1183 rvh,
1184 "window.domAutomationController.send("
1185 " document.visibilityState == 'visible');",
1186 &success));
1187 EXPECT_TRUE(success);
1189 // Now navigate the new window to a different site. This should swap out the
1190 // tab's existing RenderView, causing it become hidden.
1191 NavigateToURL(new_shell, GetCrossSiteURL("files/title1.html"));
1193 EXPECT_TRUE(ExecuteScriptAndExtractBool(
1194 rvh,
1195 "window.domAutomationController.send("
1196 " document.visibilityState == 'hidden');",
1197 &success));
1198 EXPECT_TRUE(success);
1200 // Going back should make the previously swapped-out view to become visible
1201 // again.
1203 TestNavigationObserver back_nav_load_observer(new_shell->web_contents());
1204 new_shell->web_contents()->GetController().GoBack();
1205 back_nav_load_observer.Wait();
1208 EXPECT_EQ("/files/navigate_opener.html",
1209 new_shell->web_contents()->GetLastCommittedURL().path());
1211 EXPECT_EQ(rvh, new_shell->web_contents()->GetRenderViewHost());
1213 EXPECT_TRUE(ExecuteScriptAndExtractBool(
1214 rvh,
1215 "window.domAutomationController.send("
1216 " document.visibilityState == 'visible');",
1217 &success));
1218 EXPECT_TRUE(success);
1221 // This class ensures that all the given RenderViewHosts have properly been
1222 // shutdown.
1223 class RenderViewHostDestructionObserver : public WebContentsObserver {
1224 public:
1225 explicit RenderViewHostDestructionObserver(WebContents* web_contents)
1226 : WebContentsObserver(web_contents) {}
1227 ~RenderViewHostDestructionObserver() override {}
1228 void EnsureRVHGetsDestructed(RenderViewHost* rvh) {
1229 watched_render_view_hosts_.insert(rvh);
1231 size_t GetNumberOfWatchedRenderViewHosts() const {
1232 return watched_render_view_hosts_.size();
1235 private:
1236 // WebContentsObserver implementation:
1237 void RenderViewDeleted(RenderViewHost* rvh) override {
1238 watched_render_view_hosts_.erase(rvh);
1241 std::set<RenderViewHost*> watched_render_view_hosts_;
1244 // Crashes under ThreadSanitizer, http://crbug.com/356758.
1245 #if defined(THREAD_SANITIZER)
1246 #define MAYBE_LeakingRenderViewHosts DISABLED_LeakingRenderViewHosts
1247 #else
1248 #define MAYBE_LeakingRenderViewHosts LeakingRenderViewHosts
1249 #endif
1250 // Test for crbug.com/90867. Make sure we don't leak render view hosts since
1251 // they may cause crashes or memory corruptions when trying to call dead
1252 // delegate_. This test also verifies crbug.com/117420 and crbug.com/143255 to
1253 // ensure that a separate SiteInstance is created when navigating to view-source
1254 // URLs, regardless of current URL.
1255 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
1256 MAYBE_LeakingRenderViewHosts) {
1257 StartServer();
1259 // Observe the created render_view_host's to make sure they will not leak.
1260 RenderViewHostDestructionObserver rvh_observers(shell()->web_contents());
1262 GURL navigated_url(test_server()->GetURL("files/title2.html"));
1263 GURL view_source_url(kViewSourceScheme + std::string(":") +
1264 navigated_url.spec());
1266 // Let's ensure that when we start with a blank window, navigating away to a
1267 // view-source URL, we create a new SiteInstance.
1268 RenderViewHost* blank_rvh = shell()->web_contents()->GetRenderViewHost();
1269 SiteInstance* blank_site_instance = blank_rvh->GetSiteInstance();
1270 EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), GURL::EmptyGURL());
1271 EXPECT_EQ(blank_site_instance->GetSiteURL(), GURL::EmptyGURL());
1272 rvh_observers.EnsureRVHGetsDestructed(blank_rvh);
1274 // Now navigate to the view-source URL and ensure we got a different
1275 // SiteInstance and RenderViewHost.
1276 NavigateToURL(shell(), view_source_url);
1277 EXPECT_NE(blank_rvh, shell()->web_contents()->GetRenderViewHost());
1278 EXPECT_NE(blank_site_instance, shell()->web_contents()->
1279 GetRenderViewHost()->GetSiteInstance());
1280 rvh_observers.EnsureRVHGetsDestructed(
1281 shell()->web_contents()->GetRenderViewHost());
1283 // Load a random page and then navigate to view-source: of it.
1284 // This used to cause two RVH instances for the same SiteInstance, which
1285 // was a problem. This is no longer the case.
1286 NavigateToURL(shell(), navigated_url);
1287 SiteInstance* site_instance1 = shell()->web_contents()->
1288 GetRenderViewHost()->GetSiteInstance();
1289 rvh_observers.EnsureRVHGetsDestructed(
1290 shell()->web_contents()->GetRenderViewHost());
1292 NavigateToURL(shell(), view_source_url);
1293 rvh_observers.EnsureRVHGetsDestructed(
1294 shell()->web_contents()->GetRenderViewHost());
1295 SiteInstance* site_instance2 = shell()->web_contents()->
1296 GetRenderViewHost()->GetSiteInstance();
1298 // Ensure that view-source navigations force a new SiteInstance.
1299 EXPECT_NE(site_instance1, site_instance2);
1301 // Now navigate to a different instance so that we swap out again.
1302 NavigateToURL(shell(), GetCrossSiteURL("files/title2.html"));
1303 rvh_observers.EnsureRVHGetsDestructed(
1304 shell()->web_contents()->GetRenderViewHost());
1306 // This used to leak a render view host.
1307 shell()->Close();
1309 RunAllPendingInMessageLoop(); // Needed on ChromeOS.
1311 EXPECT_EQ(0U, rvh_observers.GetNumberOfWatchedRenderViewHosts());
1314 // Test for crbug.com/143155. Frame tree updates during unload should not
1315 // interrupt the intended navigation and show swappedout:// instead.
1316 // Specifically:
1317 // 1) Open 2 tabs in an HTTP SiteInstance, with a subframe in the opener.
1318 // 2) Send the second tab to a different foo.com SiteInstance.
1319 // This creates a swapped out opener for the first tab in the foo process.
1320 // 3) Navigate the first tab to the foo.com SiteInstance, and have the first
1321 // tab's unload handler remove its frame.
1322 // This used to cause an update to the frame tree of the swapped out RV,
1323 // just as it was navigating to a real page. That pre-empted the real
1324 // navigation and visibly sent the tab to swappedout://.
1325 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
1326 DontPreemptNavigationWithFrameTreeUpdate) {
1327 StartServer();
1329 // 1. Load a page that deletes its iframe during unload.
1330 NavigateToURL(shell(),
1331 test_server()->GetURL("files/remove_frame_on_unload.html"));
1333 // Get the original SiteInstance for later comparison.
1334 scoped_refptr<SiteInstance> orig_site_instance(
1335 shell()->web_contents()->GetSiteInstance());
1337 // Open a same-site page in a new window.
1338 ShellAddedObserver new_shell_observer;
1339 bool success = false;
1340 EXPECT_TRUE(ExecuteScriptAndExtractBool(
1341 shell()->web_contents(),
1342 "window.domAutomationController.send(openWindow());",
1343 &success));
1344 EXPECT_TRUE(success);
1345 Shell* new_shell = new_shell_observer.GetShell();
1347 // Wait for the navigation in the new window to finish, if it hasn't.
1348 WaitForLoadStop(new_shell->web_contents());
1349 EXPECT_EQ("/files/title1.html",
1350 new_shell->web_contents()->GetLastCommittedURL().path());
1352 // Should have the same SiteInstance.
1353 EXPECT_EQ(orig_site_instance.get(),
1354 new_shell->web_contents()->GetSiteInstance());
1356 // 2. Send the second tab to a different process.
1357 NavigateToURL(new_shell, GetCrossSiteURL("files/title1.html"));
1358 scoped_refptr<SiteInstance> new_site_instance(
1359 new_shell->web_contents()->GetSiteInstance());
1360 EXPECT_NE(orig_site_instance, new_site_instance);
1362 // 3. Send the first tab to the second tab's process.
1363 NavigateToURL(shell(), GetCrossSiteURL("files/title1.html"));
1365 // Make sure it ends up at the right page.
1366 WaitForLoadStop(shell()->web_contents());
1367 EXPECT_EQ(GetCrossSiteURL("files/title1.html"),
1368 shell()->web_contents()->GetLastCommittedURL());
1369 EXPECT_EQ(new_site_instance.get(),
1370 shell()->web_contents()->GetSiteInstance());
1373 // Ensure that renderer-side debug URLs do not cause a process swap, since they
1374 // are meant to run in the current page. We had a bug where we expected a
1375 // BrowsingInstance swap to occur on pages like view-source and extensions,
1376 // which broke chrome://crash and javascript: URLs.
1377 // See http://crbug.com/335503.
1378 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, RendererDebugURLsDontSwap) {
1379 ASSERT_TRUE(test_server()->Start());
1381 GURL original_url(test_server()->GetURL("files/title2.html"));
1382 GURL view_source_url(kViewSourceScheme + std::string(":") +
1383 original_url.spec());
1385 NavigateToURL(shell(), view_source_url);
1387 // Check that javascript: URLs work.
1388 base::string16 expected_title = ASCIIToUTF16("msg");
1389 TitleWatcher title_watcher(shell()->web_contents(), expected_title);
1390 shell()->LoadURL(GURL("javascript:document.title='msg'"));
1391 ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
1393 // Crash the renderer of the view-source page.
1394 RenderProcessHostWatcher crash_observer(
1395 shell()->web_contents(),
1396 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
1397 EXPECT_TRUE(
1398 NavigateToURLAndExpectNoCommit(shell(), GURL(kChromeUICrashURL)));
1399 crash_observer.Wait();
1402 // Ensure that renderer-side debug URLs don't take effect on crashed renderers.
1403 // Otherwise, we might try to load an unprivileged about:blank page into a
1404 // WebUI-enabled RenderProcessHost, failing a safety check in InitRenderView.
1405 // See http://crbug.com/334214.
1406 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
1407 IgnoreRendererDebugURLsWhenCrashed) {
1408 // Visit a WebUI page with bindings.
1409 GURL webui_url = GURL(std::string(kChromeUIScheme) + "://" +
1410 std::string(kChromeUIGpuHost));
1411 NavigateToURL(shell(), webui_url);
1412 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1413 shell()->web_contents()->GetRenderProcessHost()->GetID()));
1415 // Crash the renderer of the WebUI page.
1416 RenderProcessHostWatcher crash_observer(
1417 shell()->web_contents(),
1418 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
1419 EXPECT_TRUE(
1420 NavigateToURLAndExpectNoCommit(shell(), GURL(kChromeUICrashURL)));
1421 crash_observer.Wait();
1423 // Load the crash URL again but don't wait for any action. If it is not
1424 // ignored this time, we will fail the WebUI CHECK in InitRenderView.
1425 shell()->LoadURL(GURL(kChromeUICrashURL));
1427 // Ensure that such URLs can still work as the initial navigation of a tab.
1428 // We postpone the initial navigation of the tab using an empty GURL, so that
1429 // we can add a watcher for crashes.
1430 Shell* shell2 = Shell::CreateNewWindow(
1431 shell()->web_contents()->GetBrowserContext(), GURL(), NULL, gfx::Size());
1432 RenderProcessHostWatcher crash_observer2(
1433 shell2->web_contents(),
1434 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
1435 EXPECT_TRUE(
1436 NavigateToURLAndExpectNoCommit(shell2, GURL(kChromeUIKillURL)));
1437 crash_observer2.Wait();
1440 // The test fails with Android ASAN with changes in v8 that seem unrelated.
1441 // See http://crbug.com/428329.
1442 #if defined(OS_ANDROID) && defined(THREAD_SANITIZER)
1443 #define MAYBE_ClearPendingWebUIOnCommit DISABLED_ClearPendingWebUIOnCommit
1444 #else
1445 #define MAYBE_ClearPendingWebUIOnCommit ClearPendingWebUIOnCommit
1446 #endif
1447 // Ensure that pending_and_current_web_ui_ is cleared when a URL commits.
1448 // Otherwise it might get picked up by InitRenderView when granting bindings
1449 // to other RenderViewHosts. See http://crbug.com/330811.
1450 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
1451 MAYBE_ClearPendingWebUIOnCommit) {
1452 // Visit a WebUI page with bindings.
1453 GURL webui_url(GURL(std::string(kChromeUIScheme) + "://" +
1454 std::string(kChromeUIGpuHost)));
1455 NavigateToURL(shell(), webui_url);
1456 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1457 shell()->web_contents()->GetRenderProcessHost()->GetID()));
1458 WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
1459 shell()->web_contents());
1460 WebUIImpl* webui = web_contents->GetRenderManagerForTesting()->web_ui();
1461 EXPECT_TRUE(webui);
1462 EXPECT_FALSE(web_contents->GetRenderManagerForTesting()->pending_web_ui());
1464 // Navigate to another WebUI URL that reuses the WebUI object. Make sure we
1465 // clear pending_web_ui() when it commits.
1466 GURL webui_url2(webui_url.spec() + "#foo");
1467 NavigateToURL(shell(), webui_url2);
1468 EXPECT_EQ(webui, web_contents->GetRenderManagerForTesting()->web_ui());
1469 EXPECT_FALSE(web_contents->GetRenderManagerForTesting()->pending_web_ui());
1472 class RFHMProcessPerTabTest : public RenderFrameHostManagerTest {
1473 public:
1474 RFHMProcessPerTabTest() {}
1476 void SetUpCommandLine(base::CommandLine* command_line) override {
1477 command_line->AppendSwitch(switches::kProcessPerTab);
1481 // Test that we still swap processes for BrowsingInstance changes even in
1482 // --process-per-tab mode. See http://crbug.com/343017.
1483 // Disabled on Android: http://crbug.com/345873.
1484 // Crashes under ThreadSanitizer, http://crbug.com/356758.
1485 #if defined(OS_ANDROID) || defined(THREAD_SANITIZER)
1486 #define MAYBE_BackFromWebUI DISABLED_BackFromWebUI
1487 #else
1488 #define MAYBE_BackFromWebUI BackFromWebUI
1489 #endif
1490 IN_PROC_BROWSER_TEST_F(RFHMProcessPerTabTest, MAYBE_BackFromWebUI) {
1491 ASSERT_TRUE(test_server()->Start());
1492 GURL original_url(test_server()->GetURL("files/title2.html"));
1493 NavigateToURL(shell(), original_url);
1495 // Visit a WebUI page with bindings.
1496 GURL webui_url(GURL(std::string(kChromeUIScheme) + "://" +
1497 std::string(kChromeUIGpuHost)));
1498 NavigateToURL(shell(), webui_url);
1499 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1500 shell()->web_contents()->GetRenderProcessHost()->GetID()));
1502 // Go back and ensure we have no WebUI bindings.
1503 TestNavigationObserver back_nav_load_observer(shell()->web_contents());
1504 shell()->web_contents()->GetController().GoBack();
1505 back_nav_load_observer.Wait();
1506 EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
1507 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1508 shell()->web_contents()->GetRenderProcessHost()->GetID()));
1511 // crbug.com/372360
1512 // The test loads url1, opens a link pointing to url2 in a new tab, and
1513 // navigates the new tab to url1.
1514 // The following is needed for the bug to happen:
1515 // - url1 must require webui bindings;
1516 // - navigating to url2 in the site instance of url1 should not swap
1517 // browsing instances, but should require a new site instance.
1518 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, WebUIGetsBindings) {
1519 GURL url1(std::string(kChromeUIScheme) + "://" +
1520 std::string(kChromeUIGpuHost));
1521 GURL url2(std::string(kChromeUIScheme) + "://" +
1522 std::string(kChromeUIAccessibilityHost));
1524 // Visit a WebUI page with bindings.
1525 NavigateToURL(shell(), url1);
1526 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1527 shell()->web_contents()->GetRenderProcessHost()->GetID()));
1528 SiteInstance* site_instance1 = shell()->web_contents()->GetSiteInstance();
1530 // Open a new tab. Initially it gets a render view in the original tab's
1531 // current site instance.
1532 TestNavigationObserver nav_observer(NULL);
1533 nav_observer.StartWatchingNewWebContents();
1534 ShellAddedObserver shao;
1535 OpenUrlViaClickTarget(shell()->web_contents(), url2);
1536 nav_observer.Wait();
1537 Shell* new_shell = shao.GetShell();
1538 WebContentsImpl* new_web_contents = static_cast<WebContentsImpl*>(
1539 new_shell->web_contents());
1540 SiteInstance* site_instance2 = new_web_contents->GetSiteInstance();
1542 EXPECT_NE(site_instance2, site_instance1);
1543 EXPECT_TRUE(site_instance2->IsRelatedSiteInstance(site_instance1));
1544 RenderViewHost* initial_rvh = new_web_contents->
1545 GetRenderManagerForTesting()->GetSwappedOutRenderViewHost(site_instance1);
1546 ASSERT_TRUE(initial_rvh);
1547 // The following condition is what was causing the bug.
1548 EXPECT_EQ(0, initial_rvh->GetEnabledBindings());
1550 // Navigate to url1 and check bindings.
1551 NavigateToURL(new_shell, url1);
1552 // The navigation should have used the first SiteInstance, otherwise
1553 // |initial_rvh| did not have a chance to be used.
1554 EXPECT_EQ(new_web_contents->GetSiteInstance(), site_instance1);
1555 EXPECT_EQ(BINDINGS_POLICY_WEB_UI,
1556 new_web_contents->GetRenderViewHost()->GetEnabledBindings());
1559 // crbug.com/424526
1560 // The test loads a WebUI page in rocess-per-tab mode, then navigates to a blank
1561 // page and then to a regular page. The bug reproduces if blank page is visited
1562 // in between WebUI and regular page.
1563 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
1564 ForceSwapAfterWebUIBindings) {
1565 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1566 switches::kProcessPerTab);
1567 ASSERT_TRUE(test_server()->Start());
1569 const GURL web_ui_url(std::string(kChromeUIScheme) + "://" +
1570 std::string(kChromeUIGpuHost));
1571 NavigateToURL(shell(), web_ui_url);
1572 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1573 shell()->web_contents()->GetRenderProcessHost()->GetID()));
1575 NavigateToURL(shell(), GURL(url::kAboutBlankURL));
1577 GURL regular_page_url(test_server()->GetURL("files/title2.html"));
1578 NavigateToURL(shell(), regular_page_url);
1579 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1580 shell()->web_contents()->GetRenderProcessHost()->GetID()));
1583 class FileChooserDelegate : public WebContentsDelegate {
1584 public:
1585 FileChooserDelegate(const base::FilePath& file)
1586 : file_(file), file_chosen_(false) {}
1588 void RunFileChooser(WebContents* web_contents,
1589 const FileChooserParams& params) override {
1590 // Send the selected file to the renderer process.
1591 FileChooserFileInfo file_info;
1592 file_info.file_path = file_;
1593 std::vector<FileChooserFileInfo> files;
1594 files.push_back(file_info);
1595 web_contents->GetRenderViewHost()->FilesSelectedInChooser(
1596 files, FileChooserParams::Open);
1598 file_chosen_ = true;
1601 bool file_chosen() { return file_chosen_; }
1603 private:
1604 base::FilePath file_;
1605 bool file_chosen_;
1608 // Test for http://crbug.com/262948.
1609 // Flaky on Mac. http://crbug.com/452018
1610 #if defined(OS_MACOSX)
1611 #define MAYBE_RestoreFileAccessForHistoryNavigation \
1612 DISABLED_RestoreFileAccessForHistoryNavigation
1613 #else
1614 #define MAYBE_RestoreFileAccessForHistoryNavigation \
1615 RestoreFileAccessForHistoryNavigation
1616 #endif
1617 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
1618 MAYBE_RestoreFileAccessForHistoryNavigation) {
1619 StartServer();
1620 base::FilePath file;
1621 EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file));
1622 file = file.AppendASCII("bar");
1624 // Navigate to url and get it to reference a file in its PageState.
1625 GURL url1(test_server()->GetURL("files/file_input.html"));
1626 NavigateToURL(shell(), url1);
1627 int process_id = shell()->web_contents()->GetRenderProcessHost()->GetID();
1628 scoped_ptr<FileChooserDelegate> delegate(new FileChooserDelegate(file));
1629 shell()->web_contents()->SetDelegate(delegate.get());
1630 EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
1631 "document.getElementById('fileinput').click();"));
1632 EXPECT_TRUE(delegate->file_chosen());
1633 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
1634 process_id, file));
1636 // Navigate to a different process without access to the file, and wait for
1637 // the old process to exit.
1638 RenderProcessHostWatcher exit_observer(
1639 shell()->web_contents()->GetRenderProcessHost(),
1640 RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION);
1641 NavigateToURL(shell(), GetCrossSiteURL("files/title1.html"));
1642 exit_observer.Wait();
1643 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
1644 shell()->web_contents()->GetRenderProcessHost()->GetID(), file));
1646 // Ensure that the file ended up in the PageState of the previous entry.
1647 NavigationEntry* prev_entry =
1648 shell()->web_contents()->GetController().GetEntryAtIndex(0);
1649 EXPECT_EQ(url1, prev_entry->GetURL());
1650 const std::vector<base::FilePath>& files =
1651 prev_entry->GetPageState().GetReferencedFiles();
1652 ASSERT_EQ(1U, files.size());
1653 EXPECT_EQ(file, files.at(0));
1655 // Go back, ending up in a different RenderProcessHost than before.
1656 TestNavigationObserver back_nav_load_observer(shell()->web_contents());
1657 shell()->web_contents()->GetController().GoBack();
1658 back_nav_load_observer.Wait();
1659 EXPECT_NE(process_id,
1660 shell()->web_contents()->GetRenderProcessHost()->GetID());
1662 // Ensure that the file access still exists in the new process ID.
1663 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
1664 shell()->web_contents()->GetRenderProcessHost()->GetID(), file));
1666 // Navigate to a same site page to trigger a PageState update and ensure the
1667 // renderer is not killed.
1668 EXPECT_TRUE(
1669 NavigateToURL(shell(), test_server()->GetURL("files/title2.html")));
1672 // Test for http://crbug.com/441966.
1673 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
1674 RestoreSubframeFileAccessForHistoryNavigation) {
1675 StartServer();
1676 base::FilePath file;
1677 EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file));
1678 file = file.AppendASCII("bar");
1680 // Navigate to url and get it to reference a file in its PageState.
1681 GURL url1(test_server()->GetURL("files/file_input_subframe.html"));
1682 NavigateToURL(shell(), url1);
1683 WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
1684 FrameTreeNode* root = wc->GetFrameTree()->root();
1685 int process_id = shell()->web_contents()->GetRenderProcessHost()->GetID();
1686 scoped_ptr<FileChooserDelegate> delegate(new FileChooserDelegate(file));
1687 shell()->web_contents()->SetDelegate(delegate.get());
1688 EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(),
1689 "document.getElementById('fileinput').click();"));
1690 EXPECT_TRUE(delegate->file_chosen());
1691 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
1692 process_id, file));
1694 // Navigate to a different process without access to the file, and wait for
1695 // the old process to exit.
1696 RenderProcessHostWatcher exit_observer(
1697 shell()->web_contents()->GetRenderProcessHost(),
1698 RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION);
1699 NavigateToURL(shell(), GetCrossSiteURL("files/title1.html"));
1700 exit_observer.Wait();
1701 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
1702 shell()->web_contents()->GetRenderProcessHost()->GetID(), file));
1704 // Ensure that the file ended up in the PageState of the previous entry.
1705 NavigationEntry* prev_entry =
1706 shell()->web_contents()->GetController().GetEntryAtIndex(0);
1707 EXPECT_EQ(url1, prev_entry->GetURL());
1708 const std::vector<base::FilePath>& files =
1709 prev_entry->GetPageState().GetReferencedFiles();
1710 ASSERT_EQ(1U, files.size());
1711 EXPECT_EQ(file, files.at(0));
1713 // Go back, ending up in a different RenderProcessHost than before.
1714 TestNavigationObserver back_nav_load_observer(shell()->web_contents());
1715 shell()->web_contents()->GetController().GoBack();
1716 back_nav_load_observer.Wait();
1717 EXPECT_NE(process_id,
1718 shell()->web_contents()->GetRenderProcessHost()->GetID());
1720 // Ensure that the file access still exists in the new process ID.
1721 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
1722 shell()->web_contents()->GetRenderProcessHost()->GetID(), file));
1725 } // namespace content