Use native radiobutton for Default Search Engine picker dialog.
[chromium-blink-merge.git] / content / browser / site_per_process_browsertest.cc
blobdf9e55e8e8f68da3fa981b8a8fa6ae1b7c02b486
1 // Copyright (c) 2012 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 "content/browser/site_per_process_browsertest.h"
7 #include <algorithm>
8 #include <vector>
10 #include "base/command_line.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "content/browser/frame_host/cross_process_frame_connector.h"
14 #include "content/browser/frame_host/frame_tree.h"
15 #include "content/browser/frame_host/navigator.h"
16 #include "content/browser/frame_host/render_frame_proxy_host.h"
17 #include "content/browser/frame_host/render_widget_host_view_child_frame.h"
18 #include "content/browser/renderer_host/render_view_host_impl.h"
19 #include "content/browser/web_contents/web_contents_impl.h"
20 #include "content/common/frame_messages.h"
21 #include "content/public/browser/notification_observer.h"
22 #include "content/public/browser/notification_service.h"
23 #include "content/public/browser/notification_types.h"
24 #include "content/public/common/content_switches.h"
25 #include "content/public/test/browser_test_utils.h"
26 #include "content/public/test/content_browser_test_utils.h"
27 #include "content/public/test/test_navigation_observer.h"
28 #include "content/public/test/test_utils.h"
29 #include "content/shell/browser/shell.h"
30 #include "content/test/content_browser_test_utils_internal.h"
31 #include "content/test/test_frame_navigation_observer.h"
32 #include "ipc/ipc_security_test_util.h"
33 #include "net/dns/mock_host_resolver.h"
34 #include "net/test/embedded_test_server/embedded_test_server.h"
36 namespace content {
38 namespace {
40 // Helper function to send a postMessage and wait for a reply message. The
41 // |post_message_script| is executed on the |sender_ftn| frame, and the sender
42 // frame is expected to post |reply_status| from the DOMAutomationController
43 // when it receives a reply.
44 void PostMessageAndWaitForReply(FrameTreeNode* sender_ftn,
45 const std::string& post_message_script,
46 const std::string& reply_status) {
47 bool success = false;
48 EXPECT_TRUE(ExecuteScriptAndExtractBool(
49 sender_ftn->current_frame_host(),
50 "window.domAutomationController.send(" + post_message_script + ");",
51 &success));
52 EXPECT_TRUE(success);
54 content::DOMMessageQueue msg_queue;
55 std::string status;
56 while (msg_queue.WaitForMessage(&status)) {
57 if (status == reply_status)
58 break;
62 } // anonymous namespace
64 class RedirectNotificationObserver : public NotificationObserver {
65 public:
66 // Register to listen for notifications of the given type from either a
67 // specific source, or from all sources if |source| is
68 // NotificationService::AllSources().
69 RedirectNotificationObserver(int notification_type,
70 const NotificationSource& source);
71 ~RedirectNotificationObserver() override;
73 // Wait until the specified notification occurs. If the notification was
74 // emitted between the construction of this object and this call then it
75 // returns immediately.
76 void Wait();
78 // Returns NotificationService::AllSources() if we haven't observed a
79 // notification yet.
80 const NotificationSource& source() const {
81 return source_;
84 const NotificationDetails& details() const {
85 return details_;
88 // NotificationObserver:
89 void Observe(int type,
90 const NotificationSource& source,
91 const NotificationDetails& details) override;
93 private:
94 bool seen_;
95 bool seen_twice_;
96 bool running_;
97 NotificationRegistrar registrar_;
99 NotificationSource source_;
100 NotificationDetails details_;
101 scoped_refptr<MessageLoopRunner> message_loop_runner_;
103 DISALLOW_COPY_AND_ASSIGN(RedirectNotificationObserver);
106 RedirectNotificationObserver::RedirectNotificationObserver(
107 int notification_type,
108 const NotificationSource& source)
109 : seen_(false),
110 running_(false),
111 source_(NotificationService::AllSources()) {
112 registrar_.Add(this, notification_type, source);
115 RedirectNotificationObserver::~RedirectNotificationObserver() {}
117 void RedirectNotificationObserver::Wait() {
118 if (seen_ && seen_twice_)
119 return;
121 running_ = true;
122 message_loop_runner_ = new MessageLoopRunner;
123 message_loop_runner_->Run();
124 EXPECT_TRUE(seen_);
127 void RedirectNotificationObserver::Observe(
128 int type,
129 const NotificationSource& source,
130 const NotificationDetails& details) {
131 source_ = source;
132 details_ = details;
133 seen_twice_ = seen_;
134 seen_ = true;
135 if (!running_)
136 return;
138 message_loop_runner_->Quit();
139 running_ = false;
142 // This observer keeps track of the number of created RenderFrameHosts. Tests
143 // can use this to ensure that a certain number of child frames has been
144 // created after navigating.
145 class RenderFrameHostCreatedObserver : public WebContentsObserver {
146 public:
147 RenderFrameHostCreatedObserver(WebContents* web_contents,
148 int expected_frame_count)
149 : WebContentsObserver(web_contents),
150 expected_frame_count_(expected_frame_count),
151 frames_created_(0),
152 message_loop_runner_(new MessageLoopRunner) {}
154 ~RenderFrameHostCreatedObserver() override;
156 // Runs a nested message loop and blocks until the expected number of
157 // RenderFrameHosts is created.
158 void Wait();
160 private:
161 // WebContentsObserver
162 void RenderFrameCreated(RenderFrameHost* render_frame_host) override;
164 // The number of RenderFrameHosts to wait for.
165 int expected_frame_count_;
167 // The number of RenderFrameHosts that have been created.
168 int frames_created_;
170 // The MessageLoopRunner used to spin the message loop.
171 scoped_refptr<MessageLoopRunner> message_loop_runner_;
173 DISALLOW_COPY_AND_ASSIGN(RenderFrameHostCreatedObserver);
176 RenderFrameHostCreatedObserver::~RenderFrameHostCreatedObserver() {
179 void RenderFrameHostCreatedObserver::Wait() {
180 message_loop_runner_->Run();
183 void RenderFrameHostCreatedObserver::RenderFrameCreated(
184 RenderFrameHost* render_frame_host) {
185 frames_created_++;
186 if (frames_created_ == expected_frame_count_) {
187 message_loop_runner_->Quit();
191 // A WebContentsDelegate that catches messages sent to the console.
192 class ConsoleObserverDelegate : public WebContentsDelegate {
193 public:
194 ConsoleObserverDelegate(WebContents* web_contents, const std::string& filter)
195 : web_contents_(web_contents),
196 filter_(filter),
197 message_(""),
198 message_loop_runner_(new MessageLoopRunner) {}
200 ~ConsoleObserverDelegate() override {}
202 bool AddMessageToConsole(WebContents* source,
203 int32 level,
204 const base::string16& message,
205 int32 line_no,
206 const base::string16& source_id) override;
208 std::string message() { return message_; }
210 void Wait();
212 private:
213 WebContents* web_contents_;
214 std::string filter_;
215 std::string message_;
217 // The MessageLoopRunner used to spin the message loop.
218 scoped_refptr<MessageLoopRunner> message_loop_runner_;
220 DISALLOW_COPY_AND_ASSIGN(ConsoleObserverDelegate);
223 void ConsoleObserverDelegate::Wait() {
224 message_loop_runner_->Run();
227 bool ConsoleObserverDelegate::AddMessageToConsole(
228 WebContents* source,
229 int32 level,
230 const base::string16& message,
231 int32 line_no,
232 const base::string16& source_id) {
233 DCHECK(source == web_contents_);
235 std::string ascii_message = base::UTF16ToASCII(message);
236 if (MatchPattern(ascii_message, filter_)) {
237 message_ = ascii_message;
238 message_loop_runner_->Quit();
240 return false;
244 // SitePerProcessBrowserTest
247 SitePerProcessBrowserTest::SitePerProcessBrowserTest() {
250 std::string SitePerProcessBrowserTest::DepictFrameTree(FrameTreeNode* node) {
251 return visualizer_.DepictFrameTree(node);
254 void SitePerProcessBrowserTest::StartFrameAtDataURL() {
255 std::string data_url_script =
256 "var iframes = document.getElementById('test');iframes.src="
257 "'data:text/html,dataurl';";
258 ASSERT_TRUE(ExecuteScript(shell()->web_contents(), data_url_script));
261 void SitePerProcessBrowserTest::SetUpCommandLine(
262 base::CommandLine* command_line) {
263 command_line->AppendSwitch(switches::kSitePerProcess);
266 void SitePerProcessBrowserTest::SetUpOnMainThread() {
267 host_resolver()->AddRule("*", "127.0.0.1");
268 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
269 SetupCrossSiteRedirector(embedded_test_server());
272 // Ensure that navigating subframes in --site-per-process mode works and the
273 // correct documents are committed.
274 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframe) {
275 GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
276 NavigateToURL(shell(), main_url);
278 // It is safe to obtain the root frame tree node here, as it doesn't change.
279 FrameTreeNode* root =
280 static_cast<WebContentsImpl*>(shell()->web_contents())->
281 GetFrameTree()->root();
283 TestNavigationObserver observer(shell()->web_contents());
285 // Load same-site page into iframe.
286 FrameTreeNode* child = root->child_at(0);
287 GURL http_url(embedded_test_server()->GetURL("/title1.html"));
288 NavigateFrameToURL(child, http_url);
289 EXPECT_EQ(http_url, observer.last_navigation_url());
290 EXPECT_TRUE(observer.last_navigation_succeeded());
292 // There should be only one RenderWidgetHost when there are no
293 // cross-process iframes.
294 std::set<RenderWidgetHostView*> views_set =
295 static_cast<WebContentsImpl*>(shell()->web_contents())
296 ->GetRenderWidgetHostViewsInTree();
297 EXPECT_EQ(1U, views_set.size());
300 EXPECT_EQ(
301 " Site A\n"
302 " |--Site A\n"
303 " +--Site A\n"
304 " |--Site A\n"
305 " +--Site A\n"
306 " +--Site A\n"
307 "Where A = http://127.0.0.1/",
308 DepictFrameTree(root));
310 // Load cross-site page into iframe.
311 GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html");
312 NavigateFrameToURL(root->child_at(0), url);
313 // Verify that the navigation succeeded and the expected URL was loaded.
314 EXPECT_TRUE(observer.last_navigation_succeeded());
315 EXPECT_EQ(url, observer.last_navigation_url());
317 // Ensure that we have created a new process for the subframe.
318 ASSERT_EQ(2U, root->child_count());
319 SiteInstance* site_instance = child->current_frame_host()->GetSiteInstance();
320 RenderViewHost* rvh = child->current_frame_host()->render_view_host();
321 RenderProcessHost* rph = child->current_frame_host()->GetProcess();
322 EXPECT_NE(shell()->web_contents()->GetRenderViewHost(), rvh);
323 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), site_instance);
324 EXPECT_NE(shell()->web_contents()->GetRenderProcessHost(), rph);
326 // There should be now two RenderWidgetHosts, one for each process
327 // rendering a frame.
328 std::set<RenderWidgetHostView*> views_set =
329 static_cast<WebContentsImpl*>(shell()->web_contents())
330 ->GetRenderWidgetHostViewsInTree();
331 EXPECT_EQ(2U, views_set.size());
333 RenderFrameProxyHost* proxy_to_parent =
334 child->render_manager()->GetProxyToParent();
335 EXPECT_TRUE(proxy_to_parent);
336 EXPECT_TRUE(proxy_to_parent->cross_process_frame_connector());
337 // The out-of-process iframe should have its own RenderWidgetHost,
338 // independent of any RenderViewHost.
339 EXPECT_NE(
340 rvh->GetView(),
341 proxy_to_parent->cross_process_frame_connector()->get_view_for_testing());
342 EXPECT_TRUE(child->current_frame_host()->GetRenderWidgetHost());
344 EXPECT_EQ(
345 " Site A ------------ proxies for B\n"
346 " |--Site B ------- proxies for A\n"
347 " +--Site A ------- proxies for B\n"
348 " |--Site A -- proxies for B\n"
349 " +--Site A -- proxies for B\n"
350 " +--Site A -- proxies for B\n"
351 "Where A = http://127.0.0.1/\n"
352 " B = http://foo.com/",
353 DepictFrameTree(root));
355 // Load another cross-site page into the same iframe.
356 url = embedded_test_server()->GetURL("bar.com", "/title3.html");
357 NavigateFrameToURL(root->child_at(0), url);
358 EXPECT_TRUE(observer.last_navigation_succeeded());
359 EXPECT_EQ(url, observer.last_navigation_url());
361 // Check again that a new process is created and is different from the
362 // top level one and the previous one.
363 ASSERT_EQ(2U, root->child_count());
364 child = root->child_at(0);
365 EXPECT_NE(shell()->web_contents()->GetRenderViewHost(),
366 child->current_frame_host()->render_view_host());
367 EXPECT_NE(rvh, child->current_frame_host()->render_view_host());
368 EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
369 child->current_frame_host()->GetSiteInstance());
370 EXPECT_NE(site_instance,
371 child->current_frame_host()->GetSiteInstance());
372 EXPECT_NE(shell()->web_contents()->GetRenderProcessHost(),
373 child->current_frame_host()->GetProcess());
374 EXPECT_NE(rph, child->current_frame_host()->GetProcess());
376 std::set<RenderWidgetHostView*> views_set =
377 static_cast<WebContentsImpl*>(shell()->web_contents())
378 ->GetRenderWidgetHostViewsInTree();
379 EXPECT_EQ(2U, views_set.size());
381 EXPECT_EQ(proxy_to_parent, child->render_manager()->GetProxyToParent());
382 EXPECT_TRUE(proxy_to_parent->cross_process_frame_connector());
383 EXPECT_NE(
384 child->current_frame_host()->render_view_host()->GetView(),
385 proxy_to_parent->cross_process_frame_connector()->get_view_for_testing());
386 EXPECT_TRUE(child->current_frame_host()->GetRenderWidgetHost());
388 EXPECT_EQ(
389 " Site A ------------ proxies for C\n"
390 " |--Site C ------- proxies for A\n"
391 " +--Site A ------- proxies for C\n"
392 " |--Site A -- proxies for C\n"
393 " +--Site A -- proxies for C\n"
394 " +--Site A -- proxies for C\n"
395 "Where A = http://127.0.0.1/\n"
396 " C = http://bar.com/",
397 DepictFrameTree(root));
400 // Tests OOPIF rendering by checking that the RWH of the iframe generates
401 // OnSwapCompositorFrame message.
402 #if defined(OS_ANDROID)
403 // http://crbug.com/471850
404 #define MAYBE_CompositorFrameSwapped DISABLED_CompositorFrameSwapped
405 #else
406 #define MAYBE_CompositorFrameSwapped CompositorFrameSwapped
407 #endif
408 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
409 MAYBE_CompositorFrameSwapped) {
410 GURL main_url(
411 embedded_test_server()->GetURL("/frame_tree/page_with_one_frame.html"));
412 NavigateToURL(shell(), main_url);
414 // It is safe to obtain the root frame tree node here, as it doesn't change.
415 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
416 ->GetFrameTree()
417 ->root();
418 ASSERT_EQ(1U, root->child_count());
420 FrameTreeNode* child_node = root->child_at(0);
421 GURL site_url(embedded_test_server()->GetURL("baz.com", "/title1.html"));
422 EXPECT_EQ(site_url, child_node->current_url());
423 EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
424 child_node->current_frame_host()->GetSiteInstance());
425 RenderWidgetHostViewBase* rwhv_base = static_cast<RenderWidgetHostViewBase*>(
426 child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
428 // Wait for OnSwapCompositorFrame message.
429 while (rwhv_base->RendererFrameNumber() <= 0) {
430 // TODO(lazyboy): Find a better way to avoid sleeping like this. See
431 // http://crbug.com/405282 for details.
432 base::RunLoop run_loop;
433 base::MessageLoop::current()->PostDelayedTask(
434 FROM_HERE, run_loop.QuitClosure(),
435 base::TimeDelta::FromMilliseconds(10));
436 run_loop.Run();
440 // Ensure that OOPIFs are deleted after navigating to a new main frame.
441 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CleanupCrossSiteIframe) {
442 GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
443 NavigateToURL(shell(), main_url);
445 // It is safe to obtain the root frame tree node here, as it doesn't change.
446 FrameTreeNode* root =
447 static_cast<WebContentsImpl*>(shell()->web_contents())->
448 GetFrameTree()->root();
450 TestNavigationObserver observer(shell()->web_contents());
452 // Load a cross-site page into both iframes.
453 GURL foo_url = embedded_test_server()->GetURL("foo.com", "/title2.html");
454 NavigateFrameToURL(root->child_at(0), foo_url);
455 EXPECT_TRUE(observer.last_navigation_succeeded());
456 EXPECT_EQ(foo_url, observer.last_navigation_url());
457 NavigateFrameToURL(root->child_at(1), foo_url);
458 EXPECT_TRUE(observer.last_navigation_succeeded());
459 EXPECT_EQ(foo_url, observer.last_navigation_url());
461 // Ensure that we have created a new process for the subframes.
462 ASSERT_EQ(2U, root->child_count());
463 EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
464 root->child_at(0)->current_frame_host()->GetSiteInstance());
465 EXPECT_EQ(root->child_at(0)->current_frame_host()->GetSiteInstance(),
466 root->child_at(1)->current_frame_host()->GetSiteInstance());
468 // Use Javascript in the parent to remove one of the frames and ensure that
469 // the subframe goes away.
470 EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
471 "document.body.removeChild("
472 "document.querySelectorAll('iframe')[0])"));
473 ASSERT_EQ(1U, root->child_count());
475 // Load a new same-site page in the top-level frame and ensure the other
476 // subframe goes away.
477 GURL new_url(embedded_test_server()->GetURL("/title1.html"));
478 NavigateToURL(shell(), new_url);
479 ASSERT_EQ(0U, root->child_count());
482 // Ensure that root frames cannot be detached.
483 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, RestrictFrameDetach) {
484 GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
485 NavigateToURL(shell(), main_url);
487 // It is safe to obtain the root frame tree node here, as it doesn't change.
488 FrameTreeNode* root =
489 static_cast<WebContentsImpl*>(shell()->web_contents())->
490 GetFrameTree()->root();
492 TestNavigationObserver observer(shell()->web_contents());
494 // Load cross-site pages into both iframes.
495 GURL foo_url = embedded_test_server()->GetURL("foo.com", "/title2.html");
496 NavigateFrameToURL(root->child_at(0), foo_url);
497 EXPECT_TRUE(observer.last_navigation_succeeded());
498 EXPECT_EQ(foo_url, observer.last_navigation_url());
499 GURL bar_url = embedded_test_server()->GetURL("bar.com", "/title2.html");
500 NavigateFrameToURL(root->child_at(1), bar_url);
501 EXPECT_TRUE(observer.last_navigation_succeeded());
502 EXPECT_EQ(bar_url, observer.last_navigation_url());
504 // Ensure that we have created new processes for the subframes.
505 ASSERT_EQ(2U, root->child_count());
506 FrameTreeNode* foo_child = root->child_at(0);
507 SiteInstance* foo_site_instance =
508 foo_child->current_frame_host()->GetSiteInstance();
509 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), foo_site_instance);
510 FrameTreeNode* bar_child = root->child_at(1);
511 SiteInstance* bar_site_instance =
512 bar_child->current_frame_host()->GetSiteInstance();
513 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), bar_site_instance);
515 EXPECT_EQ(
516 " Site A ------------ proxies for B C\n"
517 " |--Site B ------- proxies for A C\n"
518 " +--Site C ------- proxies for A B\n"
519 "Where A = http://127.0.0.1/\n"
520 " B = http://foo.com/\n"
521 " C = http://bar.com/",
522 DepictFrameTree(root));
524 // Simulate an attempt to detach the root frame from foo_site_instance. This
525 // should kill foo_site_instance's process.
526 RenderFrameProxyHost* foo_mainframe_rfph =
527 root->render_manager()->GetRenderFrameProxyHost(foo_site_instance);
528 content::RenderProcessHostWatcher foo_terminated(
529 foo_mainframe_rfph->GetProcess(),
530 content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
531 FrameHostMsg_Detach evil_msg2(foo_mainframe_rfph->GetRoutingID());
532 IPC::IpcSecurityTestUtil::PwnMessageReceived(
533 foo_mainframe_rfph->GetProcess()->GetChannel(), evil_msg2);
534 foo_terminated.Wait();
536 EXPECT_EQ(
537 " Site A ------------ proxies for B C\n"
538 " |--Site B ------- proxies for A C\n"
539 " +--Site C ------- proxies for A B\n"
540 "Where A = http://127.0.0.1/\n"
541 " B = http://foo.com/ (no process)\n"
542 " C = http://bar.com/",
543 DepictFrameTree(root));
546 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
547 NavigateRemoteFrame) {
548 GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
549 NavigateToURL(shell(), main_url);
551 // It is safe to obtain the root frame tree node here, as it doesn't change.
552 FrameTreeNode* root =
553 static_cast<WebContentsImpl*>(shell()->web_contents())->
554 GetFrameTree()->root();
556 TestNavigationObserver observer(shell()->web_contents());
558 // Load same-site page into iframe.
559 FrameTreeNode* child = root->child_at(0);
560 GURL http_url(embedded_test_server()->GetURL("/title1.html"));
561 NavigateFrameToURL(child, http_url);
562 EXPECT_EQ(http_url, observer.last_navigation_url());
563 EXPECT_TRUE(observer.last_navigation_succeeded());
565 // Load cross-site page into iframe.
566 GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html");
567 NavigateFrameToURL(root->child_at(0), url);
568 EXPECT_TRUE(observer.last_navigation_succeeded());
569 EXPECT_EQ(url, observer.last_navigation_url());
571 // Ensure that we have created a new process for the subframe.
572 ASSERT_EQ(2U, root->child_count());
573 SiteInstance* site_instance = child->current_frame_host()->GetSiteInstance();
574 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), site_instance);
576 // Emulate the main frame changing the src of the iframe such that it
577 // navigates cross-site.
578 url = embedded_test_server()->GetURL("bar.com", "/title3.html");
579 NavigateIframeToURL(shell()->web_contents(), "test", url);
580 EXPECT_TRUE(observer.last_navigation_succeeded());
581 EXPECT_EQ(url, observer.last_navigation_url());
583 // Check again that a new process is created and is different from the
584 // top level one and the previous one.
585 ASSERT_EQ(2U, root->child_count());
586 child = root->child_at(0);
587 EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
588 child->current_frame_host()->GetSiteInstance());
589 EXPECT_NE(site_instance,
590 child->current_frame_host()->GetSiteInstance());
592 // Navigate back to the parent's origin and ensure we return to the
593 // parent's process.
594 NavigateFrameToURL(child, http_url);
595 EXPECT_EQ(http_url, observer.last_navigation_url());
596 EXPECT_TRUE(observer.last_navigation_succeeded());
597 EXPECT_EQ(shell()->web_contents()->GetSiteInstance(),
598 child->current_frame_host()->GetSiteInstance());
601 #if defined(OS_WIN)
602 // http://crbug.com/465722
603 #define MAYBE_NavigateRemoteFrameToBlankAndDataURLs \
604 DISABLED_NavigateRemoteFrameToBlankAndDataURLs
605 #else
606 #define MAYBE_NavigateRemoteFrameToBlankAndDataURLs \
607 NavigateRemoteFrameToBlankAndDataURLs
608 #endif
610 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
611 MAYBE_NavigateRemoteFrameToBlankAndDataURLs) {
612 GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
613 NavigateToURL(shell(), main_url);
615 // It is safe to obtain the root frame tree node here, as it doesn't change.
616 FrameTreeNode* root =
617 static_cast<WebContentsImpl*>(shell()->web_contents())->
618 GetFrameTree()->root();
620 TestNavigationObserver observer(shell()->web_contents());
622 // Load same-site page into iframe.
623 FrameTreeNode* child = root->child_at(0);
624 GURL http_url(embedded_test_server()->GetURL("/title1.html"));
625 NavigateFrameToURL(child, http_url);
626 EXPECT_EQ(http_url, observer.last_navigation_url());
627 EXPECT_TRUE(observer.last_navigation_succeeded());
629 // Load cross-site page into iframe.
630 GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html");
631 NavigateFrameToURL(root->child_at(0), url);
632 EXPECT_TRUE(observer.last_navigation_succeeded());
633 EXPECT_EQ(url, observer.last_navigation_url());
634 ASSERT_EQ(2U, root->child_count());
635 EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
636 root->child_at(0)->current_frame_host()->GetSiteInstance());
638 // Navigate iframe to a data URL. The navigation happens from a script in the
639 // parent frame, so the data URL should be committed in the same SiteInstance
640 // as the parent frame.
641 GURL data_url("data:text/html,dataurl");
642 NavigateIframeToURL(shell()->web_contents(), "test", data_url);
643 EXPECT_TRUE(observer.last_navigation_succeeded());
644 EXPECT_EQ(data_url, observer.last_navigation_url());
646 // Ensure that we have navigated using the top level process.
647 EXPECT_EQ(shell()->web_contents()->GetSiteInstance(),
648 root->child_at(0)->current_frame_host()->GetSiteInstance());
650 // Load cross-site page into iframe.
651 url = embedded_test_server()->GetURL("bar.com", "/title2.html");
652 NavigateFrameToURL(root->child_at(0), url);
653 EXPECT_TRUE(observer.last_navigation_succeeded());
654 EXPECT_EQ(url, observer.last_navigation_url());
655 ASSERT_EQ(2U, root->child_count());
656 EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
657 root->child_at(0)->current_frame_host()->GetSiteInstance());
659 // Navigate iframe to about:blank. The navigation happens from a script in the
660 // parent frame, so it should be committed in the same SiteInstance as the
661 // parent frame.
662 GURL about_blank_url("about:blank");
663 NavigateIframeToURL(shell()->web_contents(), "test", about_blank_url);
664 EXPECT_TRUE(observer.last_navigation_succeeded());
665 EXPECT_EQ(about_blank_url, observer.last_navigation_url());
667 // Ensure that we have navigated using the top level process.
668 EXPECT_EQ(shell()->web_contents()->GetSiteInstance(),
669 root->child_at(0)->current_frame_host()->GetSiteInstance());
672 // This test checks that killing a renderer process of a remote frame
673 // and then navigating some other frame to the same SiteInstance of the killed
674 // process works properly.
675 // This can be illustrated as follows,
676 // where 1/2/3 are FrameTreeNode-s and A/B are processes and B* is the killed
677 // B process:
679 // 1 A A A
680 // / \ -> / \ -> Kill B -> / \ -> Navigate 3 to B -> / \ .
681 // 2 3 B A B* A B* B
683 // Initially, node1.proxy_hosts_ = {B}
684 // After we kill B, we make sure B stays in node1.proxy_hosts_, then we navigate
685 // 3 to B and we expect that to complete normally.
686 // See http://crbug.com/432107.
688 // Note that due to http://crbug.com/450681, node2 cannot be re-navigated to
689 // site B and stays in not rendered state.
690 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
691 NavigateRemoteFrameToKilledProcess) {
692 GURL main_url(embedded_test_server()->GetURL(
693 "/frame_tree/page_with_two_frames.html"));
694 NavigateToURL(shell(), main_url);
696 // It is safe to obtain the root frame tree node here, as it doesn't change.
697 FrameTreeNode* root =
698 static_cast<WebContentsImpl*>(shell()->web_contents())->
699 GetFrameTree()->root();
701 TestNavigationObserver observer(shell()->web_contents());
702 ASSERT_EQ(2U, root->child_count());
704 // Make sure node2 points to the correct cross-site page.
705 GURL site_b_url = embedded_test_server()->GetURL("bar.com", "/title1.html");
706 FrameTreeNode* node2 = root->child_at(0);
707 EXPECT_EQ(site_b_url, node2->current_url());
709 // Kill that cross-site renderer.
710 RenderProcessHost* child_process =
711 node2->current_frame_host()->GetProcess();
712 RenderProcessHostWatcher crash_observer(
713 child_process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
714 child_process->Shutdown(0, false);
715 crash_observer.Wait();
717 // Now navigate the second iframe (node3) to the same site as the node2.
718 FrameTreeNode* node3 = root->child_at(1);
719 NavigateFrameToURL(node3, site_b_url);
720 EXPECT_TRUE(observer.last_navigation_succeeded());
721 EXPECT_EQ(site_b_url, observer.last_navigation_url());
724 // This test is similar to
725 // SitePerProcessBrowserTest.NavigateRemoteFrameToKilledProcess with
726 // addition that node2 also has a cross-origin frame to site C.
728 // 1 A A A
729 // / \ / \ / \ / \ .
730 // 2 3 -> B A -> Kill B -> B* A -> Navigate 3 -> B* B
731 // / /
732 // 4 C
734 // Initially, node1.proxy_hosts_ = {B, C}
735 // After we kill B, we make sure B stays in node1.proxy_hosts_, but
736 // C gets cleared from node1.proxy_hosts_.
738 // Note that due to http://crbug.com/450681, node2 cannot be re-navigated to
739 // site B and stays in not rendered state.
740 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
741 NavigateRemoteFrameToKilledProcessWithSubtree) {
742 GURL main_url(embedded_test_server()->GetURL(
743 "a.com", "/frame_tree/page_with_two_frames_nested.html"));
744 NavigateToURL(shell(), main_url);
746 // It is safe to obtain the root frame tree node here, as it doesn't change.
747 FrameTreeNode* root =
748 static_cast<WebContentsImpl*>(shell()->web_contents())->
749 GetFrameTree()->root();
750 TestNavigationObserver observer(shell()->web_contents());
752 ASSERT_EQ(2U, root->child_count());
754 GURL site_b_url(
755 embedded_test_server()->GetURL(
756 "bar.com", "/frame_tree/page_with_one_frame.html"));
757 // We can't use a TestNavigationObserver to verify the URL here,
758 // since the frame has children that may have clobbered it in the observer.
759 EXPECT_EQ(site_b_url, root->child_at(0)->current_url());
761 // Ensure that a new process is created for node2.
762 EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
763 root->child_at(0)->current_frame_host()->GetSiteInstance());
764 // Ensure that a new process is *not* created for node3.
765 EXPECT_EQ(shell()->web_contents()->GetSiteInstance(),
766 root->child_at(1)->current_frame_host()->GetSiteInstance());
768 ASSERT_EQ(1U, root->child_at(0)->child_count());
770 // Make sure node4 points to the correct cross-site page.
771 FrameTreeNode* node4 = root->child_at(0)->child_at(0);
772 GURL site_c_url(embedded_test_server()->GetURL("baz.com", "/title1.html"));
773 EXPECT_EQ(site_c_url, node4->current_url());
775 // |site_instance_c| is expected to go away once we kill |child_process_b|
776 // below, so create a local scope so we can extend the lifetime of
777 // |site_instance_c| with a refptr.
779 // Initially each frame has proxies for the other sites.
780 EXPECT_EQ(
781 " Site A ------------ proxies for B C\n"
782 " |--Site B ------- proxies for A C\n"
783 " | +--Site C -- proxies for A B\n"
784 " +--Site A ------- proxies for B C\n"
785 "Where A = http://a.com/\n"
786 " B = http://bar.com/\n"
787 " C = http://baz.com/",
788 DepictFrameTree(root));
790 // Kill the render process for Site B.
791 RenderProcessHost* child_process_b =
792 root->child_at(0)->current_frame_host()->GetProcess();
793 RenderProcessHostWatcher crash_observer(
794 child_process_b, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
795 child_process_b->Shutdown(0, false);
796 crash_observer.Wait();
798 // The Site C frame (a child of the crashed Site B frame) should go away,
799 // and there should be no remaining proxies for site C anywhere.
800 EXPECT_EQ(
801 " Site A ------------ proxies for B\n"
802 " |--Site B ------- proxies for A\n"
803 " +--Site A ------- proxies for B\n"
804 "Where A = http://a.com/\n"
805 " B = http://bar.com/ (no process)",
806 DepictFrameTree(root));
809 // Now navigate the second iframe (node3) to Site B also.
810 FrameTreeNode* node3 = root->child_at(1);
811 GURL url = embedded_test_server()->GetURL("bar.com", "/title1.html");
812 NavigateFrameToURL(node3, url);
813 EXPECT_TRUE(observer.last_navigation_succeeded());
814 EXPECT_EQ(url, observer.last_navigation_url());
816 EXPECT_EQ(
817 " Site A ------------ proxies for B\n"
818 " |--Site B ------- proxies for A\n"
819 " +--Site B ------- proxies for A\n"
820 "Where A = http://a.com/\n"
821 " B = http://bar.com/",
822 DepictFrameTree(root));
825 // Verify that killing a cross-site frame's process B and then navigating a
826 // frame to B correctly recreates all proxies in B.
828 // 1 A A A
829 // / | \ / | \ / | \ / | \ .
830 // 2 3 4 -> B A A -> Kill B -> B* A A -> B* B A
832 // After the last step, the test sends a postMessage from node 3 to node 4,
833 // verifying that a proxy for node 4 has been recreated in process B. This
834 // verifies the fix for https://crbug.com/478892.
835 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
836 NavigatingToKilledProcessRestoresAllProxies) {
837 // Navigate to a page with three frames: one cross-site and two same-site.
838 GURL main_url(embedded_test_server()->GetURL(
839 "a.com", "/frame_tree/page_with_three_frames.html"));
840 NavigateToURL(shell(), main_url);
842 // It is safe to obtain the root frame tree node here, as it doesn't change.
843 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
844 ->GetFrameTree()
845 ->root();
846 TestNavigationObserver observer(shell()->web_contents());
848 EXPECT_EQ(
849 " Site A ------------ proxies for B\n"
850 " |--Site B ------- proxies for A\n"
851 " |--Site A ------- proxies for B\n"
852 " +--Site A ------- proxies for B\n"
853 "Where A = http://a.com/\n"
854 " B = http://b.com/",
855 DepictFrameTree(root));
857 // Kill the first subframe's b.com renderer.
858 RenderProcessHost* child_process =
859 root->child_at(0)->current_frame_host()->GetProcess();
860 RenderProcessHostWatcher crash_observer(
861 child_process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
862 child_process->Shutdown(0, false);
863 crash_observer.Wait();
865 // Navigate the second subframe to b.com to recreate the b.com process.
866 GURL b_url = embedded_test_server()->GetURL("b.com", "/post_message.html");
867 NavigateFrameToURL(root->child_at(1), b_url);
868 // TODO(alexmos): This can be removed once TestFrameNavigationObserver is
869 // fixed to use DidFinishLoad.
870 EXPECT_TRUE(
871 WaitForRenderFrameReady(root->child_at(1)->current_frame_host()));
872 EXPECT_TRUE(observer.last_navigation_succeeded());
873 EXPECT_EQ(b_url, observer.last_navigation_url());
874 EXPECT_TRUE(root->child_at(1)->current_frame_host()->IsRenderFrameLive());
876 EXPECT_EQ(
877 " Site A ------------ proxies for B\n"
878 " |--Site B ------- proxies for A\n"
879 " |--Site B ------- proxies for A\n"
880 " +--Site A ------- proxies for B\n"
881 "Where A = http://a.com/\n"
882 " B = http://b.com/",
883 DepictFrameTree(root));
885 // Check that third subframe's proxy is available in the b.com process by
886 // sending it a postMessage from second subframe, and waiting for a reply.
887 PostMessageAndWaitForReply(root->child_at(1),
888 "postToSibling('subframe-msg','frame3')",
889 "\"done-frame2\"");
892 // In A-embed-B-embed-C scenario, verify that killing process B clears proxies
893 // of C from the tree.
895 // 1 A A
896 // / \ / \ / \ .
897 // 2 3 -> B A -> Kill B -> B* A
898 // / /
899 // 4 C
901 // node1 is the root.
902 // Initially, both node1.proxy_hosts_ and node3.proxy_hosts_ contain C.
903 // After we kill B, make sure proxies for C are cleared.
904 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
905 KillingRendererClearsDescendantProxies) {
906 GURL main_url(embedded_test_server()->GetURL(
907 "a.com", "/frame_tree/page_with_two_frames_nested.html"));
908 NavigateToURL(shell(), main_url);
910 // It is safe to obtain the root frame tree node here, as it doesn't change.
911 FrameTreeNode* root =
912 static_cast<WebContentsImpl*>(shell()->web_contents())->
913 GetFrameTree()->root();
914 TestNavigationObserver observer(shell()->web_contents());
916 ASSERT_EQ(2U, root->child_count());
918 GURL site_b_url(
919 embedded_test_server()->GetURL(
920 "bar.com", "/frame_tree/page_with_one_frame.html"));
921 // We can't use a TestNavigationObserver to verify the URL here,
922 // since the frame has children that may have clobbered it in the observer.
923 EXPECT_EQ(site_b_url, root->child_at(0)->current_url());
925 // Ensure that a new process is created for node2.
926 EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
927 root->child_at(0)->current_frame_host()->GetSiteInstance());
928 // Ensure that a new process is *not* created for node3.
929 EXPECT_EQ(shell()->web_contents()->GetSiteInstance(),
930 root->child_at(1)->current_frame_host()->GetSiteInstance());
932 ASSERT_EQ(1U, root->child_at(0)->child_count());
934 // Make sure node4 points to the correct cross-site-page.
935 FrameTreeNode* node4 = root->child_at(0)->child_at(0);
936 GURL site_c_url(embedded_test_server()->GetURL("baz.com", "/title1.html"));
937 EXPECT_EQ(site_c_url, node4->current_url());
939 // |site_instance_c| is expected to go away once we kill |child_process_b|
940 // below; refcount it to extend the lifetime.
941 scoped_refptr<SiteInstanceImpl> site_instance_c =
942 node4->current_frame_host()->GetSiteInstance();
944 // Initially proxies for both B and C will be present in the root.
945 EXPECT_EQ(
946 " Site A ------------ proxies for B C\n"
947 " |--Site B ------- proxies for A C\n"
948 " | +--Site C -- proxies for A B\n"
949 " +--Site A ------- proxies for B C\n"
950 "Where A = http://a.com/\n"
951 " B = http://bar.com/\n"
952 " C = http://baz.com/",
953 DepictFrameTree(root));
954 // Kill process B.
955 RenderProcessHost* child_process_b =
956 root->child_at(0)->current_frame_host()->GetProcess();
957 RenderProcessHostWatcher crash_observer(
958 child_process_b, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
959 child_process_b->Shutdown(0, false);
960 crash_observer.Wait();
962 // Make sure proxy C has gone from root.
963 // Make sure proxy C has gone from node3 as well.
964 // Make sure proxy B stays around in root and node3.
965 EXPECT_EQ(
966 " Site A ------------ proxies for B\n"
967 " |--Site B ------- proxies for A\n"
968 " +--Site A ------- proxies for B\n"
969 "Where A = http://a.com/\n"
970 " B = http://bar.com/ (no process)",
971 DepictFrameTree(root));
973 EXPECT_TRUE(site_instance_c->HasOneRef());
976 // Crash a subframe and ensures its children are cleared from the FrameTree.
977 // See http://crbug.com/338508.
978 // TODO(creis): Disabled for flakiness; see http://crbug.com/405582.
979 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DISABLED_CrashSubframe) {
980 GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
981 NavigateToURL(shell(), main_url);
983 StartFrameAtDataURL();
985 // These must stay in scope with replace_host.
986 GURL::Replacements replace_host;
987 std::string foo_com("foo.com");
989 // Load cross-site page into iframe.
990 EXPECT_TRUE(NavigateIframeToURL(
991 shell()->web_contents(), "test",
992 embedded_test_server()->GetURL("/cross-site/foo.com/title2.html")));
994 // Check the subframe process.
995 FrameTreeNode* root =
996 static_cast<WebContentsImpl*>(shell()->web_contents())->
997 GetFrameTree()->root();
998 ASSERT_EQ(2U, root->child_count());
999 FrameTreeNode* child = root->child_at(0);
1000 EXPECT_EQ(main_url, root->current_url());
1001 EXPECT_EQ("foo.com", child->current_url().host());
1002 EXPECT_EQ("/title2.html", child->current_url().path());
1004 EXPECT_TRUE(
1005 child->current_frame_host()->render_view_host()->IsRenderViewLive());
1006 EXPECT_TRUE(child->current_frame_host()->IsRenderFrameLive());
1008 // Crash the subframe process.
1009 RenderProcessHost* root_process = root->current_frame_host()->GetProcess();
1010 RenderProcessHost* child_process = child->current_frame_host()->GetProcess();
1012 RenderProcessHostWatcher crash_observer(
1013 child_process,
1014 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
1015 child_process->Shutdown(0, false);
1016 crash_observer.Wait();
1019 // Ensure that the child frame still exists but has been cleared.
1020 EXPECT_EQ(2U, root->child_count());
1021 EXPECT_EQ(main_url, root->current_url());
1022 EXPECT_EQ(GURL(), child->current_url());
1024 EXPECT_FALSE(
1025 child->current_frame_host()->render_view_host()->IsRenderViewLive());
1026 EXPECT_FALSE(child->current_frame_host()->IsRenderFrameLive());
1027 EXPECT_FALSE(child->current_frame_host()->render_frame_created_);
1029 // Now crash the top-level page to clear the child frame.
1031 RenderProcessHostWatcher crash_observer(
1032 root_process,
1033 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
1034 root_process->Shutdown(0, false);
1035 crash_observer.Wait();
1037 EXPECT_EQ(0U, root->child_count());
1038 EXPECT_EQ(GURL(), root->current_url());
1041 // When a new subframe is added, related SiteInstances that can reach the
1042 // subframe should create proxies for it (https://crbug.com/423587). This test
1043 // checks that if A embeds B and later adds a new subframe A2, A2 gets a proxy
1044 // in B's process.
1045 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CreateProxiesForNewFrames) {
1046 GURL main_url(embedded_test_server()->GetURL(
1047 "b.com", "/frame_tree/page_with_one_frame.html"));
1048 EXPECT_TRUE(NavigateToURL(shell(), main_url));
1050 // It is safe to obtain the root frame tree node here, as it doesn't change.
1051 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
1052 ->GetFrameTree()
1053 ->root();
1054 ASSERT_EQ(1U, root->child_count());
1056 // Make sure the frame starts out at the correct cross-site URL.
1057 EXPECT_EQ(embedded_test_server()->GetURL("baz.com", "/title1.html"),
1058 root->child_at(0)->current_url());
1060 EXPECT_EQ(
1061 " Site A ------------ proxies for B\n"
1062 " +--Site B ------- proxies for A\n"
1063 "Where A = http://b.com/\n"
1064 " B = http://baz.com/",
1065 DepictFrameTree(root));
1067 // Add a new child frame to the top-level frame.
1068 RenderFrameHostCreatedObserver frame_observer(shell()->web_contents(), 1);
1069 EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
1070 "window.domAutomationController.send("
1071 " addFrame('data:text/html,foo'));"));
1072 frame_observer.Wait();
1074 // The new frame should have a proxy in Site B, for use by the old frame.
1075 EXPECT_EQ(
1076 " Site A ------------ proxies for B\n"
1077 " |--Site B ------- proxies for A\n"
1078 " +--Site A ------- proxies for B\n"
1079 "Where A = http://b.com/\n"
1080 " B = http://baz.com/",
1081 DepictFrameTree(root));
1084 // TODO(nasko): Disable this test until out-of-process iframes is ready and the
1085 // security checks are back in place.
1086 // TODO(creis): Replace SpawnedTestServer with host_resolver to get test to run
1087 // on Android (http://crbug.com/187570).
1088 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
1089 DISABLED_CrossSiteIframeRedirectOnce) {
1090 ASSERT_TRUE(test_server()->Start());
1091 net::SpawnedTestServer https_server(
1092 net::SpawnedTestServer::TYPE_HTTPS,
1093 net::SpawnedTestServer::kLocalhost,
1094 base::FilePath(FILE_PATH_LITERAL("content/test/data")));
1095 ASSERT_TRUE(https_server.Start());
1097 GURL main_url(test_server()->GetURL("files/site_per_process_main.html"));
1098 GURL http_url(test_server()->GetURL("files/title1.html"));
1099 GURL https_url(https_server.GetURL("files/title1.html"));
1101 NavigateToURL(shell(), main_url);
1103 TestNavigationObserver observer(shell()->web_contents());
1105 // Load cross-site client-redirect page into Iframe.
1106 // Should be blocked.
1107 GURL client_redirect_https_url(https_server.GetURL(
1108 "client-redirect?files/title1.html"));
1109 EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test",
1110 client_redirect_https_url));
1111 // DidFailProvisionalLoad when navigating to client_redirect_https_url.
1112 EXPECT_EQ(observer.last_navigation_url(), client_redirect_https_url);
1113 EXPECT_FALSE(observer.last_navigation_succeeded());
1117 // Load cross-site server-redirect page into Iframe,
1118 // which redirects to same-site page.
1119 GURL server_redirect_http_url(https_server.GetURL(
1120 "server-redirect?" + http_url.spec()));
1121 EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test",
1122 server_redirect_http_url));
1123 EXPECT_EQ(observer.last_navigation_url(), http_url);
1124 EXPECT_TRUE(observer.last_navigation_succeeded());
1128 // Load cross-site server-redirect page into Iframe,
1129 // which redirects to cross-site page.
1130 GURL server_redirect_http_url(https_server.GetURL(
1131 "server-redirect?files/title1.html"));
1132 EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test",
1133 server_redirect_http_url));
1134 // DidFailProvisionalLoad when navigating to https_url.
1135 EXPECT_EQ(observer.last_navigation_url(), https_url);
1136 EXPECT_FALSE(observer.last_navigation_succeeded());
1140 // Load same-site server-redirect page into Iframe,
1141 // which redirects to cross-site page.
1142 GURL server_redirect_http_url(test_server()->GetURL(
1143 "server-redirect?" + https_url.spec()));
1144 EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test",
1145 server_redirect_http_url));
1147 EXPECT_EQ(observer.last_navigation_url(), https_url);
1148 EXPECT_FALSE(observer.last_navigation_succeeded());
1152 // Load same-site client-redirect page into Iframe,
1153 // which redirects to cross-site page.
1154 GURL client_redirect_http_url(test_server()->GetURL(
1155 "client-redirect?" + https_url.spec()));
1157 RedirectNotificationObserver load_observer2(
1158 NOTIFICATION_LOAD_STOP,
1159 Source<NavigationController>(
1160 &shell()->web_contents()->GetController()));
1162 EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test",
1163 client_redirect_http_url));
1165 // Same-site Client-Redirect Page should be loaded successfully.
1166 EXPECT_EQ(observer.last_navigation_url(), client_redirect_http_url);
1167 EXPECT_TRUE(observer.last_navigation_succeeded());
1169 // Redirecting to Cross-site Page should be blocked.
1170 load_observer2.Wait();
1171 EXPECT_EQ(observer.last_navigation_url(), https_url);
1172 EXPECT_FALSE(observer.last_navigation_succeeded());
1176 // Load same-site server-redirect page into Iframe,
1177 // which redirects to same-site page.
1178 GURL server_redirect_http_url(test_server()->GetURL(
1179 "server-redirect?files/title1.html"));
1180 EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test",
1181 server_redirect_http_url));
1182 EXPECT_EQ(observer.last_navigation_url(), http_url);
1183 EXPECT_TRUE(observer.last_navigation_succeeded());
1187 // Load same-site client-redirect page into Iframe,
1188 // which redirects to same-site page.
1189 GURL client_redirect_http_url(test_server()->GetURL(
1190 "client-redirect?" + http_url.spec()));
1191 RedirectNotificationObserver load_observer2(
1192 NOTIFICATION_LOAD_STOP,
1193 Source<NavigationController>(
1194 &shell()->web_contents()->GetController()));
1196 EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test",
1197 client_redirect_http_url));
1199 // Same-site Client-Redirect Page should be loaded successfully.
1200 EXPECT_EQ(observer.last_navigation_url(), client_redirect_http_url);
1201 EXPECT_TRUE(observer.last_navigation_succeeded());
1203 // Redirecting to Same-site Page should be loaded successfully.
1204 load_observer2.Wait();
1205 EXPECT_EQ(observer.last_navigation_url(), http_url);
1206 EXPECT_TRUE(observer.last_navigation_succeeded());
1210 // TODO(nasko): Disable this test until out-of-process iframes is ready and the
1211 // security checks are back in place.
1212 // TODO(creis): Replace SpawnedTestServer with host_resolver to get test to run
1213 // on Android (http://crbug.com/187570).
1214 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
1215 DISABLED_CrossSiteIframeRedirectTwice) {
1216 ASSERT_TRUE(test_server()->Start());
1217 net::SpawnedTestServer https_server(
1218 net::SpawnedTestServer::TYPE_HTTPS,
1219 net::SpawnedTestServer::kLocalhost,
1220 base::FilePath(FILE_PATH_LITERAL("content/test/data")));
1221 ASSERT_TRUE(https_server.Start());
1223 GURL main_url(test_server()->GetURL("files/site_per_process_main.html"));
1224 GURL http_url(test_server()->GetURL("files/title1.html"));
1225 GURL https_url(https_server.GetURL("files/title1.html"));
1227 NavigateToURL(shell(), main_url);
1229 TestNavigationObserver observer(shell()->web_contents());
1231 // Load client-redirect page pointing to a cross-site client-redirect page,
1232 // which eventually redirects back to same-site page.
1233 GURL client_redirect_https_url(https_server.GetURL(
1234 "client-redirect?" + http_url.spec()));
1235 GURL client_redirect_http_url(test_server()->GetURL(
1236 "client-redirect?" + client_redirect_https_url.spec()));
1238 // We should wait until second client redirect get cancelled.
1239 RedirectNotificationObserver load_observer2(
1240 NOTIFICATION_LOAD_STOP,
1241 Source<NavigationController>(
1242 &shell()->web_contents()->GetController()));
1244 EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test",
1245 client_redirect_http_url));
1247 // DidFailProvisionalLoad when navigating to client_redirect_https_url.
1248 load_observer2.Wait();
1249 EXPECT_EQ(observer.last_navigation_url(), client_redirect_https_url);
1250 EXPECT_FALSE(observer.last_navigation_succeeded());
1254 // Load server-redirect page pointing to a cross-site server-redirect page,
1255 // which eventually redirect back to same-site page.
1256 GURL server_redirect_https_url(https_server.GetURL(
1257 "server-redirect?" + http_url.spec()));
1258 GURL server_redirect_http_url(test_server()->GetURL(
1259 "server-redirect?" + server_redirect_https_url.spec()));
1260 EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test",
1261 server_redirect_http_url));
1262 EXPECT_EQ(observer.last_navigation_url(), http_url);
1263 EXPECT_TRUE(observer.last_navigation_succeeded());
1267 // Load server-redirect page pointing to a cross-site server-redirect page,
1268 // which eventually redirects back to cross-site page.
1269 GURL server_redirect_https_url(https_server.GetURL(
1270 "server-redirect?" + https_url.spec()));
1271 GURL server_redirect_http_url(test_server()->GetURL(
1272 "server-redirect?" + server_redirect_https_url.spec()));
1273 EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test",
1274 server_redirect_http_url));
1276 // DidFailProvisionalLoad when navigating to https_url.
1277 EXPECT_EQ(observer.last_navigation_url(), https_url);
1278 EXPECT_FALSE(observer.last_navigation_succeeded());
1282 // Load server-redirect page pointing to a cross-site client-redirect page,
1283 // which eventually redirects back to same-site page.
1284 GURL client_redirect_http_url(https_server.GetURL(
1285 "client-redirect?" + http_url.spec()));
1286 GURL server_redirect_http_url(test_server()->GetURL(
1287 "server-redirect?" + client_redirect_http_url.spec()));
1288 EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test",
1289 server_redirect_http_url));
1291 // DidFailProvisionalLoad when navigating to client_redirect_http_url.
1292 EXPECT_EQ(observer.last_navigation_url(), client_redirect_http_url);
1293 EXPECT_FALSE(observer.last_navigation_succeeded());
1297 // Ensure that when navigating a frame cross-process RenderFrameProxyHosts are
1298 // created in the FrameTree skipping the subtree of the navigating frame.
1299 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
1300 ProxyCreationSkipsSubtree) {
1301 GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
1302 NavigateToURL(shell(), main_url);
1304 // It is safe to obtain the root frame tree node here, as it doesn't change.
1305 FrameTreeNode* root =
1306 static_cast<WebContentsImpl*>(shell()->web_contents())->
1307 GetFrameTree()->root();
1309 EXPECT_TRUE(root->child_at(1) != NULL);
1310 EXPECT_EQ(2U, root->child_at(1)->child_count());
1313 // Load same-site page into iframe.
1314 TestNavigationObserver observer(shell()->web_contents());
1315 GURL http_url(embedded_test_server()->GetURL("/title1.html"));
1316 NavigateFrameToURL(root->child_at(0), http_url);
1317 EXPECT_EQ(http_url, observer.last_navigation_url());
1318 EXPECT_TRUE(observer.last_navigation_succeeded());
1319 EXPECT_EQ(
1320 " Site A\n"
1321 " |--Site A\n"
1322 " +--Site A\n"
1323 " |--Site A\n"
1324 " +--Site A\n"
1325 " +--Site A\n"
1326 "Where A = http://127.0.0.1/",
1327 DepictFrameTree(root));
1330 // Create the cross-site URL to navigate to.
1331 GURL cross_site_url =
1332 embedded_test_server()->GetURL("foo.com", "/frame_tree/1-1.html");
1334 // Load cross-site page into the second iframe without waiting for the
1335 // navigation to complete. Once LoadURLWithParams returns, we would expect
1336 // proxies to have been created in the frame tree, but children of the
1337 // navigating frame to still be present. The reason is that we don't run the
1338 // message loop, so no IPCs that alter the frame tree can be processed.
1339 FrameTreeNode* child = root->child_at(1);
1340 SiteInstance* site = NULL;
1342 TestNavigationObserver observer(shell()->web_contents());
1343 TestFrameNavigationObserver navigation_observer(child);
1344 NavigationController::LoadURLParams params(cross_site_url);
1345 params.transition_type = PageTransitionFromInt(ui::PAGE_TRANSITION_LINK);
1346 params.frame_tree_node_id = child->frame_tree_node_id();
1347 child->navigator()->GetController()->LoadURLWithParams(params);
1349 site = child->render_manager()->pending_frame_host()->GetSiteInstance();
1350 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), site);
1352 EXPECT_EQ(
1353 " Site A ------------ proxies for B\n"
1354 " |--Site A ------- proxies for B\n"
1355 " +--Site A (B pending)\n"
1356 " |--Site A\n"
1357 " +--Site A\n"
1358 " +--Site A\n"
1359 "Where A = http://127.0.0.1/\n"
1360 " B = http://foo.com/",
1361 DepictFrameTree(root));
1363 // Now that the verification is done, run the message loop and wait for the
1364 // navigation to complete.
1365 navigation_observer.Wait();
1366 EXPECT_FALSE(child->render_manager()->pending_frame_host());
1367 EXPECT_TRUE(observer.last_navigation_succeeded());
1368 EXPECT_EQ(cross_site_url, observer.last_navigation_url());
1370 EXPECT_EQ(
1371 " Site A ------------ proxies for B\n"
1372 " |--Site A ------- proxies for B\n"
1373 " +--Site B ------- proxies for A\n"
1374 "Where A = http://127.0.0.1/\n"
1375 " B = http://foo.com/",
1376 DepictFrameTree(root));
1379 // Load another cross-site page into the same iframe.
1380 cross_site_url = embedded_test_server()->GetURL("bar.com", "/title2.html");
1382 // Perform the same checks as the first cross-site navigation, since
1383 // there have been issues in subsequent cross-site navigations. Also ensure
1384 // that the SiteInstance has properly changed.
1385 // TODO(nasko): Once we have proper cleanup of resources, add code to
1386 // verify that the intermediate SiteInstance/RenderFrameHost have been
1387 // properly cleaned up.
1388 TestNavigationObserver observer(shell()->web_contents());
1389 TestFrameNavigationObserver navigation_observer(child);
1390 NavigationController::LoadURLParams params(cross_site_url);
1391 params.transition_type = PageTransitionFromInt(ui::PAGE_TRANSITION_LINK);
1392 params.frame_tree_node_id = child->frame_tree_node_id();
1393 child->navigator()->GetController()->LoadURLWithParams(params);
1395 SiteInstance* site2 =
1396 child->render_manager()->pending_frame_host()->GetSiteInstance();
1397 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), site2);
1398 EXPECT_NE(site, site2);
1400 EXPECT_EQ(
1401 " Site A ------------ proxies for B C\n"
1402 " |--Site A ------- proxies for B C\n"
1403 " +--Site B (C pending) -- proxies for A\n"
1404 "Where A = http://127.0.0.1/\n"
1405 " B = http://foo.com/\n"
1406 " C = http://bar.com/",
1407 DepictFrameTree(root));
1409 navigation_observer.Wait();
1410 EXPECT_TRUE(observer.last_navigation_succeeded());
1411 EXPECT_EQ(cross_site_url, observer.last_navigation_url());
1412 EXPECT_EQ(0U, child->child_count());
1416 // Verify that origin replication works for an A-embed-B-embed-C hierarchy.
1417 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, OriginReplication) {
1418 GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
1419 EXPECT_TRUE(NavigateToURL(shell(), main_url));
1421 // It is safe to obtain the root frame tree node here, as it doesn't change.
1422 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
1423 ->GetFrameTree()
1424 ->root();
1426 TestNavigationObserver observer(shell()->web_contents());
1428 // Navigate the first subframe to a cross-site page with two subframes.
1429 // NavigateFrameToURL can't be used here because it doesn't guarantee that
1430 // FrameTreeNodes will have been created for child frames when it returns.
1431 RenderFrameHostCreatedObserver frame_observer(shell()->web_contents(), 4);
1432 GURL foo_url(
1433 embedded_test_server()->GetURL("foo.com", "/frame_tree/1-1.html"));
1434 NavigationController::LoadURLParams params(foo_url);
1435 params.transition_type = ui::PAGE_TRANSITION_LINK;
1436 params.frame_tree_node_id = root->child_at(0)->frame_tree_node_id();
1437 root->child_at(0)->navigator()->GetController()->LoadURLWithParams(params);
1438 frame_observer.Wait();
1440 // We can't use a TestNavigationObserver to verify the URL here,
1441 // since the frame has children that may have clobbered it in the observer.
1442 EXPECT_EQ(foo_url, root->child_at(0)->current_url());
1444 // Ensure that a new process is created for the subframe.
1445 EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
1446 root->child_at(0)->current_frame_host()->GetSiteInstance());
1448 // Load cross-site page into subframe's subframe.
1449 ASSERT_EQ(2U, root->child_at(0)->child_count());
1450 GURL bar_url(embedded_test_server()->GetURL("bar.com", "/title1.html"));
1451 NavigateFrameToURL(root->child_at(0)->child_at(0), bar_url);
1452 EXPECT_TRUE(observer.last_navigation_succeeded());
1453 EXPECT_EQ(bar_url, observer.last_navigation_url());
1455 // Check that a new process is created and is different from the top one and
1456 // the middle one.
1457 FrameTreeNode* bottom_child = root->child_at(0)->child_at(0);
1458 EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
1459 bottom_child->current_frame_host()->GetSiteInstance());
1460 EXPECT_NE(root->child_at(0)->current_frame_host()->GetSiteInstance(),
1461 bottom_child->current_frame_host()->GetSiteInstance());
1463 // Check that foo.com frame's location.ancestorOrigins contains the correct
1464 // origin for the parent. The origin should have been replicated as part of
1465 // the ViewMsg_New message that created the parent's RenderFrameProxy in
1466 // foo.com's process.
1467 int ancestor_origins_length = 0;
1468 EXPECT_TRUE(ExecuteScriptAndExtractInt(
1469 root->child_at(0)->current_frame_host(),
1470 "window.domAutomationController.send(location.ancestorOrigins.length);",
1471 &ancestor_origins_length));
1472 EXPECT_EQ(1, ancestor_origins_length);
1473 std::string result;
1474 EXPECT_TRUE(ExecuteScriptAndExtractString(
1475 root->child_at(0)->current_frame_host(),
1476 "window.domAutomationController.send(location.ancestorOrigins[0]);",
1477 &result));
1478 EXPECT_EQ(result + "/", main_url.GetOrigin().spec());
1480 // Check that bar.com frame's location.ancestorOrigins contains the correct
1481 // origin for its two ancestors. The topmost parent origin should be
1482 // replicated as part of ViewMsg_New, and the middle frame (foo.com's) origin
1483 // should be replicated as part of FrameMsg_NewFrameProxy sent for foo.com's
1484 // frame in bar.com's process.
1485 EXPECT_TRUE(ExecuteScriptAndExtractInt(
1486 bottom_child->current_frame_host(),
1487 "window.domAutomationController.send(location.ancestorOrigins.length);",
1488 &ancestor_origins_length));
1489 EXPECT_EQ(2, ancestor_origins_length);
1490 EXPECT_TRUE(ExecuteScriptAndExtractString(
1491 bottom_child->current_frame_host(),
1492 "window.domAutomationController.send(location.ancestorOrigins[0]);",
1493 &result));
1494 EXPECT_EQ(result + "/", foo_url.GetOrigin().spec());
1495 EXPECT_TRUE(ExecuteScriptAndExtractString(
1496 bottom_child->current_frame_host(),
1497 "window.domAutomationController.send(location.ancestorOrigins[1]);",
1498 &result));
1499 EXPECT_EQ(result + "/", main_url.GetOrigin().spec());
1502 // Check that iframe sandbox flags are replicated correctly.
1503 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, SandboxFlagsReplication) {
1504 GURL main_url(embedded_test_server()->GetURL("/sandboxed_frames.html"));
1505 EXPECT_TRUE(NavigateToURL(shell(), main_url));
1507 // It is safe to obtain the root frame tree node here, as it doesn't change.
1508 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
1509 ->GetFrameTree()
1510 ->root();
1512 TestNavigationObserver observer(shell()->web_contents());
1514 // Navigate the second (sandboxed) subframe to a cross-site page with a
1515 // subframe. Use RenderFrameHostCreatedObserver to guarantee that all
1516 // FrameTreeNodes are created for child frames.
1517 RenderFrameHostCreatedObserver frame_observer(shell()->web_contents(), 4);
1518 GURL foo_url(
1519 embedded_test_server()->GetURL("foo.com", "/frame_tree/1-1.html"));
1520 NavigateFrameToURL(root->child_at(1), foo_url);
1521 frame_observer.Wait();
1523 // We can't use a TestNavigationObserver to verify the URL here,
1524 // since the frame has children that may have clobbered it in the observer.
1525 EXPECT_EQ(foo_url, root->child_at(1)->current_url());
1527 // Load cross-site page into subframe's subframe.
1528 ASSERT_EQ(2U, root->child_at(1)->child_count());
1529 GURL bar_url(embedded_test_server()->GetURL("bar.com", "/title1.html"));
1530 NavigateFrameToURL(root->child_at(1)->child_at(0), bar_url);
1531 EXPECT_TRUE(observer.last_navigation_succeeded());
1532 EXPECT_EQ(bar_url, observer.last_navigation_url());
1534 // Opening a popup in the sandboxed foo.com iframe should fail.
1535 bool success = false;
1536 EXPECT_TRUE(
1537 ExecuteScriptAndExtractBool(root->child_at(1)->current_frame_host(),
1538 "window.domAutomationController.send("
1539 "!window.open('data:text/html,dataurl'));",
1540 &success));
1541 EXPECT_TRUE(success);
1542 EXPECT_EQ(1u, Shell::windows().size());
1544 // Opening a popup in a frame whose parent is sandboxed should also fail.
1545 // Here, bar.com frame's sandboxed parent frame is a remote frame in
1546 // bar.com's process.
1547 success = false;
1548 EXPECT_TRUE(ExecuteScriptAndExtractBool(
1549 root->child_at(1)->child_at(0)->current_frame_host(),
1550 "window.domAutomationController.send("
1551 "!window.open('data:text/html,dataurl'));",
1552 &success));
1553 EXPECT_TRUE(success);
1554 EXPECT_EQ(1u, Shell::windows().size());
1556 // Same, but now try the case where bar.com frame's sandboxed parent is a
1557 // local frame in bar.com's process.
1558 success = false;
1559 EXPECT_TRUE(ExecuteScriptAndExtractBool(
1560 root->child_at(2)->child_at(0)->current_frame_host(),
1561 "window.domAutomationController.send("
1562 "!window.open('data:text/html,dataurl'));",
1563 &success));
1564 EXPECT_TRUE(success);
1565 EXPECT_EQ(1u, Shell::windows().size());
1567 // Check that foo.com frame's location.ancestorOrigins contains the correct
1568 // origin for the parent, which should be unaffected by sandboxing.
1569 int ancestor_origins_length = 0;
1570 EXPECT_TRUE(ExecuteScriptAndExtractInt(
1571 root->child_at(1)->current_frame_host(),
1572 "window.domAutomationController.send(location.ancestorOrigins.length);",
1573 &ancestor_origins_length));
1574 EXPECT_EQ(1, ancestor_origins_length);
1575 std::string result;
1576 EXPECT_TRUE(ExecuteScriptAndExtractString(
1577 root->child_at(1)->current_frame_host(),
1578 "window.domAutomationController.send(location.ancestorOrigins[0]);",
1579 &result));
1580 EXPECT_EQ(result + "/", main_url.GetOrigin().spec());
1582 // Now check location.ancestorOrigins for the bar.com frame. The middle frame
1583 // (foo.com's) origin should be unique, since that frame is sandboxed, and
1584 // the top frame should match |main_url|.
1585 FrameTreeNode* bottom_child = root->child_at(1)->child_at(0);
1586 EXPECT_TRUE(ExecuteScriptAndExtractInt(
1587 bottom_child->current_frame_host(),
1588 "window.domAutomationController.send(location.ancestorOrigins.length);",
1589 &ancestor_origins_length));
1590 EXPECT_EQ(2, ancestor_origins_length);
1591 EXPECT_TRUE(ExecuteScriptAndExtractString(
1592 bottom_child->current_frame_host(),
1593 "window.domAutomationController.send(location.ancestorOrigins[0]);",
1594 &result));
1595 EXPECT_EQ("null", result);
1596 EXPECT_TRUE(ExecuteScriptAndExtractString(
1597 bottom_child->current_frame_host(),
1598 "window.domAutomationController.send(location.ancestorOrigins[1]);",
1599 &result));
1600 EXPECT_EQ(main_url.GetOrigin().spec(), result + "/");
1603 // Check that dynamic updates to iframe sandbox flags are propagated correctly.
1604 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DynamicSandboxFlags) {
1605 GURL main_url(
1606 embedded_test_server()->GetURL("/frame_tree/page_with_two_frames.html"));
1607 EXPECT_TRUE(NavigateToURL(shell(), main_url));
1609 // It is safe to obtain the root frame tree node here, as it doesn't change.
1610 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
1611 ->GetFrameTree()
1612 ->root();
1614 TestNavigationObserver observer(shell()->web_contents());
1615 ASSERT_EQ(2U, root->child_count());
1617 // Make sure first frame starts out at the correct cross-site page.
1618 EXPECT_EQ(embedded_test_server()->GetURL("bar.com", "/title1.html"),
1619 root->child_at(0)->current_url());
1621 // Navigate second frame to another cross-site page.
1622 GURL baz_url(embedded_test_server()->GetURL("baz.com", "/title1.html"));
1623 NavigateFrameToURL(root->child_at(1), baz_url);
1624 EXPECT_TRUE(observer.last_navigation_succeeded());
1625 EXPECT_EQ(baz_url, observer.last_navigation_url());
1627 // Both frames should not be sandboxed to start with.
1628 EXPECT_EQ(SandboxFlags::NONE,
1629 root->child_at(0)->current_replication_state().sandbox_flags);
1630 EXPECT_EQ(SandboxFlags::NONE, root->child_at(0)->effective_sandbox_flags());
1631 EXPECT_EQ(SandboxFlags::NONE,
1632 root->child_at(1)->current_replication_state().sandbox_flags);
1633 EXPECT_EQ(SandboxFlags::NONE, root->child_at(1)->effective_sandbox_flags());
1635 // Dynamically update sandbox flags for the first frame.
1636 EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
1637 "window.domAutomationController.send("
1638 "document.querySelector('iframe').sandbox="
1639 "'allow-scripts');"));
1641 // Check that updated sandbox flags are propagated to browser process.
1642 // The new flags should be set in current_replication_state(), while
1643 // effective_sandbox_flags() should still reflect the old flags, because
1644 // sandbox flag updates take place only after navigations. "allow-scripts"
1645 // resets both SandboxFlags::Scripts and SandboxFlags::AutomaticFeatures bits
1646 // per blink::parseSandboxPolicy().
1647 SandboxFlags expected_flags = SandboxFlags::ALL & ~SandboxFlags::SCRIPTS &
1648 ~SandboxFlags::AUTOMATIC_FEATURES;
1649 EXPECT_EQ(expected_flags,
1650 root->child_at(0)->current_replication_state().sandbox_flags);
1651 EXPECT_EQ(SandboxFlags::NONE, root->child_at(0)->effective_sandbox_flags());
1653 // Navigate the first frame to a page on the same site. The new sandbox
1654 // flags should take effect. The new page has a child frame, so use
1655 // TestFrameNavigationObserver to wait for it to be loaded.
1656 TestFrameNavigationObserver frame_observer(root->child_at(0), 2);
1657 GURL bar_url(
1658 embedded_test_server()->GetURL("bar.com", "/frame_tree/2-4.html"));
1659 NavigateFrameToURL(root->child_at(0), bar_url);
1660 frame_observer.Wait();
1661 EXPECT_EQ(bar_url, root->child_at(0)->current_url());
1662 ASSERT_EQ(1U, root->child_at(0)->child_count());
1664 // Confirm that the browser process has updated the frame's current sandbox
1665 // flags.
1666 EXPECT_EQ(expected_flags,
1667 root->child_at(0)->current_replication_state().sandbox_flags);
1668 EXPECT_EQ(expected_flags, root->child_at(0)->effective_sandbox_flags());
1670 // Opening a popup in the now-sandboxed frame should fail.
1671 bool success = false;
1672 EXPECT_TRUE(
1673 ExecuteScriptAndExtractBool(root->child_at(0)->current_frame_host(),
1674 "window.domAutomationController.send("
1675 "!window.open('data:text/html,dataurl'));",
1676 &success));
1677 EXPECT_TRUE(success);
1678 EXPECT_EQ(1u, Shell::windows().size());
1680 // Navigate the child of the now-sandboxed frame to a page on baz.com. The
1681 // child should inherit the latest sandbox flags from its parent frame, which
1682 // is currently a proxy in baz.com's renderer process. This checks that the
1683 // proxies of |root->child_at(0)| were also updated with the latest sandbox
1684 // flags.
1685 GURL baz_child_url(embedded_test_server()->GetURL("baz.com", "/title2.html"));
1686 NavigateFrameToURL(root->child_at(0)->child_at(0), baz_child_url);
1687 EXPECT_TRUE(observer.last_navigation_succeeded());
1688 EXPECT_EQ(baz_child_url, observer.last_navigation_url());
1690 // Opening a popup in the child of a sandboxed frame should fail.
1691 success = false;
1692 EXPECT_TRUE(ExecuteScriptAndExtractBool(
1693 root->child_at(0)->child_at(0)->current_frame_host(),
1694 "window.domAutomationController.send("
1695 "!window.open('data:text/html,dataurl'));",
1696 &success));
1697 EXPECT_TRUE(success);
1698 EXPECT_EQ(1u, Shell::windows().size());
1701 // Check that dynamic updates to iframe sandbox flags are propagated correctly.
1702 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
1703 DynamicSandboxFlagsRemoteToLocal) {
1704 GURL main_url(
1705 embedded_test_server()->GetURL("/frame_tree/page_with_two_frames.html"));
1706 EXPECT_TRUE(NavigateToURL(shell(), main_url));
1708 // It is safe to obtain the root frame tree node here, as it doesn't change.
1709 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
1710 ->GetFrameTree()
1711 ->root();
1713 TestNavigationObserver observer(shell()->web_contents());
1714 ASSERT_EQ(2U, root->child_count());
1716 // Make sure the two frames starts out at correct URLs.
1717 EXPECT_EQ(embedded_test_server()->GetURL("bar.com", "/title1.html"),
1718 root->child_at(0)->current_url());
1719 EXPECT_EQ(embedded_test_server()->GetURL("/title1.html"),
1720 root->child_at(1)->current_url());
1722 // Update the second frame's sandbox flags.
1723 EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
1724 "window.domAutomationController.send("
1725 "document.querySelectorAll('iframe')[1].sandbox="
1726 "'allow-scripts');"));
1728 // Check that the current sandbox flags are updated but the effective
1729 // sandbox flags are not.
1730 SandboxFlags expected_flags = SandboxFlags::ALL & ~SandboxFlags::SCRIPTS &
1731 ~SandboxFlags::AUTOMATIC_FEATURES;
1732 EXPECT_EQ(expected_flags,
1733 root->child_at(1)->current_replication_state().sandbox_flags);
1734 EXPECT_EQ(SandboxFlags::NONE, root->child_at(1)->effective_sandbox_flags());
1736 // Navigate the second subframe to a page on bar.com. This will trigger a
1737 // remote-to-local frame swap in bar.com's process. The target page has
1738 // another frame, so use TestFrameNavigationObserver to wait for all frames
1739 // to be loaded.
1740 TestFrameNavigationObserver frame_observer(root->child_at(1), 2);
1741 GURL bar_url(embedded_test_server()->GetURL(
1742 "bar.com", "/frame_tree/page_with_one_frame.html"));
1743 NavigateFrameToURL(root->child_at(1), bar_url);
1744 frame_observer.Wait();
1745 EXPECT_EQ(bar_url, root->child_at(1)->current_url());
1746 ASSERT_EQ(1U, root->child_at(1)->child_count());
1748 // Confirm that the browser process has updated the current sandbox flags.
1749 EXPECT_EQ(expected_flags,
1750 root->child_at(1)->current_replication_state().sandbox_flags);
1751 EXPECT_EQ(expected_flags, root->child_at(1)->effective_sandbox_flags());
1753 // Opening a popup in the sandboxed second frame should fail.
1754 bool success = false;
1755 EXPECT_TRUE(
1756 ExecuteScriptAndExtractBool(root->child_at(1)->current_frame_host(),
1757 "window.domAutomationController.send("
1758 "!window.open('data:text/html,dataurl'));",
1759 &success));
1760 EXPECT_TRUE(success);
1761 EXPECT_EQ(1u, Shell::windows().size());
1763 // Make sure that the child frame inherits the sandbox flags of its
1764 // now-sandboxed parent frame.
1765 success = false;
1766 EXPECT_TRUE(ExecuteScriptAndExtractBool(
1767 root->child_at(1)->child_at(0)->current_frame_host(),
1768 "window.domAutomationController.send("
1769 "!window.open('data:text/html,dataurl'));",
1770 &success));
1771 EXPECT_TRUE(success);
1772 EXPECT_EQ(1u, Shell::windows().size());
1775 // Check that dynamic updates to iframe sandbox flags are propagated correctly.
1776 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
1777 DynamicSandboxFlagsRendererInitiatedNavigation) {
1778 GURL main_url(
1779 embedded_test_server()->GetURL("/frame_tree/page_with_one_frame.html"));
1780 EXPECT_TRUE(NavigateToURL(shell(), main_url));
1782 // It is safe to obtain the root frame tree node here, as it doesn't change.
1783 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
1784 ->GetFrameTree()
1785 ->root();
1787 TestNavigationObserver observer(shell()->web_contents());
1788 ASSERT_EQ(1U, root->child_count());
1790 // Make sure the frame starts out at the correct cross-site page.
1791 EXPECT_EQ(embedded_test_server()->GetURL("baz.com", "/title1.html"),
1792 root->child_at(0)->current_url());
1794 // The frame should not be sandboxed to start with.
1795 EXPECT_EQ(SandboxFlags::NONE,
1796 root->child_at(0)->current_replication_state().sandbox_flags);
1797 EXPECT_EQ(SandboxFlags::NONE, root->child_at(0)->effective_sandbox_flags());
1799 // Dynamically update the frame's sandbox flags.
1800 EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
1801 "window.domAutomationController.send("
1802 "document.querySelector('iframe').sandbox="
1803 "'allow-scripts');"));
1805 // Check that updated sandbox flags are propagated to browser process.
1806 // The new flags should be set in current_replication_state(), while
1807 // effective_sandbox_flags() should still reflect the old flags, because
1808 // sandbox flag updates take place only after navigations. "allow-scripts"
1809 // resets both SandboxFlags::Scripts and SandboxFlags::AutomaticFeatures bits
1810 // per blink::parseSandboxPolicy().
1811 SandboxFlags expected_flags = SandboxFlags::ALL & ~SandboxFlags::SCRIPTS &
1812 ~SandboxFlags::AUTOMATIC_FEATURES;
1813 EXPECT_EQ(expected_flags,
1814 root->child_at(0)->current_replication_state().sandbox_flags);
1815 EXPECT_EQ(SandboxFlags::NONE, root->child_at(0)->effective_sandbox_flags());
1817 // Perform a renderer-initiated same-site navigation in the first frame. The
1818 // new sandbox flags should take effect.
1819 TestFrameNavigationObserver frame_observer(root->child_at(0));
1820 ASSERT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(),
1821 "window.location.href='/title2.html'"));
1822 frame_observer.Wait();
1823 EXPECT_EQ(embedded_test_server()->GetURL("baz.com", "/title2.html"),
1824 root->child_at(0)->current_url());
1826 // Confirm that the browser process has updated the frame's current sandbox
1827 // flags.
1828 EXPECT_EQ(expected_flags,
1829 root->child_at(0)->current_replication_state().sandbox_flags);
1830 EXPECT_EQ(expected_flags, root->child_at(0)->effective_sandbox_flags());
1832 // Opening a popup in the now-sandboxed frame should fail.
1833 bool success = false;
1834 EXPECT_TRUE(
1835 ExecuteScriptAndExtractBool(root->child_at(0)->current_frame_host(),
1836 "window.domAutomationController.send("
1837 "!window.open('data:text/html,dataurl'));",
1838 &success));
1839 EXPECT_TRUE(success);
1840 EXPECT_EQ(1u, Shell::windows().size());
1843 // Verify that when a new child frame is added, the proxies created for it in
1844 // other SiteInstances have correct sandbox flags and origin.
1846 // A A A
1847 // / / \ / \ .
1848 // B -> B A -> B A
1849 // \ .
1850 // B
1852 // The test checks sandbox flags and origin for the proxy added in step 2, by
1853 // checking whether the grandchild frame added in step 3 sees proper sandbox
1854 // flags and origin for its (remote) parent. This wasn't addressed when
1855 // https://crbug.com/423587 was fixed.
1856 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
1857 ProxiesForNewChildFramesHaveCorrectReplicationState) {
1858 GURL main_url(
1859 embedded_test_server()->GetURL("/frame_tree/page_with_one_frame.html"));
1860 EXPECT_TRUE(NavigateToURL(shell(), main_url));
1862 // It is safe to obtain the root frame tree node here, as it doesn't change.
1863 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
1864 ->GetFrameTree()
1865 ->root();
1866 TestNavigationObserver observer(shell()->web_contents());
1868 EXPECT_EQ(
1869 " Site A ------------ proxies for B\n"
1870 " +--Site B ------- proxies for A\n"
1871 "Where A = http://127.0.0.1/\n"
1872 " B = http://baz.com/",
1873 DepictFrameTree(root));
1875 // In the root frame, add a new sandboxed local frame, which itself has a
1876 // child frame on baz.com. Wait for three RenderFrameHosts to be created:
1877 // the new sandboxed local frame, its child (while it's still local), and a
1878 // pending RFH when starting the cross-site navigation to baz.com.
1879 RenderFrameHostCreatedObserver frame_observer(shell()->web_contents(), 3);
1880 EXPECT_TRUE(
1881 ExecuteScript(root->current_frame_host(),
1882 "window.domAutomationController.send("
1883 " addFrame('/frame_tree/page_with_one_frame.html',"
1884 " 'allow-scripts allow-same-origin'))"));
1885 frame_observer.Wait();
1887 // Wait for the cross-site navigation to baz.com in the grandchild to finish.
1888 FrameTreeNode* bottom_child = root->child_at(1)->child_at(0);
1889 TestFrameNavigationObserver navigation_observer(bottom_child);
1890 navigation_observer.Wait();
1892 EXPECT_EQ(
1893 " Site A ------------ proxies for B\n"
1894 " |--Site B ------- proxies for A\n"
1895 " +--Site A ------- proxies for B\n"
1896 " +--Site B -- proxies for A\n"
1897 "Where A = http://127.0.0.1/\n"
1898 " B = http://baz.com/",
1899 DepictFrameTree(root));
1901 // Use location.ancestorOrigins to check that the grandchild on baz.com sees
1902 // correct origin for its parent.
1903 int ancestor_origins_length = 0;
1904 EXPECT_TRUE(ExecuteScriptAndExtractInt(
1905 bottom_child->current_frame_host(),
1906 "window.domAutomationController.send(location.ancestorOrigins.length);",
1907 &ancestor_origins_length));
1908 EXPECT_EQ(2, ancestor_origins_length);
1909 std::string parent_origin;
1910 EXPECT_TRUE(ExecuteScriptAndExtractString(
1911 bottom_child->current_frame_host(),
1912 "window.domAutomationController.send(location.ancestorOrigins[0]);",
1913 &parent_origin));
1914 EXPECT_EQ(main_url.GetOrigin().spec(), parent_origin + "/");
1916 // Check that the sandbox flags in the browser process are correct.
1917 // "allow-scripts" resets both SandboxFlags::Scripts and
1918 // SandboxFlags::AutomaticFeatures bits per blink::parseSandboxPolicy().
1919 SandboxFlags expected_flags = SandboxFlags::ALL & ~SandboxFlags::SCRIPTS &
1920 ~SandboxFlags::AUTOMATIC_FEATURES &
1921 ~SandboxFlags::ORIGIN;
1922 EXPECT_EQ(expected_flags,
1923 root->child_at(1)->current_replication_state().sandbox_flags);
1925 // The child of the sandboxed frame should've inherited sandbox flags, so it
1926 // should not be able to create popups.
1927 bool success = false;
1928 EXPECT_TRUE(
1929 ExecuteScriptAndExtractBool(bottom_child->current_frame_host(),
1930 "window.domAutomationController.send("
1931 "!window.open('data:text/html,dataurl'));",
1932 &success));
1933 EXPECT_TRUE(success);
1934 EXPECT_EQ(1u, Shell::windows().size());
1937 // Verify that a child frame can retrieve the name property set by its parent.
1938 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, WindowNameReplication) {
1939 GURL main_url(embedded_test_server()->GetURL("/frame_tree/2-4.html"));
1940 EXPECT_TRUE(NavigateToURL(shell(), main_url));
1942 // It is safe to obtain the root frame tree node here, as it doesn't change.
1943 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
1944 ->GetFrameTree()
1945 ->root();
1947 TestNavigationObserver observer(shell()->web_contents());
1949 // Load cross-site page into iframe.
1950 GURL frame_url =
1951 embedded_test_server()->GetURL("foo.com", "/frame_tree/3-1.html");
1952 NavigateFrameToURL(root->child_at(0), frame_url);
1953 EXPECT_TRUE(observer.last_navigation_succeeded());
1954 EXPECT_EQ(frame_url, observer.last_navigation_url());
1956 // Ensure that a new process is created for the subframe.
1957 EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
1958 root->child_at(0)->current_frame_host()->GetSiteInstance());
1960 // Check that the window.name seen by the frame matches the name attribute
1961 // specified by its parent in the iframe tag.
1962 std::string result;
1963 EXPECT_TRUE(ExecuteScriptAndExtractString(
1964 root->child_at(0)->current_frame_host(),
1965 "window.domAutomationController.send(window.name);", &result));
1966 EXPECT_EQ("3-1-name", result);
1969 // Verify that dynamic updates to a frame's window.name propagate to the
1970 // frame's proxies, so that the latest frame names can be used in navigations.
1971 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DynamicWindowName) {
1972 GURL main_url(embedded_test_server()->GetURL("/frame_tree/2-4.html"));
1973 EXPECT_TRUE(NavigateToURL(shell(), main_url));
1975 // It is safe to obtain the root frame tree node here, as it doesn't change.
1976 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
1977 ->GetFrameTree()
1978 ->root();
1979 TestNavigationObserver observer(shell()->web_contents());
1981 // Load cross-site page into iframe.
1982 GURL frame_url =
1983 embedded_test_server()->GetURL("foo.com", "/frame_tree/3-1.html");
1984 NavigateFrameToURL(root->child_at(0), frame_url);
1985 EXPECT_TRUE(observer.last_navigation_succeeded());
1986 EXPECT_EQ(frame_url, observer.last_navigation_url());
1988 // Browser process should know the child frame's original window.name
1989 // specified in the iframe element.
1990 EXPECT_EQ(root->child_at(0)->frame_name(), "3-1-name");
1992 // Update the child frame's window.name.
1993 EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(),
1994 "window.domAutomationController.send("
1995 "window.name = 'updated-name');"));
1997 // The change should propagate to the browser process.
1998 EXPECT_EQ(root->child_at(0)->frame_name(), "updated-name");
2000 // The proxy in the parent process should also receive the updated name.
2001 // Check that it can reference the child frame by its new name.
2002 bool success = false;
2003 EXPECT_TRUE(
2004 ExecuteScriptAndExtractBool(shell()->web_contents(),
2005 "window.domAutomationController.send("
2006 "frames['updated-name'] == frames[0]);",
2007 &success));
2008 EXPECT_TRUE(success);
2010 // Issue a renderer-initiated navigation from the root frame to the child
2011 // frame using the frame's name. Make sure correct frame is navigated.
2013 // TODO(alexmos): When blink::createWindow is refactored to handle
2014 // RemoteFrames, this should also be tested via window.open(url, frame_name)
2015 // and a more complicated frame hierarchy (https://crbug.com/463742)
2016 TestFrameNavigationObserver frame_observer(root->child_at(0));
2017 GURL foo_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
2018 std::string script = base::StringPrintf(
2019 "window.domAutomationController.send("
2020 "frames['updated-name'].location.href = '%s');",
2021 foo_url.spec().c_str());
2022 EXPECT_TRUE(ExecuteScript(shell()->web_contents(), script));
2023 frame_observer.Wait();
2024 EXPECT_EQ(foo_url, root->child_at(0)->current_url());
2027 // Verify that when a frame is navigated to a new origin, the origin update
2028 // propagates to the frame's proxies.
2029 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, OriginUpdatesReachProxies) {
2030 GURL main_url(
2031 embedded_test_server()->GetURL("/frame_tree/page_with_two_frames.html"));
2032 EXPECT_TRUE(NavigateToURL(shell(), main_url));
2034 // It is safe to obtain the root frame tree node here, as it doesn't change.
2035 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
2036 ->GetFrameTree()
2037 ->root();
2038 TestNavigationObserver observer(shell()->web_contents());
2040 EXPECT_EQ(
2041 " Site A ------------ proxies for B\n"
2042 " |--Site B ------- proxies for A\n"
2043 " +--Site A ------- proxies for B\n"
2044 "Where A = http://127.0.0.1/\n"
2045 " B = http://bar.com/",
2046 DepictFrameTree(root));
2048 // Navigate second subframe to a baz.com. This should send an origin update
2049 // to the frame's proxy in the bar.com (first frame's) process.
2050 GURL frame_url = embedded_test_server()->GetURL("baz.com", "/title2.html");
2051 NavigateFrameToURL(root->child_at(1), frame_url);
2052 EXPECT_TRUE(observer.last_navigation_succeeded());
2053 EXPECT_EQ(frame_url, observer.last_navigation_url());
2055 // The first frame can't directly observe the second frame's origin with
2056 // JavaScript. Instead, try to navigate the second frame from the first
2057 // frame. This should fail with a console error message, which should
2058 // contain the second frame's updated origin (see blink::Frame::canNavigate).
2059 scoped_ptr<ConsoleObserverDelegate> console_delegate(
2060 new ConsoleObserverDelegate(
2061 shell()->web_contents(),
2062 "Unsafe JavaScript attempt to initiate navigation*"));
2063 shell()->web_contents()->SetDelegate(console_delegate.get());
2065 // frames[1] can't be used due to a bug where RemoteFrames are created out of
2066 // order (https://crbug.com/478792). Instead, target second frame by name.
2067 EXPECT_TRUE(ExecuteScript(
2068 root->child_at(0)->current_frame_host(),
2069 "window.domAutomationController.send("
2070 " parent.frames['frame2'].location.href = 'data:text/html,foo');"));
2071 console_delegate->Wait();
2073 std::string frame_origin =
2074 root->child_at(1)->current_replication_state().origin.string();
2075 EXPECT_EQ(frame_origin + "/", frame_url.GetOrigin().spec());
2076 EXPECT_TRUE(
2077 MatchPattern(console_delegate->message(), "*" + frame_origin + "*"))
2078 << "Error message does not contain the frame's latest origin ("
2079 << frame_origin << ")";
2082 // Ensure that navigating subframes in --site-per-process mode properly fires
2083 // the DidStopLoading event on WebContentsObserver.
2084 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteDidStopLoading) {
2085 GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
2086 NavigateToURL(shell(), main_url);
2088 // It is safe to obtain the root frame tree node here, as it doesn't change.
2089 FrameTreeNode* root =
2090 static_cast<WebContentsImpl*>(shell()->web_contents())->
2091 GetFrameTree()->root();
2093 TestNavigationObserver observer(shell()->web_contents());
2095 // Load same-site page into iframe.
2096 FrameTreeNode* child = root->child_at(0);
2097 GURL http_url(embedded_test_server()->GetURL("/title1.html"));
2098 NavigateFrameToURL(child, http_url);
2099 EXPECT_EQ(http_url, observer.last_navigation_url());
2100 EXPECT_TRUE(observer.last_navigation_succeeded());
2102 // Load cross-site page into iframe.
2103 TestNavigationObserver nav_observer(shell()->web_contents(), 1);
2104 GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html");
2105 NavigationController::LoadURLParams params(url);
2106 params.transition_type = ui::PAGE_TRANSITION_LINK;
2107 params.frame_tree_node_id = child->frame_tree_node_id();
2108 child->navigator()->GetController()->LoadURLWithParams(params);
2109 nav_observer.Wait();
2111 // Verify that the navigation succeeded and the expected URL was loaded.
2112 EXPECT_TRUE(observer.last_navigation_succeeded());
2113 EXPECT_EQ(url, observer.last_navigation_url());
2116 // Ensure that the renderer does not crash when navigating a frame that has a
2117 // sibling RemoteFrame. See https://crbug.com/426953.
2118 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
2119 NavigateWithSiblingRemoteFrame) {
2120 GURL main_url(
2121 embedded_test_server()->GetURL("/frame_tree/page_with_two_frames.html"));
2122 NavigateToURL(shell(), main_url);
2124 // It is safe to obtain the root frame tree node here, as it doesn't change.
2125 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
2126 ->GetFrameTree()
2127 ->root();
2128 TestNavigationObserver observer(shell()->web_contents());
2130 // Make sure the first frame is out of process.
2131 ASSERT_EQ(2U, root->child_count());
2132 FrameTreeNode* node2 = root->child_at(0);
2133 EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
2134 node2->current_frame_host()->GetSiteInstance());
2136 // Make sure the second frame is in the parent's process.
2137 FrameTreeNode* node3 = root->child_at(1);
2138 EXPECT_EQ(root->current_frame_host()->GetSiteInstance(),
2139 node3->current_frame_host()->GetSiteInstance());
2141 // Navigate the second iframe (node3) to a URL in its own process.
2142 GURL title_url = embedded_test_server()->GetURL("/title2.html");
2143 NavigateFrameToURL(node3, title_url);
2144 EXPECT_TRUE(observer.last_navigation_succeeded());
2145 EXPECT_EQ(title_url, observer.last_navigation_url());
2146 EXPECT_EQ(root->current_frame_host()->GetSiteInstance(),
2147 node3->current_frame_host()->GetSiteInstance());
2148 EXPECT_TRUE(node3->current_frame_host()->IsRenderFrameLive());
2151 // Verify that load events for iframe elements work when the child frame is
2152 // out-of-process. In such cases, the load event is forwarded from the child
2153 // frame to the parent frame via the browser process.
2154 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, LoadEventForwarding) {
2155 // Load a page with a cross-site frame. The parent page has an onload
2156 // handler in the iframe element that appends "LOADED" to the document title.
2158 GURL main_url(
2159 embedded_test_server()->GetURL("/frame_with_load_event.html"));
2160 base::string16 expected_title(base::UTF8ToUTF16("LOADED"));
2161 TitleWatcher title_watcher(shell()->web_contents(), expected_title);
2162 EXPECT_TRUE(NavigateToURL(shell(), main_url));
2163 EXPECT_EQ(title_watcher.WaitAndGetTitle(), expected_title);
2166 // It is safe to obtain the root frame tree node here, as it doesn't change.
2167 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
2168 ->GetFrameTree()
2169 ->root();
2171 // Load another cross-site page into the iframe and check that the load event
2172 // is fired.
2174 GURL foo_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
2175 base::string16 expected_title(base::UTF8ToUTF16("LOADEDLOADED"));
2176 TitleWatcher title_watcher(shell()->web_contents(), expected_title);
2177 TestNavigationObserver observer(shell()->web_contents());
2178 NavigateFrameToURL(root->child_at(0), foo_url);
2179 EXPECT_TRUE(observer.last_navigation_succeeded());
2180 EXPECT_EQ(foo_url, observer.last_navigation_url());
2181 EXPECT_EQ(title_watcher.WaitAndGetTitle(), expected_title);
2185 // Check that postMessage can be routed between cross-site iframes.
2186 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, SubframePostMessage) {
2187 GURL main_url(embedded_test_server()->GetURL(
2188 "/frame_tree/page_with_post_message_frames.html"));
2189 EXPECT_TRUE(NavigateToURL(shell(), main_url));
2191 // It is safe to obtain the root frame tree node here, as it doesn't change.
2192 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
2193 ->GetFrameTree()
2194 ->root();
2196 TestNavigationObserver observer(shell()->web_contents());
2197 ASSERT_EQ(2U, root->child_count());
2199 // Verify the frames start at correct URLs. First frame should be
2200 // same-site; second frame should be cross-site.
2201 GURL same_site_url(embedded_test_server()->GetURL("/post_message.html"));
2202 EXPECT_EQ(same_site_url, root->child_at(0)->current_url());
2203 GURL foo_url(embedded_test_server()->GetURL("foo.com",
2204 "/post_message.html"));
2205 EXPECT_EQ(foo_url, root->child_at(1)->current_url());
2206 EXPECT_NE(root->child_at(0)->current_frame_host()->GetSiteInstance(),
2207 root->child_at(1)->current_frame_host()->GetSiteInstance());
2209 // Send a message from first, same-site frame to second, cross-site frame.
2210 // Expect the second frame to reply back to the first frame.
2211 PostMessageAndWaitForReply(root->child_at(0),
2212 "postToSibling('subframe-msg','subframe2')",
2213 "\"done-subframe1\"");
2215 // Send a postMessage from second, cross-site frame to its parent. Expect
2216 // parent to send a reply to the frame.
2217 base::string16 expected_title(base::ASCIIToUTF16("subframe-msg"));
2218 TitleWatcher title_watcher(shell()->web_contents(), expected_title);
2219 PostMessageAndWaitForReply(root->child_at(1), "postToParent('subframe-msg')",
2220 "\"done-subframe2\"");
2221 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
2223 // Verify the total number of received messages for each subframe. First
2224 // frame should have one message (reply from second frame), and second frame
2225 // should have two messages (message from first frame and reply from parent).
2226 int subframe1_received_messages = 0;
2227 int subframe2_received_messages = 0;
2228 EXPECT_TRUE(ExecuteScriptAndExtractInt(
2229 root->child_at(0)->current_frame_host(),
2230 "window.domAutomationController.send(window.receivedMessages);",
2231 &subframe1_received_messages));
2232 EXPECT_EQ(1, subframe1_received_messages);
2233 EXPECT_TRUE(ExecuteScriptAndExtractInt(
2234 root->child_at(1)->current_frame_host(),
2235 "window.domAutomationController.send(window.receivedMessages);",
2236 &subframe2_received_messages));
2237 EXPECT_EQ(2, subframe2_received_messages);
2240 // Check that parent.frames[num] references correct sibling frames when the
2241 // parent is remote. See https://crbug.com/478792.
2242 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, IndexedFrameAccess) {
2243 // Start on a page with three same-site subframes.
2244 GURL main_url(
2245 embedded_test_server()->GetURL("a.com", "/frame_tree/top.html"));
2246 EXPECT_TRUE(NavigateToURL(shell(), main_url));
2248 // It is safe to obtain the root frame tree node here, as it doesn't change.
2249 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
2250 ->GetFrameTree()
2251 ->root();
2252 ASSERT_EQ(3U, root->child_count());
2253 FrameTreeNode* child0 = root->child_at(0);
2254 FrameTreeNode* child1 = root->child_at(1);
2255 FrameTreeNode* child2 = root->child_at(2);
2257 // Send each of the frames to a different site. Each new renderer will first
2258 // create proxies for the parent and two sibling subframes and then create
2259 // and insert the new RenderFrame into the frame tree.
2260 GURL b_url(embedded_test_server()->GetURL("b.com", "/post_message.html"));
2261 GURL c_url(embedded_test_server()->GetURL("c.com", "/post_message.html"));
2262 GURL d_url(embedded_test_server()->GetURL("d.com", "/post_message.html"));
2263 NavigateFrameToURL(child0, b_url);
2264 // TODO(alexmos): The calls to WaitForRenderFrameReady can be removed once
2265 // TestFrameNavigationObserver is fixed to use DidFinishLoad.
2266 EXPECT_TRUE(WaitForRenderFrameReady(child0->current_frame_host()));
2267 NavigateFrameToURL(child1, c_url);
2268 EXPECT_TRUE(WaitForRenderFrameReady(child1->current_frame_host()));
2269 NavigateFrameToURL(child2, d_url);
2270 EXPECT_TRUE(WaitForRenderFrameReady(child2->current_frame_host()));
2272 EXPECT_EQ(
2273 " Site A ------------ proxies for B C D\n"
2274 " |--Site B ------- proxies for A C D\n"
2275 " |--Site C ------- proxies for A B D\n"
2276 " +--Site D ------- proxies for A B C\n"
2277 "Where A = http://a.com/\n"
2278 " B = http://b.com/\n"
2279 " C = http://c.com/\n"
2280 " D = http://d.com/",
2281 DepictFrameTree(root));
2283 // Check that each subframe sees itself at correct index in parent.frames.
2284 bool success = false;
2285 EXPECT_TRUE(ExecuteScriptAndExtractBool(
2286 child0->current_frame_host(),
2287 "window.domAutomationController.send(window === parent.frames[0]);",
2288 &success));
2289 EXPECT_TRUE(success);
2291 success = false;
2292 EXPECT_TRUE(ExecuteScriptAndExtractBool(
2293 child1->current_frame_host(),
2294 "window.domAutomationController.send(window === parent.frames[1]);",
2295 &success));
2296 EXPECT_TRUE(success);
2298 success = false;
2299 EXPECT_TRUE(ExecuteScriptAndExtractBool(
2300 child2->current_frame_host(),
2301 "window.domAutomationController.send(window === parent.frames[2]);",
2302 &success));
2303 EXPECT_TRUE(success);
2305 // Send a postMessage from B to parent.frames[1], which should go to C, and
2306 // wait for reply.
2307 PostMessageAndWaitForReply(child0, "postToSibling('subframe-msg', 1)",
2308 "\"done-1-1-name\"");
2310 // Send a postMessage from C to parent.frames[2], which should go to D, and
2311 // wait for reply.
2312 PostMessageAndWaitForReply(child1, "postToSibling('subframe-msg', 2)",
2313 "\"done-1-2-name\"");
2315 // Verify the total number of received messages for each subframe.
2316 int child0_received_messages = 0;
2317 EXPECT_TRUE(ExecuteScriptAndExtractInt(
2318 child0->current_frame_host(),
2319 "window.domAutomationController.send(window.receivedMessages);",
2320 &child0_received_messages));
2321 EXPECT_EQ(1, child0_received_messages);
2323 int child1_received_messages = 0;
2324 EXPECT_TRUE(ExecuteScriptAndExtractInt(
2325 child1->current_frame_host(),
2326 "window.domAutomationController.send(window.receivedMessages);",
2327 &child1_received_messages));
2328 EXPECT_EQ(2, child1_received_messages);
2330 int child2_received_messages = 0;
2331 EXPECT_TRUE(ExecuteScriptAndExtractInt(
2332 child2->current_frame_host(),
2333 "window.domAutomationController.send(window.receivedMessages);",
2334 &child2_received_messages));
2335 EXPECT_EQ(1, child2_received_messages);
2338 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, RFPHDestruction) {
2339 GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
2340 NavigateToURL(shell(), main_url);
2342 // It is safe to obtain the root frame tree node here, as it doesn't change.
2343 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
2344 ->GetFrameTree()
2345 ->root();
2347 TestNavigationObserver observer(shell()->web_contents());
2349 // Load cross-site page into iframe.
2350 FrameTreeNode* child = root->child_at(0);
2351 GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html");
2352 NavigateFrameToURL(root->child_at(0), url);
2353 EXPECT_TRUE(observer.last_navigation_succeeded());
2354 EXPECT_EQ(url, observer.last_navigation_url());
2355 EXPECT_EQ(
2356 " Site A ------------ proxies for B\n"
2357 " |--Site B ------- proxies for A\n"
2358 " +--Site A ------- proxies for B\n"
2359 " |--Site A -- proxies for B\n"
2360 " +--Site A -- proxies for B\n"
2361 " +--Site A -- proxies for B\n"
2362 "Where A = http://127.0.0.1/\n"
2363 " B = http://foo.com/",
2364 DepictFrameTree(root));
2366 // Load another cross-site page.
2367 url = embedded_test_server()->GetURL("bar.com", "/title3.html");
2368 NavigateIframeToURL(shell()->web_contents(), "test", url);
2369 EXPECT_TRUE(observer.last_navigation_succeeded());
2370 EXPECT_EQ(url, observer.last_navigation_url());
2371 EXPECT_EQ(
2372 " Site A ------------ proxies for C\n"
2373 " |--Site C ------- proxies for A\n"
2374 " +--Site A ------- proxies for C\n"
2375 " |--Site A -- proxies for C\n"
2376 " +--Site A -- proxies for C\n"
2377 " +--Site A -- proxies for C\n"
2378 "Where A = http://127.0.0.1/\n"
2379 " C = http://bar.com/",
2380 DepictFrameTree(root));
2382 // Navigate back to the parent's origin.
2383 url = embedded_test_server()->GetURL("/title1.html");
2384 NavigateFrameToURL(child, url);
2385 EXPECT_EQ(url, observer.last_navigation_url());
2386 EXPECT_TRUE(observer.last_navigation_succeeded());
2387 EXPECT_EQ(
2388 " Site A\n"
2389 " |--Site A\n"
2390 " +--Site A\n"
2391 " |--Site A\n"
2392 " +--Site A\n"
2393 " +--Site A\n"
2394 "Where A = http://127.0.0.1/",
2395 DepictFrameTree(root));
2398 } // namespace content