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