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"
29 class SitePerProcessWebContentsObserver
: public WebContentsObserver
{
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
,
40 bool is_iframe_srcdoc
) OVERRIDE
{
41 navigation_succeeded_
= false;
44 virtual void DidFailProvisionalLoad(
45 RenderFrameHost
* render_frame_host
,
46 const GURL
& validated_url
,
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
,
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_
; }
69 bool navigation_succeeded_
;
71 DISALLOW_COPY_AND_ASSIGN(SitePerProcessWebContentsObserver
);
74 class RedirectNotificationObserver
: public NotificationObserver
{
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.
88 // Returns NotificationService::AllSources() if we haven't observed a
90 const NotificationSource
& source() const {
94 const NotificationDetails
& details() const {
98 // NotificationObserver:
99 virtual void Observe(int type
,
100 const NotificationSource
& source
,
101 const NotificationDetails
& details
) OVERRIDE
;
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
)
121 source_(NotificationService::AllSources()) {
122 registrar_
.Add(this, notification_type
, source
);
125 RedirectNotificationObserver::~RedirectNotificationObserver() {}
127 void RedirectNotificationObserver::Wait() {
128 if (seen_
&& seen_twice_
)
132 message_loop_runner_
= new MessageLoopRunner
;
133 message_loop_runner_
->Run();
137 void RedirectNotificationObserver::Observe(
139 const NotificationSource
& source
,
140 const NotificationDetails
& details
) {
148 message_loop_runner_
->Quit();
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
,
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
174 std::string script
= base::StringPrintf(
176 "var iframes = document.getElementById('%s');iframes.src='%s';"
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();
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
197 #define MAYBE_CrossSiteIframe CrossSiteIframe
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());
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());
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
307 #define MAYBE_NavigateRemoteFrame NavigateRemoteFrame
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());
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(
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());
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(
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