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.
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
;
46 const char kOpenUrlViaClickTargetFunc
[] =
48 " var lnk = document.createElement(\"a\");\n"
50 " lnk.target = \"_blank\";\n"
51 " document.body.appendChild(lnk);\n"
55 // Adds a link with given url and target=_blank, and clicks on it.
56 void OpenUrlViaClickTarget(const internal::ToRenderFrameHost
& adapter
,
58 EXPECT_TRUE(ExecuteScript(adapter
,
59 std::string(kOpenUrlViaClickTargetFunc
) + "(\"" + url
.spec() + "\");"));
62 } // anonymous namespace
64 class RenderFrameHostManagerTest
: public ContentBrowserTest
{
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
);
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_
);
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
) {
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",
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());",
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.
139 EXPECT_TRUE(ExecuteScriptAndExtractBool(
140 shell()->web_contents(),
141 "window.domAutomationController.send(testScriptAccessToWindow());",
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.
153 EXPECT_TRUE(ExecuteScriptAndExtractBool(
154 shell()->web_contents(),
155 "window.domAutomationController.send(testScriptAccessToWindow());",
157 EXPECT_FALSE(success
);
159 // We now navigate the window to an about:blank page.
161 EXPECT_TRUE(ExecuteScriptAndExtractBool(
162 shell()->web_contents(),
163 "window.domAutomationController.send(clickBlankTargetedLink());",
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
);
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.
176 EXPECT_TRUE(ExecuteScriptAndExtractBool(
177 shell()->web_contents(),
178 "window.domAutomationController.send(testScriptAccessToWindow());",
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
) {
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",
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());",
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
233 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest
,
234 SwapProcessWithSameSiteRelNoreferrer
) {
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",
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());",
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
) {
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",
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());",
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
);
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
) {
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",
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());",
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
);
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
) {
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",
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());",
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());",
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());",
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
451 #define MAYBE_DisownOpener DisownOpener
453 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest
, MAYBE_DisownOpener
) {
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",
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());",
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();
509 EXPECT_TRUE(ExecuteScriptAndExtractBool(
510 new_shell
->web_contents(),
511 "window.domAutomationController.send(window.opener == null);",
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"));
519 EXPECT_TRUE(ExecuteScriptAndExtractBool(
520 new_shell
->web_contents(),
521 "window.domAutomationController.send(window.opener == null);",
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.
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
) {
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",
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(
578 "window.domAutomationController.send(clickSameSiteTargetedLink());",
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());",
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());
617 opener_manager
->GetSwappedOutRenderViewHost(foo_site_instance
.get()));
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(
626 "window.domAutomationController.send(postToOpener('msg',"
627 " 'http://google.com'));",
629 EXPECT_TRUE(success
);
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(
639 "window.domAutomationController.send(postToOpener('msg','*'));",
641 EXPECT_TRUE(success
);
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(
651 "window.domAutomationController.send(window.receivedMessages);",
652 &opener_received_messages
));
653 int foo_received_messages
= 0;
654 EXPECT_TRUE(ExecuteScriptAndExtractInt(
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(
668 "window.domAutomationController.send(postToFoo('msg2'));",
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.
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.
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
) {
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",
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(
717 "window.domAutomationController.send(clickSameSiteTargetedLink());",
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());
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(
746 "window.domAutomationController.send(postWithPortToFoo());",
748 EXPECT_TRUE(success
);
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(
757 "window.domAutomationController.send(window.receivedMessagesViaPort);",
758 &opener_received_messages_via_port
));
759 int foo_received_messages
= 0;
760 EXPECT_TRUE(ExecuteScriptAndExtractInt(
762 "window.domAutomationController.send(window.receivedMessages);",
763 &foo_received_messages
));
764 int foo_received_messages_with_port
= 0;
765 EXPECT_TRUE(ExecuteScriptAndExtractInt(
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
) {
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",
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(
801 "window.domAutomationController.send(clickSameSiteTargetedLink());",
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());",
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 opening a new window in the same SiteInstance and then navigating
838 // both windows to a different SiteInstance allows the first process to exit.
839 // See http://crbug.com/126333.
840 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest
,
841 ProcessExitWithSwappedOutViews
) {
844 // Load a page with links that open in a new window.
845 std::string replacement_path
;
846 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
847 "files/click-noreferrer-links.html",
850 NavigateToURL(shell(), test_server()->GetURL(replacement_path
));
852 // Get the original SiteInstance for later comparison.
853 scoped_refptr
<SiteInstance
> orig_site_instance(
854 shell()->web_contents()->GetSiteInstance());
855 EXPECT_TRUE(orig_site_instance
.get() != NULL
);
857 // Test clicking a target=foo link.
858 ShellAddedObserver new_shell_observer
;
859 bool success
= false;
860 EXPECT_TRUE(ExecuteScriptAndExtractBool(
861 shell()->web_contents(),
862 "window.domAutomationController.send(clickSameSiteTargetedLink());",
864 EXPECT_TRUE(success
);
865 Shell
* new_shell
= new_shell_observer
.GetShell();
867 // Wait for the navigation in the new window to finish, if it hasn't.
868 WaitForLoadStop(new_shell
->web_contents());
869 EXPECT_EQ("/files/navigate_opener.html",
870 new_shell
->web_contents()->GetLastCommittedURL().path());
872 // Should have the same SiteInstance.
873 scoped_refptr
<SiteInstance
> opened_site_instance(
874 new_shell
->web_contents()->GetSiteInstance());
875 EXPECT_EQ(orig_site_instance
, opened_site_instance
);
877 // Now navigate the opened window to a different site.
878 NavigateToURL(new_shell
, GetCrossSiteURL("files/title1.html"));
879 scoped_refptr
<SiteInstance
> new_site_instance(
880 new_shell
->web_contents()->GetSiteInstance());
881 EXPECT_NE(orig_site_instance
, new_site_instance
);
883 // The original process should still be alive, since it is still used in the
885 RenderProcessHost
* orig_process
= orig_site_instance
->GetProcess();
886 EXPECT_TRUE(orig_process
->HasConnection());
888 // Navigate the first window to a different site as well. The original
889 // process should exit, since all of its views are now swapped out.
890 RenderProcessHostWatcher
exit_observer(
892 RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION
);
893 NavigateToURL(shell(), GetCrossSiteURL("files/title1.html"));
894 exit_observer
.Wait();
895 scoped_refptr
<SiteInstance
> new_site_instance2(
896 shell()->web_contents()->GetSiteInstance());
897 EXPECT_EQ(new_site_instance
, new_site_instance2
);
900 // Test for crbug.com/76666. A cross-site navigation that fails with a 204
901 // error should not make us ignore future renderer-initiated navigations.
902 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest
, ClickLinkAfter204Error
) {
905 // Get the original SiteInstance for later comparison.
906 scoped_refptr
<SiteInstance
> orig_site_instance(
907 shell()->web_contents()->GetSiteInstance());
908 EXPECT_TRUE(orig_site_instance
.get() != NULL
);
910 // Load a cross-site page that fails with a 204 error.
911 EXPECT_TRUE(NavigateToURLAndExpectNoCommit(shell(),
912 GetCrossSiteURL("nocontent")));
914 // We should still be looking at the normal page. Because we started from a
915 // blank new tab, the typed URL will still be visible until the user clears it
916 // manually. The last committed URL will be the previous page.
917 scoped_refptr
<SiteInstance
> post_nav_site_instance(
918 shell()->web_contents()->GetSiteInstance());
919 EXPECT_EQ(orig_site_instance
, post_nav_site_instance
);
920 EXPECT_EQ("/nocontent",
921 shell()->web_contents()->GetVisibleURL().path());
923 shell()->web_contents()->GetController().GetLastCommittedEntry());
925 // Renderer-initiated navigations should work.
926 base::string16 expected_title
= ASCIIToUTF16("Title Of Awesomeness");
927 TitleWatcher
title_watcher(shell()->web_contents(), expected_title
);
928 GURL url
= test_server()->GetURL("files/title2.html");
929 EXPECT_TRUE(ExecuteScript(
930 shell()->web_contents(),
931 base::StringPrintf("location.href = '%s'", url
.spec().c_str())));
932 ASSERT_EQ(expected_title
, title_watcher
.WaitAndGetTitle());
934 // Opens in same tab.
935 EXPECT_EQ(1u, Shell::windows().size());
936 EXPECT_EQ("/files/title2.html",
937 shell()->web_contents()->GetLastCommittedURL().path());
939 // Should have the same SiteInstance.
940 scoped_refptr
<SiteInstance
> new_site_instance(
941 shell()->web_contents()->GetSiteInstance());
942 EXPECT_EQ(orig_site_instance
, new_site_instance
);
945 // Test for crbug.com/9682. We should show the URL for a pending renderer-
946 // initiated navigation in a new tab, until the content of the initial
947 // about:blank page is modified by another window. At that point, we should
948 // revert to showing about:blank to prevent a URL spoof.
949 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest
, ShowLoadingURLUntilSpoof
) {
950 ASSERT_TRUE(test_server()->Start());
952 // Load a page that can open a URL that won't commit in a new window.
954 shell(), test_server()->GetURL("files/click-nocontent-link.html"));
955 WebContents
* orig_contents
= shell()->web_contents();
957 // Click a /nocontent link that opens in a new window but never commits.
958 ShellAddedObserver new_shell_observer
;
959 bool success
= false;
960 EXPECT_TRUE(ExecuteScriptAndExtractBool(
962 "window.domAutomationController.send(clickNoContentTargetedLink());",
964 EXPECT_TRUE(success
);
966 // Wait for the window to open.
967 Shell
* new_shell
= new_shell_observer
.GetShell();
969 // Ensure the destination URL is visible, because it is considered the
970 // initial navigation.
971 WebContents
* contents
= new_shell
->web_contents();
972 EXPECT_TRUE(contents
->GetController().IsInitialNavigation());
973 EXPECT_EQ("/nocontent",
974 contents
->GetController().GetVisibleEntry()->GetURL().path());
976 // Now modify the contents of the new window from the opener. This will also
977 // modify the title of the document to give us something to listen for.
978 base::string16 expected_title
= ASCIIToUTF16("Modified Title");
979 TitleWatcher
title_watcher(contents
, expected_title
);
981 EXPECT_TRUE(ExecuteScriptAndExtractBool(
983 "window.domAutomationController.send(modifyNewWindow());",
985 EXPECT_TRUE(success
);
986 ASSERT_EQ(expected_title
, title_watcher
.WaitAndGetTitle());
988 // At this point, we should no longer be showing the destination URL.
989 // The visible entry should be null, resulting in about:blank in the address
991 EXPECT_FALSE(contents
->GetController().GetVisibleEntry());
994 // Test for crbug.com/9682. We should not show the URL for a pending renderer-
995 // initiated navigation in a new tab if it is not the initial navigation. In
996 // this case, the renderer will not notify us of a modification, so we cannot
997 // show the pending URL without allowing a spoof.
998 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest
,
999 DontShowLoadingURLIfNotInitialNav
) {
1000 ASSERT_TRUE(test_server()->Start());
1002 // Load a page that can open a URL that won't commit in a new window.
1004 shell(), test_server()->GetURL("files/click-nocontent-link.html"));
1005 WebContents
* orig_contents
= shell()->web_contents();
1007 // Click a /nocontent link that opens in a new window but never commits.
1008 // By using an onclick handler that first creates the window, the slow
1009 // navigation is not considered an initial navigation.
1010 ShellAddedObserver new_shell_observer
;
1011 bool success
= false;
1012 EXPECT_TRUE(ExecuteScriptAndExtractBool(
1014 "window.domAutomationController.send("
1015 "clickNoContentScriptedTargetedLink());",
1017 EXPECT_TRUE(success
);
1019 // Wait for the window to open.
1020 Shell
* new_shell
= new_shell_observer
.GetShell();
1022 // Ensure the destination URL is not visible, because it is not the initial
1024 WebContents
* contents
= new_shell
->web_contents();
1025 EXPECT_FALSE(contents
->GetController().IsInitialNavigation());
1026 EXPECT_FALSE(contents
->GetController().GetVisibleEntry());
1029 // Crashes under ThreadSanitizer, http://crbug.com/356758.
1030 #if defined(THREAD_SANITIZER)
1031 #define MAYBE_BackForwardNotStale DISABLED_BackForwardNotStale
1033 #define MAYBE_BackForwardNotStale BackForwardNotStale
1035 // Test for http://crbug.com/93427. Ensure that cross-site navigations
1036 // do not cause back/forward navigations to be considered stale by the
1038 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest
, MAYBE_BackForwardNotStale
) {
1040 NavigateToURL(shell(), GURL(url::kAboutBlankURL
));
1042 // Visit a page on first site.
1043 NavigateToURL(shell(), test_server()->GetURL("files/title1.html"));
1045 // Visit three pages on second site.
1046 NavigateToURL(shell(), GetCrossSiteURL("files/title1.html"));
1047 NavigateToURL(shell(), GetCrossSiteURL("files/title2.html"));
1048 NavigateToURL(shell(), GetCrossSiteURL("files/title3.html"));
1050 // History is now [blank, A1, B1, B2, *B3].
1051 WebContents
* contents
= shell()->web_contents();
1052 EXPECT_EQ(5, contents
->GetController().GetEntryCount());
1054 // Open another window in same process to keep this process alive.
1055 Shell
* new_shell
= CreateBrowser();
1056 NavigateToURL(new_shell
, GetCrossSiteURL("files/title1.html"));
1058 // Go back three times to first site.
1060 TestNavigationObserver
back_nav_load_observer(shell()->web_contents());
1061 shell()->web_contents()->GetController().GoBack();
1062 back_nav_load_observer
.Wait();
1065 TestNavigationObserver
back_nav_load_observer(shell()->web_contents());
1066 shell()->web_contents()->GetController().GoBack();
1067 back_nav_load_observer
.Wait();
1070 TestNavigationObserver
back_nav_load_observer(shell()->web_contents());
1071 shell()->web_contents()->GetController().GoBack();
1072 back_nav_load_observer
.Wait();
1075 // Now go forward twice to B2. Shouldn't be left spinning.
1077 TestNavigationObserver
forward_nav_load_observer(shell()->web_contents());
1078 shell()->web_contents()->GetController().GoForward();
1079 forward_nav_load_observer
.Wait();
1082 TestNavigationObserver
forward_nav_load_observer(shell()->web_contents());
1083 shell()->web_contents()->GetController().GoForward();
1084 forward_nav_load_observer
.Wait();
1087 // Go back twice to first site.
1089 TestNavigationObserver
back_nav_load_observer(shell()->web_contents());
1090 shell()->web_contents()->GetController().GoBack();
1091 back_nav_load_observer
.Wait();
1094 TestNavigationObserver
back_nav_load_observer(shell()->web_contents());
1095 shell()->web_contents()->GetController().GoBack();
1096 back_nav_load_observer
.Wait();
1099 // Now go forward directly to B3. Shouldn't be left spinning.
1101 TestNavigationObserver
forward_nav_load_observer(shell()->web_contents());
1102 shell()->web_contents()->GetController().GoToIndex(4);
1103 forward_nav_load_observer
.Wait();
1107 // Test for http://crbug.com/130016.
1108 // Swapping out a render view should update its visiblity state.
1109 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest
,
1110 SwappedOutViewHasCorrectVisibilityState
) {
1113 // Load a page with links that open in a new window.
1114 std::string replacement_path
;
1115 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
1116 "files/click-noreferrer-links.html",
1118 &replacement_path
));
1119 NavigateToURL(shell(), test_server()->GetURL(replacement_path
));
1121 // Open a same-site link in a new widnow.
1122 ShellAddedObserver new_shell_observer
;
1123 bool success
= false;
1124 EXPECT_TRUE(ExecuteScriptAndExtractBool(
1125 shell()->web_contents(),
1126 "window.domAutomationController.send(clickSameSiteTargetedLink());",
1128 EXPECT_TRUE(success
);
1129 Shell
* new_shell
= new_shell_observer
.GetShell();
1131 // Wait for the navigation in the new tab to finish, if it hasn't.
1132 WaitForLoadStop(new_shell
->web_contents());
1133 EXPECT_EQ("/files/navigate_opener.html",
1134 new_shell
->web_contents()->GetLastCommittedURL().path());
1136 RenderViewHost
* rvh
= new_shell
->web_contents()->GetRenderViewHost();
1138 EXPECT_TRUE(ExecuteScriptAndExtractBool(
1140 "window.domAutomationController.send("
1141 " document.visibilityState == 'visible');",
1143 EXPECT_TRUE(success
);
1145 // Now navigate the new window to a different site. This should swap out the
1146 // tab's existing RenderView, causing it become hidden.
1147 NavigateToURL(new_shell
, GetCrossSiteURL("files/title1.html"));
1149 EXPECT_TRUE(ExecuteScriptAndExtractBool(
1151 "window.domAutomationController.send("
1152 " document.visibilityState == 'hidden');",
1154 EXPECT_TRUE(success
);
1156 // Going back should make the previously swapped-out view to become visible
1159 TestNavigationObserver
back_nav_load_observer(new_shell
->web_contents());
1160 new_shell
->web_contents()->GetController().GoBack();
1161 back_nav_load_observer
.Wait();
1164 EXPECT_EQ("/files/navigate_opener.html",
1165 new_shell
->web_contents()->GetLastCommittedURL().path());
1167 EXPECT_EQ(rvh
, new_shell
->web_contents()->GetRenderViewHost());
1169 EXPECT_TRUE(ExecuteScriptAndExtractBool(
1171 "window.domAutomationController.send("
1172 " document.visibilityState == 'visible');",
1174 EXPECT_TRUE(success
);
1177 // This class ensures that all the given RenderViewHosts have properly been
1179 class RenderViewHostDestructionObserver
: public WebContentsObserver
{
1181 explicit RenderViewHostDestructionObserver(WebContents
* web_contents
)
1182 : WebContentsObserver(web_contents
) {}
1183 ~RenderViewHostDestructionObserver() override
{}
1184 void EnsureRVHGetsDestructed(RenderViewHost
* rvh
) {
1185 watched_render_view_hosts_
.insert(rvh
);
1187 size_t GetNumberOfWatchedRenderViewHosts() const {
1188 return watched_render_view_hosts_
.size();
1192 // WebContentsObserver implementation:
1193 void RenderViewDeleted(RenderViewHost
* rvh
) override
{
1194 watched_render_view_hosts_
.erase(rvh
);
1197 std::set
<RenderViewHost
*> watched_render_view_hosts_
;
1200 // Crashes under ThreadSanitizer, http://crbug.com/356758.
1201 #if defined(THREAD_SANITIZER)
1202 #define MAYBE_LeakingRenderViewHosts DISABLED_LeakingRenderViewHosts
1204 #define MAYBE_LeakingRenderViewHosts LeakingRenderViewHosts
1206 // Test for crbug.com/90867. Make sure we don't leak render view hosts since
1207 // they may cause crashes or memory corruptions when trying to call dead
1208 // delegate_. This test also verifies crbug.com/117420 and crbug.com/143255 to
1209 // ensure that a separate SiteInstance is created when navigating to view-source
1210 // URLs, regardless of current URL.
1211 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest
,
1212 MAYBE_LeakingRenderViewHosts
) {
1215 // Observe the created render_view_host's to make sure they will not leak.
1216 RenderViewHostDestructionObserver
rvh_observers(shell()->web_contents());
1218 GURL
navigated_url(test_server()->GetURL("files/title2.html"));
1219 GURL
view_source_url(kViewSourceScheme
+ std::string(":") +
1220 navigated_url
.spec());
1222 // Let's ensure that when we start with a blank window, navigating away to a
1223 // view-source URL, we create a new SiteInstance.
1224 RenderViewHost
* blank_rvh
= shell()->web_contents()->GetRenderViewHost();
1225 SiteInstance
* blank_site_instance
= blank_rvh
->GetSiteInstance();
1226 EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), GURL::EmptyGURL());
1227 EXPECT_EQ(blank_site_instance
->GetSiteURL(), GURL::EmptyGURL());
1228 rvh_observers
.EnsureRVHGetsDestructed(blank_rvh
);
1230 // Now navigate to the view-source URL and ensure we got a different
1231 // SiteInstance and RenderViewHost.
1232 NavigateToURL(shell(), view_source_url
);
1233 EXPECT_NE(blank_rvh
, shell()->web_contents()->GetRenderViewHost());
1234 EXPECT_NE(blank_site_instance
, shell()->web_contents()->
1235 GetRenderViewHost()->GetSiteInstance());
1236 rvh_observers
.EnsureRVHGetsDestructed(
1237 shell()->web_contents()->GetRenderViewHost());
1239 // Load a random page and then navigate to view-source: of it.
1240 // This used to cause two RVH instances for the same SiteInstance, which
1241 // was a problem. This is no longer the case.
1242 NavigateToURL(shell(), navigated_url
);
1243 SiteInstance
* site_instance1
= shell()->web_contents()->
1244 GetRenderViewHost()->GetSiteInstance();
1245 rvh_observers
.EnsureRVHGetsDestructed(
1246 shell()->web_contents()->GetRenderViewHost());
1248 NavigateToURL(shell(), view_source_url
);
1249 rvh_observers
.EnsureRVHGetsDestructed(
1250 shell()->web_contents()->GetRenderViewHost());
1251 SiteInstance
* site_instance2
= shell()->web_contents()->
1252 GetRenderViewHost()->GetSiteInstance();
1254 // Ensure that view-source navigations force a new SiteInstance.
1255 EXPECT_NE(site_instance1
, site_instance2
);
1257 // Now navigate to a different instance so that we swap out again.
1258 NavigateToURL(shell(), GetCrossSiteURL("files/title2.html"));
1259 rvh_observers
.EnsureRVHGetsDestructed(
1260 shell()->web_contents()->GetRenderViewHost());
1262 // This used to leak a render view host.
1265 RunAllPendingInMessageLoop(); // Needed on ChromeOS.
1267 EXPECT_EQ(0U, rvh_observers
.GetNumberOfWatchedRenderViewHosts());
1270 // Test for crbug.com/143155. Frame tree updates during unload should not
1271 // interrupt the intended navigation and show swappedout:// instead.
1273 // 1) Open 2 tabs in an HTTP SiteInstance, with a subframe in the opener.
1274 // 2) Send the second tab to a different foo.com SiteInstance.
1275 // This creates a swapped out opener for the first tab in the foo process.
1276 // 3) Navigate the first tab to the foo.com SiteInstance, and have the first
1277 // tab's unload handler remove its frame.
1278 // This used to cause an update to the frame tree of the swapped out RV,
1279 // just as it was navigating to a real page. That pre-empted the real
1280 // navigation and visibly sent the tab to swappedout://.
1281 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest
,
1282 DontPreemptNavigationWithFrameTreeUpdate
) {
1285 // 1. Load a page that deletes its iframe during unload.
1286 NavigateToURL(shell(),
1287 test_server()->GetURL("files/remove_frame_on_unload.html"));
1289 // Get the original SiteInstance for later comparison.
1290 scoped_refptr
<SiteInstance
> orig_site_instance(
1291 shell()->web_contents()->GetSiteInstance());
1293 // Open a same-site page in a new window.
1294 ShellAddedObserver new_shell_observer
;
1295 bool success
= false;
1296 EXPECT_TRUE(ExecuteScriptAndExtractBool(
1297 shell()->web_contents(),
1298 "window.domAutomationController.send(openWindow());",
1300 EXPECT_TRUE(success
);
1301 Shell
* new_shell
= new_shell_observer
.GetShell();
1303 // Wait for the navigation in the new window to finish, if it hasn't.
1304 WaitForLoadStop(new_shell
->web_contents());
1305 EXPECT_EQ("/files/title1.html",
1306 new_shell
->web_contents()->GetLastCommittedURL().path());
1308 // Should have the same SiteInstance.
1309 EXPECT_EQ(orig_site_instance
.get(),
1310 new_shell
->web_contents()->GetSiteInstance());
1312 // 2. Send the second tab to a different process.
1313 NavigateToURL(new_shell
, GetCrossSiteURL("files/title1.html"));
1314 scoped_refptr
<SiteInstance
> new_site_instance(
1315 new_shell
->web_contents()->GetSiteInstance());
1316 EXPECT_NE(orig_site_instance
, new_site_instance
);
1318 // 3. Send the first tab to the second tab's process.
1319 NavigateToURL(shell(), GetCrossSiteURL("files/title1.html"));
1321 // Make sure it ends up at the right page.
1322 WaitForLoadStop(shell()->web_contents());
1323 EXPECT_EQ(GetCrossSiteURL("files/title1.html"),
1324 shell()->web_contents()->GetLastCommittedURL());
1325 EXPECT_EQ(new_site_instance
.get(),
1326 shell()->web_contents()->GetSiteInstance());
1329 // Ensure that renderer-side debug URLs do not cause a process swap, since they
1330 // are meant to run in the current page. We had a bug where we expected a
1331 // BrowsingInstance swap to occur on pages like view-source and extensions,
1332 // which broke chrome://crash and javascript: URLs.
1333 // See http://crbug.com/335503.
1334 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest
, RendererDebugURLsDontSwap
) {
1335 ASSERT_TRUE(test_server()->Start());
1337 GURL
original_url(test_server()->GetURL("files/title2.html"));
1338 GURL
view_source_url(kViewSourceScheme
+ std::string(":") +
1339 original_url
.spec());
1341 NavigateToURL(shell(), view_source_url
);
1343 // Check that javascript: URLs work.
1344 base::string16 expected_title
= ASCIIToUTF16("msg");
1345 TitleWatcher
title_watcher(shell()->web_contents(), expected_title
);
1346 shell()->LoadURL(GURL("javascript:document.title='msg'"));
1347 ASSERT_EQ(expected_title
, title_watcher
.WaitAndGetTitle());
1349 // Crash the renderer of the view-source page.
1350 RenderProcessHostWatcher
crash_observer(
1351 shell()->web_contents(),
1352 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT
);
1354 NavigateToURLAndExpectNoCommit(shell(), GURL(kChromeUICrashURL
)));
1355 crash_observer
.Wait();
1358 // Ensure that renderer-side debug URLs don't take effect on crashed renderers.
1359 // Otherwise, we might try to load an unprivileged about:blank page into a
1360 // WebUI-enabled RenderProcessHost, failing a safety check in InitRenderView.
1361 // See http://crbug.com/334214.
1362 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest
,
1363 IgnoreRendererDebugURLsWhenCrashed
) {
1364 // Visit a WebUI page with bindings.
1365 GURL webui_url
= GURL(std::string(kChromeUIScheme
) + "://" +
1366 std::string(kChromeUIGpuHost
));
1367 NavigateToURL(shell(), webui_url
);
1368 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1369 shell()->web_contents()->GetRenderProcessHost()->GetID()));
1371 // Crash the renderer of the WebUI page.
1372 RenderProcessHostWatcher
crash_observer(
1373 shell()->web_contents(),
1374 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT
);
1376 NavigateToURLAndExpectNoCommit(shell(), GURL(kChromeUICrashURL
)));
1377 crash_observer
.Wait();
1379 // Load the crash URL again but don't wait for any action. If it is not
1380 // ignored this time, we will fail the WebUI CHECK in InitRenderView.
1381 shell()->LoadURL(GURL(kChromeUICrashURL
));
1383 // Ensure that such URLs can still work as the initial navigation of a tab.
1384 // We postpone the initial navigation of the tab using an empty GURL, so that
1385 // we can add a watcher for crashes.
1386 Shell
* shell2
= Shell::CreateNewWindow(
1387 shell()->web_contents()->GetBrowserContext(), GURL(), NULL
, gfx::Size());
1388 RenderProcessHostWatcher
crash_observer2(
1389 shell2
->web_contents(),
1390 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT
);
1392 NavigateToURLAndExpectNoCommit(shell2
, GURL(kChromeUIKillURL
)));
1393 crash_observer2
.Wait();
1396 // The test fails with Android ASAN with changes in v8 that seem unrelated.
1397 // See http://crbug.com/428329.
1398 #if defined(OS_ANDROID) && defined(THREAD_SANITIZER)
1399 #define MAYBE_ClearPendingWebUIOnCommit DISABLED_ClearPendingWebUIOnCommit
1401 #define MAYBE_ClearPendingWebUIOnCommit ClearPendingWebUIOnCommit
1403 // Ensure that pending_and_current_web_ui_ is cleared when a URL commits.
1404 // Otherwise it might get picked up by InitRenderView when granting bindings
1405 // to other RenderViewHosts. See http://crbug.com/330811.
1406 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest
,
1407 MAYBE_ClearPendingWebUIOnCommit
) {
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()));
1414 WebContentsImpl
* web_contents
= static_cast<WebContentsImpl
*>(
1415 shell()->web_contents());
1416 WebUIImpl
* webui
= web_contents
->GetRenderManagerForTesting()->web_ui();
1418 EXPECT_FALSE(web_contents
->GetRenderManagerForTesting()->pending_web_ui());
1420 // Navigate to another WebUI URL that reuses the WebUI object. Make sure we
1421 // clear pending_web_ui() when it commits.
1422 GURL
webui_url2(webui_url
.spec() + "#foo");
1423 NavigateToURL(shell(), webui_url2
);
1424 EXPECT_EQ(webui
, web_contents
->GetRenderManagerForTesting()->web_ui());
1425 EXPECT_FALSE(web_contents
->GetRenderManagerForTesting()->pending_web_ui());
1428 class RFHMProcessPerTabTest
: public RenderFrameHostManagerTest
{
1430 RFHMProcessPerTabTest() {}
1432 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
1433 command_line
->AppendSwitch(switches::kProcessPerTab
);
1437 // Test that we still swap processes for BrowsingInstance changes even in
1438 // --process-per-tab mode. See http://crbug.com/343017.
1439 // Disabled on Android: http://crbug.com/345873.
1440 // Crashes under ThreadSanitizer, http://crbug.com/356758.
1441 #if defined(OS_ANDROID) || defined(THREAD_SANITIZER)
1442 #define MAYBE_BackFromWebUI DISABLED_BackFromWebUI
1444 #define MAYBE_BackFromWebUI BackFromWebUI
1446 IN_PROC_BROWSER_TEST_F(RFHMProcessPerTabTest
, MAYBE_BackFromWebUI
) {
1447 ASSERT_TRUE(test_server()->Start());
1448 GURL
original_url(test_server()->GetURL("files/title2.html"));
1449 NavigateToURL(shell(), original_url
);
1451 // Visit a WebUI page with bindings.
1452 GURL
webui_url(GURL(std::string(kChromeUIScheme
) + "://" +
1453 std::string(kChromeUIGpuHost
)));
1454 NavigateToURL(shell(), webui_url
);
1455 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1456 shell()->web_contents()->GetRenderProcessHost()->GetID()));
1458 // Go back and ensure we have no WebUI bindings.
1459 TestNavigationObserver
back_nav_load_observer(shell()->web_contents());
1460 shell()->web_contents()->GetController().GoBack();
1461 back_nav_load_observer
.Wait();
1462 EXPECT_EQ(original_url
, shell()->web_contents()->GetLastCommittedURL());
1463 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1464 shell()->web_contents()->GetRenderProcessHost()->GetID()));
1468 // The test loads url1, opens a link pointing to url2 in a new tab, and
1469 // navigates the new tab to url1.
1470 // The following is needed for the bug to happen:
1471 // - url1 must require webui bindings;
1472 // - navigating to url2 in the site instance of url1 should not swap
1473 // browsing instances, but should require a new site instance.
1474 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest
, WebUIGetsBindings
) {
1475 GURL
url1(std::string(kChromeUIScheme
) + "://" +
1476 std::string(kChromeUIGpuHost
));
1477 GURL
url2(std::string(kChromeUIScheme
) + "://" +
1478 std::string(kChromeUIAccessibilityHost
));
1480 // Visit a WebUI page with bindings.
1481 NavigateToURL(shell(), url1
);
1482 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1483 shell()->web_contents()->GetRenderProcessHost()->GetID()));
1484 SiteInstance
* site_instance1
= shell()->web_contents()->GetSiteInstance();
1486 // Open a new tab. Initially it gets a render view in the original tab's
1487 // current site instance.
1488 TestNavigationObserver
nav_observer(NULL
);
1489 nav_observer
.StartWatchingNewWebContents();
1490 ShellAddedObserver shao
;
1491 OpenUrlViaClickTarget(shell()->web_contents(), url2
);
1492 nav_observer
.Wait();
1493 Shell
* new_shell
= shao
.GetShell();
1494 WebContentsImpl
* new_web_contents
= static_cast<WebContentsImpl
*>(
1495 new_shell
->web_contents());
1496 SiteInstance
* site_instance2
= new_web_contents
->GetSiteInstance();
1498 EXPECT_NE(site_instance2
, site_instance1
);
1499 EXPECT_TRUE(site_instance2
->IsRelatedSiteInstance(site_instance1
));
1500 RenderViewHost
* initial_rvh
= new_web_contents
->
1501 GetRenderManagerForTesting()->GetSwappedOutRenderViewHost(site_instance1
);
1502 ASSERT_TRUE(initial_rvh
);
1503 // The following condition is what was causing the bug.
1504 EXPECT_EQ(0, initial_rvh
->GetEnabledBindings());
1506 // Navigate to url1 and check bindings.
1507 NavigateToURL(new_shell
, url1
);
1508 // The navigation should have used the first SiteInstance, otherwise
1509 // |initial_rvh| did not have a chance to be used.
1510 EXPECT_EQ(new_web_contents
->GetSiteInstance(), site_instance1
);
1511 EXPECT_EQ(BINDINGS_POLICY_WEB_UI
,
1512 new_web_contents
->GetRenderViewHost()->GetEnabledBindings());
1516 // The test loads a WebUI page in rocess-per-tab mode, then navigates to a blank
1517 // page and then to a regular page. The bug reproduces if blank page is visited
1518 // in between WebUI and regular page.
1519 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest
,
1520 ForceSwapAfterWebUIBindings
) {
1521 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1522 switches::kProcessPerTab
);
1523 ASSERT_TRUE(test_server()->Start());
1525 const GURL
web_ui_url(std::string(kChromeUIScheme
) + "://" +
1526 std::string(kChromeUIGpuHost
));
1527 NavigateToURL(shell(), web_ui_url
);
1528 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1529 shell()->web_contents()->GetRenderProcessHost()->GetID()));
1531 NavigateToURL(shell(), GURL(url::kAboutBlankURL
));
1533 GURL
regular_page_url(test_server()->GetURL("files/title2.html"));
1534 NavigateToURL(shell(), regular_page_url
);
1535 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1536 shell()->web_contents()->GetRenderProcessHost()->GetID()));
1539 class FileChooserDelegate
: public WebContentsDelegate
{
1541 FileChooserDelegate(const base::FilePath
& file
)
1542 : file_(file
), file_chosen_(false) {}
1544 void RunFileChooser(WebContents
* web_contents
,
1545 const FileChooserParams
& params
) override
{
1546 // Send the selected file to the renderer process.
1547 FileChooserFileInfo file_info
;
1548 file_info
.file_path
= file_
;
1549 std::vector
<FileChooserFileInfo
> files
;
1550 files
.push_back(file_info
);
1551 web_contents
->GetRenderViewHost()->FilesSelectedInChooser(
1552 files
, FileChooserParams::Open
);
1554 file_chosen_
= true;
1557 bool file_chosen() { return file_chosen_
; }
1560 base::FilePath file_
;
1564 // Test for http://crbug.com/262948.
1565 // Flaky on Mac. http://crbug.com/452018
1566 #if defined(OS_MACOSX)
1567 #define MAYBE_RestoreFileAccessForHistoryNavigation \
1568 DISABLED_RestoreFileAccessForHistoryNavigation
1570 #define MAYBE_RestoreFileAccessForHistoryNavigation \
1571 RestoreFileAccessForHistoryNavigation
1573 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest
,
1574 MAYBE_RestoreFileAccessForHistoryNavigation
) {
1576 base::FilePath file
;
1577 EXPECT_TRUE(PathService::Get(base::DIR_TEMP
, &file
));
1578 file
= file
.AppendASCII("bar");
1580 // Navigate to url and get it to reference a file in its PageState.
1581 GURL
url1(test_server()->GetURL("files/file_input.html"));
1582 NavigateToURL(shell(), url1
);
1583 int process_id
= shell()->web_contents()->GetRenderProcessHost()->GetID();
1584 scoped_ptr
<FileChooserDelegate
> delegate(new FileChooserDelegate(file
));
1585 shell()->web_contents()->SetDelegate(delegate
.get());
1586 EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
1587 "document.getElementById('fileinput').click();"));
1588 EXPECT_TRUE(delegate
->file_chosen());
1589 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
1592 // Navigate to a different process without access to the file, and wait for
1593 // the old process to exit.
1594 RenderProcessHostWatcher
exit_observer(
1595 shell()->web_contents()->GetRenderProcessHost(),
1596 RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION
);
1597 NavigateToURL(shell(), GetCrossSiteURL("files/title1.html"));
1598 exit_observer
.Wait();
1599 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
1600 shell()->web_contents()->GetRenderProcessHost()->GetID(), file
));
1602 // Ensure that the file ended up in the PageState of the previous entry.
1603 NavigationEntry
* prev_entry
=
1604 shell()->web_contents()->GetController().GetEntryAtIndex(0);
1605 EXPECT_EQ(url1
, prev_entry
->GetURL());
1606 const std::vector
<base::FilePath
>& files
=
1607 prev_entry
->GetPageState().GetReferencedFiles();
1608 ASSERT_EQ(1U, files
.size());
1609 EXPECT_EQ(file
, files
.at(0));
1611 // Go back, ending up in a different RenderProcessHost than before.
1612 TestNavigationObserver
back_nav_load_observer(shell()->web_contents());
1613 shell()->web_contents()->GetController().GoBack();
1614 back_nav_load_observer
.Wait();
1615 EXPECT_NE(process_id
,
1616 shell()->web_contents()->GetRenderProcessHost()->GetID());
1618 // Ensure that the file access still exists in the new process ID.
1619 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
1620 shell()->web_contents()->GetRenderProcessHost()->GetID(), file
));
1622 // Navigate to a same site page to trigger a PageState update and ensure the
1623 // renderer is not killed.
1625 NavigateToURL(shell(), test_server()->GetURL("files/title2.html")));
1628 // Test for http://crbug.com/441966.
1629 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest
,
1630 RestoreSubframeFileAccessForHistoryNavigation
) {
1632 base::FilePath file
;
1633 EXPECT_TRUE(PathService::Get(base::DIR_TEMP
, &file
));
1634 file
= file
.AppendASCII("bar");
1636 // Navigate to url and get it to reference a file in its PageState.
1637 GURL
url1(test_server()->GetURL("files/file_input_subframe.html"));
1638 NavigateToURL(shell(), url1
);
1639 WebContentsImpl
* wc
= static_cast<WebContentsImpl
*>(shell()->web_contents());
1640 FrameTreeNode
* root
= wc
->GetFrameTree()->root();
1641 int process_id
= shell()->web_contents()->GetRenderProcessHost()->GetID();
1642 scoped_ptr
<FileChooserDelegate
> delegate(new FileChooserDelegate(file
));
1643 shell()->web_contents()->SetDelegate(delegate
.get());
1644 EXPECT_TRUE(ExecuteScript(root
->child_at(0)->current_frame_host(),
1645 "document.getElementById('fileinput').click();"));
1646 EXPECT_TRUE(delegate
->file_chosen());
1647 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
1650 // Navigate to a different process without access to the file, and wait for
1651 // the old process to exit.
1652 RenderProcessHostWatcher
exit_observer(
1653 shell()->web_contents()->GetRenderProcessHost(),
1654 RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION
);
1655 NavigateToURL(shell(), GetCrossSiteURL("files/title1.html"));
1656 exit_observer
.Wait();
1657 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
1658 shell()->web_contents()->GetRenderProcessHost()->GetID(), file
));
1660 // Ensure that the file ended up in the PageState of the previous entry.
1661 NavigationEntry
* prev_entry
=
1662 shell()->web_contents()->GetController().GetEntryAtIndex(0);
1663 EXPECT_EQ(url1
, prev_entry
->GetURL());
1664 const std::vector
<base::FilePath
>& files
=
1665 prev_entry
->GetPageState().GetReferencedFiles();
1666 ASSERT_EQ(1U, files
.size());
1667 EXPECT_EQ(file
, files
.at(0));
1669 // Go back, ending up in a different RenderProcessHost than before.
1670 TestNavigationObserver
back_nav_load_observer(shell()->web_contents());
1671 shell()->web_contents()->GetController().GoBack();
1672 back_nav_load_observer
.Wait();
1673 EXPECT_NE(process_id
,
1674 shell()->web_contents()->GetRenderProcessHost()->GetID());
1676 // Ensure that the file access still exists in the new process ID.
1677 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
1678 shell()->web_contents()->GetRenderProcessHost()->GetID(), file
));
1681 } // namespace content