Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "content/browser/frame_host/navigation_handle_impl.h" | 5 #include "content/browser/frame_host/navigation_handle_impl.h" |
| 6 #include "content/browser/web_contents/web_contents_impl.h" | 6 #include "content/browser/web_contents/web_contents_impl.h" |
| 7 #include "content/public/browser/web_contents.h" | 7 #include "content/public/browser/web_contents.h" |
| 8 #include "content/public/browser/web_contents_observer.h" | 8 #include "content/public/browser/web_contents_observer.h" |
| 9 #include "content/public/test/browser_test_utils.h" | 9 #include "content/public/test/browser_test_utils.h" |
| 10 #include "content/public/test/content_browser_test.h" | 10 #include "content/public/test/content_browser_test.h" |
| 11 #include "content/public/test/content_browser_test_utils.h" | 11 #include "content/public/test/content_browser_test_utils.h" |
| 12 #include "content/public/test/test_navigation_observer.h" | |
| 13 #include "content/public/test/test_utils.h" | |
| 12 #include "content/shell/browser/shell.h" | 14 #include "content/shell/browser/shell.h" |
| 13 #include "net/dns/mock_host_resolver.h" | 15 #include "net/dns/mock_host_resolver.h" |
| 14 #include "ui/base/page_transition_types.h" | 16 #include "ui/base/page_transition_types.h" |
| 15 #include "url/url_constants.h" | 17 #include "url/url_constants.h" |
| 16 | 18 |
| 17 namespace content { | 19 namespace content { |
| 18 | 20 |
| 19 namespace { | 21 namespace { |
| 20 | 22 |
| 21 class NavigationHandleObserver : public WebContentsObserver { | 23 class NavigationHandleObserver : public WebContentsObserver { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 104 bool is_parent_main_frame_; | 106 bool is_parent_main_frame_; |
| 105 bool is_synchronous_; | 107 bool is_synchronous_; |
| 106 bool is_srcdoc_; | 108 bool is_srcdoc_; |
| 107 bool was_redirected_; | 109 bool was_redirected_; |
| 108 int frame_tree_node_id_; | 110 int frame_tree_node_id_; |
| 109 ui::PageTransition page_transition_; | 111 ui::PageTransition page_transition_; |
| 110 GURL expected_url_; | 112 GURL expected_url_; |
| 111 GURL last_committed_url_; | 113 GURL last_committed_url_; |
| 112 }; | 114 }; |
| 113 | 115 |
| 116 // A test NavigationThrottle that will return pre-determined checks and run | |
| 117 // callbacks when the various NavigationThrottle methods are called. | |
| 118 class TestNavigationThrottle : public NavigationThrottle { | |
| 119 public: | |
| 120 TestNavigationThrottle( | |
| 121 NavigationHandle* handle, | |
| 122 NavigationThrottle::ThrottleCheckResult will_start_result, | |
| 123 NavigationThrottle::ThrottleCheckResult will_redirect_result, | |
| 124 NavigationThrottle::ThrottleCheckResult will_process_result, | |
| 125 base::Closure did_call_will_start, | |
| 126 base::Closure did_call_will_redirect, | |
| 127 base::Closure did_call_will_process) | |
| 128 : NavigationThrottle(handle), | |
| 129 will_start_result_(will_start_result), | |
| 130 will_redirect_result_(will_redirect_result), | |
| 131 will_process_result_(will_process_result), | |
| 132 did_call_will_start_(did_call_will_start), | |
| 133 did_call_will_redirect_(did_call_will_redirect), | |
| 134 did_call_will_process_(did_call_will_process) {} | |
| 135 ~TestNavigationThrottle() override {} | |
| 136 | |
| 137 void Resume() { navigation_handle()->Resume(); } | |
| 138 | |
| 139 private: | |
| 140 // NavigationThrottle implementation. | |
| 141 NavigationThrottle::ThrottleCheckResult WillStartRequest() override { | |
| 142 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, did_call_will_start_); | |
| 143 return will_start_result_; | |
| 144 } | |
| 145 | |
| 146 NavigationThrottle::ThrottleCheckResult WillRedirectRequest() override { | |
| 147 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 148 did_call_will_redirect_); | |
| 149 return will_redirect_result_; | |
| 150 } | |
| 151 | |
| 152 NavigationThrottle::ThrottleCheckResult WillProcessResponse() override { | |
| 153 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 154 did_call_will_process_); | |
| 155 return will_process_result_; | |
| 156 } | |
| 157 | |
| 158 NavigationThrottle::ThrottleCheckResult will_start_result_; | |
| 159 NavigationThrottle::ThrottleCheckResult will_redirect_result_; | |
| 160 NavigationThrottle::ThrottleCheckResult will_process_result_; | |
| 161 base::Closure did_call_will_start_; | |
| 162 base::Closure did_call_will_redirect_; | |
| 163 base::Closure did_call_will_process_; | |
| 164 }; | |
| 165 | |
| 166 // Install a TestNavigationThrottle on all requests and allows waiting for | |
| 167 // various NavigationThrottle related events. | |
| 168 class TestNavigationThrottleInstaller : public WebContentsObserver { | |
| 169 public: | |
| 170 TestNavigationThrottleInstaller( | |
| 171 WebContents* web_contents, | |
| 172 NavigationThrottle::ThrottleCheckResult will_start_result, | |
| 173 NavigationThrottle::ThrottleCheckResult will_redirect_result, | |
| 174 NavigationThrottle::ThrottleCheckResult will_process_result) | |
| 175 : WebContentsObserver(web_contents), | |
| 176 will_start_result_(will_start_result), | |
| 177 will_redirect_result_(will_redirect_result), | |
| 178 will_process_result_(will_process_result), | |
| 179 will_start_called_(0), | |
| 180 will_redirect_called_(0), | |
| 181 will_process_called_(0), | |
| 182 navigation_throttle_(nullptr) {} | |
| 183 ~TestNavigationThrottleInstaller() override{}; | |
| 184 | |
| 185 TestNavigationThrottle* navigation_throttle() { return navigation_throttle_; } | |
| 186 | |
| 187 void WaitForThrottleInstallation() { | |
| 188 if (navigation_throttle_) | |
| 189 return; | |
| 190 install_loop_runner_ = new MessageLoopRunner(); | |
| 191 install_loop_runner_->Run(); | |
| 192 install_loop_runner_ = nullptr; | |
| 193 } | |
| 194 | |
| 195 void WaitForThrottleWillStart() { | |
| 196 if (will_start_called_) | |
| 197 return; | |
| 198 will_start_loop_runner_ = new MessageLoopRunner(); | |
| 199 will_start_loop_runner_->Run(); | |
| 200 will_start_loop_runner_ = nullptr; | |
| 201 } | |
| 202 | |
| 203 void WaitForThrottleWillRedirect() { | |
| 204 if (will_redirect_called_) | |
| 205 return; | |
| 206 will_redirect_loop_runner_ = new MessageLoopRunner(); | |
| 207 will_redirect_loop_runner_->Run(); | |
| 208 will_redirect_loop_runner_ = nullptr; | |
| 209 } | |
| 210 | |
| 211 void WaitForThrottleWillProcess() { | |
| 212 if (will_process_called_) | |
| 213 return; | |
| 214 will_process_loop_runner_ = new MessageLoopRunner(); | |
| 215 will_process_loop_runner_->Run(); | |
| 216 will_process_loop_runner_ = nullptr; | |
| 217 } | |
| 218 | |
| 219 int will_start_called() { return will_start_called_; } | |
| 220 int will_redirect_called() { return will_redirect_called_; } | |
| 221 int will_process_called() { return will_process_called_; } | |
| 222 | |
| 223 private: | |
| 224 void DidStartNavigation(NavigationHandle* handle) override { | |
| 225 scoped_ptr<NavigationThrottle> throttle(new TestNavigationThrottle( | |
| 226 handle, will_start_result_, will_redirect_result_, will_process_result_, | |
| 227 base::Bind(&TestNavigationThrottleInstaller::DidCallWillStartRequest, | |
| 228 base::Unretained(this)), | |
| 229 base::Bind(&TestNavigationThrottleInstaller::DidCallWillRedirectRequest, | |
| 230 base::Unretained(this)), | |
| 231 base::Bind(&TestNavigationThrottleInstaller::DidCallWillProcessResponse, | |
| 232 base::Unretained(this)))); | |
| 233 navigation_throttle_ = static_cast<TestNavigationThrottle*>(throttle.get()); | |
| 234 handle->RegisterThrottleForTesting(std::move(throttle)); | |
| 235 | |
| 236 if (install_loop_runner_) | |
| 237 install_loop_runner_->Quit(); | |
|
nasko
2016/03/18 21:51:43
Why do we need to run the message loop here?
clamy
2016/03/23 14:36:44
Removed the functionality to wait for the installa
| |
| 238 } | |
| 239 | |
| 240 void DidFinishNavigation(NavigationHandle* handle) override { | |
| 241 if (!navigation_throttle_) | |
| 242 return; | |
| 243 | |
| 244 if (handle == navigation_throttle_->navigation_handle()) | |
| 245 navigation_throttle_ = nullptr; | |
|
nasko
2016/03/18 21:51:43
nit: .reset()?
clamy
2016/03/23 14:36:43
navigation_throttle_ is a raw pointer (NavigationH
| |
| 246 } | |
| 247 | |
| 248 void DidCallWillStartRequest() { | |
| 249 will_start_called_++; | |
| 250 if (will_start_loop_runner_) | |
| 251 will_start_loop_runner_->Quit(); | |
| 252 } | |
| 253 | |
| 254 void DidCallWillRedirectRequest() { | |
| 255 will_redirect_called_++; | |
| 256 if (will_redirect_loop_runner_) | |
| 257 will_redirect_loop_runner_->Quit(); | |
| 258 } | |
| 259 | |
| 260 void DidCallWillProcessResponse() { | |
| 261 will_process_called_++; | |
| 262 if (will_process_loop_runner_) | |
| 263 will_process_loop_runner_->Quit(); | |
| 264 } | |
| 265 | |
| 266 NavigationThrottle::ThrottleCheckResult will_start_result_; | |
| 267 NavigationThrottle::ThrottleCheckResult will_redirect_result_; | |
| 268 NavigationThrottle::ThrottleCheckResult will_process_result_; | |
| 269 int will_start_called_; | |
| 270 int will_redirect_called_; | |
| 271 int will_process_called_; | |
| 272 TestNavigationThrottle* navigation_throttle_; | |
| 273 scoped_refptr<MessageLoopRunner> install_loop_runner_; | |
| 274 scoped_refptr<MessageLoopRunner> will_start_loop_runner_; | |
| 275 scoped_refptr<MessageLoopRunner> will_redirect_loop_runner_; | |
| 276 scoped_refptr<MessageLoopRunner> will_process_loop_runner_; | |
| 277 }; | |
| 278 | |
| 114 } // namespace | 279 } // namespace |
| 115 | 280 |
| 116 class NavigationHandleImplBrowserTest : public ContentBrowserTest { | 281 class NavigationHandleImplBrowserTest : public ContentBrowserTest { |
| 117 protected: | 282 protected: |
| 118 void SetUpOnMainThread() override { | 283 void SetUpOnMainThread() override { |
| 119 host_resolver()->AddRule("*", "127.0.0.1"); | 284 host_resolver()->AddRule("*", "127.0.0.1"); |
| 120 ASSERT_TRUE(embedded_test_server()->Start()); | 285 ASSERT_TRUE(embedded_test_server()->Start()); |
| 121 SetupCrossSiteRedirector(embedded_test_server()); | 286 SetupCrossSiteRedirector(embedded_test_server()); |
| 122 } | 287 } |
| 123 }; | 288 }; |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 262 NavigationHandleObserver observer( | 427 NavigationHandleObserver observer( |
| 263 shell()->web_contents(), embedded_test_server()->GetURL("a.com", "/bar")); | 428 shell()->web_contents(), embedded_test_server()->GetURL("a.com", "/bar")); |
| 264 EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), | 429 EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), |
| 265 "window.history.pushState({}, '', 'bar');")); | 430 "window.history.pushState({}, '', 'bar');")); |
| 266 | 431 |
| 267 EXPECT_TRUE(observer.has_committed()); | 432 EXPECT_TRUE(observer.has_committed()); |
| 268 EXPECT_FALSE(observer.is_error()); | 433 EXPECT_FALSE(observer.is_error()); |
| 269 EXPECT_TRUE(observer.is_synchronous()); | 434 EXPECT_TRUE(observer.is_synchronous()); |
| 270 } | 435 } |
| 271 | 436 |
| 437 // Ensure that NavigationThrottles can cancel the navigation at navigation | |
|
nasko
2016/03/18 21:51:43
Thanks for adding those browser tests!
nit: Navig
clamy
2016/03/23 14:36:44
Done.
| |
| 438 // start. | |
| 439 IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, ThrottleCancelStart) { | |
| 440 GURL start_url(embedded_test_server()->GetURL("/title1.html")); | |
| 441 EXPECT_TRUE(NavigateToURL(shell(), start_url)); | |
| 442 | |
| 443 GURL redirect_url( | |
| 444 embedded_test_server()->GetURL("/cross-site/bar.com/title2.html")); | |
| 445 NavigationHandleObserver observer(shell()->web_contents(), redirect_url); | |
| 446 TestNavigationThrottleInstaller installer( | |
| 447 shell()->web_contents(), NavigationThrottle::CANCEL, | |
| 448 NavigationThrottle::PROCEED, NavigationThrottle::PROCEED); | |
| 449 | |
| 450 EXPECT_FALSE(NavigateToURL(shell(), redirect_url)); | |
| 451 | |
| 452 EXPECT_FALSE(observer.has_committed()); | |
| 453 EXPECT_TRUE(observer.is_error()); | |
| 454 // The navigation should have been canceled before being redirected. | |
|
nasko
2016/03/18 21:51:43
nit: Empty line above comment for readability.
clamy
2016/03/23 14:36:43
Done.
| |
| 455 EXPECT_FALSE(observer.was_redirected()); | |
| 456 EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), start_url); | |
| 457 } | |
| 458 | |
| 459 // Ensure that NavigationThrottles can cancel the navigation when a navigation | |
| 460 // is redirected. | |
| 461 IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, | |
| 462 ThrottleCancelRedirect) { | |
| 463 GURL start_url(embedded_test_server()->GetURL("/title1.html")); | |
| 464 EXPECT_TRUE(NavigateToURL(shell(), start_url)); | |
| 465 | |
| 466 // A navigation with a redirect should be canceled. | |
| 467 { | |
| 468 GURL redirect_url( | |
| 469 embedded_test_server()->GetURL("/cross-site/bar.com/title2.html")); | |
| 470 NavigationHandleObserver observer(shell()->web_contents(), redirect_url); | |
| 471 TestNavigationThrottleInstaller installer( | |
| 472 shell()->web_contents(), NavigationThrottle::PROCEED, | |
| 473 NavigationThrottle::CANCEL, NavigationThrottle::PROCEED); | |
| 474 | |
| 475 EXPECT_FALSE(NavigateToURL(shell(), redirect_url)); | |
| 476 | |
| 477 EXPECT_FALSE(observer.has_committed()); | |
| 478 EXPECT_TRUE(observer.is_error()); | |
| 479 EXPECT_TRUE(observer.was_redirected()); | |
| 480 EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), start_url); | |
| 481 } | |
| 482 | |
| 483 // A navigation without redirects should be successful. | |
| 484 { | |
| 485 GURL no_redirect_url(embedded_test_server()->GetURL("/title2.html")); | |
| 486 NavigationHandleObserver observer(shell()->web_contents(), no_redirect_url); | |
| 487 TestNavigationThrottleInstaller installer( | |
| 488 shell()->web_contents(), NavigationThrottle::PROCEED, | |
| 489 NavigationThrottle::CANCEL, NavigationThrottle::PROCEED); | |
| 490 | |
| 491 EXPECT_TRUE(NavigateToURL(shell(), no_redirect_url)); | |
| 492 | |
| 493 EXPECT_TRUE(observer.has_committed()); | |
| 494 EXPECT_FALSE(observer.is_error()); | |
| 495 EXPECT_FALSE(observer.was_redirected()); | |
| 496 EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), no_redirect_url); | |
| 497 } | |
| 498 } | |
| 499 | |
| 500 // Ensure that NavigationThrottles can cancel the navigation when the response | |
| 501 // is received. | |
| 502 IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, | |
| 503 ThrottleCancelResponse) { | |
| 504 GURL start_url(embedded_test_server()->GetURL("/title1.html")); | |
| 505 EXPECT_TRUE(NavigateToURL(shell(), start_url)); | |
| 506 | |
| 507 GURL redirect_url( | |
| 508 embedded_test_server()->GetURL("/cross-site/bar.com/title2.html")); | |
| 509 NavigationHandleObserver observer(shell()->web_contents(), redirect_url); | |
| 510 TestNavigationThrottleInstaller installer( | |
| 511 shell()->web_contents(), NavigationThrottle::PROCEED, | |
| 512 NavigationThrottle::PROCEED, NavigationThrottle::CANCEL); | |
| 513 | |
| 514 EXPECT_FALSE(NavigateToURL(shell(), redirect_url)); | |
| 515 | |
| 516 EXPECT_FALSE(observer.has_committed()); | |
| 517 EXPECT_TRUE(observer.is_error()); | |
| 518 // The navigation should have been redirected first, and then canceled when | |
| 519 // the response arrived. | |
| 520 EXPECT_TRUE(observer.was_redirected()); | |
| 521 EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), start_url); | |
| 522 } | |
| 523 | |
| 524 // Ensure that NavigationThrottles can defer and resume the navigation at | |
| 525 // navigation start, navigation redirect and response received. | |
| 526 IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, ThrottleDefer) { | |
| 527 GURL start_url(embedded_test_server()->GetURL("/title1.html")); | |
| 528 EXPECT_TRUE(NavigateToURL(shell(), start_url)); | |
| 529 | |
| 530 GURL redirect_url( | |
| 531 embedded_test_server()->GetURL("/cross-site/bar.com/title2.html")); | |
| 532 TestNavigationObserver navigation_observer(shell()->web_contents(), 1); | |
| 533 NavigationHandleObserver observer(shell()->web_contents(), redirect_url); | |
| 534 TestNavigationThrottleInstaller installer( | |
| 535 shell()->web_contents(), NavigationThrottle::DEFER, | |
| 536 NavigationThrottle::DEFER, NavigationThrottle::DEFER); | |
| 537 | |
| 538 shell()->LoadURL(redirect_url); | |
| 539 | |
| 540 installer.WaitForThrottleInstallation(); | |
|
nasko
2016/03/18 21:51:43
Why do we need to wait for this? Isn't the throttl
clamy
2016/03/23 14:36:44
Removed it since it's not very useful.
| |
| 541 CHECK(installer.navigation_throttle()); | |
| 542 | |
| 543 // Wait for WillStartRequest. | |
| 544 installer.WaitForThrottleWillStart(); | |
| 545 EXPECT_EQ(1, installer.will_start_called()); | |
| 546 EXPECT_EQ(0, installer.will_redirect_called()); | |
| 547 EXPECT_EQ(0, installer.will_process_called()); | |
| 548 installer.navigation_throttle()->Resume(); | |
| 549 | |
| 550 // Wait for WillRedirectRequest. | |
| 551 installer.WaitForThrottleWillRedirect(); | |
| 552 EXPECT_EQ(1, installer.will_start_called()); | |
| 553 EXPECT_EQ(1, installer.will_redirect_called()); | |
| 554 EXPECT_EQ(0, installer.will_process_called()); | |
| 555 installer.navigation_throttle()->Resume(); | |
| 556 | |
| 557 // Wait for WillProcessResponse. | |
| 558 installer.WaitForThrottleWillProcess(); | |
| 559 EXPECT_EQ(1, installer.will_start_called()); | |
| 560 EXPECT_EQ(1, installer.will_redirect_called()); | |
| 561 EXPECT_EQ(1, installer.will_process_called()); | |
| 562 installer.navigation_throttle()->Resume(); | |
| 563 | |
| 564 // Wait for the end of the navigation. | |
| 565 navigation_observer.Wait(); | |
| 566 | |
| 567 EXPECT_TRUE(observer.has_committed()); | |
| 568 EXPECT_TRUE(observer.was_redirected()); | |
| 569 EXPECT_FALSE(observer.is_error()); | |
| 570 EXPECT_TRUE(observer.was_redirected()); | |
|
nasko
2016/03/18 21:51:43
Isn't this the same check as the one two lines abo
clamy
2016/03/23 14:36:44
Indeed. Removed it.
| |
| 571 EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), | |
| 572 GURL(embedded_test_server()->GetURL("bar.com", "/title2.html"))); | |
| 573 } | |
| 574 | |
| 272 } // namespace content | 575 } // namespace content |
| OLD | NEW |