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 3// found in the LICENSE file. 4 5#include "base/command_line.h" 6#include "base/format_macros.h" 7#include "base/memory/scoped_vector.h" 8#include "base/message_loop/message_loop.h" 9#include "base/strings/stringprintf.h" 10#include "base/time/time.h" 11#include "chrome/browser/prerender/prerender_contents.h" 12#include "chrome/browser/prerender/prerender_handle.h" 13#include "chrome/browser/prerender/prerender_link_manager.h" 14#include "chrome/browser/prerender/prerender_manager.h" 15#include "chrome/browser/prerender/prerender_origin.h" 16#include "chrome/common/chrome_switches.h" 17#include "chrome/test/base/testing_browser_process.h" 18#include "chrome/test/base/testing_profile.h" 19#include "content/public/browser/render_view_host.h" 20#include "content/public/test/test_browser_thread.h" 21#include "testing/gtest/include/gtest/gtest.h" 22#include "ui/gfx/size.h" 23#include "url/gurl.h" 24 25using base::Time; 26using base::TimeDelta; 27using base::TimeTicks; 28using content::BrowserThread; 29using content::Referrer; 30 31namespace prerender { 32 33class UnitTestPrerenderManager; 34 35namespace { 36 37class DummyPrerenderContents : public PrerenderContents { 38 public: 39 DummyPrerenderContents(UnitTestPrerenderManager* test_prerender_manager, 40 PrerenderTracker* prerender_tracker, 41 const GURL& url, 42 Origin origin, 43 FinalStatus expected_final_status); 44 45 virtual ~DummyPrerenderContents() { 46 EXPECT_EQ(expected_final_status_, final_status()); 47 } 48 49 virtual void StartPrerendering( 50 int ALLOW_UNUSED creator_child_id, 51 const gfx::Size& ALLOW_UNUSED size, 52 content::SessionStorageNamespace* ALLOW_UNUSED session_storage_namespace) 53 OVERRIDE; 54 55 virtual bool GetChildId(int* child_id) const OVERRIDE { 56 // Having a default child_id of -1 forces pending prerenders not to fail 57 // on session storage and cross domain checking. 58 *child_id = -1; 59 return true; 60 } 61 62 virtual bool GetRouteId(int* route_id) const OVERRIDE { 63 *route_id = route_id_; 64 return true; 65 } 66 67 FinalStatus expected_final_status() const { return expected_final_status_; } 68 69 bool prerendering_has_been_cancelled() const { 70 return PrerenderContents::prerendering_has_been_cancelled(); 71 } 72 73 private: 74 static int g_next_route_id_; 75 int route_id_; 76 77 UnitTestPrerenderManager* test_prerender_manager_; 78 FinalStatus expected_final_status_; 79}; 80 81int DummyPrerenderContents::g_next_route_id_ = 0; 82 83const gfx::Size kSize(640, 480); 84 85} // namespace 86 87class UnitTestPrerenderManager : public PrerenderManager { 88 public: 89 using PrerenderManager::kMinTimeBetweenPrerendersMs; 90 using PrerenderManager::kNavigationRecordWindowMs; 91 92 explicit UnitTestPrerenderManager(Profile* profile, 93 PrerenderTracker* prerender_tracker) 94 : PrerenderManager(profile, prerender_tracker), 95 time_(Time::Now()), 96 time_ticks_(TimeTicks::Now()), 97 prerender_tracker_(prerender_tracker) { 98 set_rate_limit_enabled(false); 99 } 100 101 virtual ~UnitTestPrerenderManager() { 102 } 103 104 // From BrowserContextKeyedService, via PrererenderManager: 105 virtual void Shutdown() OVERRIDE { 106 if (next_prerender_contents()) 107 next_prerender_contents_->Destroy(FINAL_STATUS_MANAGER_SHUTDOWN); 108 PrerenderManager::Shutdown(); 109 } 110 111 // From PrerenderManager: 112 virtual void MoveEntryToPendingDelete(PrerenderContents* entry, 113 FinalStatus final_status) OVERRIDE { 114 if (entry == next_prerender_contents_.get()) 115 return; 116 PrerenderManager::MoveEntryToPendingDelete(entry, final_status); 117 } 118 119 PrerenderContents* FindEntry(const GURL& url) { 120 DeleteOldEntries(); 121 to_delete_prerenders_.clear(); 122 if (PrerenderData* data = FindPrerenderData(url, NULL)) 123 return data->contents(); 124 return NULL; 125 } 126 127 PrerenderContents* FindAndUseEntry(const GURL& url) { 128 PrerenderData* prerender_data = FindPrerenderData(url, NULL); 129 if (!prerender_data) 130 return NULL; 131 ScopedVector<PrerenderData>::iterator to_erase = 132 FindIteratorForPrerenderContents(prerender_data->contents()); 133 CHECK(to_erase != active_prerenders_.end()); 134 PrerenderContents* prerender_contents = prerender_data->ReleaseContents(); 135 active_prerenders_.erase(to_erase); 136 137 prerender_contents->SetFinalStatus(FINAL_STATUS_USED); 138 prerender_contents->PrepareForUse(); 139 return prerender_contents; 140 } 141 142 void AdvanceTime(TimeDelta delta) { 143 time_ += delta; 144 } 145 146 void AdvanceTimeTicks(TimeDelta delta) { 147 time_ticks_ += delta; 148 } 149 150 DummyPrerenderContents* CreateNextPrerenderContents( 151 const GURL& url, 152 FinalStatus expected_final_status) { 153 DummyPrerenderContents* prerender_contents = 154 new DummyPrerenderContents(this, prerender_tracker_, url, 155 ORIGIN_LINK_REL_PRERENDER_CROSSDOMAIN, 156 expected_final_status); 157 SetNextPrerenderContents(prerender_contents); 158 return prerender_contents; 159 } 160 161 DummyPrerenderContents* CreateNextPrerenderContents( 162 const GURL& url, 163 Origin origin, 164 FinalStatus expected_final_status) { 165 DummyPrerenderContents* prerender_contents = 166 new DummyPrerenderContents(this, prerender_tracker_, url, 167 origin, expected_final_status); 168 SetNextPrerenderContents(prerender_contents); 169 return prerender_contents; 170 } 171 172 DummyPrerenderContents* CreateNextPrerenderContents( 173 const GURL& url, 174 const std::vector<GURL>& alias_urls, 175 FinalStatus expected_final_status) { 176 DummyPrerenderContents* prerender_contents = 177 new DummyPrerenderContents(this, prerender_tracker_, url, 178 ORIGIN_LINK_REL_PRERENDER_CROSSDOMAIN, 179 expected_final_status); 180 for (std::vector<GURL>::const_iterator it = alias_urls.begin(); 181 it != alias_urls.end(); 182 ++it) { 183 EXPECT_TRUE(prerender_contents->AddAliasURL(*it)); 184 } 185 SetNextPrerenderContents(prerender_contents); 186 return prerender_contents; 187 } 188 189 void set_rate_limit_enabled(bool enabled) { 190 mutable_config().rate_limit_enabled = enabled; 191 } 192 193 PrerenderContents* next_prerender_contents() { 194 return next_prerender_contents_.get(); 195 } 196 197 // from PrerenderManager 198 virtual Time GetCurrentTime() const OVERRIDE { 199 return time_; 200 } 201 202 virtual TimeTicks GetCurrentTimeTicks() const OVERRIDE { 203 return time_ticks_; 204 } 205 206 private: 207 void SetNextPrerenderContents(DummyPrerenderContents* prerender_contents) { 208 CHECK(!next_prerender_contents_.get()); 209 next_prerender_contents_.reset(prerender_contents); 210 if (prerender_contents->expected_final_status() == FINAL_STATUS_USED) 211 used_prerender_contents_.push_back(prerender_contents); 212 } 213 214 215 virtual PrerenderContents* CreatePrerenderContents( 216 const GURL& url, 217 const Referrer& referrer, 218 Origin origin, 219 uint8 experiment_id) OVERRIDE { 220 CHECK(next_prerender_contents_.get()); 221 EXPECT_EQ(url, next_prerender_contents_->prerender_url()); 222 EXPECT_EQ(origin, next_prerender_contents_->origin()); 223 return next_prerender_contents_.release(); 224 } 225 226 Time time_; 227 TimeTicks time_ticks_; 228 scoped_ptr<PrerenderContents> next_prerender_contents_; 229 // PrerenderContents with an |expected_final_status| of FINAL_STATUS_USED, 230 // tracked so they will be automatically deleted. 231 ScopedVector<PrerenderContents> used_prerender_contents_; 232 233 PrerenderTracker* prerender_tracker_; 234}; 235 236class RestorePrerenderMode { 237 public: 238 RestorePrerenderMode() : prev_mode_(PrerenderManager::GetMode()) { 239 } 240 241 ~RestorePrerenderMode() { PrerenderManager::SetMode(prev_mode_); } 242 private: 243 PrerenderManager::PrerenderManagerMode prev_mode_; 244}; 245 246DummyPrerenderContents::DummyPrerenderContents( 247 UnitTestPrerenderManager* test_prerender_manager, 248 PrerenderTracker* prerender_tracker, 249 const GURL& url, 250 Origin origin, 251 FinalStatus expected_final_status) 252 : PrerenderContents(test_prerender_manager, 253 NULL, url, Referrer(), origin, 254 PrerenderManager::kNoExperiment), 255 route_id_(g_next_route_id_++), 256 test_prerender_manager_(test_prerender_manager), 257 expected_final_status_(expected_final_status) { 258} 259 260void DummyPrerenderContents::StartPrerendering( 261 int ALLOW_UNUSED creator_child_id, 262 const gfx::Size& ALLOW_UNUSED size, 263 content::SessionStorageNamespace* ALLOW_UNUSED session_storage_namespace) { 264 // In the base PrerenderContents implementation, StartPrerendering will 265 // be called even when the PrerenderManager is part of the control group, 266 // but it will early exit before actually creating a new RenderView if 267 // |is_control_group| is true; 268 load_start_time_ = test_prerender_manager_->GetCurrentTimeTicks(); 269 if (!test_prerender_manager_->IsControlGroup(experiment_id())) { 270 prerendering_has_started_ = true; 271 NotifyPrerenderStart(); 272 } 273} 274 275class PrerenderTest : public testing::Test { 276 public: 277 static const int kDefaultChildId = -1; 278 static const int kDefaultRenderViewRouteId = -1; 279 280 PrerenderTest() : ui_thread_(BrowserThread::UI, &message_loop_), 281 prerender_manager_(new UnitTestPrerenderManager( 282 &profile_, prerender_tracker())), 283 prerender_link_manager_( 284 new PrerenderLinkManager(prerender_manager_.get())), 285 last_prerender_id_(0) { 286 // Enable omnibox prerendering. 287 CommandLine::ForCurrentProcess()->AppendSwitchASCII( 288 switches::kPrerenderFromOmnibox, 289 switches::kPrerenderFromOmniboxSwitchValueEnabled); 290 } 291 292 virtual ~PrerenderTest() { 293 prerender_link_manager_->OnChannelClosing(kDefaultChildId); 294 prerender_link_manager_->Shutdown(); 295 prerender_manager_->Shutdown(); 296 } 297 298 UnitTestPrerenderManager* prerender_manager() { 299 return prerender_manager_.get(); 300 } 301 302 PrerenderLinkManager* prerender_link_manager() { 303 return prerender_link_manager_.get(); 304 } 305 306 void SetConcurrency(size_t concurrency) { 307 prerender_manager()->mutable_config().max_link_concurrency_per_launcher = 308 concurrency; 309 prerender_manager()->mutable_config().max_link_concurrency = 310 std::max(prerender_manager()->mutable_config().max_link_concurrency, 311 concurrency); 312 } 313 314 bool IsEmptyPrerenderLinkManager() const { 315 return prerender_link_manager_->IsEmpty(); 316 } 317 318 int last_prerender_id() const { 319 return last_prerender_id_; 320 } 321 322 int GetNextPrerenderID() { 323 return ++last_prerender_id_; 324 } 325 326 bool LauncherHasRunningPrerender(int child_id, int prerender_id) { 327 PrerenderLinkManager::LinkPrerender* prerender = 328 prerender_link_manager()->FindByLauncherChildIdAndPrerenderId( 329 child_id, prerender_id); 330 return prerender && prerender->handle; 331 } 332 333 // Shorthand to add a simple prerender with a reasonable source. Returns 334 // true iff the prerender has been added to the PrerenderManager by the 335 // PrerenderLinkManager and the PrerenderManager returned a handle. 336 bool AddSimplePrerender(const GURL& url) { 337 prerender_link_manager()->OnAddPrerender(kDefaultChildId, 338 GetNextPrerenderID(), 339 url, content::Referrer(), 340 kSize, kDefaultRenderViewRouteId); 341 return LauncherHasRunningPrerender(kDefaultChildId, last_prerender_id()); 342 } 343 344 private: 345 PrerenderTracker* prerender_tracker() { 346 return g_browser_process->prerender_tracker(); 347 } 348 349 // Needed to pass PrerenderManager's DCHECKs. 350 TestingProfile profile_; 351 base::MessageLoop message_loop_; 352 content::TestBrowserThread ui_thread_; 353 scoped_ptr<UnitTestPrerenderManager> prerender_manager_; 354 scoped_ptr<PrerenderLinkManager> prerender_link_manager_; 355 int last_prerender_id_; 356}; 357 358TEST_F(PrerenderTest, FoundTest) { 359 GURL url("http://www.google.com/"); 360 DummyPrerenderContents* prerender_contents = 361 prerender_manager()->CreateNextPrerenderContents( 362 url, 363 FINAL_STATUS_USED); 364 EXPECT_TRUE(AddSimplePrerender(url)); 365 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 366 ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); 367} 368 369// Make sure that if queue a request, and a second prerender request for the 370// same URL comes in, that the second request attaches to the first prerender, 371// and we don't use the second prerender contents. 372TEST_F(PrerenderTest, DuplicateTest) { 373 SetConcurrency(2); 374 GURL url("http://www.google.com/"); 375 DummyPrerenderContents* prerender_contents = 376 prerender_manager()->CreateNextPrerenderContents( 377 url, 378 FINAL_STATUS_USED); 379 DummyPrerenderContents* null = NULL; 380 EXPECT_TRUE(AddSimplePrerender(url)); 381 EXPECT_EQ(null, prerender_manager()->next_prerender_contents()); 382 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 383 384 DummyPrerenderContents* prerender_contents1 = 385 prerender_manager()->CreateNextPrerenderContents( 386 url, 387 FINAL_STATUS_MANAGER_SHUTDOWN); 388 EXPECT_TRUE(AddSimplePrerender(url)); 389 EXPECT_EQ(prerender_contents1, 390 prerender_manager()->next_prerender_contents()); 391 EXPECT_FALSE(prerender_contents1->prerendering_has_started()); 392 393 ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); 394} 395 396// Ensure that we expire a prerendered page after the max. permitted time. 397TEST_F(PrerenderTest, ExpireTest) { 398 GURL url("http://www.google.com/"); 399 DummyPrerenderContents* prerender_contents = 400 prerender_manager()->CreateNextPrerenderContents( 401 url, 402 FINAL_STATUS_TIMED_OUT); 403 DummyPrerenderContents* null = NULL; 404 EXPECT_TRUE(AddSimplePrerender(url)); 405 EXPECT_EQ(null, prerender_manager()->next_prerender_contents()); 406 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 407 prerender_manager()->AdvanceTimeTicks( 408 prerender_manager()->config().time_to_live + TimeDelta::FromSeconds(1)); 409 ASSERT_EQ(null, prerender_manager()->FindEntry(url)); 410} 411 412// Ensure that we don't launch prerenders of bad urls (in this case, a mailto: 413// url) 414TEST_F(PrerenderTest, BadURLTest) { 415 GURL url("mailto:test@gmail.com"); 416 DummyPrerenderContents* prerender_contents = 417 prerender_manager()->CreateNextPrerenderContents( 418 url, 419 FINAL_STATUS_UNSUPPORTED_SCHEME); 420 EXPECT_FALSE(AddSimplePrerender(url)); 421 EXPECT_FALSE(prerender_contents->prerendering_has_started()); 422 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 423 DummyPrerenderContents* null = NULL; 424 EXPECT_EQ(null, prerender_manager()->FindEntry(url)); 425} 426 427// When the user navigates away from a page, the prerenders it launched should 428// have their time to expiry shortened from the default time to live. 429TEST_F(PrerenderTest, LinkManagerNavigateAwayExpire) { 430 const TimeDelta time_to_live = TimeDelta::FromSeconds(300); 431 const TimeDelta abandon_time_to_live = TimeDelta::FromSeconds(20); 432 const TimeDelta test_advance = TimeDelta::FromSeconds(22); 433 ASSERT_LT(test_advance, time_to_live); 434 ASSERT_LT(abandon_time_to_live, test_advance); 435 436 prerender_manager()->mutable_config().time_to_live = time_to_live; 437 prerender_manager()->mutable_config().abandon_time_to_live = 438 abandon_time_to_live; 439 440 GURL url("http://example.com"); 441 DummyPrerenderContents* prerender_contents = 442 prerender_manager()->CreateNextPrerenderContents(url, 443 FINAL_STATUS_TIMED_OUT); 444 EXPECT_TRUE(AddSimplePrerender(url)); 445 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 446 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 447 ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 448 prerender_link_manager()->OnAbandonPrerender(kDefaultChildId, 449 last_prerender_id()); 450 EXPECT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 451 DummyPrerenderContents* null = NULL; 452 EXPECT_EQ(null, prerender_manager()->next_prerender_contents()); 453 prerender_manager()->AdvanceTimeTicks(test_advance); 454 455 EXPECT_EQ(null, prerender_manager()->FindEntry(url)); 456} 457 458// But when we navigate away very close to the original expiry of a prerender, 459// we shouldn't expect it to be extended. 460TEST_F(PrerenderTest, LinkManagerNavigateAwayNearExpiry) { 461 const TimeDelta time_to_live = TimeDelta::FromSeconds(300); 462 const TimeDelta abandon_time_to_live = TimeDelta::FromSeconds(20); 463 464 // We will expect the prerender to still be alive after advancing the clock 465 // by first_advance. But, after second_advance, we expect it to have timed 466 // out, demonstrating that you can't extend a prerender by navigating away 467 // from its launcher. 468 const TimeDelta first_advance = TimeDelta::FromSeconds(298); 469 const TimeDelta second_advance = TimeDelta::FromSeconds(4); 470 ASSERT_LT(first_advance, time_to_live); 471 ASSERT_LT(time_to_live - first_advance, abandon_time_to_live); 472 ASSERT_LT(time_to_live, first_advance + second_advance); 473 474 prerender_manager()->mutable_config().time_to_live = time_to_live; 475 prerender_manager()->mutable_config().abandon_time_to_live = 476 abandon_time_to_live; 477 478 GURL url("http://example2.com"); 479 DummyPrerenderContents* prerender_contents = 480 prerender_manager()->CreateNextPrerenderContents(url, 481 FINAL_STATUS_TIMED_OUT); 482 EXPECT_TRUE(AddSimplePrerender(url)); 483 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 484 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 485 ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 486 487 prerender_manager()->AdvanceTimeTicks(first_advance); 488 EXPECT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 489 490 prerender_link_manager()->OnAbandonPrerender(kDefaultChildId, 491 last_prerender_id()); 492 EXPECT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 493 494 DummyPrerenderContents* null = NULL; 495 EXPECT_EQ(null, prerender_manager()->next_prerender_contents()); 496 497 prerender_manager()->AdvanceTimeTicks(second_advance); 498 EXPECT_EQ(null, prerender_manager()->FindEntry(url)); 499} 500 501// Make sure that if we prerender more requests than we support, that we launch 502// them in the order given up until we reach MaxConcurrency, at which point we 503// queue them and launch them in the order given. As well, insure that limits 504// are enforced for the system as a whole and on a per launcher basis. 505TEST_F(PrerenderTest, MaxConcurrencyTest) { 506 struct TestConcurrency { 507 size_t max_link_concurrency; 508 size_t max_link_concurrency_per_launcher; 509 }; 510 511 TestConcurrency concurrencies_to_test[] = { 512 { prerender_manager()->config().max_link_concurrency, 513 prerender_manager()->config().max_link_concurrency_per_launcher}, 514 515 // With the system limit higher than the per launcher limit, the per 516 // launcher limit should be in effect. 517 { 2, 1 }, 518 519 // With the per launcher limit higher than system limit, the system limit 520 // should be in effect. 521 { 2, 4 }, 522 }; 523 524 DummyPrerenderContents* null = NULL; 525 GURL url_to_delay("http://www.google.com/delayme"); 526 527 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(concurrencies_to_test); ++i) { 528 prerender_manager()->mutable_config().max_link_concurrency = 529 concurrencies_to_test[i].max_link_concurrency; 530 prerender_manager()->mutable_config().max_link_concurrency_per_launcher = 531 concurrencies_to_test[i].max_link_concurrency_per_launcher; 532 533 const size_t effective_max_link_concurrency = 534 std::min(concurrencies_to_test[i].max_link_concurrency, 535 concurrencies_to_test[i].max_link_concurrency_per_launcher); 536 537 std::vector<GURL> urls; 538 std::vector<PrerenderContents*> prerender_contentses; 539 540 // Launch prerenders up to the maximum this launcher can support. 541 for (size_t j = 0; j < effective_max_link_concurrency; ++j) { 542 urls.push_back( 543 GURL(base::StringPrintf("http://google.com/use#%" PRIuS, j))); 544 prerender_contentses.push_back( 545 prerender_manager()->CreateNextPrerenderContents(urls.back(), 546 FINAL_STATUS_USED)); 547 EXPECT_TRUE(AddSimplePrerender(urls.back())); 548 EXPECT_EQ(null, prerender_manager()->next_prerender_contents()); 549 EXPECT_TRUE(prerender_contentses.back()->prerendering_has_started()); 550 } 551 552 if (concurrencies_to_test[i].max_link_concurrency > 553 effective_max_link_concurrency) { 554 // We should be able to launch more prerenders on this system, but not for 555 // our current launcher. 556 int child_id; 557 int route_id; 558 ASSERT_TRUE(prerender_contentses.back()->GetChildId(&child_id)); 559 ASSERT_TRUE(prerender_contentses.back()->GetRouteId(&route_id)); 560 561 GURL extra_url("http://google.com/extraurl"); 562 prerender_link_manager()->OnAddPrerender(child_id, 563 GetNextPrerenderID(), 564 extra_url, content::Referrer(), 565 kSize, route_id); 566 const int prerender_id = last_prerender_id(); 567 EXPECT_TRUE(LauncherHasRunningPrerender(child_id, prerender_id)); 568 prerender_link_manager()->OnCancelPrerender(child_id, prerender_id); 569 EXPECT_FALSE(LauncherHasRunningPrerender(child_id, prerender_id)); 570 } 571 572 DummyPrerenderContents* prerender_contents_to_delay = 573 prerender_manager()->CreateNextPrerenderContents(url_to_delay, 574 FINAL_STATUS_USED); 575 EXPECT_FALSE(AddSimplePrerender(url_to_delay)); 576 EXPECT_FALSE(prerender_contents_to_delay->prerendering_has_started()); 577 EXPECT_NE(null, prerender_manager()->next_prerender_contents()); 578 EXPECT_EQ(null, prerender_manager()->FindEntry(url_to_delay)); 579 for (size_t j = 0; j < effective_max_link_concurrency; ++j) { 580 EXPECT_EQ(prerender_contentses[j], 581 prerender_manager()->FindAndUseEntry(urls[j])); 582 EXPECT_TRUE(prerender_contents_to_delay->prerendering_has_started()); 583 } 584 585 EXPECT_EQ(prerender_contents_to_delay, 586 prerender_manager()->FindAndUseEntry(url_to_delay)); 587 EXPECT_EQ(null, prerender_manager()->next_prerender_contents()); 588 } 589} 590 591TEST_F(PrerenderTest, AliasURLTest) { 592 SetConcurrency(7); 593 594 GURL url("http://www.google.com/"); 595 GURL alias_url1("http://www.google.com/index.html"); 596 GURL alias_url2("http://google.com/"); 597 GURL not_an_alias_url("http://google.com/index.html"); 598 std::vector<GURL> alias_urls; 599 alias_urls.push_back(alias_url1); 600 alias_urls.push_back(alias_url2); 601 602 // Test that all of the aliases work, but not_an_alias_url does not. 603 DummyPrerenderContents* prerender_contents = 604 prerender_manager()->CreateNextPrerenderContents( 605 url, alias_urls, FINAL_STATUS_USED); 606 EXPECT_TRUE(AddSimplePrerender(url)); 607 ASSERT_EQ(NULL, prerender_manager()->FindEntry(not_an_alias_url)); 608 ASSERT_EQ(prerender_contents, 609 prerender_manager()->FindAndUseEntry(alias_url1)); 610 prerender_contents = prerender_manager()->CreateNextPrerenderContents( 611 url, alias_urls, FINAL_STATUS_USED); 612 EXPECT_TRUE(AddSimplePrerender(url)); 613 ASSERT_EQ(prerender_contents, 614 prerender_manager()->FindAndUseEntry(alias_url2)); 615 prerender_contents = prerender_manager()->CreateNextPrerenderContents( 616 url, alias_urls, FINAL_STATUS_USED); 617 EXPECT_TRUE(AddSimplePrerender(url)); 618 ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); 619 620 // Test that alias URLs can not be added. 621 prerender_contents = prerender_manager()->CreateNextPrerenderContents( 622 url, alias_urls, FINAL_STATUS_USED); 623 EXPECT_TRUE(AddSimplePrerender(url)); 624 EXPECT_TRUE(AddSimplePrerender(url)); 625 EXPECT_TRUE(AddSimplePrerender(alias_url1)); 626 EXPECT_TRUE(AddSimplePrerender(alias_url2)); 627 ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); 628} 629 630TEST_F(PrerenderTest, PendingPrerenderTest) { 631 GURL url("http://www.google.com/"); 632 DummyPrerenderContents* prerender_contents = 633 prerender_manager()->CreateNextPrerenderContents( 634 url, 635 FINAL_STATUS_USED); 636 EXPECT_TRUE(AddSimplePrerender(url)); 637 638 int child_id; 639 int route_id; 640 ASSERT_TRUE(prerender_contents->GetChildId(&child_id)); 641 ASSERT_TRUE(prerender_contents->GetRouteId(&route_id)); 642 643 GURL pending_url("http://news.google.com/"); 644 645 DummyPrerenderContents* pending_prerender_contents = 646 prerender_manager()->CreateNextPrerenderContents( 647 pending_url, 648 ORIGIN_GWS_PRERENDER, 649 FINAL_STATUS_USED); 650 scoped_ptr<PrerenderHandle> pending_prerender_handle( 651 prerender_manager()->AddPrerenderFromLinkRelPrerender( 652 child_id, route_id, pending_url, 653 Referrer(url, WebKit::WebReferrerPolicyDefault), kSize)); 654 CHECK(pending_prerender_handle.get()); 655 EXPECT_FALSE(pending_prerender_handle->IsPrerendering()); 656 657 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 658 ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); 659 660 EXPECT_TRUE(pending_prerender_handle->IsPrerendering()); 661 ASSERT_EQ(pending_prerender_contents, 662 prerender_manager()->FindAndUseEntry(pending_url)); 663 EXPECT_FALSE(pending_prerender_handle->IsPrerendering()); 664} 665 666TEST_F(PrerenderTest, InvalidPendingPrerenderTest) { 667 GURL url("http://www.google.com/"); 668 DummyPrerenderContents* prerender_contents = 669 prerender_manager()->CreateNextPrerenderContents( 670 url, 671 FINAL_STATUS_USED); 672 EXPECT_TRUE(AddSimplePrerender(url)); 673 674 int child_id; 675 int route_id; 676 ASSERT_TRUE(prerender_contents->GetChildId(&child_id)); 677 ASSERT_TRUE(prerender_contents->GetRouteId(&route_id)); 678 679 // This pending URL has an unsupported scheme, and won't be able 680 // to start. 681 GURL pending_url("ftp://news.google.com/"); 682 683 prerender_manager()->CreateNextPrerenderContents( 684 pending_url, 685 ORIGIN_GWS_PRERENDER, 686 FINAL_STATUS_UNSUPPORTED_SCHEME); 687 scoped_ptr<PrerenderHandle> pending_prerender_handle( 688 prerender_manager()->AddPrerenderFromLinkRelPrerender( 689 child_id, route_id, pending_url, 690 Referrer(url, WebKit::WebReferrerPolicyDefault), kSize)); 691 DCHECK(pending_prerender_handle.get()); 692 EXPECT_FALSE(pending_prerender_handle->IsPrerendering()); 693 694 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 695 ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); 696 697 EXPECT_FALSE(pending_prerender_handle->IsPrerendering()); 698} 699 700TEST_F(PrerenderTest, CancelPendingPrerenderTest) { 701 GURL url("http://www.google.com/"); 702 DummyPrerenderContents* prerender_contents = 703 prerender_manager()->CreateNextPrerenderContents( 704 url, 705 FINAL_STATUS_USED); 706 EXPECT_TRUE(AddSimplePrerender(url)); 707 708 int child_id; 709 int route_id; 710 ASSERT_TRUE(prerender_contents->GetChildId(&child_id)); 711 ASSERT_TRUE(prerender_contents->GetRouteId(&route_id)); 712 713 GURL pending_url("http://news.google.com/"); 714 715 scoped_ptr<PrerenderHandle> pending_prerender_handle( 716 prerender_manager()->AddPrerenderFromLinkRelPrerender( 717 child_id, route_id, pending_url, 718 Referrer(url, WebKit::WebReferrerPolicyDefault), kSize)); 719 CHECK(pending_prerender_handle.get()); 720 EXPECT_FALSE(pending_prerender_handle->IsPrerendering()); 721 722 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 723 724 pending_prerender_handle.reset(); 725 726 ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); 727} 728 729// Tests that a PrerenderManager created for a browser session in the control 730// group works as expected. 731TEST_F(PrerenderTest, ControlGroup) { 732 RestorePrerenderMode restore_prerender_mode; 733 PrerenderManager::SetMode( 734 PrerenderManager::PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP); 735 GURL url("http://www.google.com/"); 736 DummyPrerenderContents* prerender_contents = 737 prerender_manager()->CreateNextPrerenderContents( 738 url, 739 FINAL_STATUS_MANAGER_SHUTDOWN); 740 EXPECT_TRUE(AddSimplePrerender(url)); 741 EXPECT_FALSE(prerender_contents->prerendering_has_started()); 742} 743 744// Tests that prerendering is cancelled when the source render view does not 745// exist. On failure, the DCHECK in CreatePrerenderContents() above should be 746// triggered. 747TEST_F(PrerenderTest, SourceRenderViewClosed) { 748 GURL url("http://www.google.com/"); 749 prerender_manager()->CreateNextPrerenderContents( 750 url, 751 FINAL_STATUS_MANAGER_SHUTDOWN); 752 prerender_link_manager()->OnAddPrerender(100, GetNextPrerenderID(), url, 753 Referrer(), kSize, 200); 754 EXPECT_FALSE(LauncherHasRunningPrerender(100, last_prerender_id())); 755} 756 757// Tests that prerendering is cancelled when we launch a second prerender of 758// the same target within a short time interval. 759TEST_F(PrerenderTest, RecentlyVisited) { 760 GURL url("http://www.google.com/"); 761 762 prerender_manager()->RecordNavigation(url); 763 764 DummyPrerenderContents* prerender_contents = 765 prerender_manager()->CreateNextPrerenderContents( 766 url, FINAL_STATUS_RECENTLY_VISITED); 767 EXPECT_FALSE(AddSimplePrerender(url)); 768 EXPECT_FALSE(prerender_contents->prerendering_has_started()); 769} 770 771TEST_F(PrerenderTest, NotSoRecentlyVisited) { 772 GURL url("http://www.google.com/"); 773 774 prerender_manager()->RecordNavigation(url); 775 prerender_manager()->AdvanceTimeTicks( 776 TimeDelta::FromMilliseconds( 777 UnitTestPrerenderManager::kNavigationRecordWindowMs + 500)); 778 779 DummyPrerenderContents* prerender_contents = 780 prerender_manager()->CreateNextPrerenderContents( 781 url, FINAL_STATUS_USED); 782 EXPECT_TRUE(AddSimplePrerender(url)); 783 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 784 ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); 785} 786 787// Tests that our PPLT dummy prerender gets created properly. 788TEST_F(PrerenderTest, PPLTDummy) { 789 GURL url("http://www.google.com/"); 790 DummyPrerenderContents* prerender_contents = 791 prerender_manager()->CreateNextPrerenderContents( 792 url, FINAL_STATUS_UNSUPPORTED_SCHEME); 793 EXPECT_TRUE(AddSimplePrerender(url)); 794 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 795 EXPECT_FALSE(IsEmptyPrerenderLinkManager()); 796 797 DummyPrerenderContents* pplt_dummy_contents = 798 prerender_manager()->CreateNextPrerenderContents(url, 799 FINAL_STATUS_USED); 800 GURL ftp_url("ftp://ftp.google.com/"); 801 // Adding this ftp URL will force the expected unsupported scheme error. 802 prerender_contents->AddAliasURL(ftp_url); 803 EXPECT_FALSE(IsEmptyPrerenderLinkManager()); 804 805 ASSERT_EQ(pplt_dummy_contents, prerender_manager()->FindAndUseEntry(url)); 806 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 807} 808 809// Tests that our PPLT dummy prerender gets created properly, even 810// when navigating to a page that has been recently navigated to. 811TEST_F(PrerenderTest, RecentlyVisitedPPLTDummy) { 812 GURL url("http://www.google.com/"); 813 DummyPrerenderContents* prerender_contents = 814 prerender_manager()->CreateNextPrerenderContents( 815 url, FINAL_STATUS_UNSUPPORTED_SCHEME); 816 EXPECT_TRUE(AddSimplePrerender(url)); 817 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 818 819 DummyPrerenderContents* pplt_dummy_contents = 820 prerender_manager()->CreateNextPrerenderContents(url, 821 FINAL_STATUS_USED); 822 prerender_manager()->RecordNavigation(url); 823 GURL ftp_url("ftp://ftp.google.com/"); 824 prerender_contents->AddAliasURL(ftp_url); 825 826 ASSERT_EQ(pplt_dummy_contents, prerender_manager()->FindAndUseEntry(url)); 827} 828 829TEST_F(PrerenderTest, PPLTLateCancel) { 830 GURL url("http://www.google.com"); 831 DummyPrerenderContents* prerender_contents = 832 prerender_manager()->CreateNextPrerenderContents( 833 url, FINAL_STATUS_JAVASCRIPT_ALERT); 834 EXPECT_TRUE(AddSimplePrerender(url)); 835 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 836 // Force the creation of a match complete dummy. 837 DummyPrerenderContents* duplicate_prerender_contents = 838 prerender_manager()->CreateNextPrerenderContents(url, 839 FINAL_STATUS_CANCELLED); 840 ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 841 prerender_contents->Destroy(FINAL_STATUS_JAVASCRIPT_ALERT); 842 ASSERT_EQ(duplicate_prerender_contents, prerender_manager()->FindEntry(url)); 843 844 // Make sure that events on prerender handles propogate to the match 845 // complete replacement. 846 DummyPrerenderContents* null = NULL; 847 prerender_link_manager()->OnCancelPrerender(kDefaultChildId, 848 last_prerender_id()); 849 ASSERT_EQ(null, prerender_manager()->FindEntry(url)); 850} 851 852// Tests that the prerender manager matches include the fragment. 853TEST_F(PrerenderTest, FragmentMatchesTest) { 854 GURL fragment_url("http://www.google.com/#test"); 855 856 DummyPrerenderContents* prerender_contents = 857 prerender_manager()->CreateNextPrerenderContents(fragment_url, 858 FINAL_STATUS_USED); 859 EXPECT_TRUE(AddSimplePrerender(fragment_url)); 860 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 861 ASSERT_EQ(prerender_contents, 862 prerender_manager()->FindAndUseEntry(fragment_url)); 863} 864 865// Tests that the prerender manager uses fragment references when matching 866// prerender URLs in the case a different fragment is in both URLs. 867TEST_F(PrerenderTest, FragmentsDifferTest) { 868 GURL fragment_url("http://www.google.com/#test"); 869 GURL other_fragment_url("http://www.google.com/#other_test"); 870 871 DummyPrerenderContents* prerender_contents = 872 prerender_manager()->CreateNextPrerenderContents(fragment_url, 873 FINAL_STATUS_USED); 874 EXPECT_TRUE(AddSimplePrerender(fragment_url)); 875 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 876 877 DummyPrerenderContents* null = NULL; 878 ASSERT_EQ(null, prerender_manager()->FindEntry(other_fragment_url)); 879 880 ASSERT_EQ(prerender_contents, 881 prerender_manager()->FindAndUseEntry(fragment_url)); 882} 883 884// Make sure that clearing works as expected. 885TEST_F(PrerenderTest, ClearTest) { 886 GURL url("http://www.google.com/"); 887 DummyPrerenderContents* prerender_contents = 888 prerender_manager()->CreateNextPrerenderContents( 889 url, 890 FINAL_STATUS_CACHE_OR_HISTORY_CLEARED); 891 EXPECT_TRUE(AddSimplePrerender(url)); 892 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 893 prerender_manager()->ClearData(PrerenderManager::CLEAR_PRERENDER_CONTENTS); 894 DummyPrerenderContents* null = NULL; 895 EXPECT_EQ(null, prerender_manager()->FindEntry(url)); 896} 897 898// Make sure canceling works as expected. 899TEST_F(PrerenderTest, CancelAllTest) { 900 GURL url("http://www.google.com/"); 901 DummyPrerenderContents* prerender_contents = 902 prerender_manager()->CreateNextPrerenderContents( 903 url, FINAL_STATUS_CANCELLED); 904 EXPECT_TRUE(AddSimplePrerender(url)); 905 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 906 prerender_manager()->CancelAllPrerenders(); 907 const DummyPrerenderContents* null = NULL; 908 EXPECT_EQ(null, prerender_manager()->FindEntry(url)); 909} 910 911TEST_F(PrerenderTest, OmniboxNotAllowedWhenDisabled) { 912 prerender_manager()->set_enabled(false); 913 EXPECT_FALSE(prerender_manager()->AddPrerenderFromOmnibox( 914 GURL("http://www.example.com"), NULL, gfx::Size())); 915} 916 917TEST_F(PrerenderTest, LinkRelNotAllowedWhenDisabled) { 918 prerender_manager()->set_enabled(false); 919 EXPECT_FALSE(AddSimplePrerender( 920 GURL("http://www.example.com"))); 921} 922 923TEST_F(PrerenderTest, LinkManagerCancel) { 924 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 925 GURL url("http://www.myexample.com"); 926 DummyPrerenderContents* prerender_contents = 927 prerender_manager()->CreateNextPrerenderContents( 928 url, FINAL_STATUS_CANCELLED); 929 930 EXPECT_TRUE(AddSimplePrerender(url)); 931 932 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 933 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 934 ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 935 EXPECT_FALSE(IsEmptyPrerenderLinkManager()); 936 prerender_link_manager()->OnCancelPrerender(kDefaultChildId, 937 last_prerender_id()); 938 939 EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled()); 940 DummyPrerenderContents* null = NULL; 941 ASSERT_EQ(null, prerender_manager()->FindEntry(url)); 942 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 943} 944 945TEST_F(PrerenderTest, LinkManagerCancelThenAbandon) { 946 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 947 GURL url("http://www.myexample.com"); 948 DummyPrerenderContents* prerender_contents = 949 prerender_manager()->CreateNextPrerenderContents( 950 url, FINAL_STATUS_CANCELLED); 951 952 EXPECT_TRUE(AddSimplePrerender(url)); 953 954 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 955 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 956 ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 957 EXPECT_FALSE(IsEmptyPrerenderLinkManager()); 958 prerender_link_manager()->OnCancelPrerender(kDefaultChildId, 959 last_prerender_id()); 960 961 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 962 EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled()); 963 prerender_link_manager()->OnAbandonPrerender(kDefaultChildId, 964 last_prerender_id()); 965 966 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 967 EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled()); 968 DummyPrerenderContents* null = NULL; 969 ASSERT_EQ(null, prerender_manager()->FindEntry(url)); 970} 971 972TEST_F(PrerenderTest, LinkManagerAbandon) { 973 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 974 GURL url("http://www.myexample.com"); 975 DummyPrerenderContents* prerender_contents = 976 prerender_manager()->CreateNextPrerenderContents( 977 url, FINAL_STATUS_USED); 978 979 EXPECT_TRUE(AddSimplePrerender(url)); 980 981 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 982 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 983 ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 984 EXPECT_FALSE(IsEmptyPrerenderLinkManager()); 985 prerender_link_manager()->OnAbandonPrerender(kDefaultChildId, 986 last_prerender_id()); 987 988 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 989 ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); 990} 991 992TEST_F(PrerenderTest, LinkManagerAbandonThenCancel) { 993 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 994 GURL url("http://www.myexample.com"); 995 DummyPrerenderContents* prerender_contents = 996 prerender_manager()->CreateNextPrerenderContents( 997 url, FINAL_STATUS_CANCELLED); 998 999 EXPECT_TRUE(AddSimplePrerender(url)); 1000 1001 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 1002 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 1003 ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 1004 EXPECT_FALSE(IsEmptyPrerenderLinkManager()); 1005 prerender_link_manager()->OnAbandonPrerender(kDefaultChildId, 1006 last_prerender_id()); 1007 1008 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 1009 ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 1010 1011 prerender_link_manager()->OnCancelPrerender(kDefaultChildId, 1012 last_prerender_id()); 1013 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1014 EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled()); 1015 DummyPrerenderContents* null = NULL; 1016 ASSERT_EQ(null, prerender_manager()->FindEntry(url)); 1017} 1018 1019TEST_F(PrerenderTest, LinkManagerCancelTwice) { 1020 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1021 GURL url("http://www.myexample.com"); 1022 DummyPrerenderContents* prerender_contents = 1023 prerender_manager()->CreateNextPrerenderContents( 1024 url, FINAL_STATUS_CANCELLED); 1025 1026 EXPECT_TRUE(AddSimplePrerender(url)); 1027 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 1028 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 1029 EXPECT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 1030 prerender_link_manager()->OnCancelPrerender(kDefaultChildId, 1031 last_prerender_id()); 1032 1033 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1034 EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled()); 1035 DummyPrerenderContents* null = NULL; 1036 ASSERT_EQ(null, prerender_manager()->FindEntry(url)); 1037 prerender_link_manager()->OnCancelPrerender(kDefaultChildId, 1038 last_prerender_id()); 1039} 1040 1041TEST_F(PrerenderTest, LinkManagerAddTwiceCancelTwice) { 1042 SetConcurrency(2); 1043 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1044 GURL url("http://www.myexample.com"); 1045 DummyPrerenderContents* prerender_contents = 1046 prerender_manager()->CreateNextPrerenderContents( 1047 url, FINAL_STATUS_CANCELLED); 1048 1049 EXPECT_TRUE(AddSimplePrerender(url)); 1050 1051 const int first_prerender_id = last_prerender_id(); 1052 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 1053 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 1054 EXPECT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 1055 EXPECT_TRUE(AddSimplePrerender(url)); 1056 1057 const int second_prerender_id = last_prerender_id(); 1058 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 1059 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 1060 EXPECT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 1061 prerender_link_manager()->OnCancelPrerender(kDefaultChildId, 1062 first_prerender_id); 1063 1064 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 1065 EXPECT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 1066 prerender_link_manager()->OnCancelPrerender(kDefaultChildId, 1067 second_prerender_id); 1068 1069 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1070 EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled()); 1071 DummyPrerenderContents* null = NULL; 1072 ASSERT_EQ(null, prerender_manager()->FindEntry(url)); 1073} 1074 1075TEST_F(PrerenderTest, LinkManagerAddTwiceCancelTwiceThenAbandonTwice) { 1076 SetConcurrency(2); 1077 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1078 GURL url("http://www.myexample.com"); 1079 DummyPrerenderContents* prerender_contents = 1080 prerender_manager()->CreateNextPrerenderContents( 1081 url, FINAL_STATUS_CANCELLED); 1082 1083 EXPECT_TRUE(AddSimplePrerender(url)); 1084 1085 const int first_prerender_id = last_prerender_id(); 1086 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 1087 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 1088 ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 1089 EXPECT_TRUE(AddSimplePrerender(url)); 1090 1091 const int second_prerender_id = last_prerender_id(); 1092 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 1093 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 1094 ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 1095 prerender_link_manager()->OnCancelPrerender(kDefaultChildId, 1096 first_prerender_id); 1097 1098 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 1099 ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 1100 prerender_link_manager()->OnCancelPrerender(kDefaultChildId, 1101 second_prerender_id); 1102 1103 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1104 EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled()); 1105 prerender_link_manager()->OnAbandonPrerender(kDefaultChildId, 1106 first_prerender_id); 1107 1108 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1109 EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled()); 1110 prerender_link_manager()->OnAbandonPrerender(kDefaultChildId, 1111 second_prerender_id); 1112 1113 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1114 EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled()); 1115 DummyPrerenderContents* null = NULL; 1116 ASSERT_EQ(null, prerender_manager()->FindEntry(url)); 1117} 1118 1119// TODO(gavinp): Update this test after abandon has an effect on Prerenders, 1120// like shortening the timeouts. 1121TEST_F(PrerenderTest, LinkManagerAddTwiceAbandonTwiceUseTwice) { 1122 SetConcurrency(2); 1123 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1124 GURL url("http://www.myexample.com"); 1125 DummyPrerenderContents* prerender_contents = 1126 prerender_manager()->CreateNextPrerenderContents( 1127 url, FINAL_STATUS_USED); 1128 1129 EXPECT_TRUE(AddSimplePrerender(url)); 1130 1131 const int first_prerender_id = last_prerender_id(); 1132 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 1133 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 1134 ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 1135 EXPECT_TRUE(AddSimplePrerender(url)); 1136 1137 const int second_prerender_id = last_prerender_id(); 1138 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 1139 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 1140 ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 1141 prerender_link_manager()->OnAbandonPrerender(kDefaultChildId, 1142 first_prerender_id); 1143 1144 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 1145 ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 1146 prerender_link_manager()->OnAbandonPrerender(kDefaultChildId, 1147 second_prerender_id); 1148 1149 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 1150 ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); 1151 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1152} 1153 1154// TODO(gavinp): After abandon shortens the expire time on a Prerender, 1155// add a series of tests testing advancing the time by either the abandon 1156// or normal expire, and verifying the expected behaviour with groups 1157// of links. 1158TEST_F(PrerenderTest, LinkManagerExpireThenCancel) { 1159 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1160 GURL url("http://www.myexample.com"); 1161 DummyPrerenderContents* prerender_contents = 1162 prerender_manager()->CreateNextPrerenderContents( 1163 url, FINAL_STATUS_TIMED_OUT); 1164 1165 EXPECT_TRUE(AddSimplePrerender(url)); 1166 1167 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 1168 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 1169 ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 1170 prerender_manager()->AdvanceTimeTicks( 1171 prerender_manager()->config().time_to_live + TimeDelta::FromSeconds(1)); 1172 1173 EXPECT_FALSE(IsEmptyPrerenderLinkManager()); 1174 DummyPrerenderContents* null = NULL; 1175 ASSERT_EQ(null, prerender_manager()->FindEntry(url)); 1176 prerender_link_manager()->OnCancelPrerender(kDefaultChildId, 1177 last_prerender_id()); 1178 1179 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1180 ASSERT_EQ(null, prerender_manager()->FindEntry(url)); 1181} 1182 1183TEST_F(PrerenderTest, LinkManagerExpireThenAddAgain) { 1184 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1185 GURL url("http://www.myexample.com"); 1186 DummyPrerenderContents* first_prerender_contents = 1187 prerender_manager()->CreateNextPrerenderContents( 1188 url, FINAL_STATUS_TIMED_OUT); 1189 EXPECT_TRUE(AddSimplePrerender(url)); 1190 EXPECT_TRUE(first_prerender_contents->prerendering_has_started()); 1191 EXPECT_FALSE(first_prerender_contents->prerendering_has_been_cancelled()); 1192 ASSERT_EQ(first_prerender_contents, 1193 prerender_manager()->FindEntry(url)); 1194 prerender_manager()->AdvanceTimeTicks( 1195 prerender_manager()->config().time_to_live + TimeDelta::FromSeconds(1)); 1196 DummyPrerenderContents* null = NULL; 1197 ASSERT_EQ(null, prerender_manager()->FindEntry(url)); 1198 DummyPrerenderContents* second_prerender_contents = 1199 prerender_manager()->CreateNextPrerenderContents( 1200 url, FINAL_STATUS_USED); 1201 EXPECT_TRUE(AddSimplePrerender(url)); 1202 EXPECT_TRUE(second_prerender_contents->prerendering_has_started()); 1203 ASSERT_EQ(second_prerender_contents, 1204 prerender_manager()->FindAndUseEntry(url)); 1205} 1206 1207TEST_F(PrerenderTest, LinkManagerCancelThenAddAgain) { 1208 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1209 GURL url("http://www.myexample.com"); 1210 DummyPrerenderContents* first_prerender_contents = 1211 prerender_manager()->CreateNextPrerenderContents( 1212 url, FINAL_STATUS_CANCELLED); 1213 EXPECT_TRUE(AddSimplePrerender(url)); 1214 EXPECT_TRUE(first_prerender_contents->prerendering_has_started()); 1215 EXPECT_FALSE(first_prerender_contents->prerendering_has_been_cancelled()); 1216 ASSERT_EQ(first_prerender_contents, prerender_manager()->FindEntry(url)); 1217 prerender_link_manager()->OnCancelPrerender(kDefaultChildId, 1218 last_prerender_id()); 1219 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1220 EXPECT_TRUE(first_prerender_contents->prerendering_has_been_cancelled()); 1221 DummyPrerenderContents* null = NULL; 1222 ASSERT_EQ(null, prerender_manager()->FindEntry(url)); 1223 DummyPrerenderContents* second_prerender_contents = 1224 prerender_manager()->CreateNextPrerenderContents( 1225 url, FINAL_STATUS_USED); 1226 EXPECT_TRUE(AddSimplePrerender(url)); 1227 EXPECT_TRUE(second_prerender_contents->prerendering_has_started()); 1228 ASSERT_EQ(second_prerender_contents, 1229 prerender_manager()->FindAndUseEntry(url)); 1230} 1231 1232TEST_F(PrerenderTest, LinkManagerChannelClosing) { 1233 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1234 GURL url("http://www.myexample.com"); 1235 DummyPrerenderContents* prerender_contents = 1236 prerender_manager()->CreateNextPrerenderContents( 1237 url, FINAL_STATUS_TIMED_OUT); 1238 1239 EXPECT_TRUE(AddSimplePrerender(url)); 1240 EXPECT_TRUE(prerender_contents->prerendering_has_started()); 1241 EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); 1242 ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); 1243 1244 prerender_link_manager()->OnChannelClosing(kDefaultChildId); 1245 1246 prerender_manager()->AdvanceTimeTicks( 1247 prerender_manager()->config().abandon_time_to_live + 1248 TimeDelta::FromSeconds(1)); 1249 1250 DummyPrerenderContents* null = NULL; 1251 EXPECT_EQ(null, prerender_manager()->FindEntry(url)); 1252 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1253} 1254 1255// Creates two prerenders, one of which should be blocked by the 1256// max_link_concurrency; abandons both of them and waits to make sure both 1257// are cleared from the PrerenderLinkManager. 1258TEST_F(PrerenderTest, LinkManagerAbandonInactivePrerender) { 1259 SetConcurrency(1); 1260 ASSERT_LT(prerender_manager()->config().abandon_time_to_live, 1261 prerender_manager()->config().time_to_live); 1262 GURL first_url("http://www.myexample.com"); 1263 DummyPrerenderContents* prerender_contents = 1264 prerender_manager()->CreateNextPrerenderContents( 1265 first_url, FINAL_STATUS_TIMED_OUT); 1266 EXPECT_TRUE(AddSimplePrerender(first_url)); 1267 const int first_prerender_id = last_prerender_id(); 1268 1269 GURL second_url("http://www.neverlaunched.com"); 1270 EXPECT_FALSE(AddSimplePrerender(second_url)); 1271 const int second_prerender_id = last_prerender_id(); 1272 1273 EXPECT_FALSE(IsEmptyPrerenderLinkManager()); 1274 1275 DummyPrerenderContents* null = NULL; 1276 EXPECT_EQ(prerender_contents, prerender_manager()->FindEntry(first_url)); 1277 EXPECT_EQ(null, prerender_manager()->FindEntry(second_url)); 1278 1279 prerender_link_manager()->OnAbandonPrerender(kDefaultChildId, 1280 first_prerender_id); 1281 prerender_link_manager()->OnAbandonPrerender(kDefaultChildId, 1282 second_prerender_id); 1283 1284 prerender_manager()->AdvanceTimeTicks( 1285 prerender_manager()->config().abandon_time_to_live + 1286 TimeDelta::FromSeconds(1)); 1287 EXPECT_EQ(null, prerender_manager()->FindEntry(first_url)); 1288 EXPECT_EQ(null, prerender_manager()->FindEntry(second_url)); 1289 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1290} 1291 1292// Creates two prerenders, the second one started by the first, both of which 1293// should be blocked by max_concurrency; abandons both of them and waits to make 1294// sure both are cleared from the PrerenderLinkManager. 1295TEST_F(PrerenderTest, LinkManagerClearOnPendingAbandon) { 1296 SetConcurrency(1); 1297 ASSERT_LT(prerender_manager()->config().abandon_time_to_live, 1298 prerender_manager()->config().time_to_live); 1299 GURL first_url("http://www.myexample.com"); 1300 DummyPrerenderContents* prerender_contents = 1301 prerender_manager()->CreateNextPrerenderContents( 1302 first_url, FINAL_STATUS_TIMED_OUT); 1303 EXPECT_TRUE(AddSimplePrerender(first_url)); 1304 const int first_prerender_id = last_prerender_id(); 1305 1306 int child_id; 1307 int route_id; 1308 ASSERT_TRUE(prerender_contents->GetChildId(&child_id)); 1309 ASSERT_TRUE(prerender_contents->GetRouteId(&route_id)); 1310 1311 GURL pending_url("http://www.neverlaunched.com"); 1312 prerender_link_manager()->OnAddPrerender(child_id, 1313 GetNextPrerenderID(), 1314 pending_url, content::Referrer(), 1315 kSize, route_id); 1316 const int second_prerender_id = last_prerender_id(); 1317 1318 EXPECT_FALSE(IsEmptyPrerenderLinkManager()); 1319 1320 DummyPrerenderContents* null = NULL; 1321 EXPECT_EQ(prerender_contents, prerender_manager()->FindEntry(first_url)); 1322 EXPECT_EQ(null, prerender_manager()->FindEntry(pending_url)); 1323 1324 prerender_link_manager()->OnAbandonPrerender(kDefaultChildId, 1325 first_prerender_id); 1326 prerender_link_manager()->OnAbandonPrerender(kDefaultChildId, 1327 second_prerender_id); 1328 1329 prerender_manager()->AdvanceTimeTicks( 1330 prerender_manager()->config().abandon_time_to_live + 1331 TimeDelta::FromSeconds(1)); 1332 EXPECT_EQ(null, prerender_manager()->FindEntry(first_url)); 1333 EXPECT_EQ(null, prerender_manager()->FindEntry(pending_url)); 1334 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1335} 1336 1337// Creates two prerenders, one of which should be blocked by the 1338// max_link_concurrency; uses one after the max wait to launch, and 1339// ensures the second prerender does not start. 1340TEST_F(PrerenderTest, LinkManagerWaitToLaunchNotLaunched) { 1341 SetConcurrency(1); 1342 ASSERT_LT(prerender_manager()->config().max_wait_to_launch, 1343 prerender_manager()->config().time_to_live); 1344 GURL first_url("http://www.myexample.com"); 1345 DummyPrerenderContents* prerender_contents = 1346 prerender_manager()->CreateNextPrerenderContents( 1347 first_url, FINAL_STATUS_USED); 1348 EXPECT_TRUE(AddSimplePrerender(first_url)); 1349 1350 GURL second_url("http://www.neverlaunched.com"); 1351 EXPECT_FALSE(AddSimplePrerender(second_url)); 1352 1353 EXPECT_FALSE(IsEmptyPrerenderLinkManager()); 1354 1355 DummyPrerenderContents* null = NULL; 1356 EXPECT_EQ(prerender_contents, prerender_manager()->FindEntry(first_url)); 1357 EXPECT_EQ(null, prerender_manager()->FindEntry(second_url)); 1358 1359 prerender_manager()->AdvanceTimeTicks( 1360 prerender_manager()->config().max_wait_to_launch + 1361 TimeDelta::FromSeconds(1)); 1362 EXPECT_EQ(prerender_contents, prerender_manager()->FindEntry(first_url)); 1363 EXPECT_EQ(null, prerender_manager()->FindEntry(second_url)); 1364 1365 EXPECT_EQ(prerender_contents, 1366 prerender_manager()->FindAndUseEntry(first_url)); 1367 1368 EXPECT_EQ(null, prerender_manager()->FindEntry(first_url)); 1369 EXPECT_EQ(null, prerender_manager()->FindEntry(second_url)); 1370 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1371} 1372 1373// Creates two prerenders, one of which should start when the first one expires. 1374TEST_F(PrerenderTest, LinkManagerExpireRevealingLaunch) { 1375 SetConcurrency(1); 1376 ASSERT_LT(prerender_manager()->config().max_wait_to_launch, 1377 prerender_manager()->config().time_to_live); 1378 1379 GURL first_url("http://www.willexpire.com"); 1380 DummyPrerenderContents* first_prerender_contents = 1381 prerender_manager()->CreateNextPrerenderContents( 1382 first_url, FINAL_STATUS_TIMED_OUT); 1383 EXPECT_TRUE(AddSimplePrerender(first_url)); 1384 EXPECT_EQ(first_prerender_contents, 1385 prerender_manager()->FindEntry(first_url)); 1386 1387 // Insert the second prerender so it will be still be launchable when the 1388 // first expires. 1389 const TimeDelta wait_to_launch_second_prerender = 1390 prerender_manager()->config().time_to_live - 1391 prerender_manager()->config().max_wait_to_launch + 1392 TimeDelta::FromSeconds(2); 1393 const TimeDelta wait_for_first_prerender_to_expire = 1394 prerender_manager()->config().time_to_live - 1395 wait_to_launch_second_prerender + 1396 TimeDelta::FromSeconds(1); 1397 ASSERT_LT(prerender_manager()->config().time_to_live, 1398 wait_to_launch_second_prerender + 1399 wait_for_first_prerender_to_expire); 1400 ASSERT_GT(prerender_manager()->config().max_wait_to_launch.InSeconds(), 1401 wait_for_first_prerender_to_expire.InSeconds()); 1402 1403 prerender_manager()->AdvanceTimeTicks(wait_to_launch_second_prerender); 1404 GURL second_url("http://www.willlaunch.com"); 1405 DummyPrerenderContents* second_prerender_contents = 1406 prerender_manager()->CreateNextPrerenderContents( 1407 second_url, FINAL_STATUS_USED); 1408 EXPECT_FALSE(AddSimplePrerender(second_url)); 1409 1410 // The first prerender is still running, but the second has not yet launched. 1411 EXPECT_EQ(first_prerender_contents, 1412 prerender_manager()->FindEntry(first_url)); 1413 PrerenderContents* null = NULL; 1414 EXPECT_EQ(null, prerender_manager()->FindEntry(second_url)); 1415 1416 // The first prerender should have died, giving life to the second one. 1417 prerender_manager()->AdvanceTimeTicks(wait_for_first_prerender_to_expire); 1418 EXPECT_EQ(null, prerender_manager()->FindEntry(first_url)); 1419 EXPECT_EQ(second_prerender_contents, 1420 prerender_manager()->FindAndUseEntry(second_url)); 1421} 1422 1423} // namespace prerender 1424