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 |