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 "base/command_line.h" | 5 #include "base/command_line.h" |
6 #include "base/path_service.h" | 6 #include "base/path_service.h" |
7 #include "chrome/browser/prerender/prerender_contents.h" | 7 #include "chrome/browser/prerender/prerender_contents.h" |
8 #include "chrome/browser/prerender/prerender_manager.h" | 8 #include "chrome/browser/prerender/prerender_manager.h" |
9 #include "chrome/browser/profiles/profile.h" | 9 #include "chrome/browser/profiles/profile.h" |
10 #include "chrome/browser/ui/browser.h" | 10 #include "chrome/browser/ui/browser.h" |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 }; | 78 }; |
79 | 79 |
80 // PrerenderManager that uses TestPrerenderContents. | 80 // PrerenderManager that uses TestPrerenderContents. |
81 class WaitForLoadPrerenderContentsFactory : public PrerenderContents::Factory { | 81 class WaitForLoadPrerenderContentsFactory : public PrerenderContents::Factory { |
82 public: | 82 public: |
83 explicit WaitForLoadPrerenderContentsFactory( | 83 explicit WaitForLoadPrerenderContentsFactory( |
84 FinalStatus expected_final_status) | 84 FinalStatus expected_final_status) |
85 : expected_final_status_(expected_final_status) { | 85 : expected_final_status_(expected_final_status) { |
86 } | 86 } |
87 | 87 |
| 88 void set_expected_final_status(FinalStatus expected_final_status) { |
| 89 expected_final_status_ = expected_final_status; |
| 90 } |
| 91 |
| 92 void set_expected_final_status_for_url(const GURL& url, |
| 93 FinalStatus expected_final_status) { |
| 94 DCHECK(expected_final_status_map_.find(url) == |
| 95 expected_final_status_map_.end()); |
| 96 expected_final_status_map_[url] = expected_final_status; |
| 97 } |
| 98 |
88 virtual PrerenderContents* CreatePrerenderContents( | 99 virtual PrerenderContents* CreatePrerenderContents( |
89 PrerenderManager* prerender_manager, Profile* profile, const GURL& url, | 100 PrerenderManager* prerender_manager, Profile* profile, const GURL& url, |
90 const std::vector<GURL>& alias_urls, const GURL& referrer) { | 101 const std::vector<GURL>& alias_urls, const GURL& referrer) { |
| 102 FinalStatus expected_final_status = expected_final_status_; |
| 103 std::map<GURL, FinalStatus>::iterator it = |
| 104 expected_final_status_map_.find(url); |
| 105 if (it != expected_final_status_map_.end()) { |
| 106 expected_final_status = it->second; |
| 107 expected_final_status_map_.erase(it); |
| 108 } |
91 return new TestPrerenderContents(prerender_manager, profile, url, | 109 return new TestPrerenderContents(prerender_manager, profile, url, |
92 alias_urls, referrer, | 110 alias_urls, referrer, |
93 expected_final_status_); | 111 expected_final_status); |
94 } | 112 } |
95 | 113 |
96 private: | 114 private: |
97 FinalStatus expected_final_status_; | 115 FinalStatus expected_final_status_; |
| 116 std::map<GURL, FinalStatus> expected_final_status_map_; |
98 }; | 117 }; |
99 | 118 |
100 } // namespace | 119 } // namespace |
101 | 120 |
102 class PrerenderBrowserTest : public InProcessBrowserTest { | 121 class PrerenderBrowserTest : public InProcessBrowserTest { |
103 public: | 122 public: |
104 PrerenderBrowserTest() : use_https_src_server_(false), | 123 PrerenderBrowserTest() |
105 on_iteration_succeeded_(true) { | 124 : prc_factory_(NULL), |
| 125 use_https_src_server_(false), |
| 126 on_iteration_succeeded_(true) { |
106 EnableDOMAutomation(); | 127 EnableDOMAutomation(); |
107 } | 128 } |
108 | 129 |
109 virtual void SetUpCommandLine(CommandLine* command_line) { | 130 virtual void SetUpCommandLine(CommandLine* command_line) { |
110 command_line->AppendSwitchASCII(switches::kPrerender, | 131 command_line->AppendSwitchASCII(switches::kPrerender, |
111 switches::kPrerenderSwitchValueEnabled); | 132 switches::kPrerenderSwitchValueEnabled); |
112 #if defined(OS_MACOSX) | 133 #if defined(OS_MACOSX) |
113 // The plugins directory isn't read by default on the Mac, so it needs to be | 134 // The plugins directory isn't read by default on the Mac, so it needs to be |
114 // explicitly registered. | 135 // explicitly registered. |
115 FilePath app_dir; | 136 FilePath app_dir; |
116 PathService::Get(chrome::DIR_APP, &app_dir); | 137 PathService::Get(chrome::DIR_APP, &app_dir); |
117 command_line->AppendSwitchPath( | 138 command_line->AppendSwitchPath( |
118 switches::kExtraPluginDir, | 139 switches::kExtraPluginDir, |
119 app_dir.Append(FILE_PATH_LITERAL("plugins"))); | 140 app_dir.Append(FILE_PATH_LITERAL("plugins"))); |
120 #endif | 141 #endif |
121 } | 142 } |
122 | 143 |
123 void PrerenderTestURL(const std::string& html_file, | 144 void PrerenderTestURL(const std::string& html_file, |
124 FinalStatus expected_final_status, | 145 FinalStatus expected_final_status, |
125 int total_navigations) { | 146 int total_navigations) { |
126 ASSERT_TRUE(test_server()->Start()); | 147 ASSERT_TRUE(test_server()->Start()); |
127 std::string dest_path = "files/prerender/"; | 148 dest_url_ = UrlForHtmlFile(html_file); |
128 dest_path.append(html_file); | |
129 dest_url_ = test_server()->GetURL(dest_path); | |
130 | 149 |
131 std::vector<net::TestServer::StringPair> replacement_text; | 150 std::vector<net::TestServer::StringPair> replacement_text; |
132 replacement_text.push_back( | 151 replacement_text.push_back( |
133 make_pair("REPLACE_WITH_PREFETCH_URL", dest_url_.spec())); | 152 make_pair("REPLACE_WITH_PREFETCH_URL", dest_url_.spec())); |
134 std::string replacement_path; | 153 std::string replacement_path; |
135 ASSERT_TRUE(net::TestServer::GetFilePathWithReplacements( | 154 ASSERT_TRUE(net::TestServer::GetFilePathWithReplacements( |
136 "files/prerender/prerender_loader.html", | 155 "files/prerender/prerender_loader.html", |
137 replacement_text, | 156 replacement_text, |
138 &replacement_path)); | 157 &replacement_path)); |
139 | 158 |
140 net::TestServer* src_server = test_server(); | 159 net::TestServer* src_server = test_server(); |
141 scoped_ptr<net::TestServer> https_src_server; | 160 scoped_ptr<net::TestServer> https_src_server; |
142 if (use_https_src_server_) { | 161 if (use_https_src_server_) { |
143 https_src_server.reset( | 162 https_src_server.reset( |
144 new net::TestServer(net::TestServer::TYPE_HTTPS, | 163 new net::TestServer(net::TestServer::TYPE_HTTPS, |
145 FilePath(FILE_PATH_LITERAL("chrome/test/data")))); | 164 FilePath(FILE_PATH_LITERAL("chrome/test/data")))); |
146 ASSERT_TRUE(https_src_server->Start()); | 165 ASSERT_TRUE(https_src_server->Start()); |
147 src_server = https_src_server.get(); | 166 src_server = https_src_server.get(); |
148 } | 167 } |
149 GURL src_url = src_server->GetURL(replacement_path); | 168 GURL src_url = src_server->GetURL(replacement_path); |
150 | 169 |
151 Profile* profile = browser()->GetSelectedTabContents()->profile(); | |
152 PrerenderManager* prerender_manager = profile->GetPrerenderManager(); | |
153 ASSERT_TRUE(prerender_manager); | |
154 | |
155 // This is needed to exit the event loop once the prerendered page has | 170 // This is needed to exit the event loop once the prerendered page has |
156 // stopped loading or was cancelled. | 171 // stopped loading or was cancelled. |
157 prerender_manager->SetPrerenderContentsFactory( | 172 ASSERT_TRUE(prerender_manager()); |
158 new WaitForLoadPrerenderContentsFactory(expected_final_status)); | 173 ASSERT_TRUE(prc_factory_ == NULL); |
| 174 prc_factory_ = |
| 175 new WaitForLoadPrerenderContentsFactory(expected_final_status); |
| 176 prerender_manager()->SetPrerenderContentsFactory(prc_factory_); |
159 | 177 |
160 // ui_test_utils::NavigateToURL uses its own observer and message loop. | 178 // ui_test_utils::NavigateToURL uses its own observer and message loop. |
161 // Since the test needs to wait until the prerendered page has stopped | 179 // Since the test needs to wait until the prerendered page has stopped |
162 // loading, rathather than the page directly navigated to, need to | 180 // loading, rathather than the page directly navigated to, need to |
163 // handle browser navigation directly. | 181 // handle browser navigation directly. |
164 browser()->OpenURL(src_url, GURL(), CURRENT_TAB, PageTransition::TYPED); | 182 browser()->OpenURL(src_url, GURL(), CURRENT_TAB, PageTransition::TYPED); |
165 | 183 |
166 TestPrerenderContents* prerender_contents = NULL; | 184 TestPrerenderContents* prerender_contents = NULL; |
167 int navigations = 0; | 185 int navigations = 0; |
168 while (true) { | 186 while (true) { |
169 ui_test_utils::RunMessageLoop(); | 187 ui_test_utils::RunMessageLoop(); |
170 ++navigations; | 188 ++navigations; |
171 EXPECT_TRUE(on_iteration_succeeded_); | 189 EXPECT_TRUE(on_iteration_succeeded_); |
172 | 190 |
173 prerender_contents = | 191 prerender_contents = |
174 static_cast<TestPrerenderContents*>( | 192 static_cast<TestPrerenderContents*>( |
175 prerender_manager->FindEntry(dest_url_)); | 193 prerender_manager()->FindEntry(dest_url_)); |
176 if (prerender_contents == NULL || | 194 if (prerender_contents == NULL || |
177 !prerender_contents->did_finish_loading() || | 195 !prerender_contents->did_finish_loading() || |
178 navigations >= total_navigations) { | 196 navigations >= total_navigations) { |
179 EXPECT_EQ(navigations, total_navigations); | 197 EXPECT_EQ(navigations, total_navigations); |
180 break; | 198 break; |
181 } | 199 } |
182 prerender_contents->set_did_finish_loading(false); | 200 prerender_contents->set_did_finish_loading(false); |
183 MessageLoopForUI::current()->PostTask( | 201 MessageLoopForUI::current()->PostTask( |
184 FROM_HERE, | 202 FROM_HERE, |
185 NewRunnableMethod(this, | 203 NewRunnableMethod(this, |
(...skipping 19 matching lines...) Expand all Loading... |
205 // In the failure case, we should have removed dest_url_ from the | 223 // In the failure case, we should have removed dest_url_ from the |
206 // prerender_manager. | 224 // prerender_manager. |
207 EXPECT_TRUE(prerender_contents == NULL); | 225 EXPECT_TRUE(prerender_contents == NULL); |
208 break; | 226 break; |
209 } | 227 } |
210 } | 228 } |
211 | 229 |
212 void NavigateToDestURL() const { | 230 void NavigateToDestURL() const { |
213 ui_test_utils::NavigateToURL(browser(), dest_url_); | 231 ui_test_utils::NavigateToURL(browser(), dest_url_); |
214 | 232 |
215 Profile* profile = browser()->GetSelectedTabContents()->profile(); | |
216 PrerenderManager* prerender_manager = profile->GetPrerenderManager(); | |
217 ASSERT_TRUE(prerender_manager); | |
218 | |
219 // Make sure the PrerenderContents found earlier was used or removed | 233 // Make sure the PrerenderContents found earlier was used or removed |
220 EXPECT_TRUE(prerender_manager->FindEntry(dest_url_) == NULL); | 234 EXPECT_TRUE(prerender_manager()->FindEntry(dest_url_) == NULL); |
221 | 235 |
222 // Check if page behaved as expected when actually displayed. | 236 // Check if page behaved as expected when actually displayed. |
223 bool display_test_result = false; | 237 bool display_test_result = false; |
224 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( | 238 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( |
225 browser()->GetSelectedTabContents()->render_view_host(), L"", | 239 browser()->GetSelectedTabContents()->render_view_host(), L"", |
226 L"window.domAutomationController.send(DidDisplayPass())", | 240 L"window.domAutomationController.send(DidDisplayPass())", |
227 &display_test_result)); | 241 &display_test_result)); |
228 EXPECT_TRUE(display_test_result); | 242 EXPECT_TRUE(display_test_result); |
229 } | 243 } |
230 | 244 |
| 245 bool UrlIsInPrerenderManager(const std::string& html_file) { |
| 246 GURL dest_url = UrlForHtmlFile(html_file); |
| 247 |
| 248 return (prerender_manager()->FindEntry(dest_url) != NULL); |
| 249 } |
| 250 |
| 251 bool UrlIsPendingInPrerenderManager(const std::string& html_file) { |
| 252 GURL dest_url = UrlForHtmlFile(html_file); |
| 253 |
| 254 return (prerender_manager()->FindPendingEntry(dest_url) != NULL); |
| 255 } |
| 256 |
231 void set_use_https_src(bool use_https_src_server) { | 257 void set_use_https_src(bool use_https_src_server) { |
232 use_https_src_server_ = use_https_src_server; | 258 use_https_src_server_ = use_https_src_server; |
233 } | 259 } |
234 | 260 |
| 261 void SetExpectedFinalStatus(FinalStatus expected_final_status) { |
| 262 DCHECK(prerender_manager()->prerender_contents_factory_.get() == |
| 263 prc_factory_); |
| 264 prc_factory_->set_expected_final_status(expected_final_status); |
| 265 } |
| 266 |
| 267 void SetExpectedFinalStatusForUrl(const std::string& html_file, |
| 268 FinalStatus expected_final_status) { |
| 269 GURL url = UrlForHtmlFile(html_file); |
| 270 DCHECK(prerender_manager()->prerender_contents_factory_.get() == |
| 271 prc_factory_); |
| 272 prc_factory_->set_expected_final_status_for_url(url, expected_final_status); |
| 273 } |
| 274 |
235 private: | 275 private: |
| 276 PrerenderManager* prerender_manager() const { |
| 277 Profile* profile = browser()->GetSelectedTabContents()->profile(); |
| 278 PrerenderManager* prerender_manager = profile->GetPrerenderManager(); |
| 279 return prerender_manager; |
| 280 } |
| 281 |
| 282 // Non-const as test_server()->GetURL() is not const |
| 283 GURL UrlForHtmlFile(const std::string& html_file) { |
| 284 std::string dest_path = "files/prerender/"; |
| 285 dest_path.append(html_file); |
| 286 return test_server()->GetURL(dest_path); |
| 287 } |
| 288 |
236 void CallOnIteration(RenderViewHost* rvh) { | 289 void CallOnIteration(RenderViewHost* rvh) { |
237 on_iteration_succeeded_ = ui_test_utils::ExecuteJavaScript( | 290 on_iteration_succeeded_ = ui_test_utils::ExecuteJavaScript( |
238 rvh, | 291 rvh, |
239 L"", | 292 L"", |
240 L"if (typeof(OnIteration) != 'undefined') {OnIteration();}"); | 293 L"if (typeof(OnIteration) != 'undefined') {OnIteration();}"); |
241 } | 294 } |
242 | 295 |
| 296 WaitForLoadPrerenderContentsFactory* prc_factory_; |
243 GURL dest_url_; | 297 GURL dest_url_; |
244 bool use_https_src_server_; | 298 bool use_https_src_server_; |
245 bool on_iteration_succeeded_; | 299 bool on_iteration_succeeded_; |
246 }; | 300 }; |
247 | 301 |
248 // Checks that a page is correctly prerendered in the case of a | 302 // Checks that a page is correctly prerendered in the case of a |
249 // <link rel=prefetch> tag and then loaded into a tab in response to a | 303 // <link rel=prefetch> tag and then loaded into a tab in response to a |
250 // navigation. | 304 // navigation. |
251 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPage) { | 305 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPage) { |
252 PrerenderTestURL("prerender_page.html", | 306 PrerenderTestURL("prerender_page.html", |
253 FINAL_STATUS_USED, 1); | 307 FINAL_STATUS_USED, 1); |
254 NavigateToDestURL(); | 308 NavigateToDestURL(); |
255 } | 309 } |
256 | 310 |
257 // Checks that the prerendering of a page is canceled correctly when a | 311 // Checks that the prerendering of a page is canceled correctly when a |
258 // Javascript alert is called. | 312 // Javascript alert is called. |
259 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderAlertBeforeOnload) { | 313 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderAlertBeforeOnload) { |
260 PrerenderTestURL( | 314 PrerenderTestURL("prerender_alert_before_onload.html", |
261 "prerender_alert_before_onload.html", | 315 FINAL_STATUS_JAVASCRIPT_ALERT, 1); |
262 FINAL_STATUS_JAVASCRIPT_ALERT, 1); | |
263 } | 316 } |
264 | 317 |
265 // Checks that the prerendering of a page is canceled correctly when a | 318 // Checks that the prerendering of a page is canceled correctly when a |
266 // Javascript alert is called. | 319 // Javascript alert is called. |
267 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderAlertAfterOnload) { | 320 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderAlertAfterOnload) { |
268 PrerenderTestURL( | 321 PrerenderTestURL("prerender_alert_after_onload.html", |
269 "prerender_alert_after_onload.html", | 322 FINAL_STATUS_JAVASCRIPT_ALERT, 1); |
270 FINAL_STATUS_JAVASCRIPT_ALERT, 1); | |
271 } | 323 } |
272 | 324 |
273 // Checks that plugins are not loaded while a page is being preloaded, but | 325 // Checks that plugins are not loaded while a page is being preloaded, but |
274 // are loaded when the page is displayed. | 326 // are loaded when the page is displayed. |
275 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDelayLoadPlugin) { | 327 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDelayLoadPlugin) { |
276 PrerenderTestURL("plugin_delay_load.html", | 328 PrerenderTestURL("plugin_delay_load.html", |
277 FINAL_STATUS_USED, 1); | 329 FINAL_STATUS_USED, 1); |
278 NavigateToDestURL(); | 330 NavigateToDestURL(); |
279 } | 331 } |
280 | 332 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 } | 416 } |
365 | 417 |
366 // Checks that renderers using excessive memory will be terminated. | 418 // Checks that renderers using excessive memory will be terminated. |
367 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderExcessiveMemory) { | 419 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderExcessiveMemory) { |
368 PrerenderTestURL("prerender_excessive_memory.html", | 420 PrerenderTestURL("prerender_excessive_memory.html", |
369 FINAL_STATUS_MEMORY_LIMIT_EXCEEDED, 1); | 421 FINAL_STATUS_MEMORY_LIMIT_EXCEEDED, 1); |
370 } | 422 } |
371 | 423 |
372 // Checks that we don't prerender in an infinite loop. | 424 // Checks that we don't prerender in an infinite loop. |
373 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderInfiniteLoop) { | 425 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderInfiniteLoop) { |
374 PrerenderTestURL("prerender_infinite_a.html", FINAL_STATUS_USED, 1); | 426 const char* const kHtmlFileA = "prerender_infinite_a.html"; |
| 427 const char* const kHtmlFileB = "prerender_infinite_b.html"; |
| 428 |
| 429 PrerenderTestURL(kHtmlFileA, FINAL_STATUS_USED, 1); |
| 430 |
| 431 // Next url should be in pending list but not an active entry. |
| 432 EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileB)); |
| 433 EXPECT_TRUE(UrlIsPendingInPrerenderManager(kHtmlFileB)); |
| 434 |
| 435 // We are not going to navigate back to kHtmlFileA but we will start the |
| 436 // preload so we need to set the final status to expect here before |
| 437 // navigating. |
| 438 SetExpectedFinalStatus(FINAL_STATUS_APP_TERMINATING); |
| 439 |
375 NavigateToDestURL(); | 440 NavigateToDestURL(); |
| 441 |
| 442 // Make sure the PrerenderContents for the next url is now in the manager |
| 443 // and not pending. |
| 444 EXPECT_TRUE(UrlIsInPrerenderManager(kHtmlFileB)); |
| 445 EXPECT_FALSE(UrlIsPendingInPrerenderManager(kHtmlFileB)); |
| 446 } |
| 447 |
| 448 // Checks that we don't prerender in an infinite loop and multiple links are |
| 449 // handled correctly. |
| 450 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderInfiniteLoopMultiple) { |
| 451 const char* const kHtmlFileA = "prerender_infinite_a_multiple.html"; |
| 452 const char* const kHtmlFileB = "prerender_infinite_b_multiple.html"; |
| 453 const char* const kHtmlFileC = "prerender_infinite_c_multiple.html"; |
| 454 |
| 455 PrerenderTestURL(kHtmlFileA, FINAL_STATUS_USED, 1); |
| 456 |
| 457 // Next url should be in pending list but not an active entry. |
| 458 EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileB)); |
| 459 EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileC)); |
| 460 EXPECT_TRUE(UrlIsPendingInPrerenderManager(kHtmlFileB)); |
| 461 EXPECT_TRUE(UrlIsPendingInPrerenderManager(kHtmlFileC)); |
| 462 |
| 463 // We are not going to navigate back to kHtmlFileA but we will start the |
| 464 // preload so we need to set the final status to expect here before |
| 465 // navigating. |
| 466 SetExpectedFinalStatusForUrl(kHtmlFileB, FINAL_STATUS_EVICTED); |
| 467 SetExpectedFinalStatusForUrl(kHtmlFileC, FINAL_STATUS_APP_TERMINATING); |
| 468 |
| 469 NavigateToDestURL(); |
| 470 |
| 471 // Make sure the PrerenderContents for the next urls are now in the manager |
| 472 // and not pending. url_c was the last seen so should be the active |
| 473 // entry. |
| 474 EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileB)); |
| 475 EXPECT_TRUE(UrlIsInPrerenderManager(kHtmlFileC)); |
| 476 EXPECT_FALSE(UrlIsPendingInPrerenderManager(kHtmlFileB)); |
| 477 EXPECT_FALSE(UrlIsPendingInPrerenderManager(kHtmlFileC)); |
376 } | 478 } |
377 | 479 |
378 } // namespace prerender | 480 } // namespace prerender |
OLD | NEW |