If a RemoteFrame asks to navigate, send an OpenURL IPC
[chromium-blink-merge.git] / content / browser / site_per_process_browsertest.cc
blob465fed363fb06e5615697ef151b5a65ac3b7eba4
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 "base/command_line.h"
8 #include "base/strings/stringprintf.h"
9 #include "content/browser/frame_host/cross_process_frame_connector.h"
10 #include "content/browser/frame_host/frame_tree.h"
11 #include "content/browser/frame_host/render_frame_proxy_host.h"
12 #include "content/browser/frame_host/render_widget_host_view_child_frame.h"
13 #include "content/browser/renderer_host/render_view_host_impl.h"
14 #include "content/browser/web_contents/web_contents_impl.h"
15 #include "content/public/browser/notification_observer.h"
16 #include "content/public/browser/notification_service.h"
17 #include "content/public/browser/notification_types.h"
18 #include "content/public/browser/web_contents_observer.h"
19 #include "content/public/common/content_switches.h"
20 #include "content/public/test/browser_test_utils.h"
21 #include "content/public/test/content_browser_test_utils.h"
22 #include "content/public/test/test_utils.h"
23 #include "content/shell/browser/shell.h"
24 #include "content/test/content_browser_test_utils_internal.h"
25 #include "net/dns/mock_host_resolver.h"
27 namespace content {
29 class SitePerProcessWebContentsObserver: public WebContentsObserver {
30 public:
31 explicit SitePerProcessWebContentsObserver(WebContents* web_contents)
32 : WebContentsObserver(web_contents),
33 navigation_succeeded_(false) {}
34 virtual ~SitePerProcessWebContentsObserver() {}
36 virtual void DidStartProvisionalLoadForFrame(
37 RenderFrameHost* render_frame_host,
38 const GURL& validated_url,
39 bool is_error_page,
40 bool is_iframe_srcdoc) OVERRIDE {
41 navigation_succeeded_ = false;
44 virtual void DidFailProvisionalLoad(
45 RenderFrameHost* render_frame_host,
46 const GURL& validated_url,
47 int error_code,
48 const base::string16& error_description) OVERRIDE {
49 navigation_url_ = validated_url;
50 navigation_succeeded_ = false;
53 virtual void DidCommitProvisionalLoadForFrame(
54 RenderFrameHost* render_frame_host,
55 const GURL& url,
56 ui::PageTransition transition_type) OVERRIDE {
57 navigation_url_ = url;
58 navigation_succeeded_ = true;
61 const GURL& navigation_url() const {
62 return navigation_url_;
65 int navigation_succeeded() const { return navigation_succeeded_; }
67 private:
68 GURL navigation_url_;
69 bool navigation_succeeded_;
71 DISALLOW_COPY_AND_ASSIGN(SitePerProcessWebContentsObserver);
74 class RedirectNotificationObserver : public NotificationObserver {
75 public:
76 // Register to listen for notifications of the given type from either a
77 // specific source, or from all sources if |source| is
78 // NotificationService::AllSources().
79 RedirectNotificationObserver(int notification_type,
80 const NotificationSource& source);
81 virtual ~RedirectNotificationObserver();
83 // Wait until the specified notification occurs. If the notification was
84 // emitted between the construction of this object and this call then it
85 // returns immediately.
86 void Wait();
88 // Returns NotificationService::AllSources() if we haven't observed a
89 // notification yet.
90 const NotificationSource& source() const {
91 return source_;
94 const NotificationDetails& details() const {
95 return details_;
98 // NotificationObserver:
99 virtual void Observe(int type,
100 const NotificationSource& source,
101 const NotificationDetails& details) OVERRIDE;
103 private:
104 bool seen_;
105 bool seen_twice_;
106 bool running_;
107 NotificationRegistrar registrar_;
109 NotificationSource source_;
110 NotificationDetails details_;
111 scoped_refptr<MessageLoopRunner> message_loop_runner_;
113 DISALLOW_COPY_AND_ASSIGN(RedirectNotificationObserver);
116 RedirectNotificationObserver::RedirectNotificationObserver(
117 int notification_type,
118 const NotificationSource& source)
119 : seen_(false),
120 running_(false),
121 source_(NotificationService::AllSources()) {
122 registrar_.Add(this, notification_type, source);
125 RedirectNotificationObserver::~RedirectNotificationObserver() {}
127 void RedirectNotificationObserver::Wait() {
128 if (seen_ && seen_twice_)
129 return;
131 running_ = true;
132 message_loop_runner_ = new MessageLoopRunner;
133 message_loop_runner_->Run();
134 EXPECT_TRUE(seen_);
137 void RedirectNotificationObserver::Observe(
138 int type,
139 const NotificationSource& source,
140 const NotificationDetails& details) {
141 source_ = source;
142 details_ = details;
143 seen_twice_ = seen_;
144 seen_ = true;
145 if (!running_)
146 return;
148 message_loop_runner_->Quit();
149 running_ = false;
153 // SitePerProcessBrowserTest
156 SitePerProcessBrowserTest::SitePerProcessBrowserTest() {
159 void SitePerProcessBrowserTest::StartFrameAtDataURL() {
160 std::string data_url_script =
161 "var iframes = document.getElementById('test');iframes.src="
162 "'data:text/html,dataurl';";
163 ASSERT_TRUE(ExecuteScript(shell()->web_contents(), data_url_script));
166 bool SitePerProcessBrowserTest::NavigateIframeToURL(Shell* window,
167 const GURL& url,
168 std::string iframe_id) {
169 // TODO(creis): This should wait for LOAD_STOP, but cross-site subframe
170 // navigations generate extra DidStartLoading and DidStopLoading messages.
171 // Until we replace swappedout:// with frame proxies, we need to listen for
172 // something else. For now, we trigger NEW_SUBFRAME navigations and listen
173 // for commit.
174 std::string script = base::StringPrintf(
175 "setTimeout(\""
176 "var iframes = document.getElementById('%s');iframes.src='%s';"
177 "\",0)",
178 iframe_id.c_str(), url.spec().c_str());
179 WindowedNotificationObserver load_observer(
180 NOTIFICATION_NAV_ENTRY_COMMITTED,
181 Source<NavigationController>(
182 &window->web_contents()->GetController()));
183 bool result = ExecuteScript(window->web_contents(), script);
184 load_observer.Wait();
185 return result;
188 void SitePerProcessBrowserTest::SetUpCommandLine(CommandLine* command_line) {
189 command_line->AppendSwitch(switches::kSitePerProcess);
192 // It fails on ChromeOS and Android, so disabled while investigating.
193 // http://crbug.com/399775
194 #if defined(OS_ANDROID) || defined(OS_CHROMEOS)
195 #define MAYBE_CrossSiteIframe DISABLED_CrossSiteIframe
196 #else
197 #define MAYBE_CrossSiteIframe CrossSiteIframe
198 #endif
199 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_CrossSiteIframe) {
200 host_resolver()->AddRule("*", "127.0.0.1");
201 ASSERT_TRUE(test_server()->Start());
202 GURL main_url(test_server()->GetURL("files/site_per_process_main.html"));
203 NavigateToURL(shell(), main_url);
205 // It is safe to obtain the root frame tree node here, as it doesn't change.
206 FrameTreeNode* root =
207 static_cast<WebContentsImpl*>(shell()->web_contents())->
208 GetFrameTree()->root();
210 SitePerProcessWebContentsObserver observer(shell()->web_contents());
212 // Load same-site page into iframe.
213 FrameTreeNode* child = root->child_at(0);
214 GURL http_url(test_server()->GetURL("files/title1.html"));
215 NavigateFrameToURL(child, http_url);
216 EXPECT_EQ(http_url, observer.navigation_url());
217 EXPECT_TRUE(observer.navigation_succeeded());
219 // There should be only one RenderWidgetHost when there are no
220 // cross-process iframes.
221 std::set<RenderWidgetHostView*> views_set =
222 static_cast<WebContentsImpl*>(shell()->web_contents())
223 ->GetRenderWidgetHostViewsInTree();
224 EXPECT_EQ(1U, views_set.size());
226 RenderFrameProxyHost* proxy_to_parent =
227 child->render_manager()->GetRenderFrameProxyHost(
228 shell()->web_contents()->GetSiteInstance());
229 EXPECT_FALSE(proxy_to_parent);
231 // These must stay in scope with replace_host.
232 GURL::Replacements replace_host;
233 std::string foo_com("foo.com");
235 // Load cross-site page into iframe.
236 GURL cross_site_url(test_server()->GetURL("files/title2.html"));
237 replace_host.SetHostStr(foo_com);
238 cross_site_url = cross_site_url.ReplaceComponents(replace_host);
239 NavigateFrameToURL(root->child_at(0), cross_site_url);
240 EXPECT_EQ(cross_site_url, observer.navigation_url());
241 EXPECT_TRUE(observer.navigation_succeeded());
243 // Ensure that we have created a new process for the subframe.
244 ASSERT_EQ(1U, root->child_count());
245 SiteInstance* site_instance = child->current_frame_host()->GetSiteInstance();
246 RenderViewHost* rvh = child->current_frame_host()->render_view_host();
247 RenderProcessHost* rph = child->current_frame_host()->GetProcess();
248 EXPECT_NE(shell()->web_contents()->GetRenderViewHost(), rvh);
249 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), site_instance);
250 EXPECT_NE(shell()->web_contents()->GetRenderProcessHost(), rph);
252 // There should be now two RenderWidgetHosts, one for each process
253 // rendering a frame.
254 std::set<RenderWidgetHostView*> views_set =
255 static_cast<WebContentsImpl*>(shell()->web_contents())
256 ->GetRenderWidgetHostViewsInTree();
257 EXPECT_EQ(2U, views_set.size());
259 proxy_to_parent = child->render_manager()->GetProxyToParent();
260 EXPECT_TRUE(proxy_to_parent);
261 EXPECT_TRUE(proxy_to_parent->cross_process_frame_connector());
262 EXPECT_EQ(
263 rvh->GetView(),
264 proxy_to_parent->cross_process_frame_connector()->get_view_for_testing());
266 // Load another cross-site page into the same iframe.
267 cross_site_url = test_server()->GetURL("files/title3.html");
268 std::string bar_com("bar.com");
269 replace_host.SetHostStr(bar_com);
270 cross_site_url = cross_site_url.ReplaceComponents(replace_host);
271 NavigateFrameToURL(root->child_at(0), cross_site_url);
272 EXPECT_EQ(cross_site_url, observer.navigation_url());
273 EXPECT_TRUE(observer.navigation_succeeded());
275 // Check again that a new process is created and is different from the
276 // top level one and the previous one.
277 ASSERT_EQ(1U, root->child_count());
278 child = root->child_at(0);
279 EXPECT_NE(shell()->web_contents()->GetRenderViewHost(),
280 child->current_frame_host()->render_view_host());
281 EXPECT_NE(rvh, child->current_frame_host()->render_view_host());
282 EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
283 child->current_frame_host()->GetSiteInstance());
284 EXPECT_NE(site_instance,
285 child->current_frame_host()->GetSiteInstance());
286 EXPECT_NE(shell()->web_contents()->GetRenderProcessHost(),
287 child->current_frame_host()->GetProcess());
288 EXPECT_NE(rph, child->current_frame_host()->GetProcess());
290 std::set<RenderWidgetHostView*> views_set =
291 static_cast<WebContentsImpl*>(shell()->web_contents())
292 ->GetRenderWidgetHostViewsInTree();
293 EXPECT_EQ(2U, views_set.size());
295 EXPECT_EQ(proxy_to_parent, child->render_manager()->GetProxyToParent());
296 EXPECT_TRUE(proxy_to_parent->cross_process_frame_connector());
297 EXPECT_EQ(
298 child->current_frame_host()->render_view_host()->GetView(),
299 proxy_to_parent->cross_process_frame_connector()->get_view_for_testing());
302 // It fails on ChromeOS and Android, so disabled while investigating.
303 // http://crbug.com/399775
304 #if defined(OS_ANDROID) || defined(OS_CHROMEOS)
305 #define MAYBE_NavigateRemoteFrame DISABLED_NavigateRemoteFrame
306 #else
307 #define MAYBE_NavigateRemoteFrame NavigateRemoteFrame
308 #endif
309 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_NavigateRemoteFrame) {
310 host_resolver()->AddRule("*", "127.0.0.1");
311 ASSERT_TRUE(test_server()->Start());
312 GURL main_url(test_server()->GetURL("files/site_per_process_main.html"));
313 NavigateToURL(shell(), main_url);
315 // It is safe to obtain the root frame tree node here, as it doesn't change.
316 FrameTreeNode* root =
317 static_cast<WebContentsImpl*>(shell()->web_contents())->
318 GetFrameTree()->root();
320 SitePerProcessWebContentsObserver observer(shell()->web_contents());
322 // Load same-site page into iframe.
323 FrameTreeNode* child = root->child_at(0);
324 GURL http_url(test_server()->GetURL("files/title1.html"));
325 NavigateFrameToURL(child, http_url);
326 EXPECT_EQ(http_url, observer.navigation_url());
327 EXPECT_TRUE(observer.navigation_succeeded());
329 // These must stay in scope with replace_host.
330 GURL::Replacements replace_host;
331 std::string foo_com("foo.com");
333 // Load cross-site page into iframe.
334 GURL cross_site_url(test_server()->GetURL("files/title2.html"));
335 replace_host.SetHostStr(foo_com);
336 cross_site_url = cross_site_url.ReplaceComponents(replace_host);
337 NavigateFrameToURL(root->child_at(0), cross_site_url);
338 EXPECT_EQ(cross_site_url, observer.navigation_url());
339 EXPECT_TRUE(observer.navigation_succeeded());
341 // Ensure that we have created a new process for the subframe.
342 ASSERT_EQ(1U, root->child_count());
343 SiteInstance* site_instance = child->current_frame_host()->GetSiteInstance();
344 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), site_instance);
346 // Emulate the main frame changing the src of the iframe such that it
347 // navigates cross-site.
348 cross_site_url = test_server()->GetURL("files/title3.html");
349 std::string bar_com("bar.com");
350 replace_host.SetHostStr(bar_com);
351 cross_site_url = cross_site_url.ReplaceComponents(replace_host);
352 NavigateIframeToURL(shell(), cross_site_url, "test");
353 EXPECT_EQ(cross_site_url, observer.navigation_url());
354 EXPECT_TRUE(observer.navigation_succeeded());
356 // Check again that a new process is created and is different from the
357 // top level one and the previous one.
358 ASSERT_EQ(1U, root->child_count());
359 child = root->child_at(0);
360 EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
361 child->current_frame_host()->GetSiteInstance());
362 EXPECT_NE(site_instance,
363 child->current_frame_host()->GetSiteInstance());
365 // TODO(japhet): This currently causes an assertion in the renderer process.
366 // Enable when the assertion is fixed.
367 //NavigateFrameToURL(child, http_url);
368 //EXPECT_EQ(http_url, observer.navigation_url());
369 //EXPECT_TRUE(observer.navigation_succeeded());
370 //EXPECT_EQ(shell()->web_contents()->GetSiteInstance(),
371 // child->current_frame_host()->GetSiteInstance());
374 // Crash a subframe and ensures its children are cleared from the FrameTree.
375 // See http://crbug.com/338508.
376 // TODO(creis): Disabled for flakiness; see http://crbug.com/405582.
377 // TODO(creis): Enable this on Android when we can kill the process there.
378 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DISABLED_CrashSubframe) {
379 host_resolver()->AddRule("*", "127.0.0.1");
380 ASSERT_TRUE(test_server()->Start());
381 GURL main_url(test_server()->GetURL("files/site_per_process_main.html"));
382 NavigateToURL(shell(), main_url);
384 StartFrameAtDataURL();
386 // These must stay in scope with replace_host.
387 GURL::Replacements replace_host;
388 std::string foo_com("foo.com");
390 // Load cross-site page into iframe.
391 GURL cross_site_url(test_server()->GetURL("files/title2.html"));
392 replace_host.SetHostStr(foo_com);
393 cross_site_url = cross_site_url.ReplaceComponents(replace_host);
394 EXPECT_TRUE(NavigateIframeToURL(shell(), cross_site_url, "test"));
396 // Check the subframe process.
397 FrameTreeNode* root =
398 static_cast<WebContentsImpl*>(shell()->web_contents())->
399 GetFrameTree()->root();
400 ASSERT_EQ(1U, root->child_count());
401 FrameTreeNode* child = root->child_at(0);
402 EXPECT_EQ(main_url, root->current_url());
403 EXPECT_EQ(cross_site_url, child->current_url());
405 EXPECT_TRUE(
406 child->current_frame_host()->render_view_host()->IsRenderViewLive());
407 EXPECT_TRUE(child->current_frame_host()->IsRenderFrameLive());
409 // Crash the subframe process.
410 RenderProcessHost* root_process = root->current_frame_host()->GetProcess();
411 RenderProcessHost* child_process = child->current_frame_host()->GetProcess();
413 RenderProcessHostWatcher crash_observer(
414 child_process,
415 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
416 base::KillProcess(child_process->GetHandle(), 0, false);
417 crash_observer.Wait();
420 // Ensure that the child frame still exists but has been cleared.
421 EXPECT_EQ(1U, root->child_count());
422 EXPECT_EQ(main_url, root->current_url());
423 EXPECT_EQ(GURL(), child->current_url());
425 EXPECT_FALSE(
426 child->current_frame_host()->render_view_host()->IsRenderViewLive());
427 EXPECT_FALSE(child->current_frame_host()->IsRenderFrameLive());
428 EXPECT_FALSE(child->current_frame_host()->render_frame_created_);
430 // Now crash the top-level page to clear the child frame.
432 RenderProcessHostWatcher crash_observer(
433 root_process,
434 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
435 base::KillProcess(root_process->GetHandle(), 0, false);
436 crash_observer.Wait();
438 EXPECT_EQ(0U, root->child_count());
439 EXPECT_EQ(GURL(), root->current_url());
442 // TODO(nasko): Disable this test until out-of-process iframes is ready and the
443 // security checks are back in place.
444 // TODO(creis): Replace SpawnedTestServer with host_resolver to get test to run
445 // on Android (http://crbug.com/187570).
446 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
447 DISABLED_CrossSiteIframeRedirectOnce) {
448 ASSERT_TRUE(test_server()->Start());
449 net::SpawnedTestServer https_server(
450 net::SpawnedTestServer::TYPE_HTTPS,
451 net::SpawnedTestServer::kLocalhost,
452 base::FilePath(FILE_PATH_LITERAL("content/test/data")));
453 ASSERT_TRUE(https_server.Start());
455 GURL main_url(test_server()->GetURL("files/site_per_process_main.html"));
456 GURL http_url(test_server()->GetURL("files/title1.html"));
457 GURL https_url(https_server.GetURL("files/title1.html"));
459 NavigateToURL(shell(), main_url);
461 SitePerProcessWebContentsObserver observer(shell()->web_contents());
463 // Load cross-site client-redirect page into Iframe.
464 // Should be blocked.
465 GURL client_redirect_https_url(https_server.GetURL(
466 "client-redirect?files/title1.html"));
467 EXPECT_TRUE(NavigateIframeToURL(shell(),
468 client_redirect_https_url, "test"));
469 // DidFailProvisionalLoad when navigating to client_redirect_https_url.
470 EXPECT_EQ(observer.navigation_url(), client_redirect_https_url);
471 EXPECT_FALSE(observer.navigation_succeeded());
475 // Load cross-site server-redirect page into Iframe,
476 // which redirects to same-site page.
477 GURL server_redirect_http_url(https_server.GetURL(
478 "server-redirect?" + http_url.spec()));
479 EXPECT_TRUE(NavigateIframeToURL(shell(),
480 server_redirect_http_url, "test"));
481 EXPECT_EQ(observer.navigation_url(), http_url);
482 EXPECT_TRUE(observer.navigation_succeeded());
486 // Load cross-site server-redirect page into Iframe,
487 // which redirects to cross-site page.
488 GURL server_redirect_http_url(https_server.GetURL(
489 "server-redirect?files/title1.html"));
490 EXPECT_TRUE(NavigateIframeToURL(shell(),
491 server_redirect_http_url, "test"));
492 // DidFailProvisionalLoad when navigating to https_url.
493 EXPECT_EQ(observer.navigation_url(), https_url);
494 EXPECT_FALSE(observer.navigation_succeeded());
498 // Load same-site server-redirect page into Iframe,
499 // which redirects to cross-site page.
500 GURL server_redirect_http_url(test_server()->GetURL(
501 "server-redirect?" + https_url.spec()));
502 EXPECT_TRUE(NavigateIframeToURL(shell(),
503 server_redirect_http_url, "test"));
505 EXPECT_EQ(observer.navigation_url(), https_url);
506 EXPECT_FALSE(observer.navigation_succeeded());
510 // Load same-site client-redirect page into Iframe,
511 // which redirects to cross-site page.
512 GURL client_redirect_http_url(test_server()->GetURL(
513 "client-redirect?" + https_url.spec()));
515 RedirectNotificationObserver load_observer2(
516 NOTIFICATION_LOAD_STOP,
517 Source<NavigationController>(
518 &shell()->web_contents()->GetController()));
520 EXPECT_TRUE(NavigateIframeToURL(shell(),
521 client_redirect_http_url, "test"));
523 // Same-site Client-Redirect Page should be loaded successfully.
524 EXPECT_EQ(observer.navigation_url(), client_redirect_http_url);
525 EXPECT_TRUE(observer.navigation_succeeded());
527 // Redirecting to Cross-site Page should be blocked.
528 load_observer2.Wait();
529 EXPECT_EQ(observer.navigation_url(), https_url);
530 EXPECT_FALSE(observer.navigation_succeeded());
534 // Load same-site server-redirect page into Iframe,
535 // which redirects to same-site page.
536 GURL server_redirect_http_url(test_server()->GetURL(
537 "server-redirect?files/title1.html"));
538 EXPECT_TRUE(NavigateIframeToURL(shell(),
539 server_redirect_http_url, "test"));
540 EXPECT_EQ(observer.navigation_url(), http_url);
541 EXPECT_TRUE(observer.navigation_succeeded());
545 // Load same-site client-redirect page into Iframe,
546 // which redirects to same-site page.
547 GURL client_redirect_http_url(test_server()->GetURL(
548 "client-redirect?" + http_url.spec()));
549 RedirectNotificationObserver load_observer2(
550 NOTIFICATION_LOAD_STOP,
551 Source<NavigationController>(
552 &shell()->web_contents()->GetController()));
554 EXPECT_TRUE(NavigateIframeToURL(shell(),
555 client_redirect_http_url, "test"));
557 // Same-site Client-Redirect Page should be loaded successfully.
558 EXPECT_EQ(observer.navigation_url(), client_redirect_http_url);
559 EXPECT_TRUE(observer.navigation_succeeded());
561 // Redirecting to Same-site Page should be loaded successfully.
562 load_observer2.Wait();
563 EXPECT_EQ(observer.navigation_url(), http_url);
564 EXPECT_TRUE(observer.navigation_succeeded());
568 // TODO(nasko): Disable this test until out-of-process iframes is ready and the
569 // security checks are back in place.
570 // TODO(creis): Replace SpawnedTestServer with host_resolver to get test to run
571 // on Android (http://crbug.com/187570).
572 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
573 DISABLED_CrossSiteIframeRedirectTwice) {
574 ASSERT_TRUE(test_server()->Start());
575 net::SpawnedTestServer https_server(
576 net::SpawnedTestServer::TYPE_HTTPS,
577 net::SpawnedTestServer::kLocalhost,
578 base::FilePath(FILE_PATH_LITERAL("content/test/data")));
579 ASSERT_TRUE(https_server.Start());
581 GURL main_url(test_server()->GetURL("files/site_per_process_main.html"));
582 GURL http_url(test_server()->GetURL("files/title1.html"));
583 GURL https_url(https_server.GetURL("files/title1.html"));
585 NavigateToURL(shell(), main_url);
587 SitePerProcessWebContentsObserver observer(shell()->web_contents());
589 // Load client-redirect page pointing to a cross-site client-redirect page,
590 // which eventually redirects back to same-site page.
591 GURL client_redirect_https_url(https_server.GetURL(
592 "client-redirect?" + http_url.spec()));
593 GURL client_redirect_http_url(test_server()->GetURL(
594 "client-redirect?" + client_redirect_https_url.spec()));
596 // We should wait until second client redirect get cancelled.
597 RedirectNotificationObserver load_observer2(
598 NOTIFICATION_LOAD_STOP,
599 Source<NavigationController>(
600 &shell()->web_contents()->GetController()));
602 EXPECT_TRUE(NavigateIframeToURL(shell(), client_redirect_http_url, "test"));
604 // DidFailProvisionalLoad when navigating to client_redirect_https_url.
605 load_observer2.Wait();
606 EXPECT_EQ(observer.navigation_url(), client_redirect_https_url);
607 EXPECT_FALSE(observer.navigation_succeeded());
611 // Load server-redirect page pointing to a cross-site server-redirect page,
612 // which eventually redirect back to same-site page.
613 GURL server_redirect_https_url(https_server.GetURL(
614 "server-redirect?" + http_url.spec()));
615 GURL server_redirect_http_url(test_server()->GetURL(
616 "server-redirect?" + server_redirect_https_url.spec()));
617 EXPECT_TRUE(NavigateIframeToURL(shell(),
618 server_redirect_http_url, "test"));
619 EXPECT_EQ(observer.navigation_url(), http_url);
620 EXPECT_TRUE(observer.navigation_succeeded());
624 // Load server-redirect page pointing to a cross-site server-redirect page,
625 // which eventually redirects back to cross-site page.
626 GURL server_redirect_https_url(https_server.GetURL(
627 "server-redirect?" + https_url.spec()));
628 GURL server_redirect_http_url(test_server()->GetURL(
629 "server-redirect?" + server_redirect_https_url.spec()));
630 EXPECT_TRUE(NavigateIframeToURL(shell(), server_redirect_http_url, "test"));
632 // DidFailProvisionalLoad when navigating to https_url.
633 EXPECT_EQ(observer.navigation_url(), https_url);
634 EXPECT_FALSE(observer.navigation_succeeded());
638 // Load server-redirect page pointing to a cross-site client-redirect page,
639 // which eventually redirects back to same-site page.
640 GURL client_redirect_http_url(https_server.GetURL(
641 "client-redirect?" + http_url.spec()));
642 GURL server_redirect_http_url(test_server()->GetURL(
643 "server-redirect?" + client_redirect_http_url.spec()));
644 EXPECT_TRUE(NavigateIframeToURL(shell(), server_redirect_http_url, "test"));
646 // DidFailProvisionalLoad when navigating to client_redirect_http_url.
647 EXPECT_EQ(observer.navigation_url(), client_redirect_http_url);
648 EXPECT_FALSE(observer.navigation_succeeded());
652 } // namespace content