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