- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / prerender / prerender_unittest.cc
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
25 using base::Time;
26 using base::TimeDelta;
27 using base::TimeTicks;
28 using content::BrowserThread;
29 using content::Referrer;
30
31 namespace prerender {
32
33 class UnitTestPrerenderManager;
34
35 namespace {
36
37 class 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
81 int DummyPrerenderContents::g_next_route_id_ = 0;
82
83 const gfx::Size kSize(640, 480);
84
85 }  // namespace
86
87 class 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
236 class 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
246 DummyPrerenderContents::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
260 void 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
275 class 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
358 TEST_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.
372 TEST_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.
397 TEST_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)
414 TEST_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.
429 TEST_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.
460 TEST_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 // When the user navigates away from a page, and then launches a new prerender,
502 // the new prerender should preempt the abandoned prerender even if the
503 // abandoned prerender hasn't expired.
504 TEST_F(PrerenderTest, LinkManagerNavigateAwayLaunchAnother) {
505   const TimeDelta time_to_live = TimeDelta::FromSeconds(300);
506   const TimeDelta abandon_time_to_live = TimeDelta::FromSeconds(20);
507   const TimeDelta test_advance = TimeDelta::FromSeconds(5);
508   ASSERT_LT(test_advance, time_to_live);
509   ASSERT_GT(abandon_time_to_live, test_advance);
510
511   prerender_manager()->mutable_config().time_to_live = time_to_live;
512   prerender_manager()->mutable_config().abandon_time_to_live =
513       abandon_time_to_live;
514
515   GURL url("http://example.com");
516   prerender_manager()->CreateNextPrerenderContents(url, FINAL_STATUS_CANCELLED);
517   EXPECT_TRUE(AddSimplePrerender(url));
518   prerender_link_manager()->OnAbandonPrerender(kDefaultChildId,
519                                                last_prerender_id());
520
521   prerender_manager()->AdvanceTimeTicks(test_advance);
522
523   GURL second_url("http://example2.com");
524   DummyPrerenderContents* second_prerender_contents =
525       prerender_manager()->CreateNextPrerenderContents(
526           second_url, FINAL_STATUS_MANAGER_SHUTDOWN);
527   EXPECT_TRUE(AddSimplePrerender(second_url));
528   EXPECT_EQ(second_prerender_contents,
529             prerender_manager()->FindEntry(second_url));
530 }
531
532
533 // Make sure that if we prerender more requests than we support, that we launch
534 // them in the order given up until we reach MaxConcurrency, at which point we
535 // queue them and launch them in the order given. As well, insure that limits
536 // are enforced for the system as a whole and on a per launcher basis.
537 TEST_F(PrerenderTest, MaxConcurrencyTest) {
538   struct TestConcurrency {
539     size_t max_link_concurrency;
540     size_t max_link_concurrency_per_launcher;
541   };
542
543   TestConcurrency concurrencies_to_test[] = {
544     { prerender_manager()->config().max_link_concurrency,
545       prerender_manager()->config().max_link_concurrency_per_launcher},
546
547     // With the system limit higher than the per launcher limit, the per
548     // launcher limit should be in effect.
549     { 2, 1 },
550
551     // With the per launcher limit higher than system limit, the system limit
552     // should be in effect.
553     { 2, 4 },
554   };
555
556   DummyPrerenderContents* null = NULL;
557   GURL url_to_delay("http://www.google.com/delayme");
558
559   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(concurrencies_to_test); ++i) {
560     prerender_manager()->mutable_config().max_link_concurrency =
561         concurrencies_to_test[i].max_link_concurrency;
562     prerender_manager()->mutable_config().max_link_concurrency_per_launcher =
563         concurrencies_to_test[i].max_link_concurrency_per_launcher;
564
565     const size_t effective_max_link_concurrency =
566         std::min(concurrencies_to_test[i].max_link_concurrency,
567                  concurrencies_to_test[i].max_link_concurrency_per_launcher);
568
569     std::vector<GURL> urls;
570     std::vector<PrerenderContents*> prerender_contentses;
571
572     // Launch prerenders up to the maximum this launcher can support.
573     for (size_t j = 0; j < effective_max_link_concurrency; ++j) {
574       urls.push_back(
575           GURL(base::StringPrintf("http://google.com/use#%" PRIuS, j)));
576       prerender_contentses.push_back(
577           prerender_manager()->CreateNextPrerenderContents(urls.back(),
578                                                            FINAL_STATUS_USED));
579       EXPECT_TRUE(AddSimplePrerender(urls.back()));
580       EXPECT_EQ(null, prerender_manager()->next_prerender_contents());
581       EXPECT_TRUE(prerender_contentses.back()->prerendering_has_started());
582     }
583
584     if (concurrencies_to_test[i].max_link_concurrency >
585             effective_max_link_concurrency) {
586       // We should be able to launch more prerenders on this system, but not for
587       // our current launcher.
588       int child_id;
589       int route_id;
590       ASSERT_TRUE(prerender_contentses.back()->GetChildId(&child_id));
591       ASSERT_TRUE(prerender_contentses.back()->GetRouteId(&route_id));
592
593       GURL extra_url("http://google.com/extraurl");
594       prerender_link_manager()->OnAddPrerender(child_id,
595                                                GetNextPrerenderID(),
596                                                extra_url, content::Referrer(),
597                                                kSize, route_id);
598       const int prerender_id = last_prerender_id();
599       EXPECT_TRUE(LauncherHasRunningPrerender(child_id, prerender_id));
600       prerender_link_manager()->OnCancelPrerender(child_id, prerender_id);
601       EXPECT_FALSE(LauncherHasRunningPrerender(child_id, prerender_id));
602     }
603
604     DummyPrerenderContents* prerender_contents_to_delay =
605         prerender_manager()->CreateNextPrerenderContents(url_to_delay,
606                                                          FINAL_STATUS_USED);
607     EXPECT_FALSE(AddSimplePrerender(url_to_delay));
608     EXPECT_FALSE(prerender_contents_to_delay->prerendering_has_started());
609     EXPECT_NE(null, prerender_manager()->next_prerender_contents());
610     EXPECT_EQ(null, prerender_manager()->FindEntry(url_to_delay));
611     for (size_t j = 0; j < effective_max_link_concurrency; ++j) {
612       EXPECT_EQ(prerender_contentses[j],
613                 prerender_manager()->FindAndUseEntry(urls[j]));
614       EXPECT_TRUE(prerender_contents_to_delay->prerendering_has_started());
615     }
616
617     EXPECT_EQ(prerender_contents_to_delay,
618               prerender_manager()->FindAndUseEntry(url_to_delay));
619     EXPECT_EQ(null, prerender_manager()->next_prerender_contents());
620   }
621 }
622
623 TEST_F(PrerenderTest, AliasURLTest) {
624   SetConcurrency(7);
625
626   GURL url("http://www.google.com/");
627   GURL alias_url1("http://www.google.com/index.html");
628   GURL alias_url2("http://google.com/");
629   GURL not_an_alias_url("http://google.com/index.html");
630   std::vector<GURL> alias_urls;
631   alias_urls.push_back(alias_url1);
632   alias_urls.push_back(alias_url2);
633
634   // Test that all of the aliases work, but not_an_alias_url does not.
635   DummyPrerenderContents* prerender_contents =
636       prerender_manager()->CreateNextPrerenderContents(
637           url, alias_urls, FINAL_STATUS_USED);
638   EXPECT_TRUE(AddSimplePrerender(url));
639   ASSERT_EQ(NULL, prerender_manager()->FindEntry(not_an_alias_url));
640   ASSERT_EQ(prerender_contents,
641             prerender_manager()->FindAndUseEntry(alias_url1));
642   prerender_contents = prerender_manager()->CreateNextPrerenderContents(
643           url, alias_urls, FINAL_STATUS_USED);
644   EXPECT_TRUE(AddSimplePrerender(url));
645   ASSERT_EQ(prerender_contents,
646             prerender_manager()->FindAndUseEntry(alias_url2));
647   prerender_contents = prerender_manager()->CreateNextPrerenderContents(
648           url, alias_urls, FINAL_STATUS_USED);
649   EXPECT_TRUE(AddSimplePrerender(url));
650   ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url));
651
652   // Test that alias URLs can not be added.
653   prerender_contents = prerender_manager()->CreateNextPrerenderContents(
654           url, alias_urls, FINAL_STATUS_USED);
655   EXPECT_TRUE(AddSimplePrerender(url));
656   EXPECT_TRUE(AddSimplePrerender(url));
657   EXPECT_TRUE(AddSimplePrerender(alias_url1));
658   EXPECT_TRUE(AddSimplePrerender(alias_url2));
659   ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url));
660 }
661
662 TEST_F(PrerenderTest, PendingPrerenderTest) {
663   GURL url("http://www.google.com/");
664   DummyPrerenderContents* prerender_contents =
665       prerender_manager()->CreateNextPrerenderContents(
666           url,
667           FINAL_STATUS_USED);
668   EXPECT_TRUE(AddSimplePrerender(url));
669
670   int child_id;
671   int route_id;
672   ASSERT_TRUE(prerender_contents->GetChildId(&child_id));
673   ASSERT_TRUE(prerender_contents->GetRouteId(&route_id));
674
675   GURL pending_url("http://news.google.com/");
676
677   DummyPrerenderContents* pending_prerender_contents =
678       prerender_manager()->CreateNextPrerenderContents(
679           pending_url,
680           ORIGIN_GWS_PRERENDER,
681           FINAL_STATUS_USED);
682   scoped_ptr<PrerenderHandle> pending_prerender_handle(
683       prerender_manager()->AddPrerenderFromLinkRelPrerender(
684           child_id, route_id, pending_url,
685           Referrer(url, WebKit::WebReferrerPolicyDefault), kSize));
686   CHECK(pending_prerender_handle.get());
687   EXPECT_FALSE(pending_prerender_handle->IsPrerendering());
688
689   EXPECT_TRUE(prerender_contents->prerendering_has_started());
690   ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url));
691
692   EXPECT_TRUE(pending_prerender_handle->IsPrerendering());
693   ASSERT_EQ(pending_prerender_contents,
694             prerender_manager()->FindAndUseEntry(pending_url));
695   EXPECT_FALSE(pending_prerender_handle->IsPrerendering());
696 }
697
698 TEST_F(PrerenderTest, InvalidPendingPrerenderTest) {
699   GURL url("http://www.google.com/");
700   DummyPrerenderContents* prerender_contents =
701       prerender_manager()->CreateNextPrerenderContents(
702           url,
703           FINAL_STATUS_USED);
704   EXPECT_TRUE(AddSimplePrerender(url));
705
706   int child_id;
707   int route_id;
708   ASSERT_TRUE(prerender_contents->GetChildId(&child_id));
709   ASSERT_TRUE(prerender_contents->GetRouteId(&route_id));
710
711   // This pending URL has an unsupported scheme, and won't be able
712   // to start.
713   GURL pending_url("ftp://news.google.com/");
714
715   prerender_manager()->CreateNextPrerenderContents(
716       pending_url,
717       ORIGIN_GWS_PRERENDER,
718       FINAL_STATUS_UNSUPPORTED_SCHEME);
719   scoped_ptr<PrerenderHandle> pending_prerender_handle(
720       prerender_manager()->AddPrerenderFromLinkRelPrerender(
721           child_id, route_id, pending_url,
722           Referrer(url, WebKit::WebReferrerPolicyDefault), kSize));
723   DCHECK(pending_prerender_handle.get());
724   EXPECT_FALSE(pending_prerender_handle->IsPrerendering());
725
726   EXPECT_TRUE(prerender_contents->prerendering_has_started());
727   ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url));
728
729   EXPECT_FALSE(pending_prerender_handle->IsPrerendering());
730 }
731
732 TEST_F(PrerenderTest, CancelPendingPrerenderTest) {
733   GURL url("http://www.google.com/");
734   DummyPrerenderContents* prerender_contents =
735       prerender_manager()->CreateNextPrerenderContents(
736           url,
737           FINAL_STATUS_USED);
738   EXPECT_TRUE(AddSimplePrerender(url));
739
740   int child_id;
741   int route_id;
742   ASSERT_TRUE(prerender_contents->GetChildId(&child_id));
743   ASSERT_TRUE(prerender_contents->GetRouteId(&route_id));
744
745   GURL pending_url("http://news.google.com/");
746
747   scoped_ptr<PrerenderHandle> pending_prerender_handle(
748       prerender_manager()->AddPrerenderFromLinkRelPrerender(
749           child_id, route_id, pending_url,
750           Referrer(url, WebKit::WebReferrerPolicyDefault), kSize));
751   CHECK(pending_prerender_handle.get());
752   EXPECT_FALSE(pending_prerender_handle->IsPrerendering());
753
754   EXPECT_TRUE(prerender_contents->prerendering_has_started());
755
756   pending_prerender_handle.reset();
757
758   ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url));
759 }
760
761 // Tests that a PrerenderManager created for a browser session in the control
762 // group works as expected.
763 TEST_F(PrerenderTest, ControlGroup) {
764   RestorePrerenderMode restore_prerender_mode;
765   PrerenderManager::SetMode(
766       PrerenderManager::PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP);
767   GURL url("http://www.google.com/");
768   DummyPrerenderContents* prerender_contents =
769       prerender_manager()->CreateNextPrerenderContents(
770           url,
771           FINAL_STATUS_MANAGER_SHUTDOWN);
772   EXPECT_TRUE(AddSimplePrerender(url));
773   EXPECT_FALSE(prerender_contents->prerendering_has_started());
774 }
775
776 // Tests that prerendering is cancelled when the source render view does not
777 // exist.  On failure, the DCHECK in CreatePrerenderContents() above should be
778 // triggered.
779 TEST_F(PrerenderTest, SourceRenderViewClosed) {
780   GURL url("http://www.google.com/");
781   prerender_manager()->CreateNextPrerenderContents(
782       url,
783       FINAL_STATUS_MANAGER_SHUTDOWN);
784   prerender_link_manager()->OnAddPrerender(100, GetNextPrerenderID(), url,
785                                            Referrer(), kSize, 200);
786   EXPECT_FALSE(LauncherHasRunningPrerender(100, last_prerender_id()));
787 }
788
789 // Tests that prerendering is cancelled when we launch a second prerender of
790 // the same target within a short time interval.
791 TEST_F(PrerenderTest, RecentlyVisited) {
792   GURL url("http://www.google.com/");
793
794   prerender_manager()->RecordNavigation(url);
795
796   DummyPrerenderContents* prerender_contents =
797       prerender_manager()->CreateNextPrerenderContents(
798           url, FINAL_STATUS_RECENTLY_VISITED);
799   EXPECT_FALSE(AddSimplePrerender(url));
800   EXPECT_FALSE(prerender_contents->prerendering_has_started());
801 }
802
803 TEST_F(PrerenderTest, NotSoRecentlyVisited) {
804   GURL url("http://www.google.com/");
805
806   prerender_manager()->RecordNavigation(url);
807   prerender_manager()->AdvanceTimeTicks(
808       TimeDelta::FromMilliseconds(
809           UnitTestPrerenderManager::kNavigationRecordWindowMs + 500));
810
811   DummyPrerenderContents* prerender_contents =
812       prerender_manager()->CreateNextPrerenderContents(
813           url, FINAL_STATUS_USED);
814   EXPECT_TRUE(AddSimplePrerender(url));
815   EXPECT_TRUE(prerender_contents->prerendering_has_started());
816   ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url));
817 }
818
819 // Tests that our PPLT dummy prerender gets created properly.
820 TEST_F(PrerenderTest, PPLTDummy) {
821   GURL url("http://www.google.com/");
822   DummyPrerenderContents* prerender_contents =
823       prerender_manager()->CreateNextPrerenderContents(
824           url, FINAL_STATUS_UNSUPPORTED_SCHEME);
825   EXPECT_TRUE(AddSimplePrerender(url));
826   EXPECT_TRUE(prerender_contents->prerendering_has_started());
827   EXPECT_FALSE(IsEmptyPrerenderLinkManager());
828
829   DummyPrerenderContents* pplt_dummy_contents =
830       prerender_manager()->CreateNextPrerenderContents(url,
831                                                        FINAL_STATUS_USED);
832   GURL ftp_url("ftp://ftp.google.com/");
833   // Adding this ftp URL will force the expected unsupported scheme error.
834   prerender_contents->AddAliasURL(ftp_url);
835   EXPECT_FALSE(IsEmptyPrerenderLinkManager());
836
837   ASSERT_EQ(pplt_dummy_contents, prerender_manager()->FindAndUseEntry(url));
838   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
839 }
840
841 // Tests that our PPLT dummy prerender gets created properly, even
842 // when navigating to a page that has been recently navigated to.
843 TEST_F(PrerenderTest, RecentlyVisitedPPLTDummy) {
844   GURL url("http://www.google.com/");
845   DummyPrerenderContents* prerender_contents =
846       prerender_manager()->CreateNextPrerenderContents(
847           url, FINAL_STATUS_UNSUPPORTED_SCHEME);
848   EXPECT_TRUE(AddSimplePrerender(url));
849   EXPECT_TRUE(prerender_contents->prerendering_has_started());
850
851   DummyPrerenderContents* pplt_dummy_contents =
852       prerender_manager()->CreateNextPrerenderContents(url,
853                                                        FINAL_STATUS_USED);
854   prerender_manager()->RecordNavigation(url);
855   GURL ftp_url("ftp://ftp.google.com/");
856   prerender_contents->AddAliasURL(ftp_url);
857
858   ASSERT_EQ(pplt_dummy_contents, prerender_manager()->FindAndUseEntry(url));
859 }
860
861 TEST_F(PrerenderTest, PPLTLateCancel) {
862   GURL url("http://www.google.com");
863   DummyPrerenderContents* prerender_contents =
864       prerender_manager()->CreateNextPrerenderContents(
865           url, FINAL_STATUS_JAVASCRIPT_ALERT);
866   EXPECT_TRUE(AddSimplePrerender(url));
867   EXPECT_TRUE(prerender_contents->prerendering_has_started());
868   // Force the creation of a match complete dummy.
869   DummyPrerenderContents* duplicate_prerender_contents =
870       prerender_manager()->CreateNextPrerenderContents(url,
871                                                        FINAL_STATUS_CANCELLED);
872   ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url));
873   prerender_contents->Destroy(FINAL_STATUS_JAVASCRIPT_ALERT);
874   ASSERT_EQ(duplicate_prerender_contents, prerender_manager()->FindEntry(url));
875
876   // Make sure that events on prerender handles propogate to the match
877   // complete replacement.
878   DummyPrerenderContents* null = NULL;
879   prerender_link_manager()->OnCancelPrerender(kDefaultChildId,
880                                               last_prerender_id());
881   ASSERT_EQ(null, prerender_manager()->FindEntry(url));
882 }
883
884 // Tests that the prerender manager matches include the fragment.
885 TEST_F(PrerenderTest, FragmentMatchesTest) {
886   GURL fragment_url("http://www.google.com/#test");
887
888   DummyPrerenderContents* prerender_contents =
889       prerender_manager()->CreateNextPrerenderContents(fragment_url,
890                                                        FINAL_STATUS_USED);
891   EXPECT_TRUE(AddSimplePrerender(fragment_url));
892   EXPECT_TRUE(prerender_contents->prerendering_has_started());
893   ASSERT_EQ(prerender_contents,
894             prerender_manager()->FindAndUseEntry(fragment_url));
895 }
896
897 // Tests that the prerender manager uses fragment references when matching
898 // prerender URLs in the case a different fragment is in both URLs.
899 TEST_F(PrerenderTest, FragmentsDifferTest) {
900   GURL fragment_url("http://www.google.com/#test");
901   GURL other_fragment_url("http://www.google.com/#other_test");
902
903   DummyPrerenderContents* prerender_contents =
904       prerender_manager()->CreateNextPrerenderContents(fragment_url,
905                                                        FINAL_STATUS_USED);
906   EXPECT_TRUE(AddSimplePrerender(fragment_url));
907   EXPECT_TRUE(prerender_contents->prerendering_has_started());
908
909   DummyPrerenderContents* null = NULL;
910   ASSERT_EQ(null, prerender_manager()->FindEntry(other_fragment_url));
911
912   ASSERT_EQ(prerender_contents,
913             prerender_manager()->FindAndUseEntry(fragment_url));
914 }
915
916 // Make sure that clearing works as expected.
917 TEST_F(PrerenderTest, ClearTest) {
918   GURL url("http://www.google.com/");
919   DummyPrerenderContents* prerender_contents =
920       prerender_manager()->CreateNextPrerenderContents(
921           url,
922           FINAL_STATUS_CACHE_OR_HISTORY_CLEARED);
923   EXPECT_TRUE(AddSimplePrerender(url));
924   EXPECT_TRUE(prerender_contents->prerendering_has_started());
925   prerender_manager()->ClearData(PrerenderManager::CLEAR_PRERENDER_CONTENTS);
926   DummyPrerenderContents* null = NULL;
927   EXPECT_EQ(null, prerender_manager()->FindEntry(url));
928 }
929
930 // Make sure canceling works as expected.
931 TEST_F(PrerenderTest, CancelAllTest) {
932   GURL url("http://www.google.com/");
933   DummyPrerenderContents* prerender_contents =
934       prerender_manager()->CreateNextPrerenderContents(
935           url, FINAL_STATUS_CANCELLED);
936   EXPECT_TRUE(AddSimplePrerender(url));
937   EXPECT_TRUE(prerender_contents->prerendering_has_started());
938   prerender_manager()->CancelAllPrerenders();
939   const DummyPrerenderContents* null = NULL;
940   EXPECT_EQ(null, prerender_manager()->FindEntry(url));
941 }
942
943 TEST_F(PrerenderTest, OmniboxNotAllowedWhenDisabled) {
944   prerender_manager()->set_enabled(false);
945   EXPECT_FALSE(prerender_manager()->AddPrerenderFromOmnibox(
946       GURL("http://www.example.com"), NULL, gfx::Size()));
947 }
948
949 TEST_F(PrerenderTest, LinkRelNotAllowedWhenDisabled) {
950   prerender_manager()->set_enabled(false);
951   EXPECT_FALSE(AddSimplePrerender(
952       GURL("http://www.example.com")));
953 }
954
955 TEST_F(PrerenderTest, LinkManagerCancel) {
956   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
957   GURL url("http://www.myexample.com");
958   DummyPrerenderContents* prerender_contents =
959       prerender_manager()->CreateNextPrerenderContents(
960           url, FINAL_STATUS_CANCELLED);
961
962   EXPECT_TRUE(AddSimplePrerender(url));
963
964   EXPECT_TRUE(prerender_contents->prerendering_has_started());
965   EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled());
966   ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url));
967   EXPECT_FALSE(IsEmptyPrerenderLinkManager());
968   prerender_link_manager()->OnCancelPrerender(kDefaultChildId,
969                                               last_prerender_id());
970
971   EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled());
972   DummyPrerenderContents* null = NULL;
973   ASSERT_EQ(null, prerender_manager()->FindEntry(url));
974   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
975 }
976
977 TEST_F(PrerenderTest, LinkManagerCancelThenAbandon) {
978   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
979   GURL url("http://www.myexample.com");
980   DummyPrerenderContents* prerender_contents =
981       prerender_manager()->CreateNextPrerenderContents(
982           url, FINAL_STATUS_CANCELLED);
983
984   EXPECT_TRUE(AddSimplePrerender(url));
985
986   EXPECT_TRUE(prerender_contents->prerendering_has_started());
987   EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled());
988   ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url));
989   EXPECT_FALSE(IsEmptyPrerenderLinkManager());
990   prerender_link_manager()->OnCancelPrerender(kDefaultChildId,
991                                               last_prerender_id());
992
993   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
994   EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled());
995   prerender_link_manager()->OnAbandonPrerender(kDefaultChildId,
996                                                last_prerender_id());
997
998   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
999   EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled());
1000   DummyPrerenderContents* null = NULL;
1001   ASSERT_EQ(null, prerender_manager()->FindEntry(url));
1002 }
1003
1004 TEST_F(PrerenderTest, LinkManagerAbandon) {
1005   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1006   GURL url("http://www.myexample.com");
1007   DummyPrerenderContents* prerender_contents =
1008       prerender_manager()->CreateNextPrerenderContents(
1009           url, FINAL_STATUS_USED);
1010
1011   EXPECT_TRUE(AddSimplePrerender(url));
1012
1013   EXPECT_TRUE(prerender_contents->prerendering_has_started());
1014   EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled());
1015   ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url));
1016   EXPECT_FALSE(IsEmptyPrerenderLinkManager());
1017   prerender_link_manager()->OnAbandonPrerender(kDefaultChildId,
1018                                                last_prerender_id());
1019
1020   EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled());
1021   ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url));
1022 }
1023
1024 TEST_F(PrerenderTest, LinkManagerAbandonThenCancel) {
1025   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1026   GURL url("http://www.myexample.com");
1027   DummyPrerenderContents* prerender_contents =
1028       prerender_manager()->CreateNextPrerenderContents(
1029           url, FINAL_STATUS_CANCELLED);
1030
1031   EXPECT_TRUE(AddSimplePrerender(url));
1032
1033   EXPECT_TRUE(prerender_contents->prerendering_has_started());
1034   EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled());
1035   ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url));
1036   EXPECT_FALSE(IsEmptyPrerenderLinkManager());
1037   prerender_link_manager()->OnAbandonPrerender(kDefaultChildId,
1038                                                last_prerender_id());
1039
1040   EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled());
1041   ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url));
1042
1043   prerender_link_manager()->OnCancelPrerender(kDefaultChildId,
1044                                               last_prerender_id());
1045   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1046   EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled());
1047   DummyPrerenderContents* null = NULL;
1048   ASSERT_EQ(null, prerender_manager()->FindEntry(url));
1049 }
1050
1051 TEST_F(PrerenderTest, LinkManagerCancelTwice) {
1052   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1053   GURL url("http://www.myexample.com");
1054   DummyPrerenderContents* prerender_contents =
1055       prerender_manager()->CreateNextPrerenderContents(
1056           url, FINAL_STATUS_CANCELLED);
1057
1058   EXPECT_TRUE(AddSimplePrerender(url));
1059   EXPECT_TRUE(prerender_contents->prerendering_has_started());
1060   EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled());
1061   EXPECT_EQ(prerender_contents, prerender_manager()->FindEntry(url));
1062   prerender_link_manager()->OnCancelPrerender(kDefaultChildId,
1063                                               last_prerender_id());
1064
1065   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1066   EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled());
1067   DummyPrerenderContents* null = NULL;
1068   ASSERT_EQ(null, prerender_manager()->FindEntry(url));
1069   prerender_link_manager()->OnCancelPrerender(kDefaultChildId,
1070                                               last_prerender_id());
1071 }
1072
1073 TEST_F(PrerenderTest, LinkManagerAddTwiceCancelTwice) {
1074   SetConcurrency(2);
1075   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1076   GURL url("http://www.myexample.com");
1077   DummyPrerenderContents* prerender_contents =
1078       prerender_manager()->CreateNextPrerenderContents(
1079           url, FINAL_STATUS_CANCELLED);
1080
1081   EXPECT_TRUE(AddSimplePrerender(url));
1082
1083   const int first_prerender_id = last_prerender_id();
1084   EXPECT_TRUE(prerender_contents->prerendering_has_started());
1085   EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled());
1086   EXPECT_EQ(prerender_contents, prerender_manager()->FindEntry(url));
1087   EXPECT_TRUE(AddSimplePrerender(url));
1088
1089   const int second_prerender_id = last_prerender_id();
1090   EXPECT_TRUE(prerender_contents->prerendering_has_started());
1091   EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled());
1092   EXPECT_EQ(prerender_contents, prerender_manager()->FindEntry(url));
1093   prerender_link_manager()->OnCancelPrerender(kDefaultChildId,
1094                                               first_prerender_id);
1095
1096   EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled());
1097   EXPECT_EQ(prerender_contents, prerender_manager()->FindEntry(url));
1098   prerender_link_manager()->OnCancelPrerender(kDefaultChildId,
1099                                               second_prerender_id);
1100
1101   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1102   EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled());
1103   DummyPrerenderContents* null = NULL;
1104   ASSERT_EQ(null, prerender_manager()->FindEntry(url));
1105 }
1106
1107 TEST_F(PrerenderTest, LinkManagerAddTwiceCancelTwiceThenAbandonTwice) {
1108   SetConcurrency(2);
1109   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1110   GURL url("http://www.myexample.com");
1111   DummyPrerenderContents* prerender_contents =
1112       prerender_manager()->CreateNextPrerenderContents(
1113           url, FINAL_STATUS_CANCELLED);
1114
1115   EXPECT_TRUE(AddSimplePrerender(url));
1116
1117   const int first_prerender_id = last_prerender_id();
1118   EXPECT_TRUE(prerender_contents->prerendering_has_started());
1119   EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled());
1120   ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url));
1121   EXPECT_TRUE(AddSimplePrerender(url));
1122
1123   const int second_prerender_id = last_prerender_id();
1124   EXPECT_TRUE(prerender_contents->prerendering_has_started());
1125   EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled());
1126   ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url));
1127   prerender_link_manager()->OnCancelPrerender(kDefaultChildId,
1128                                               first_prerender_id);
1129
1130   EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled());
1131   ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url));
1132   prerender_link_manager()->OnCancelPrerender(kDefaultChildId,
1133                                               second_prerender_id);
1134
1135   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1136   EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled());
1137   prerender_link_manager()->OnAbandonPrerender(kDefaultChildId,
1138                                                first_prerender_id);
1139
1140   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1141   EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled());
1142   prerender_link_manager()->OnAbandonPrerender(kDefaultChildId,
1143                                                second_prerender_id);
1144
1145   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1146   EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled());
1147   DummyPrerenderContents* null = NULL;
1148   ASSERT_EQ(null, prerender_manager()->FindEntry(url));
1149 }
1150
1151 // TODO(gavinp): Update this test after abandon has an effect on Prerenders,
1152 // like shortening the timeouts.
1153 TEST_F(PrerenderTest, LinkManagerAddTwiceAbandonTwiceUseTwice) {
1154   SetConcurrency(2);
1155   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1156   GURL url("http://www.myexample.com");
1157   DummyPrerenderContents* prerender_contents =
1158       prerender_manager()->CreateNextPrerenderContents(
1159           url, FINAL_STATUS_USED);
1160
1161   EXPECT_TRUE(AddSimplePrerender(url));
1162
1163   const int first_prerender_id = last_prerender_id();
1164   EXPECT_TRUE(prerender_contents->prerendering_has_started());
1165   EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled());
1166   ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url));
1167   EXPECT_TRUE(AddSimplePrerender(url));
1168
1169   const int second_prerender_id = last_prerender_id();
1170   EXPECT_TRUE(prerender_contents->prerendering_has_started());
1171   EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled());
1172   ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url));
1173   prerender_link_manager()->OnAbandonPrerender(kDefaultChildId,
1174                                                first_prerender_id);
1175
1176   EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled());
1177   ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url));
1178   prerender_link_manager()->OnAbandonPrerender(kDefaultChildId,
1179                                                second_prerender_id);
1180
1181   EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled());
1182   ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url));
1183   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1184 }
1185
1186 // TODO(gavinp): After abandon shortens the expire time on a Prerender,
1187 // add a series of tests testing advancing the time by either the abandon
1188 // or normal expire, and verifying the expected behaviour with groups
1189 // of links.
1190 TEST_F(PrerenderTest, LinkManagerExpireThenCancel) {
1191   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1192   GURL url("http://www.myexample.com");
1193   DummyPrerenderContents* prerender_contents =
1194       prerender_manager()->CreateNextPrerenderContents(
1195           url, FINAL_STATUS_TIMED_OUT);
1196
1197   EXPECT_TRUE(AddSimplePrerender(url));
1198
1199   EXPECT_TRUE(prerender_contents->prerendering_has_started());
1200   EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled());
1201   ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url));
1202   prerender_manager()->AdvanceTimeTicks(
1203       prerender_manager()->config().time_to_live + TimeDelta::FromSeconds(1));
1204
1205   EXPECT_FALSE(IsEmptyPrerenderLinkManager());
1206   DummyPrerenderContents* null = NULL;
1207   ASSERT_EQ(null, prerender_manager()->FindEntry(url));
1208   prerender_link_manager()->OnCancelPrerender(kDefaultChildId,
1209                                               last_prerender_id());
1210
1211   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1212   ASSERT_EQ(null, prerender_manager()->FindEntry(url));
1213 }
1214
1215 TEST_F(PrerenderTest, LinkManagerExpireThenAddAgain) {
1216   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1217   GURL url("http://www.myexample.com");
1218   DummyPrerenderContents* first_prerender_contents =
1219       prerender_manager()->CreateNextPrerenderContents(
1220           url, FINAL_STATUS_TIMED_OUT);
1221   EXPECT_TRUE(AddSimplePrerender(url));
1222   EXPECT_TRUE(first_prerender_contents->prerendering_has_started());
1223   EXPECT_FALSE(first_prerender_contents->prerendering_has_been_cancelled());
1224   ASSERT_EQ(first_prerender_contents,
1225             prerender_manager()->FindEntry(url));
1226   prerender_manager()->AdvanceTimeTicks(
1227       prerender_manager()->config().time_to_live + TimeDelta::FromSeconds(1));
1228   DummyPrerenderContents* null = NULL;
1229   ASSERT_EQ(null, prerender_manager()->FindEntry(url));
1230   DummyPrerenderContents* second_prerender_contents =
1231       prerender_manager()->CreateNextPrerenderContents(
1232           url, FINAL_STATUS_USED);
1233   EXPECT_TRUE(AddSimplePrerender(url));
1234   EXPECT_TRUE(second_prerender_contents->prerendering_has_started());
1235   ASSERT_EQ(second_prerender_contents,
1236             prerender_manager()->FindAndUseEntry(url));
1237 }
1238
1239 TEST_F(PrerenderTest, LinkManagerCancelThenAddAgain) {
1240   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1241   GURL url("http://www.myexample.com");
1242   DummyPrerenderContents* first_prerender_contents =
1243       prerender_manager()->CreateNextPrerenderContents(
1244           url, FINAL_STATUS_CANCELLED);
1245   EXPECT_TRUE(AddSimplePrerender(url));
1246   EXPECT_TRUE(first_prerender_contents->prerendering_has_started());
1247   EXPECT_FALSE(first_prerender_contents->prerendering_has_been_cancelled());
1248   ASSERT_EQ(first_prerender_contents, prerender_manager()->FindEntry(url));
1249   prerender_link_manager()->OnCancelPrerender(kDefaultChildId,
1250                                               last_prerender_id());
1251   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1252   EXPECT_TRUE(first_prerender_contents->prerendering_has_been_cancelled());
1253   DummyPrerenderContents* null = NULL;
1254   ASSERT_EQ(null, prerender_manager()->FindEntry(url));
1255   DummyPrerenderContents* second_prerender_contents =
1256       prerender_manager()->CreateNextPrerenderContents(
1257           url, FINAL_STATUS_USED);
1258   EXPECT_TRUE(AddSimplePrerender(url));
1259   EXPECT_TRUE(second_prerender_contents->prerendering_has_started());
1260   ASSERT_EQ(second_prerender_contents,
1261             prerender_manager()->FindAndUseEntry(url));
1262 }
1263
1264 TEST_F(PrerenderTest, LinkManagerChannelClosing) {
1265   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1266   GURL url("http://www.myexample.com");
1267   DummyPrerenderContents* prerender_contents =
1268       prerender_manager()->CreateNextPrerenderContents(
1269           url, FINAL_STATUS_TIMED_OUT);
1270
1271   EXPECT_TRUE(AddSimplePrerender(url));
1272   EXPECT_TRUE(prerender_contents->prerendering_has_started());
1273   EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled());
1274   ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url));
1275
1276   prerender_link_manager()->OnChannelClosing(kDefaultChildId);
1277
1278   prerender_manager()->AdvanceTimeTicks(
1279       prerender_manager()->config().abandon_time_to_live +
1280       TimeDelta::FromSeconds(1));
1281
1282   DummyPrerenderContents* null = NULL;
1283   EXPECT_EQ(null, prerender_manager()->FindEntry(url));
1284   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1285 }
1286
1287 // Creates two prerenders, one of which should be blocked by the
1288 // max_link_concurrency; abandons both of them and waits to make sure both
1289 // are cleared from the PrerenderLinkManager.
1290 TEST_F(PrerenderTest, LinkManagerAbandonInactivePrerender) {
1291   SetConcurrency(1);
1292   ASSERT_LT(prerender_manager()->config().abandon_time_to_live,
1293             prerender_manager()->config().time_to_live);
1294   GURL first_url("http://www.myexample.com");
1295   DummyPrerenderContents* prerender_contents =
1296       prerender_manager()->CreateNextPrerenderContents(
1297           first_url, FINAL_STATUS_TIMED_OUT);
1298   EXPECT_TRUE(AddSimplePrerender(first_url));
1299   const int first_prerender_id = last_prerender_id();
1300
1301   GURL second_url("http://www.neverlaunched.com");
1302   EXPECT_FALSE(AddSimplePrerender(second_url));
1303   const int second_prerender_id = last_prerender_id();
1304
1305   EXPECT_FALSE(IsEmptyPrerenderLinkManager());
1306
1307   DummyPrerenderContents* null = NULL;
1308   EXPECT_EQ(prerender_contents, prerender_manager()->FindEntry(first_url));
1309   EXPECT_EQ(null, prerender_manager()->FindEntry(second_url));
1310
1311   prerender_link_manager()->OnAbandonPrerender(kDefaultChildId,
1312                                                first_prerender_id);
1313   prerender_link_manager()->OnAbandonPrerender(kDefaultChildId,
1314                                                second_prerender_id);
1315
1316   prerender_manager()->AdvanceTimeTicks(
1317       prerender_manager()->config().abandon_time_to_live +
1318       TimeDelta::FromSeconds(1));
1319   EXPECT_EQ(null, prerender_manager()->FindEntry(first_url));
1320   EXPECT_EQ(null, prerender_manager()->FindEntry(second_url));
1321   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1322 }
1323
1324 // Creates two prerenders, the second one started by the first, both of which
1325 // should be blocked by max_concurrency; abandons both of them and waits to make
1326 // sure both are cleared from the PrerenderLinkManager.
1327 TEST_F(PrerenderTest, LinkManagerClearOnPendingAbandon) {
1328   SetConcurrency(1);
1329   ASSERT_LT(prerender_manager()->config().abandon_time_to_live,
1330             prerender_manager()->config().time_to_live);
1331   GURL first_url("http://www.myexample.com");
1332   DummyPrerenderContents* prerender_contents =
1333       prerender_manager()->CreateNextPrerenderContents(
1334           first_url, FINAL_STATUS_TIMED_OUT);
1335   EXPECT_TRUE(AddSimplePrerender(first_url));
1336   const int first_prerender_id = last_prerender_id();
1337
1338   int child_id;
1339   int route_id;
1340   ASSERT_TRUE(prerender_contents->GetChildId(&child_id));
1341   ASSERT_TRUE(prerender_contents->GetRouteId(&route_id));
1342
1343   GURL pending_url("http://www.neverlaunched.com");
1344   prerender_link_manager()->OnAddPrerender(child_id,
1345                                            GetNextPrerenderID(),
1346                                            pending_url, content::Referrer(),
1347                                            kSize, route_id);
1348   const int second_prerender_id = last_prerender_id();
1349
1350   EXPECT_FALSE(IsEmptyPrerenderLinkManager());
1351
1352   DummyPrerenderContents* null = NULL;
1353   EXPECT_EQ(prerender_contents, prerender_manager()->FindEntry(first_url));
1354   EXPECT_EQ(null, prerender_manager()->FindEntry(pending_url));
1355
1356   prerender_link_manager()->OnAbandonPrerender(kDefaultChildId,
1357                                                first_prerender_id);
1358   prerender_link_manager()->OnAbandonPrerender(kDefaultChildId,
1359                                                second_prerender_id);
1360
1361   prerender_manager()->AdvanceTimeTicks(
1362       prerender_manager()->config().abandon_time_to_live +
1363       TimeDelta::FromSeconds(1));
1364   EXPECT_EQ(null, prerender_manager()->FindEntry(first_url));
1365   EXPECT_EQ(null, prerender_manager()->FindEntry(pending_url));
1366   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1367 }
1368
1369 // Creates two prerenders, one of which should be blocked by the
1370 // max_link_concurrency; uses one after the max wait to launch, and
1371 // ensures the second prerender does not start.
1372 TEST_F(PrerenderTest, LinkManagerWaitToLaunchNotLaunched) {
1373   SetConcurrency(1);
1374   ASSERT_LT(prerender_manager()->config().max_wait_to_launch,
1375             prerender_manager()->config().time_to_live);
1376   GURL first_url("http://www.myexample.com");
1377   DummyPrerenderContents* prerender_contents =
1378       prerender_manager()->CreateNextPrerenderContents(
1379           first_url, FINAL_STATUS_USED);
1380   EXPECT_TRUE(AddSimplePrerender(first_url));
1381
1382   GURL second_url("http://www.neverlaunched.com");
1383   EXPECT_FALSE(AddSimplePrerender(second_url));
1384
1385   EXPECT_FALSE(IsEmptyPrerenderLinkManager());
1386
1387   DummyPrerenderContents* null = NULL;
1388   EXPECT_EQ(prerender_contents, prerender_manager()->FindEntry(first_url));
1389   EXPECT_EQ(null, prerender_manager()->FindEntry(second_url));
1390
1391   prerender_manager()->AdvanceTimeTicks(
1392       prerender_manager()->config().max_wait_to_launch +
1393       TimeDelta::FromSeconds(1));
1394   EXPECT_EQ(prerender_contents, prerender_manager()->FindEntry(first_url));
1395   EXPECT_EQ(null, prerender_manager()->FindEntry(second_url));
1396
1397   EXPECT_EQ(prerender_contents,
1398             prerender_manager()->FindAndUseEntry(first_url));
1399
1400   EXPECT_EQ(null, prerender_manager()->FindEntry(first_url));
1401   EXPECT_EQ(null, prerender_manager()->FindEntry(second_url));
1402   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1403 }
1404
1405 // Creates two prerenders, one of which should start when the first one expires.
1406 TEST_F(PrerenderTest, LinkManagerExpireRevealingLaunch) {
1407   SetConcurrency(1);
1408   ASSERT_LT(prerender_manager()->config().max_wait_to_launch,
1409             prerender_manager()->config().time_to_live);
1410
1411   GURL first_url("http://www.willexpire.com");
1412   DummyPrerenderContents* first_prerender_contents =
1413       prerender_manager()->CreateNextPrerenderContents(
1414           first_url, FINAL_STATUS_TIMED_OUT);
1415   EXPECT_TRUE(AddSimplePrerender(first_url));
1416   EXPECT_EQ(first_prerender_contents,
1417             prerender_manager()->FindEntry(first_url));
1418
1419   // Insert the second prerender so it will be still be launchable when the
1420   // first expires.
1421   const TimeDelta wait_to_launch_second_prerender =
1422       prerender_manager()->config().time_to_live -
1423       prerender_manager()->config().max_wait_to_launch +
1424       TimeDelta::FromSeconds(2);
1425   const TimeDelta wait_for_first_prerender_to_expire =
1426       prerender_manager()->config().time_to_live -
1427       wait_to_launch_second_prerender +
1428       TimeDelta::FromSeconds(1);
1429   ASSERT_LT(prerender_manager()->config().time_to_live,
1430             wait_to_launch_second_prerender +
1431             wait_for_first_prerender_to_expire);
1432   ASSERT_GT(prerender_manager()->config().max_wait_to_launch.InSeconds(),
1433             wait_for_first_prerender_to_expire.InSeconds());
1434
1435   prerender_manager()->AdvanceTimeTicks(wait_to_launch_second_prerender);
1436   GURL second_url("http://www.willlaunch.com");
1437   DummyPrerenderContents* second_prerender_contents =
1438       prerender_manager()->CreateNextPrerenderContents(
1439           second_url, FINAL_STATUS_USED);
1440   EXPECT_FALSE(AddSimplePrerender(second_url));
1441
1442   // The first prerender is still running, but the second has not yet launched.
1443   EXPECT_EQ(first_prerender_contents,
1444             prerender_manager()->FindEntry(first_url));
1445   PrerenderContents* null = NULL;
1446   EXPECT_EQ(null, prerender_manager()->FindEntry(second_url));
1447
1448   // The first prerender should have died, giving life to the second one.
1449   prerender_manager()->AdvanceTimeTicks(wait_for_first_prerender_to_expire);
1450   EXPECT_EQ(null, prerender_manager()->FindEntry(first_url));
1451   EXPECT_EQ(second_prerender_contents,
1452             prerender_manager()->FindAndUseEntry(second_url));
1453 }
1454
1455 }  // namespace prerender