| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <deque> | 5 #include <deque> |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/memory/scoped_temp_dir.h" | 8 #include "base/memory/scoped_temp_dir.h" |
| 9 #include "base/path_service.h" | 9 #include "base/path_service.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 std::string CreateClientRedirect(const std::string& dest_url) { | 46 std::string CreateClientRedirect(const std::string& dest_url) { |
| 47 const char* const kClientRedirectBase = "client-redirect?"; | 47 const char* const kClientRedirectBase = "client-redirect?"; |
| 48 return kClientRedirectBase + dest_url; | 48 return kClientRedirectBase + dest_url; |
| 49 } | 49 } |
| 50 | 50 |
| 51 std::string CreateServerRedirect(const std::string& dest_url) { | 51 std::string CreateServerRedirect(const std::string& dest_url) { |
| 52 const char* const kServerRedirectBase = "server-redirect?"; | 52 const char* const kServerRedirectBase = "server-redirect?"; |
| 53 return kServerRedirectBase + dest_url; | 53 return kServerRedirectBase + dest_url; |
| 54 } | 54 } |
| 55 | 55 |
| 56 // Returns true iff the final status is one in which the prerendered |
| 57 // page should prerender correctly. The page still may not be used. |
| 58 bool ShouldRenderPrerenderedPageCorrectly(FinalStatus status) { |
| 59 switch (status) { |
| 60 case FINAL_STATUS_USED: |
| 61 case FINAL_STATUS_WINDOW_OPENER: |
| 62 return true; |
| 63 default: |
| 64 return false; |
| 65 } |
| 66 } |
| 67 |
| 56 // PrerenderContents that stops the UI message loop on DidStopLoading(). | 68 // PrerenderContents that stops the UI message loop on DidStopLoading(). |
| 57 class TestPrerenderContents : public PrerenderContents { | 69 class TestPrerenderContents : public PrerenderContents { |
| 58 public: | 70 public: |
| 59 TestPrerenderContents( | 71 TestPrerenderContents( |
| 60 PrerenderManager* prerender_manager, | 72 PrerenderManager* prerender_manager, |
| 61 Profile* profile, | 73 Profile* profile, |
| 62 const GURL& url, | 74 const GURL& url, |
| 63 const GURL& referrer, | 75 const GURL& referrer, |
| 64 int number_of_loads, | 76 int number_of_loads, |
| 65 FinalStatus expected_final_status) | 77 FinalStatus expected_final_status) |
| (...skipping 23 matching lines...) Expand all Loading... |
| 89 if (final_status() == FINAL_STATUS_USED) { | 101 if (final_status() == FINAL_STATUS_USED) { |
| 90 EXPECT_TRUE(new_render_view_host_); | 102 EXPECT_TRUE(new_render_view_host_); |
| 91 EXPECT_TRUE(was_shown_); | 103 EXPECT_TRUE(was_shown_); |
| 92 } else { | 104 } else { |
| 93 EXPECT_FALSE(was_shown_); | 105 EXPECT_FALSE(was_shown_); |
| 94 } | 106 } |
| 95 | 107 |
| 96 // When the PrerenderContents is destroyed, quit the UI message loop. | 108 // When the PrerenderContents is destroyed, quit the UI message loop. |
| 97 // This happens on navigation to used prerendered pages, and soon | 109 // This happens on navigation to used prerendered pages, and soon |
| 98 // after cancellation of unused prerendered pages. | 110 // after cancellation of unused prerendered pages. |
| 111 MessageLoopForUI::current()->RunAllPending(); |
| 99 MessageLoopForUI::current()->Quit(); | 112 MessageLoopForUI::current()->Quit(); |
| 100 } | 113 } |
| 101 | 114 |
| 102 virtual void OnRenderViewGone(int status, int exit_code) OVERRIDE { | 115 virtual void OnRenderViewGone(int status, int exit_code) OVERRIDE { |
| 103 // On quit, it's possible to end up here when render processes are closed | 116 // On quit, it's possible to end up here when render processes are closed |
| 104 // before the PrerenderManager is destroyed. As a result, it's possible to | 117 // before the PrerenderManager is destroyed. As a result, it's possible to |
| 105 // get either FINAL_STATUS_APP_TERMINATING or FINAL_STATUS_RENDERER_CRASHED | 118 // get either FINAL_STATUS_APP_TERMINATING or FINAL_STATUS_RENDERER_CRASHED |
| 106 // on quit. | 119 // on quit. |
| 107 if (expected_final_status_ == FINAL_STATUS_APP_TERMINATING) | 120 if (expected_final_status_ == FINAL_STATUS_APP_TERMINATING) |
| 108 expected_final_status_ = FINAL_STATUS_RENDERER_CRASHED; | 121 expected_final_status_ = FINAL_STATUS_RENDERER_CRASHED; |
| 109 | 122 |
| 110 PrerenderContents::OnRenderViewGone(status, exit_code); | 123 PrerenderContents::OnRenderViewGone(status, exit_code); |
| 111 } | 124 } |
| 112 | 125 |
| 113 virtual void DidStopLoading() OVERRIDE { | 126 virtual void DidStopLoading() OVERRIDE { |
| 114 PrerenderContents::DidStopLoading(); | 127 PrerenderContents::DidStopLoading(); |
| 115 ++number_of_loads_; | 128 ++number_of_loads_; |
| 116 if (expected_final_status_ == FINAL_STATUS_USED && | 129 if (ShouldRenderPrerenderedPageCorrectly(expected_final_status_) && |
| 117 number_of_loads_ >= expected_number_of_loads_) { | 130 number_of_loads_ >= expected_number_of_loads_) { |
| 118 MessageLoopForUI::current()->Quit(); | 131 MessageLoopForUI::current()->Quit(); |
| 119 } else if (expected_final_status_ == FINAL_STATUS_RENDERER_CRASHED) { | 132 } else if (expected_final_status_ == FINAL_STATUS_RENDERER_CRASHED) { |
| 120 // Crash the render process. This has to be done here because | 133 // Crash the render process. This has to be done here because |
| 121 // a prerender navigating to about:crash is cancelled with | 134 // a prerender navigating to about:crash is cancelled with |
| 122 // "FINAL_STATUS_HTTPS". Even if this were worked around, | 135 // "FINAL_STATUS_HTTPS". Even if this were worked around, |
| 123 // about:crash can't be navigated to by a normal webpage. | 136 // about:crash can't be navigated to by a normal webpage. |
| 124 render_view_host_mutable()->NavigateToURL(GURL("about:crash")); | 137 render_view_host_mutable()->NavigateToURL(GURL("about:crash")); |
| 125 } | 138 } |
| 126 } | 139 } |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 ASSERT_TRUE(test_server()->Start()); | 290 ASSERT_TRUE(test_server()->Start()); |
| 278 std::deque<FinalStatus> expected_final_status_queue(1, | 291 std::deque<FinalStatus> expected_final_status_queue(1, |
| 279 expected_final_status); | 292 expected_final_status); |
| 280 PrerenderTestURLImpl(url, expected_final_status_queue, total_navigations); | 293 PrerenderTestURLImpl(url, expected_final_status_queue, total_navigations); |
| 281 } | 294 } |
| 282 | 295 |
| 283 void NavigateToDestURL() const { | 296 void NavigateToDestURL() const { |
| 284 NavigateToURLImpl(dest_url_); | 297 NavigateToURLImpl(dest_url_); |
| 285 } | 298 } |
| 286 | 299 |
| 300 void OpenDestUrlInNewWindowViaJs() const { |
| 301 // Make sure in navigating we have a URL to use in the PrerenderManager. |
| 302 EXPECT_TRUE(prerender_manager()->FindEntry(dest_url_) != NULL); |
| 303 |
| 304 bool open_window_result = false; |
| 305 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( |
| 306 browser()->GetSelectedTabContents()->render_view_host(), L"", |
| 307 L"window.domAutomationController.send(JsOpenLinkInNewWindow())", |
| 308 &open_window_result)); |
| 309 EXPECT_TRUE(open_window_result); |
| 310 } |
| 311 |
| 312 void OpenDestUrlInNewWindowViaClick() const { |
| 313 // Make sure in navigating we have a URL to use in the PrerenderManager. |
| 314 EXPECT_TRUE(prerender_manager()->FindEntry(dest_url_) != NULL); |
| 315 |
| 316 bool click_prerendered_link_result = false; |
| 317 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( |
| 318 browser()->GetSelectedTabContents()->render_view_host(), L"", |
| 319 L"window.domAutomationController.send(ClickOpenLinkInNewWindow())", |
| 320 &click_prerendered_link_result)); |
| 321 EXPECT_TRUE(click_prerendered_link_result); |
| 322 } |
| 323 |
| 287 // Should be const but test_server()->GetURL(...) is not const. | 324 // Should be const but test_server()->GetURL(...) is not const. |
| 288 void NavigateToURL(const std::string& dest_html_file) { | 325 void NavigateToURL(const std::string& dest_html_file) { |
| 289 GURL dest_url = test_server()->GetURL(dest_html_file); | 326 GURL dest_url = test_server()->GetURL(dest_html_file); |
| 290 NavigateToURLImpl(dest_url); | 327 NavigateToURLImpl(dest_url); |
| 291 } | 328 } |
| 292 | 329 |
| 293 bool UrlIsInPrerenderManager(const std::string& html_file) { | 330 bool UrlIsInPrerenderManager(const std::string& html_file) { |
| 294 GURL dest_url = test_server()->GetURL(html_file); | 331 GURL dest_url = test_server()->GetURL(html_file); |
| 295 return (prerender_manager()->FindEntry(dest_url) != NULL); | 332 return (prerender_manager()->FindEntry(dest_url) != NULL); |
| 296 } | 333 } |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 // handle browser navigation directly. | 404 // handle browser navigation directly. |
| 368 browser()->OpenURL(src_url, GURL(), CURRENT_TAB, PageTransition::TYPED); | 405 browser()->OpenURL(src_url, GURL(), CURRENT_TAB, PageTransition::TYPED); |
| 369 | 406 |
| 370 TestPrerenderContents* prerender_contents = NULL; | 407 TestPrerenderContents* prerender_contents = NULL; |
| 371 ui_test_utils::RunMessageLoop(); | 408 ui_test_utils::RunMessageLoop(); |
| 372 | 409 |
| 373 prerender_contents = | 410 prerender_contents = |
| 374 static_cast<TestPrerenderContents*>( | 411 static_cast<TestPrerenderContents*>( |
| 375 prerender_manager()->FindEntry(dest_url_)); | 412 prerender_manager()->FindEntry(dest_url_)); |
| 376 | 413 |
| 377 switch (expected_final_status) { | 414 if (ShouldRenderPrerenderedPageCorrectly(expected_final_status)) { |
| 378 case FINAL_STATUS_USED: { | 415 ASSERT_TRUE(prerender_contents != NULL); |
| 379 ASSERT_TRUE(prerender_contents != NULL); | 416 EXPECT_EQ(FINAL_STATUS_MAX, prerender_contents->final_status()); |
| 380 | 417 |
| 381 if (call_javascript_) { | 418 if (call_javascript_) { |
| 382 // Check if page behaves as expected while in prerendered state. | 419 // Check if page behaves as expected while in prerendered state. |
| 383 bool prerender_test_result = false; | 420 bool prerender_test_result = false; |
| 384 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( | 421 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( |
| 385 prerender_contents->render_view_host_mutable(), L"", | 422 prerender_contents->render_view_host_mutable(), L"", |
| 386 L"window.domAutomationController.send(DidPrerenderPass())", | 423 L"window.domAutomationController.send(DidPrerenderPass())", |
| 387 &prerender_test_result)); | 424 &prerender_test_result)); |
| 388 EXPECT_TRUE(prerender_test_result); | 425 EXPECT_TRUE(prerender_test_result); |
| 389 } | |
| 390 break; | |
| 391 } | 426 } |
| 392 default: | 427 } else { |
| 393 // In the failure case, we should have removed dest_url_ from the | 428 // In the failure case, we should have removed dest_url_ from the |
| 394 // prerender_manager. | 429 // prerender_manager. |
| 395 EXPECT_TRUE(prerender_contents == NULL); | 430 EXPECT_TRUE(prerender_contents == NULL); |
| 396 break; | |
| 397 } | 431 } |
| 398 } | 432 } |
| 399 | 433 |
| 400 void NavigateToURLImpl(const GURL& dest_url) const { | 434 void NavigateToURLImpl(const GURL& dest_url) const { |
| 401 // Make sure in navigating we have a URL to use in the PrerenderManager. | 435 // Make sure in navigating we have a URL to use in the PrerenderManager. |
| 402 EXPECT_TRUE(prerender_manager()->FindEntry(dest_url_) != NULL); | 436 EXPECT_TRUE(prerender_manager()->FindEntry(dest_url_) != NULL); |
| 403 | 437 |
| 404 // ui_test_utils::NavigateToURL waits until DidStopLoading is called on | 438 // ui_test_utils::NavigateToURL waits until DidStopLoading is called on |
| 405 // the current tab. As that tab is going to end up deleted, and may never | 439 // the current tab. As that tab is going to end up deleted, and may never |
| 406 // finish loading before that happens, exit the message loop on the deletion | 440 // finish loading before that happens, exit the message loop on the deletion |
| (...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1074 NavigateToDestURL(); | 1108 NavigateToDestURL(); |
| 1075 } | 1109 } |
| 1076 | 1110 |
| 1077 // Checks that we cancel correctly when window.print() is called. | 1111 // Checks that we cancel correctly when window.print() is called. |
| 1078 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPrint) { | 1112 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPrint) { |
| 1079 PrerenderTestURL("files/prerender/prerender_print.html", | 1113 PrerenderTestURL("files/prerender/prerender_print.html", |
| 1080 FINAL_STATUS_WINDOW_PRINT, | 1114 FINAL_STATUS_WINDOW_PRINT, |
| 1081 1); | 1115 1); |
| 1082 } | 1116 } |
| 1083 | 1117 |
| 1118 // Checks that if a page is opened in a new window by javascript the |
| 1119 // prerendered page is not used. |
| 1120 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, |
| 1121 PrerenderWindowOpenerJsOpenInNewPageTest) { |
| 1122 PrerenderTestURL("files/prerender/prerender_page.html", |
| 1123 FINAL_STATUS_WINDOW_OPENER, |
| 1124 1); |
| 1125 OpenDestUrlInNewWindowViaJs(); |
| 1126 } |
| 1127 |
| 1128 // Checks that if a page is opened due to click on a href with target="_blank" |
| 1129 // the prerendered page is not used. |
| 1130 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, |
| 1131 PrerenderWindowOpenerClickOpenInNewPageTest) { |
| 1132 PrerenderTestURL("files/prerender/prerender_page.html", |
| 1133 FINAL_STATUS_WINDOW_OPENER, |
| 1134 1); |
| 1135 OpenDestUrlInNewWindowViaClick(); |
| 1136 } |
| 1137 |
| 1138 // TODO(shishir): Add a test for the case when the page having the |
| 1139 // prerendering link already has an opener set. |
| 1140 |
| 1084 } // namespace prerender | 1141 } // namespace prerender |
| OLD | NEW |