| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/command_line.h" | 5 #include "base/command_line.h" |
| 6 #include "base/strings/stringprintf.h" | 6 #include "base/strings/stringprintf.h" |
| 7 #include "base/strings/utf_string_conversions.h" | |
| 8 #include "content/browser/frame_host/frame_tree.h" | |
| 9 #include "content/browser/loader/resource_dispatcher_host_impl.h" | 7 #include "content/browser/loader/resource_dispatcher_host_impl.h" |
| 10 #include "content/browser/renderer_host/render_view_host_impl.h" | |
| 11 #include "content/browser/web_contents/web_contents_impl.h" | |
| 12 #include "content/public/browser/navigation_entry.h" | 8 #include "content/public/browser/navigation_entry.h" |
| 13 #include "content/public/browser/notification_observer.h" | |
| 14 #include "content/public/browser/notification_service.h" | |
| 15 #include "content/public/browser/notification_types.h" | |
| 16 #include "content/public/browser/resource_dispatcher_host_delegate.h" | 9 #include "content/public/browser/resource_dispatcher_host_delegate.h" |
| 17 #include "content/public/browser/resource_throttle.h" | 10 #include "content/public/browser/resource_throttle.h" |
| 18 #include "content/public/browser/web_contents_observer.h" | 11 #include "content/public/browser/web_contents.h" |
| 19 #include "content/public/common/content_switches.h" | 12 #include "content/public/common/content_switches.h" |
| 20 #include "content/public/common/url_constants.h" | |
| 21 #include "content/public/test/browser_test_utils.h" | 13 #include "content/public/test/browser_test_utils.h" |
| 22 #include "content/public/test/test_navigation_observer.h" | 14 #include "content/public/test/test_navigation_observer.h" |
| 23 #include "content/public/test/test_utils.h" | |
| 24 #include "content/shell/browser/shell.h" | 15 #include "content/shell/browser/shell.h" |
| 25 #include "content/shell/browser/shell_content_browser_client.h" | 16 #include "content/shell/browser/shell_content_browser_client.h" |
| 26 #include "content/shell/browser/shell_resource_dispatcher_host_delegate.h" | 17 #include "content/shell/browser/shell_resource_dispatcher_host_delegate.h" |
| 27 #include "content/test/content_browser_test.h" | 18 #include "content/test/content_browser_test.h" |
| 28 #include "content/test/content_browser_test_utils.h" | 19 #include "content/test/content_browser_test_utils.h" |
| 29 #include "net/base/escape.h" | 20 #include "net/base/escape.h" |
| 30 #include "net/dns/mock_host_resolver.h" | 21 #include "net/dns/mock_host_resolver.h" |
| 31 #include "net/url_request/url_request.h" | 22 #include "net/url_request/url_request.h" |
| 32 #include "net/url_request/url_request_status.h" | 23 #include "net/url_request/url_request_status.h" |
| 24 #include "url/gurl.h" |
| 33 | 25 |
| 34 namespace content { | 26 namespace content { |
| 35 | 27 |
| 36 class SitePerProcessWebContentsObserver: public WebContentsObserver { | |
| 37 public: | |
| 38 explicit SitePerProcessWebContentsObserver(WebContents* web_contents) | |
| 39 : WebContentsObserver(web_contents), | |
| 40 navigation_succeeded_(false) {} | |
| 41 virtual ~SitePerProcessWebContentsObserver() {} | |
| 42 | |
| 43 virtual void DidStartProvisionalLoadForFrame( | |
| 44 int64 frame_id, | |
| 45 int64 parent_frame_id, | |
| 46 bool is_main_frame, | |
| 47 const GURL& validated_url, | |
| 48 bool is_error_page, | |
| 49 bool is_iframe_srcdoc, | |
| 50 RenderViewHost* render_view_host) OVERRIDE { | |
| 51 navigation_succeeded_ = false; | |
| 52 } | |
| 53 | |
| 54 virtual void DidFailProvisionalLoad( | |
| 55 int64 frame_id, | |
| 56 const base::string16& frame_unique_name, | |
| 57 bool is_main_frame, | |
| 58 const GURL& validated_url, | |
| 59 int error_code, | |
| 60 const base::string16& error_description, | |
| 61 RenderViewHost* render_view_host) OVERRIDE { | |
| 62 navigation_url_ = validated_url; | |
| 63 navigation_succeeded_ = false; | |
| 64 } | |
| 65 | |
| 66 virtual void DidCommitProvisionalLoadForFrame( | |
| 67 int64 frame_id, | |
| 68 const base::string16& frame_unique_name, | |
| 69 bool is_main_frame, | |
| 70 const GURL& url, | |
| 71 PageTransition transition_type, | |
| 72 RenderViewHost* render_view_host) OVERRIDE{ | |
| 73 navigation_url_ = url; | |
| 74 navigation_succeeded_ = true; | |
| 75 } | |
| 76 | |
| 77 const GURL& navigation_url() const { | |
| 78 return navigation_url_; | |
| 79 } | |
| 80 | |
| 81 int navigation_succeeded() const { return navigation_succeeded_; } | |
| 82 | |
| 83 private: | |
| 84 GURL navigation_url_; | |
| 85 bool navigation_succeeded_; | |
| 86 | |
| 87 DISALLOW_COPY_AND_ASSIGN(SitePerProcessWebContentsObserver); | |
| 88 }; | |
| 89 | |
| 90 class RedirectNotificationObserver : public NotificationObserver { | |
| 91 public: | |
| 92 // Register to listen for notifications of the given type from either a | |
| 93 // specific source, or from all sources if |source| is | |
| 94 // NotificationService::AllSources(). | |
| 95 RedirectNotificationObserver(int notification_type, | |
| 96 const NotificationSource& source); | |
| 97 virtual ~RedirectNotificationObserver(); | |
| 98 | |
| 99 // Wait until the specified notification occurs. If the notification was | |
| 100 // emitted between the construction of this object and this call then it | |
| 101 // returns immediately. | |
| 102 void Wait(); | |
| 103 | |
| 104 // Returns NotificationService::AllSources() if we haven't observed a | |
| 105 // notification yet. | |
| 106 const NotificationSource& source() const { | |
| 107 return source_; | |
| 108 } | |
| 109 | |
| 110 const NotificationDetails& details() const { | |
| 111 return details_; | |
| 112 } | |
| 113 | |
| 114 // NotificationObserver: | |
| 115 virtual void Observe(int type, | |
| 116 const NotificationSource& source, | |
| 117 const NotificationDetails& details) OVERRIDE; | |
| 118 | |
| 119 private: | |
| 120 bool seen_; | |
| 121 bool seen_twice_; | |
| 122 bool running_; | |
| 123 NotificationRegistrar registrar_; | |
| 124 | |
| 125 NotificationSource source_; | |
| 126 NotificationDetails details_; | |
| 127 scoped_refptr<MessageLoopRunner> message_loop_runner_; | |
| 128 | |
| 129 DISALLOW_COPY_AND_ASSIGN(RedirectNotificationObserver); | |
| 130 }; | |
| 131 | |
| 132 RedirectNotificationObserver::RedirectNotificationObserver( | |
| 133 int notification_type, | |
| 134 const NotificationSource& source) | |
| 135 : seen_(false), | |
| 136 running_(false), | |
| 137 source_(NotificationService::AllSources()) { | |
| 138 registrar_.Add(this, notification_type, source); | |
| 139 } | |
| 140 | |
| 141 RedirectNotificationObserver::~RedirectNotificationObserver() {} | |
| 142 | |
| 143 void RedirectNotificationObserver::Wait() { | |
| 144 if (seen_ && seen_twice_) | |
| 145 return; | |
| 146 | |
| 147 running_ = true; | |
| 148 message_loop_runner_ = new MessageLoopRunner; | |
| 149 message_loop_runner_->Run(); | |
| 150 EXPECT_TRUE(seen_); | |
| 151 } | |
| 152 | |
| 153 void RedirectNotificationObserver::Observe( | |
| 154 int type, | |
| 155 const NotificationSource& source, | |
| 156 const NotificationDetails& details) { | |
| 157 source_ = source; | |
| 158 details_ = details; | |
| 159 seen_twice_ = seen_; | |
| 160 seen_ = true; | |
| 161 if (!running_) | |
| 162 return; | |
| 163 | |
| 164 message_loop_runner_->Quit(); | |
| 165 running_ = false; | |
| 166 } | |
| 167 | |
| 168 // Tracks a single request for a specified URL, and allows waiting until the | 28 // Tracks a single request for a specified URL, and allows waiting until the |
| 169 // request is destroyed, and then inspecting whether it completed successfully. | 29 // request is destroyed, and then inspecting whether it completed successfully. |
| 170 class TrackingResourceDispatcherHostDelegate | 30 class TrackingResourceDispatcherHostDelegate |
| 171 : public ShellResourceDispatcherHostDelegate { | 31 : public ShellResourceDispatcherHostDelegate { |
| 172 public: | 32 public: |
| 173 TrackingResourceDispatcherHostDelegate() : throttle_created_(false) { | 33 TrackingResourceDispatcherHostDelegate() : throttle_created_(false) { |
| 174 } | 34 } |
| 175 | 35 |
| 176 virtual void RequestBeginning( | 36 virtual void RequestBeginning( |
| 177 net::URLRequest* request, | 37 net::URLRequest* request, |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 params.should_replace_current_entry; | 162 params.should_replace_current_entry; |
| 303 load_url_params.is_renderer_initiated = true; | 163 load_url_params.is_renderer_initiated = true; |
| 304 source->GetController().LoadURLWithParams(load_url_params); | 164 source->GetController().LoadURLWithParams(load_url_params); |
| 305 return source; | 165 return source; |
| 306 } | 166 } |
| 307 | 167 |
| 308 private: | 168 private: |
| 309 DISALLOW_COPY_AND_ASSIGN(NoTransferRequestDelegate); | 169 DISALLOW_COPY_AND_ASSIGN(NoTransferRequestDelegate); |
| 310 }; | 170 }; |
| 311 | 171 |
| 312 class SitePerProcessBrowserTest : public ContentBrowserTest { | 172 class CrossSiteTransferTest : public ContentBrowserTest { |
| 313 public: | 173 public: |
| 314 SitePerProcessBrowserTest() : old_delegate_(NULL) { | 174 CrossSiteTransferTest() : old_delegate_(NULL) { |
| 315 } | 175 } |
| 316 | 176 |
| 317 // ContentBrowserTest implementation: | 177 // ContentBrowserTest implementation: |
| 318 virtual void SetUpOnMainThread() OVERRIDE { | 178 virtual void SetUpOnMainThread() OVERRIDE { |
| 319 BrowserThread::PostTask( | 179 BrowserThread::PostTask( |
| 320 BrowserThread::IO, FROM_HERE, | 180 BrowserThread::IO, FROM_HERE, |
| 321 base::Bind( | 181 base::Bind( |
| 322 &SitePerProcessBrowserTest::InjectResourceDisptcherHostDelegate, | 182 &CrossSiteTransferTest::InjectResourceDisptcherHostDelegate, |
| 323 base::Unretained(this))); | 183 base::Unretained(this))); |
| 324 } | 184 } |
| 325 | 185 |
| 326 virtual void TearDownOnMainThread() OVERRIDE { | 186 virtual void TearDownOnMainThread() OVERRIDE { |
| 327 BrowserThread::PostTask( | 187 BrowserThread::PostTask( |
| 328 BrowserThread::IO, FROM_HERE, | 188 BrowserThread::IO, FROM_HERE, |
| 329 base::Bind( | 189 base::Bind( |
| 330 &SitePerProcessBrowserTest::RestoreResourceDisptcherHostDelegate, | 190 &CrossSiteTransferTest::RestoreResourceDisptcherHostDelegate, |
| 331 base::Unretained(this))); | 191 base::Unretained(this))); |
| 332 } | 192 } |
| 333 | 193 |
| 334 protected: | 194 protected: |
| 335 // Start at a data URL so each extra navigation creates a navigation entry. | |
| 336 // (The first navigation will silently be classified as AUTO_SUBFRAME.) | |
| 337 // TODO(creis): This won't be necessary when we can wait for LOAD_STOP. | |
| 338 void StartFrameAtDataURL() { | |
| 339 std::string data_url_script = | |
| 340 "var iframes = document.getElementById('test');iframes.src=" | |
| 341 "'data:text/html,dataurl';"; | |
| 342 ASSERT_TRUE(ExecuteScript(shell()->web_contents(), data_url_script)); | |
| 343 } | |
| 344 | |
| 345 bool NavigateIframeToURL(Shell* window, | |
| 346 const GURL& url, | |
| 347 std::string iframe_id) { | |
| 348 // TODO(creis): This should wait for LOAD_STOP, but cross-site subframe | |
| 349 // navigations generate extra DidStartLoading and DidStopLoading messages. | |
| 350 // Until we replace swappedout:// with frame proxies, we need to listen for | |
| 351 // something else. For now, we trigger NEW_SUBFRAME navigations and listen | |
| 352 // for commit. | |
| 353 std::string script = base::StringPrintf( | |
| 354 "setTimeout(\"" | |
| 355 "var iframes = document.getElementById('%s');iframes.src='%s';" | |
| 356 "\",0)", | |
| 357 iframe_id.c_str(), url.spec().c_str()); | |
| 358 WindowedNotificationObserver load_observer( | |
| 359 NOTIFICATION_NAV_ENTRY_COMMITTED, | |
| 360 Source<NavigationController>( | |
| 361 &window->web_contents()->GetController())); | |
| 362 bool result = ExecuteScript(window->web_contents(), script); | |
| 363 load_observer.Wait(); | |
| 364 return result; | |
| 365 } | |
| 366 | |
| 367 void NavigateToURLContentInitiated(Shell* window, | 195 void NavigateToURLContentInitiated(Shell* window, |
| 368 const GURL& url, | 196 const GURL& url, |
| 369 bool should_replace_current_entry, | 197 bool should_replace_current_entry, |
| 370 bool should_wait_for_navigation) { | 198 bool should_wait_for_navigation) { |
| 371 std::string script; | 199 std::string script; |
| 372 if (should_replace_current_entry) | 200 if (should_replace_current_entry) |
| 373 script = base::StringPrintf("location.replace('%s')", url.spec().c_str()); | 201 script = base::StringPrintf("location.replace('%s')", url.spec().c_str()); |
| 374 else | 202 else |
| 375 script = base::StringPrintf("location.href = '%s'", url.spec().c_str()); | 203 script = base::StringPrintf("location.href = '%s'", url.spec().c_str()); |
| 376 TestNavigationObserver load_observer(shell()->web_contents(), 1); | 204 TestNavigationObserver load_observer(shell()->web_contents(), 1); |
| 377 bool result = ExecuteScript(window->web_contents(), script); | 205 bool result = ExecuteScript(window->web_contents(), script); |
| 378 EXPECT_TRUE(result); | 206 EXPECT_TRUE(result); |
| 379 if (should_wait_for_navigation) | 207 if (should_wait_for_navigation) |
| 380 load_observer.Wait(); | 208 load_observer.Wait(); |
| 381 } | 209 } |
| 382 | 210 |
| 383 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | 211 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { |
| 212 // Use --site-per-process to force process swaps for cross-site transfers. |
| 384 command_line->AppendSwitch(switches::kSitePerProcess); | 213 command_line->AppendSwitch(switches::kSitePerProcess); |
| 385 | |
| 386 // TODO(creis): Remove this when GTK is no longer a supported platform. | |
| 387 command_line->AppendSwitch(switches::kForceCompositingMode); | |
| 388 } | 214 } |
| 389 | 215 |
| 390 void InjectResourceDisptcherHostDelegate() { | 216 void InjectResourceDisptcherHostDelegate() { |
| 391 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 217 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 392 old_delegate_ = ResourceDispatcherHostImpl::Get()->delegate(); | 218 old_delegate_ = ResourceDispatcherHostImpl::Get()->delegate(); |
| 393 ResourceDispatcherHostImpl::Get()->SetDelegate(&tracking_delegate_); | 219 ResourceDispatcherHostImpl::Get()->SetDelegate(&tracking_delegate_); |
| 394 } | 220 } |
| 395 | 221 |
| 396 void RestoreResourceDisptcherHostDelegate() { | 222 void RestoreResourceDisptcherHostDelegate() { |
| 397 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 223 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 398 ResourceDispatcherHostImpl::Get()->SetDelegate(old_delegate_); | 224 ResourceDispatcherHostImpl::Get()->SetDelegate(old_delegate_); |
| 399 old_delegate_ = NULL; | 225 old_delegate_ = NULL; |
| 400 } | 226 } |
| 401 | 227 |
| 402 TrackingResourceDispatcherHostDelegate& tracking_delegate() { | 228 TrackingResourceDispatcherHostDelegate& tracking_delegate() { |
| 403 return tracking_delegate_; | 229 return tracking_delegate_; |
| 404 } | 230 } |
| 405 | 231 |
| 406 private: | 232 private: |
| 407 TrackingResourceDispatcherHostDelegate tracking_delegate_; | 233 TrackingResourceDispatcherHostDelegate tracking_delegate_; |
| 408 ResourceDispatcherHostDelegate* old_delegate_; | 234 ResourceDispatcherHostDelegate* old_delegate_; |
| 409 }; | 235 }; |
| 410 | 236 |
| 411 // Ensure that we can complete a cross-process subframe navigation. | |
| 412 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframe) { | |
| 413 host_resolver()->AddRule("*", "127.0.0.1"); | |
| 414 ASSERT_TRUE(test_server()->Start()); | |
| 415 GURL main_url(test_server()->GetURL("files/site_per_process_main.html")); | |
| 416 NavigateToURL(shell(), main_url); | |
| 417 | |
| 418 StartFrameAtDataURL(); | |
| 419 | |
| 420 SitePerProcessWebContentsObserver observer(shell()->web_contents()); | |
| 421 | |
| 422 // Load same-site page into iframe. | |
| 423 GURL http_url(test_server()->GetURL("files/title1.html")); | |
| 424 EXPECT_TRUE(NavigateIframeToURL(shell(), http_url, "test")); | |
| 425 EXPECT_EQ(http_url, observer.navigation_url()); | |
| 426 EXPECT_TRUE(observer.navigation_succeeded()); | |
| 427 | |
| 428 // These must stay in scope with replace_host. | |
| 429 GURL::Replacements replace_host; | |
| 430 std::string foo_com("foo.com"); | |
| 431 | |
| 432 // Load cross-site page into iframe. | |
| 433 GURL cross_site_url(test_server()->GetURL("files/title2.html")); | |
| 434 replace_host.SetHostStr(foo_com); | |
| 435 cross_site_url = cross_site_url.ReplaceComponents(replace_host); | |
| 436 EXPECT_TRUE(NavigateIframeToURL(shell(), cross_site_url, "test")); | |
| 437 EXPECT_EQ(cross_site_url, observer.navigation_url()); | |
| 438 EXPECT_TRUE(observer.navigation_succeeded()); | |
| 439 | |
| 440 // Ensure that we have created a new process for the subframe. | |
| 441 FrameTreeNode* root = | |
| 442 static_cast<WebContentsImpl*>(shell()->web_contents())-> | |
| 443 GetFrameTree()->root(); | |
| 444 ASSERT_EQ(1U, root->child_count()); | |
| 445 FrameTreeNode* child = root->child_at(0); | |
| 446 EXPECT_NE(shell()->web_contents()->GetRenderViewHost(), | |
| 447 child->current_frame_host()->render_view_host()); | |
| 448 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), | |
| 449 child->current_frame_host()->render_view_host()->GetSiteInstance()); | |
| 450 EXPECT_NE(shell()->web_contents()->GetRenderProcessHost(), | |
| 451 child->current_frame_host()->GetProcess()); | |
| 452 } | |
| 453 | |
| 454 // Crash a subframe and ensures its children are cleared from the FrameTree. | |
| 455 // See http://crbug.com/338508. | |
| 456 // TODO(creis): Enable this on Android when we can kill the process there. | |
| 457 #if defined(OS_ANDROID) | |
| 458 #define MAYBE_CrashSubframe DISABLED_CrashSubframe | |
| 459 #else | |
| 460 #define MAYBE_CrashSubframe CrashSubframe | |
| 461 #endif | |
| 462 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_CrashSubframe) { | |
| 463 host_resolver()->AddRule("*", "127.0.0.1"); | |
| 464 ASSERT_TRUE(test_server()->Start()); | |
| 465 GURL main_url(test_server()->GetURL("files/site_per_process_main.html")); | |
| 466 NavigateToURL(shell(), main_url); | |
| 467 | |
| 468 StartFrameAtDataURL(); | |
| 469 | |
| 470 // These must stay in scope with replace_host. | |
| 471 GURL::Replacements replace_host; | |
| 472 std::string foo_com("foo.com"); | |
| 473 | |
| 474 // Load cross-site page into iframe. | |
| 475 GURL cross_site_url(test_server()->GetURL("files/title2.html")); | |
| 476 replace_host.SetHostStr(foo_com); | |
| 477 cross_site_url = cross_site_url.ReplaceComponents(replace_host); | |
| 478 EXPECT_TRUE(NavigateIframeToURL(shell(), cross_site_url, "test")); | |
| 479 | |
| 480 // Check the subframe process. | |
| 481 FrameTreeNode* root = | |
| 482 static_cast<WebContentsImpl*>(shell()->web_contents())-> | |
| 483 GetFrameTree()->root(); | |
| 484 ASSERT_EQ(1U, root->child_count()); | |
| 485 FrameTreeNode* child = root->child_at(0); | |
| 486 EXPECT_EQ(main_url, root->current_url()); | |
| 487 EXPECT_EQ(cross_site_url, child->current_url()); | |
| 488 | |
| 489 // Crash the subframe process. | |
| 490 RenderProcessHost* root_process = root->current_frame_host()->GetProcess(); | |
| 491 RenderProcessHost* child_process = child->current_frame_host()->GetProcess(); | |
| 492 { | |
| 493 RenderProcessHostWatcher crash_observer( | |
| 494 child_process, | |
| 495 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); | |
| 496 base::KillProcess(child_process->GetHandle(), 0, false); | |
| 497 crash_observer.Wait(); | |
| 498 } | |
| 499 | |
| 500 // Ensure that the child frame still exists but has been cleared. | |
| 501 EXPECT_EQ(1U, root->child_count()); | |
| 502 EXPECT_EQ(main_url, root->current_url()); | |
| 503 EXPECT_EQ(GURL(), child->current_url()); | |
| 504 | |
| 505 // Now crash the top-level page to clear the child frame. | |
| 506 { | |
| 507 RenderProcessHostWatcher crash_observer( | |
| 508 root_process, | |
| 509 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); | |
| 510 base::KillProcess(root_process->GetHandle(), 0, false); | |
| 511 crash_observer.Wait(); | |
| 512 } | |
| 513 EXPECT_EQ(0U, root->child_count()); | |
| 514 EXPECT_EQ(GURL(), root->current_url()); | |
| 515 } | |
| 516 | |
| 517 // TODO(nasko): Disable this test until out-of-process iframes is ready and the | |
| 518 // security checks are back in place. | |
| 519 // TODO(creis): Replace SpawnedTestServer with host_resolver to get test to run | |
| 520 // on Android (http://crbug.com/187570). | |
| 521 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, | |
| 522 DISABLED_CrossSiteIframeRedirectOnce) { | |
| 523 ASSERT_TRUE(test_server()->Start()); | |
| 524 net::SpawnedTestServer https_server( | |
| 525 net::SpawnedTestServer::TYPE_HTTPS, | |
| 526 net::SpawnedTestServer::kLocalhost, | |
| 527 base::FilePath(FILE_PATH_LITERAL("content/test/data"))); | |
| 528 ASSERT_TRUE(https_server.Start()); | |
| 529 | |
| 530 GURL main_url(test_server()->GetURL("files/site_per_process_main.html")); | |
| 531 GURL http_url(test_server()->GetURL("files/title1.html")); | |
| 532 GURL https_url(https_server.GetURL("files/title1.html")); | |
| 533 | |
| 534 NavigateToURL(shell(), main_url); | |
| 535 | |
| 536 SitePerProcessWebContentsObserver observer(shell()->web_contents()); | |
| 537 { | |
| 538 // Load cross-site client-redirect page into Iframe. | |
| 539 // Should be blocked. | |
| 540 GURL client_redirect_https_url(https_server.GetURL( | |
| 541 "client-redirect?files/title1.html")); | |
| 542 EXPECT_TRUE(NavigateIframeToURL(shell(), | |
| 543 client_redirect_https_url, "test")); | |
| 544 // DidFailProvisionalLoad when navigating to client_redirect_https_url. | |
| 545 EXPECT_EQ(observer.navigation_url(), client_redirect_https_url); | |
| 546 EXPECT_FALSE(observer.navigation_succeeded()); | |
| 547 } | |
| 548 | |
| 549 { | |
| 550 // Load cross-site server-redirect page into Iframe, | |
| 551 // which redirects to same-site page. | |
| 552 GURL server_redirect_http_url(https_server.GetURL( | |
| 553 "server-redirect?" + http_url.spec())); | |
| 554 EXPECT_TRUE(NavigateIframeToURL(shell(), | |
| 555 server_redirect_http_url, "test")); | |
| 556 EXPECT_EQ(observer.navigation_url(), http_url); | |
| 557 EXPECT_TRUE(observer.navigation_succeeded()); | |
| 558 } | |
| 559 | |
| 560 { | |
| 561 // Load cross-site server-redirect page into Iframe, | |
| 562 // which redirects to cross-site page. | |
| 563 GURL server_redirect_http_url(https_server.GetURL( | |
| 564 "server-redirect?files/title1.html")); | |
| 565 EXPECT_TRUE(NavigateIframeToURL(shell(), | |
| 566 server_redirect_http_url, "test")); | |
| 567 // DidFailProvisionalLoad when navigating to https_url. | |
| 568 EXPECT_EQ(observer.navigation_url(), https_url); | |
| 569 EXPECT_FALSE(observer.navigation_succeeded()); | |
| 570 } | |
| 571 | |
| 572 { | |
| 573 // Load same-site server-redirect page into Iframe, | |
| 574 // which redirects to cross-site page. | |
| 575 GURL server_redirect_http_url(test_server()->GetURL( | |
| 576 "server-redirect?" + https_url.spec())); | |
| 577 EXPECT_TRUE(NavigateIframeToURL(shell(), | |
| 578 server_redirect_http_url, "test")); | |
| 579 | |
| 580 EXPECT_EQ(observer.navigation_url(), https_url); | |
| 581 EXPECT_FALSE(observer.navigation_succeeded()); | |
| 582 } | |
| 583 | |
| 584 { | |
| 585 // Load same-site client-redirect page into Iframe, | |
| 586 // which redirects to cross-site page. | |
| 587 GURL client_redirect_http_url(test_server()->GetURL( | |
| 588 "client-redirect?" + https_url.spec())); | |
| 589 | |
| 590 RedirectNotificationObserver load_observer2( | |
| 591 NOTIFICATION_LOAD_STOP, | |
| 592 Source<NavigationController>( | |
| 593 &shell()->web_contents()->GetController())); | |
| 594 | |
| 595 EXPECT_TRUE(NavigateIframeToURL(shell(), | |
| 596 client_redirect_http_url, "test")); | |
| 597 | |
| 598 // Same-site Client-Redirect Page should be loaded successfully. | |
| 599 EXPECT_EQ(observer.navigation_url(), client_redirect_http_url); | |
| 600 EXPECT_TRUE(observer.navigation_succeeded()); | |
| 601 | |
| 602 // Redirecting to Cross-site Page should be blocked. | |
| 603 load_observer2.Wait(); | |
| 604 EXPECT_EQ(observer.navigation_url(), https_url); | |
| 605 EXPECT_FALSE(observer.navigation_succeeded()); | |
| 606 } | |
| 607 | |
| 608 { | |
| 609 // Load same-site server-redirect page into Iframe, | |
| 610 // which redirects to same-site page. | |
| 611 GURL server_redirect_http_url(test_server()->GetURL( | |
| 612 "server-redirect?files/title1.html")); | |
| 613 EXPECT_TRUE(NavigateIframeToURL(shell(), | |
| 614 server_redirect_http_url, "test")); | |
| 615 EXPECT_EQ(observer.navigation_url(), http_url); | |
| 616 EXPECT_TRUE(observer.navigation_succeeded()); | |
| 617 } | |
| 618 | |
| 619 { | |
| 620 // Load same-site client-redirect page into Iframe, | |
| 621 // which redirects to same-site page. | |
| 622 GURL client_redirect_http_url(test_server()->GetURL( | |
| 623 "client-redirect?" + http_url.spec())); | |
| 624 RedirectNotificationObserver load_observer2( | |
| 625 NOTIFICATION_LOAD_STOP, | |
| 626 Source<NavigationController>( | |
| 627 &shell()->web_contents()->GetController())); | |
| 628 | |
| 629 EXPECT_TRUE(NavigateIframeToURL(shell(), | |
| 630 client_redirect_http_url, "test")); | |
| 631 | |
| 632 // Same-site Client-Redirect Page should be loaded successfully. | |
| 633 EXPECT_EQ(observer.navigation_url(), client_redirect_http_url); | |
| 634 EXPECT_TRUE(observer.navigation_succeeded()); | |
| 635 | |
| 636 // Redirecting to Same-site Page should be loaded successfully. | |
| 637 load_observer2.Wait(); | |
| 638 EXPECT_EQ(observer.navigation_url(), http_url); | |
| 639 EXPECT_TRUE(observer.navigation_succeeded()); | |
| 640 } | |
| 641 } | |
| 642 | |
| 643 // TODO(nasko): Disable this test until out-of-process iframes is ready and the | |
| 644 // security checks are back in place. | |
| 645 // TODO(creis): Replace SpawnedTestServer with host_resolver to get test to run | |
| 646 // on Android (http://crbug.com/187570). | |
| 647 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, | |
| 648 DISABLED_CrossSiteIframeRedirectTwice) { | |
| 649 ASSERT_TRUE(test_server()->Start()); | |
| 650 net::SpawnedTestServer https_server( | |
| 651 net::SpawnedTestServer::TYPE_HTTPS, | |
| 652 net::SpawnedTestServer::kLocalhost, | |
| 653 base::FilePath(FILE_PATH_LITERAL("content/test/data"))); | |
| 654 ASSERT_TRUE(https_server.Start()); | |
| 655 | |
| 656 GURL main_url(test_server()->GetURL("files/site_per_process_main.html")); | |
| 657 GURL http_url(test_server()->GetURL("files/title1.html")); | |
| 658 GURL https_url(https_server.GetURL("files/title1.html")); | |
| 659 | |
| 660 NavigateToURL(shell(), main_url); | |
| 661 | |
| 662 SitePerProcessWebContentsObserver observer(shell()->web_contents()); | |
| 663 { | |
| 664 // Load client-redirect page pointing to a cross-site client-redirect page, | |
| 665 // which eventually redirects back to same-site page. | |
| 666 GURL client_redirect_https_url(https_server.GetURL( | |
| 667 "client-redirect?" + http_url.spec())); | |
| 668 GURL client_redirect_http_url(test_server()->GetURL( | |
| 669 "client-redirect?" + client_redirect_https_url.spec())); | |
| 670 | |
| 671 // We should wait until second client redirect get cancelled. | |
| 672 RedirectNotificationObserver load_observer2( | |
| 673 NOTIFICATION_LOAD_STOP, | |
| 674 Source<NavigationController>( | |
| 675 &shell()->web_contents()->GetController())); | |
| 676 | |
| 677 EXPECT_TRUE(NavigateIframeToURL(shell(), client_redirect_http_url, "test")); | |
| 678 | |
| 679 // DidFailProvisionalLoad when navigating to client_redirect_https_url. | |
| 680 load_observer2.Wait(); | |
| 681 EXPECT_EQ(observer.navigation_url(), client_redirect_https_url); | |
| 682 EXPECT_FALSE(observer.navigation_succeeded()); | |
| 683 } | |
| 684 | |
| 685 { | |
| 686 // Load server-redirect page pointing to a cross-site server-redirect page, | |
| 687 // which eventually redirect back to same-site page. | |
| 688 GURL server_redirect_https_url(https_server.GetURL( | |
| 689 "server-redirect?" + http_url.spec())); | |
| 690 GURL server_redirect_http_url(test_server()->GetURL( | |
| 691 "server-redirect?" + server_redirect_https_url.spec())); | |
| 692 EXPECT_TRUE(NavigateIframeToURL(shell(), | |
| 693 server_redirect_http_url, "test")); | |
| 694 EXPECT_EQ(observer.navigation_url(), http_url); | |
| 695 EXPECT_TRUE(observer.navigation_succeeded()); | |
| 696 } | |
| 697 | |
| 698 { | |
| 699 // Load server-redirect page pointing to a cross-site server-redirect page, | |
| 700 // which eventually redirects back to cross-site page. | |
| 701 GURL server_redirect_https_url(https_server.GetURL( | |
| 702 "server-redirect?" + https_url.spec())); | |
| 703 GURL server_redirect_http_url(test_server()->GetURL( | |
| 704 "server-redirect?" + server_redirect_https_url.spec())); | |
| 705 EXPECT_TRUE(NavigateIframeToURL(shell(), server_redirect_http_url, "test")); | |
| 706 | |
| 707 // DidFailProvisionalLoad when navigating to https_url. | |
| 708 EXPECT_EQ(observer.navigation_url(), https_url); | |
| 709 EXPECT_FALSE(observer.navigation_succeeded()); | |
| 710 } | |
| 711 | |
| 712 { | |
| 713 // Load server-redirect page pointing to a cross-site client-redirect page, | |
| 714 // which eventually redirects back to same-site page. | |
| 715 GURL client_redirect_http_url(https_server.GetURL( | |
| 716 "client-redirect?" + http_url.spec())); | |
| 717 GURL server_redirect_http_url(test_server()->GetURL( | |
| 718 "server-redirect?" + client_redirect_http_url.spec())); | |
| 719 EXPECT_TRUE(NavigateIframeToURL(shell(), server_redirect_http_url, "test")); | |
| 720 | |
| 721 // DidFailProvisionalLoad when navigating to client_redirect_http_url. | |
| 722 EXPECT_EQ(observer.navigation_url(), client_redirect_http_url); | |
| 723 EXPECT_FALSE(observer.navigation_succeeded()); | |
| 724 } | |
| 725 } | |
| 726 | |
| 727 // Tests that the |should_replace_current_entry| flag persists correctly across | 237 // Tests that the |should_replace_current_entry| flag persists correctly across |
| 728 // request transfers that began with a cross-process navigation. | 238 // request transfers that began with a cross-process navigation. |
| 729 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, | 239 IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest, |
| 730 ReplaceEntryCrossProcessThenTransfer) { | 240 ReplaceEntryCrossProcessThenTransfer) { |
| 731 const NavigationController& controller = | 241 const NavigationController& controller = |
| 732 shell()->web_contents()->GetController(); | 242 shell()->web_contents()->GetController(); |
| 733 host_resolver()->AddRule("*", "127.0.0.1"); | 243 host_resolver()->AddRule("*", "127.0.0.1"); |
| 734 ASSERT_TRUE(test_server()->Start()); | 244 ASSERT_TRUE(test_server()->Start()); |
| 735 | 245 |
| 736 // These must all stay in scope with replace_host. | 246 // These must all stay in scope with replace_host. |
| 737 GURL::Replacements replace_host; | 247 GURL::Replacements replace_host; |
| 738 std::string a_com("A.com"); | 248 std::string a_com("A.com"); |
| 739 std::string b_com("B.com"); | 249 std::string b_com("B.com"); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 787 EXPECT_EQ(url3, controller.GetEntryAtIndex(1)->GetURL()); | 297 EXPECT_EQ(url3, controller.GetEntryAtIndex(1)->GetURL()); |
| 788 | 298 |
| 789 // Make sure the request succeeded. | 299 // Make sure the request succeeded. |
| 790 EXPECT_TRUE(tracking_delegate().WaitForTrackedURLAndGetCompleted()); | 300 EXPECT_TRUE(tracking_delegate().WaitForTrackedURLAndGetCompleted()); |
| 791 } | 301 } |
| 792 | 302 |
| 793 // Tests that the |should_replace_current_entry| flag persists correctly across | 303 // Tests that the |should_replace_current_entry| flag persists correctly across |
| 794 // request transfers that began with a content-initiated in-process | 304 // request transfers that began with a content-initiated in-process |
| 795 // navigation. This test is the same as the test above, except transfering from | 305 // navigation. This test is the same as the test above, except transfering from |
| 796 // in-process. | 306 // in-process. |
| 797 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, | 307 IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest, |
| 798 ReplaceEntryInProcessThenTranfers) { | 308 ReplaceEntryInProcessThenTranfers) { |
| 799 const NavigationController& controller = | 309 const NavigationController& controller = |
| 800 shell()->web_contents()->GetController(); | 310 shell()->web_contents()->GetController(); |
| 801 ASSERT_TRUE(test_server()->Start()); | 311 ASSERT_TRUE(test_server()->Start()); |
| 802 | 312 |
| 803 // Navigate to a starting URL, so there is a history entry to replace. | 313 // Navigate to a starting URL, so there is a history entry to replace. |
| 804 GURL url = test_server()->GetURL("files/site_isolation/blank.html?1"); | 314 GURL url = test_server()->GetURL("files/site_isolation/blank.html?1"); |
| 805 NavigateToURL(shell(), url); | 315 NavigateToURL(shell(), url); |
| 806 | 316 |
| 807 // Force all future navigations to transfer. Note that this includes same-site | 317 // Force all future navigations to transfer. Note that this includes same-site |
| (...skipping 21 matching lines...) Expand all Loading... |
| 829 // should not have replaced url3. | 339 // should not have replaced url3. |
| 830 EXPECT_TRUE(controller.GetPendingEntry() == NULL); | 340 EXPECT_TRUE(controller.GetPendingEntry() == NULL); |
| 831 EXPECT_EQ(2, controller.GetEntryCount()); | 341 EXPECT_EQ(2, controller.GetEntryCount()); |
| 832 EXPECT_EQ(1, controller.GetCurrentEntryIndex()); | 342 EXPECT_EQ(1, controller.GetCurrentEntryIndex()); |
| 833 EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL()); | 343 EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL()); |
| 834 EXPECT_EQ(url3, controller.GetEntryAtIndex(1)->GetURL()); | 344 EXPECT_EQ(url3, controller.GetEntryAtIndex(1)->GetURL()); |
| 835 } | 345 } |
| 836 | 346 |
| 837 // Tests that the |should_replace_current_entry| flag persists correctly across | 347 // Tests that the |should_replace_current_entry| flag persists correctly across |
| 838 // request transfers that cross processes twice from renderer policy. | 348 // request transfers that cross processes twice from renderer policy. |
| 839 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, | 349 IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest, |
| 840 ReplaceEntryCrossProcessTwice) { | 350 ReplaceEntryCrossProcessTwice) { |
| 841 const NavigationController& controller = | 351 const NavigationController& controller = |
| 842 shell()->web_contents()->GetController(); | 352 shell()->web_contents()->GetController(); |
| 843 host_resolver()->AddRule("*", "127.0.0.1"); | 353 host_resolver()->AddRule("*", "127.0.0.1"); |
| 844 ASSERT_TRUE(test_server()->Start()); | 354 ASSERT_TRUE(test_server()->Start()); |
| 845 | 355 |
| 846 // These must all stay in scope with replace_host. | 356 // These must all stay in scope with replace_host. |
| 847 GURL::Replacements replace_host; | 357 GURL::Replacements replace_host; |
| 848 std::string a_com("A.com"); | 358 std::string a_com("A.com"); |
| 849 std::string b_com("B.com"); | 359 std::string b_com("B.com"); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 886 // should not have replaced url3b. | 396 // should not have replaced url3b. |
| 887 EXPECT_TRUE(controller.GetPendingEntry() == NULL); | 397 EXPECT_TRUE(controller.GetPendingEntry() == NULL); |
| 888 EXPECT_EQ(2, controller.GetEntryCount()); | 398 EXPECT_EQ(2, controller.GetEntryCount()); |
| 889 EXPECT_EQ(1, controller.GetCurrentEntryIndex()); | 399 EXPECT_EQ(1, controller.GetCurrentEntryIndex()); |
| 890 EXPECT_EQ(url2b, controller.GetEntryAtIndex(0)->GetURL()); | 400 EXPECT_EQ(url2b, controller.GetEntryAtIndex(0)->GetURL()); |
| 891 EXPECT_EQ(url3b, controller.GetEntryAtIndex(1)->GetURL()); | 401 EXPECT_EQ(url3b, controller.GetEntryAtIndex(1)->GetURL()); |
| 892 } | 402 } |
| 893 | 403 |
| 894 // Tests that the request is destroyed when a cross process navigation is | 404 // Tests that the request is destroyed when a cross process navigation is |
| 895 // cancelled. | 405 // cancelled. |
| 896 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NoLeakOnCrossSiteCancel) { | 406 IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest, NoLeakOnCrossSiteCancel) { |
| 897 const NavigationController& controller = | 407 const NavigationController& controller = |
| 898 shell()->web_contents()->GetController(); | 408 shell()->web_contents()->GetController(); |
| 899 host_resolver()->AddRule("*", "127.0.0.1"); | 409 host_resolver()->AddRule("*", "127.0.0.1"); |
| 900 ASSERT_TRUE(test_server()->Start()); | 410 ASSERT_TRUE(test_server()->Start()); |
| 901 | 411 |
| 902 // These must all stay in scope with replace_host. | 412 // These must all stay in scope with replace_host. |
| 903 GURL::Replacements replace_host; | 413 GURL::Replacements replace_host; |
| 904 std::string a_com("A.com"); | 414 std::string a_com("A.com"); |
| 905 std::string b_com("B.com"); | 415 std::string b_com("B.com"); |
| 906 | 416 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 935 EXPECT_EQ(0, controller.GetCurrentEntryIndex()); | 445 EXPECT_EQ(0, controller.GetCurrentEntryIndex()); |
| 936 EXPECT_EQ(url1, controller.GetEntryAtIndex(0)->GetURL()); | 446 EXPECT_EQ(url1, controller.GetEntryAtIndex(0)->GetURL()); |
| 937 | 447 |
| 938 // Make sure the request for url2 did not complete. | 448 // Make sure the request for url2 did not complete. |
| 939 EXPECT_FALSE(tracking_delegate().WaitForTrackedURLAndGetCompleted()); | 449 EXPECT_FALSE(tracking_delegate().WaitForTrackedURLAndGetCompleted()); |
| 940 | 450 |
| 941 shell()->web_contents()->SetDelegate(old_delegate); | 451 shell()->web_contents()->SetDelegate(old_delegate); |
| 942 } | 452 } |
| 943 | 453 |
| 944 } // namespace content | 454 } // namespace content |
| OLD | NEW |