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/bind.h"
6#include "base/memory/weak_ptr.h"
7#include "base/message_loop/message_loop.h"
8#include "base/path_service.h"
9#include "base/strings/utf_string_conversions.h"
10#include "base/task/cancelable_task_tracker.h"
11#include "chrome/browser/chrome_notification_types.h"
12#include "chrome/browser/history/history_db_task.h"
13#include "chrome/browser/history/history_notifications.h"
14#include "chrome/browser/history/history_service_factory.h"
15#include "chrome/browser/history/history_unittest_base.h"
16#include "chrome/browser/history/top_sites.h"
17#include "chrome/browser/history/top_sites_cache.h"
18#include "chrome/browser/history/top_sites_impl.h"
19#include "chrome/common/chrome_constants.h"
20#include "chrome/common/chrome_paths.h"
21#include "chrome/test/base/testing_profile.h"
22#include "components/history/core/browser/history_types.h"
23#include "content/public/browser/notification_service.h"
24#include "content/public/test/test_browser_thread.h"
25#include "testing/gtest/include/gtest/gtest.h"
26#include "third_party/skia/include/core/SkBitmap.h"
27#include "ui/gfx/codec/jpeg_codec.h"
28#include "url/gurl.h"
29
30using content::BrowserThread;
31
32class TestTopSitesObserver : public history::TopSitesObserver {
33 public:
34  explicit TestTopSitesObserver(Profile* profile, history::TopSites* top_sites);
35  virtual ~TestTopSitesObserver();
36  // TopSitesObserver:
37  virtual void TopSitesLoaded(history::TopSites* top_sites) OVERRIDE;
38  virtual void TopSitesChanged(history::TopSites* top_sites) OVERRIDE;
39
40 private:
41  Profile* profile_;
42  history::TopSites* top_sites_;
43};
44
45TestTopSitesObserver::~TestTopSitesObserver() {
46  top_sites_->RemoveObserver(this);
47}
48
49TestTopSitesObserver::TestTopSitesObserver(Profile* profile,
50                                           history::TopSites* top_sites)
51    : profile_(profile), top_sites_(top_sites) {
52  DCHECK(top_sites_);
53  top_sites_->AddObserver(this);
54}
55
56void TestTopSitesObserver::TopSitesLoaded(history::TopSites* top_sites) {
57  content::NotificationService::current()->Notify(
58      chrome::NOTIFICATION_TOP_SITES_LOADED,
59      content::Source<Profile>(profile_),
60      content::Details<history::TopSites>(top_sites));
61}
62
63void TestTopSitesObserver::TopSitesChanged(history::TopSites* top_sites) {
64  content::NotificationService::current()->Notify(
65      chrome::NOTIFICATION_TOP_SITES_CHANGED,
66      content::Source<Profile>(profile_),
67      content::NotificationService::NoDetails());
68}
69
70namespace history {
71
72namespace {
73
74// Used by WaitForHistory, see it for details.
75class WaitForHistoryTask : public HistoryDBTask {
76 public:
77  WaitForHistoryTask() {}
78
79  virtual bool RunOnDBThread(HistoryBackend* backend,
80                             HistoryDatabase* db) OVERRIDE {
81    return true;
82  }
83
84  virtual void DoneRunOnMainThread() OVERRIDE {
85    base::MessageLoop::current()->Quit();
86  }
87
88 private:
89  virtual ~WaitForHistoryTask() {}
90
91  DISALLOW_COPY_AND_ASSIGN(WaitForHistoryTask);
92};
93
94// Used for querying top sites. Either runs sequentially, or runs a nested
95// nested message loop until the response is complete. The later is used when
96// TopSites is queried before it finishes loading.
97class TopSitesQuerier {
98 public:
99  TopSitesQuerier()
100      : number_of_callbacks_(0),
101        waiting_(false),
102        weak_ptr_factory_(this) {}
103
104  // Queries top sites. If |wait| is true a nested message loop is run until the
105  // callback is notified.
106  void QueryTopSites(TopSitesImpl* top_sites, bool wait) {
107    QueryAllTopSites(top_sites, wait, false);
108  }
109
110  // Queries top sites, including potentially forced URLs if
111  // |include_forced_urls| is true.
112  void QueryAllTopSites(TopSitesImpl* top_sites,
113                        bool wait,
114                        bool include_forced_urls) {
115    int start_number_of_callbacks = number_of_callbacks_;
116    top_sites->GetMostVisitedURLs(
117        base::Bind(&TopSitesQuerier::OnTopSitesAvailable,
118                   weak_ptr_factory_.GetWeakPtr()),
119        include_forced_urls);
120    if (wait && start_number_of_callbacks == number_of_callbacks_) {
121      waiting_ = true;
122      base::MessageLoop::current()->Run();
123    }
124  }
125
126  void CancelRequest() {
127    weak_ptr_factory_.InvalidateWeakPtrs();
128  }
129
130  void set_urls(const MostVisitedURLList& urls) { urls_ = urls; }
131  const MostVisitedURLList& urls() const { return urls_; }
132
133  int number_of_callbacks() const { return number_of_callbacks_; }
134
135 private:
136  // Callback for TopSitesImpl::GetMostVisitedURLs.
137  void OnTopSitesAvailable(const history::MostVisitedURLList& data) {
138    urls_ = data;
139    number_of_callbacks_++;
140    if (waiting_) {
141      base::MessageLoop::current()->Quit();
142      waiting_ = false;
143    }
144  }
145
146  MostVisitedURLList urls_;
147  int number_of_callbacks_;
148  bool waiting_;
149  base::WeakPtrFactory<TopSitesQuerier> weak_ptr_factory_;
150
151  DISALLOW_COPY_AND_ASSIGN(TopSitesQuerier);
152};
153
154// Extracts the data from |t1| into a SkBitmap. This is intended for usage of
155// thumbnail data, which is stored as jpgs.
156SkBitmap ExtractThumbnail(const base::RefCountedMemory& t1) {
157  scoped_ptr<SkBitmap> image(gfx::JPEGCodec::Decode(t1.front(),
158                                                    t1.size()));
159  return image.get() ? *image : SkBitmap();
160}
161
162// Returns true if t1 and t2 contain the same data.
163bool ThumbnailsAreEqual(base::RefCountedMemory* t1,
164                        base::RefCountedMemory* t2) {
165  if (!t1 || !t2)
166    return false;
167  if (t1->size() != t2->size())
168    return false;
169  return !memcmp(t1->front(), t2->front(), t1->size());
170}
171
172}  // namespace
173
174class TopSitesImplTest : public HistoryUnitTestBase {
175 public:
176  TopSitesImplTest()
177      : ui_thread_(BrowserThread::UI, &message_loop_),
178        db_thread_(BrowserThread::DB, &message_loop_) {
179  }
180
181  virtual void SetUp() {
182    profile_.reset(new TestingProfile);
183    if (CreateHistoryAndTopSites()) {
184      ASSERT_TRUE(profile_->CreateHistoryService(false, false));
185      CreateTopSitesAndObserver();
186      profile_->BlockUntilTopSitesLoaded();
187    }
188  }
189
190  virtual void TearDown() {
191    top_sites_observer_.reset();
192    profile_.reset();
193  }
194
195  // Returns true if history and top sites should be created in SetUp.
196  virtual bool CreateHistoryAndTopSites() {
197    return true;
198  }
199
200  // Gets the thumbnail for |url| from TopSites.
201  SkBitmap GetThumbnail(const GURL& url) {
202    scoped_refptr<base::RefCountedMemory> data;
203    return top_sites()->GetPageThumbnail(url, false, &data) ?
204        ExtractThumbnail(*data.get()) : SkBitmap();
205  }
206
207  // Creates a bitmap of the specified color. Caller takes ownership.
208  gfx::Image CreateBitmap(SkColor color) {
209    SkBitmap thumbnail;
210    thumbnail.allocN32Pixels(4, 4);
211    thumbnail.eraseColor(color);
212    return gfx::Image::CreateFrom1xBitmap(thumbnail);  // adds ref.
213  }
214
215  // Forces top sites to load top sites from history, then recreates top sites.
216  // Recreating top sites makes sure the changes from history are saved and
217  // loaded from the db.
218  void RefreshTopSitesAndRecreate() {
219    StartQueryForMostVisited();
220    WaitForHistory();
221    RecreateTopSitesAndBlock();
222  }
223
224  // Blocks the caller until history processes a task. This is useful if you
225  // need to wait until you know history has processed a task.
226  void WaitForHistory() {
227    history_service()->ScheduleDBTask(
228        scoped_ptr<history::HistoryDBTask>(new WaitForHistoryTask()),
229        &history_tracker_);
230    base::MessageLoop::current()->Run();
231  }
232
233  // Waits for top sites to finish processing a task. This is useful if you need
234  // to wait until top sites finishes processing a task.
235  void WaitForTopSites() {
236    top_sites()->backend_->DoEmptyRequest(
237        base::Bind(&TopSitesImplTest::QuitCallback, base::Unretained(this)),
238        &top_sites_tracker_);
239    base::MessageLoop::current()->Run();
240  }
241
242  TopSitesImpl* top_sites() {
243    return static_cast<TopSitesImpl*>(profile_->GetTopSites());
244  }
245  TestingProfile* profile() {return profile_.get();}
246  HistoryService* history_service() {
247    return HistoryServiceFactory::GetForProfile(profile_.get(),
248                                                Profile::EXPLICIT_ACCESS);
249  }
250
251  MostVisitedURLList GetPrepopulatePages() {
252    return top_sites()->GetPrepopulatePages();
253  }
254
255  // Returns true if the TopSitesQuerier contains the prepopulate data starting
256  // at |start_index|.
257  void ContainsPrepopulatePages(const TopSitesQuerier& querier,
258                                size_t start_index) {
259    MostVisitedURLList prepopulate_urls = GetPrepopulatePages();
260    ASSERT_LE(start_index + prepopulate_urls.size(), querier.urls().size());
261    for (size_t i = 0; i < prepopulate_urls.size(); ++i) {
262      EXPECT_EQ(prepopulate_urls[i].url.spec(),
263                querier.urls()[start_index + i].url.spec()) << " @ index " <<
264          i;
265    }
266  }
267
268  // Used for callbacks from history.
269  void EmptyCallback() {
270  }
271
272  // Quit the current message loop when invoked. Useful when running a nested
273  // message loop.
274  void QuitCallback() {
275    base::MessageLoop::current()->Quit();
276  }
277
278  // Adds a page to history.
279  void AddPageToHistory(const GURL& url) {
280    RedirectList redirects;
281    redirects.push_back(url);
282    history_service()->AddPage(
283        url, base::Time::Now(), reinterpret_cast<ContextID>(1), 0, GURL(),
284        redirects, ui::PAGE_TRANSITION_TYPED, history::SOURCE_BROWSED,
285        false);
286  }
287
288  // Adds a page to history.
289  void AddPageToHistory(const GURL& url, const base::string16& title) {
290    RedirectList redirects;
291    redirects.push_back(url);
292    history_service()->AddPage(
293        url, base::Time::Now(), reinterpret_cast<ContextID>(1), 0, GURL(),
294        redirects, ui::PAGE_TRANSITION_TYPED, history::SOURCE_BROWSED,
295        false);
296    history_service()->SetPageTitle(url, title);
297  }
298
299  // Adds a page to history.
300  void AddPageToHistory(const GURL& url,
301                        const base::string16& title,
302                        const history::RedirectList& redirects,
303                        base::Time time) {
304    history_service()->AddPage(
305        url, time, reinterpret_cast<ContextID>(1), 0, GURL(),
306        redirects, ui::PAGE_TRANSITION_TYPED, history::SOURCE_BROWSED,
307        false);
308    history_service()->SetPageTitle(url, title);
309  }
310
311  // Delets a url.
312  void DeleteURL(const GURL& url) {
313    history_service()->DeleteURL(url);
314  }
315
316  // Returns true if the thumbnail equals the specified bytes.
317  bool ThumbnailEqualsBytes(const gfx::Image& image,
318                            base::RefCountedMemory* bytes) {
319    scoped_refptr<base::RefCountedBytes> encoded_image;
320    TopSitesImpl::EncodeBitmap(image, &encoded_image);
321    return ThumbnailsAreEqual(encoded_image.get(), bytes);
322  }
323
324  // Recreates top sites. This forces top sites to reread from the db.
325  void RecreateTopSitesAndBlock() {
326    // Recreate TopSites and wait for it to load.
327    CreateTopSitesAndObserver();
328    // As history already loaded we have to fake this call.
329    profile()->BlockUntilTopSitesLoaded();
330  }
331
332  // Wrappers that allow private TopSites functions to be called from the
333  // individual tests without making them all be friends.
334  GURL GetCanonicalURL(const GURL& url) {
335    return top_sites()->cache_->GetCanonicalURL(url);
336  }
337
338  void SetTopSites(const MostVisitedURLList& new_top_sites) {
339    top_sites()->SetTopSites(new_top_sites);
340  }
341
342  bool AddForcedURL(const GURL& url, base::Time time) {
343    return top_sites()->AddForcedURL(url, time);
344  }
345
346  void StartQueryForMostVisited() {
347    top_sites()->StartQueryForMostVisited();
348  }
349
350  void SetLastNumUrlsChanged(size_t value) {
351    top_sites()->last_num_urls_changed_ = value;
352  }
353
354  size_t last_num_urls_changed() { return top_sites()->last_num_urls_changed_; }
355
356  base::TimeDelta GetUpdateDelay() {
357    return top_sites()->GetUpdateDelay();
358  }
359
360  bool IsTopSitesLoaded() { return top_sites()->loaded_; }
361
362  bool AddPrepopulatedPages(MostVisitedURLList* urls) {
363    return top_sites()->AddPrepopulatedPages(urls, 0u);
364  }
365
366  void EmptyThreadSafeCache() {
367    base::AutoLock lock(top_sites()->lock_);
368    MostVisitedURLList empty;
369    top_sites()->thread_safe_cache_->SetTopSites(empty);
370  }
371
372  void CreateTopSitesAndObserver() {
373    if (top_sites_observer_)
374      top_sites_observer_.reset();
375
376    profile_->CreateTopSites();
377    top_sites_observer_.reset(
378        new TestTopSitesObserver(profile_.get(), profile_->GetTopSites()));
379  }
380
381 private:
382  base::MessageLoopForUI message_loop_;
383  content::TestBrowserThread ui_thread_;
384  content::TestBrowserThread db_thread_;
385  scoped_ptr<TestingProfile> profile_;
386  scoped_ptr<TestTopSitesObserver> top_sites_observer_;
387  // To cancel HistoryService tasks.
388  base::CancelableTaskTracker history_tracker_;
389
390  // To cancel TopSitesBackend tasks.
391  base::CancelableTaskTracker top_sites_tracker_;
392
393  DISALLOW_COPY_AND_ASSIGN(TopSitesImplTest);
394};  // Class TopSitesImplTest
395
396// Helper function for appending a URL to a vector of "most visited" URLs,
397// using the default values for everything but the URL.
398static void AppendMostVisitedURL(std::vector<MostVisitedURL>* list,
399                                 const GURL& url) {
400  MostVisitedURL mv;
401  mv.url = url;
402  mv.redirects.push_back(url);
403  list->push_back(mv);
404}
405
406// Helper function for appending a URL to a vector of "most visited" URLs,
407// using the default values for everything but the URL.
408static void AppendForcedMostVisitedURL(std::vector<MostVisitedURL>* list,
409                                       const GURL& url,
410                                       double last_forced_time) {
411  MostVisitedURL mv;
412  mv.url = url;
413  mv.last_forced_time = base::Time::FromJsTime(last_forced_time);
414  mv.redirects.push_back(url);
415  list->push_back(mv);
416}
417
418// Same as AppendMostVisitedURL except that it adds a redirect from the first
419// URL to the second.
420static void AppendMostVisitedURLWithRedirect(
421    std::vector<MostVisitedURL>* list,
422    const GURL& redirect_source, const GURL& redirect_dest) {
423  MostVisitedURL mv;
424  mv.url = redirect_dest;
425  mv.redirects.push_back(redirect_source);
426  mv.redirects.push_back(redirect_dest);
427  list->push_back(mv);
428}
429
430// Tests GetCanonicalURL.
431TEST_F(TopSitesImplTest, GetCanonicalURL) {
432  // Have two chains:
433  //   google.com -> www.google.com
434  //   news.google.com (no redirects)
435  GURL news("http://news.google.com/");
436  GURL source("http://google.com/");
437  GURL dest("http://www.google.com/");
438
439  std::vector<MostVisitedURL> most_visited;
440  AppendMostVisitedURLWithRedirect(&most_visited, source, dest);
441  AppendMostVisitedURL(&most_visited, news);
442  SetTopSites(most_visited);
443
444  // Random URLs not in the database are returned unchanged.
445  GURL result = GetCanonicalURL(GURL("http://fark.com/"));
446  EXPECT_EQ(GURL("http://fark.com/"), result);
447
448  // Easy case, there are no redirects and the exact URL is stored.
449  result = GetCanonicalURL(news);
450  EXPECT_EQ(news, result);
451
452  // The URL in question is the source URL in a redirect list.
453  result = GetCanonicalURL(source);
454  EXPECT_EQ(dest, result);
455
456  // The URL in question is the destination of a redirect.
457  result = GetCanonicalURL(dest);
458  EXPECT_EQ(dest, result);
459}
460
461// Tests DiffMostVisited.
462TEST_F(TopSitesImplTest, DiffMostVisited) {
463  GURL stays_the_same("http://staysthesame/");
464  GURL gets_added_1("http://getsadded1/");
465  GURL gets_added_2("http://getsadded2/");
466  GURL gets_deleted_1("http://getsdeleted1/");
467  GURL gets_moved_1("http://getsmoved1/");
468
469  std::vector<MostVisitedURL> old_list;
470  AppendMostVisitedURL(&old_list, stays_the_same);  // 0  (unchanged)
471  AppendMostVisitedURL(&old_list, gets_deleted_1);  // 1  (deleted)
472  AppendMostVisitedURL(&old_list, gets_moved_1);    // 2  (moved to 3)
473
474  std::vector<MostVisitedURL> new_list;
475  AppendMostVisitedURL(&new_list, stays_the_same);  // 0  (unchanged)
476  AppendMostVisitedURL(&new_list, gets_added_1);    // 1  (added)
477  AppendMostVisitedURL(&new_list, gets_added_2);    // 2  (added)
478  AppendMostVisitedURL(&new_list, gets_moved_1);    // 3  (moved from 2)
479
480  history::TopSitesDelta delta;
481  history::TopSitesImpl::DiffMostVisited(old_list, new_list, &delta);
482
483  ASSERT_EQ(2u, delta.added.size());
484  EXPECT_TRUE(gets_added_1 == delta.added[0].url.url);
485  EXPECT_EQ(1, delta.added[0].rank);
486  EXPECT_TRUE(gets_added_2 == delta.added[1].url.url);
487  EXPECT_EQ(2, delta.added[1].rank);
488
489  ASSERT_EQ(1u, delta.deleted.size());
490  EXPECT_TRUE(gets_deleted_1 == delta.deleted[0].url);
491
492  ASSERT_EQ(1u, delta.moved.size());
493  EXPECT_TRUE(gets_moved_1 == delta.moved[0].url.url);
494  EXPECT_EQ(3, delta.moved[0].rank);
495}
496
497// Tests DiffMostVisited with forced URLs.
498TEST_F(TopSitesImplTest, DiffMostVisitedWithForced) {
499  // Forced URLs.
500  GURL stays_the_same_1("http://staysthesame1/");
501  GURL new_last_forced_time("http://newlastforcedtime/");
502  GURL stays_the_same_2("http://staysthesame2/");
503  GURL move_to_nonforced("http://movetononforced/");
504  GURL gets_added_1("http://getsadded1/");
505  GURL gets_deleted_1("http://getsdeleted1/");
506  // Non-forced URLs.
507  GURL move_to_forced("http://movetoforced/");
508  GURL stays_the_same_3("http://staysthesame3/");
509  GURL gets_added_2("http://getsadded2/");
510  GURL gets_deleted_2("http://getsdeleted2/");
511  GURL gets_moved_1("http://getsmoved1/");
512
513  std::vector<MostVisitedURL> old_list;
514  AppendForcedMostVisitedURL(&old_list, stays_the_same_1, 1000);
515  AppendForcedMostVisitedURL(&old_list, new_last_forced_time, 2000);
516  AppendForcedMostVisitedURL(&old_list, stays_the_same_2, 3000);
517  AppendForcedMostVisitedURL(&old_list, move_to_nonforced, 4000);
518  AppendForcedMostVisitedURL(&old_list, gets_deleted_1, 5000);
519  AppendMostVisitedURL(&old_list, move_to_forced);
520  AppendMostVisitedURL(&old_list, stays_the_same_3);
521  AppendMostVisitedURL(&old_list, gets_deleted_2);
522  AppendMostVisitedURL(&old_list, gets_moved_1);
523
524  std::vector<MostVisitedURL> new_list;
525  AppendForcedMostVisitedURL(&new_list, stays_the_same_1, 1000);
526  AppendForcedMostVisitedURL(&new_list, stays_the_same_2, 3000);
527  AppendForcedMostVisitedURL(&new_list, new_last_forced_time, 4000);
528  AppendForcedMostVisitedURL(&new_list, gets_added_1, 5000);
529  AppendForcedMostVisitedURL(&new_list, move_to_forced, 6000);
530  AppendMostVisitedURL(&new_list, move_to_nonforced);
531  AppendMostVisitedURL(&new_list, stays_the_same_3);
532  AppendMostVisitedURL(&new_list, gets_added_2);
533  AppendMostVisitedURL(&new_list, gets_moved_1);
534
535  history::TopSitesDelta delta;
536  history::TopSitesImpl::DiffMostVisited(old_list, new_list, &delta);
537
538  ASSERT_EQ(2u, delta.added.size());
539  EXPECT_TRUE(gets_added_1 == delta.added[0].url.url);
540  EXPECT_EQ(-1, delta.added[0].rank);
541  EXPECT_TRUE(gets_added_2 == delta.added[1].url.url);
542  EXPECT_EQ(2, delta.added[1].rank);
543
544  ASSERT_EQ(2u, delta.deleted.size());
545  EXPECT_TRUE(gets_deleted_1 == delta.deleted[0].url);
546  EXPECT_TRUE(gets_deleted_2 == delta.deleted[1].url);
547
548  ASSERT_EQ(3u, delta.moved.size());
549  EXPECT_TRUE(new_last_forced_time == delta.moved[0].url.url);
550  EXPECT_EQ(-1, delta.moved[0].rank);
551  EXPECT_EQ(base::Time::FromJsTime(4000), delta.moved[0].url.last_forced_time);
552  EXPECT_TRUE(move_to_forced == delta.moved[1].url.url);
553  EXPECT_EQ(-1, delta.moved[1].rank);
554  EXPECT_EQ(base::Time::FromJsTime(6000), delta.moved[1].url.last_forced_time);
555  EXPECT_TRUE(move_to_nonforced == delta.moved[2].url.url);
556  EXPECT_EQ(0, delta.moved[2].rank);
557  EXPECT_TRUE(delta.moved[2].url.last_forced_time.is_null());
558}
559
560// Tests SetPageThumbnail.
561TEST_F(TopSitesImplTest, SetPageThumbnail) {
562  GURL url1a("http://google.com/");
563  GURL url1b("http://www.google.com/");
564  GURL url2("http://images.google.com/");
565  GURL invalid_url("chrome://favicon/http://google.com/");
566
567  std::vector<MostVisitedURL> list;
568  AppendMostVisitedURL(&list, url2);
569
570  MostVisitedURL mv;
571  mv.url = url1b;
572  mv.redirects.push_back(url1a);
573  mv.redirects.push_back(url1b);
574  list.push_back(mv);
575
576  // Save our most visited data containing that one site.
577  SetTopSites(list);
578
579  // Create a dummy thumbnail.
580  gfx::Image thumbnail(CreateBitmap(SK_ColorWHITE));
581
582  base::Time now = base::Time::Now();
583  ThumbnailScore low_score(1.0, true, true, now);
584  ThumbnailScore medium_score(0.5, true, true, now);
585  ThumbnailScore high_score(0.0, true, true, now);
586
587  // Setting the thumbnail for invalid pages should fail.
588  EXPECT_FALSE(top_sites()->SetPageThumbnail(invalid_url,
589                                             thumbnail, medium_score));
590
591  // Setting the thumbnail for url2 should succeed, lower scores shouldn't
592  // replace it, higher scores should.
593  EXPECT_TRUE(top_sites()->SetPageThumbnail(url2, thumbnail, medium_score));
594  EXPECT_FALSE(top_sites()->SetPageThumbnail(url2, thumbnail, low_score));
595  EXPECT_TRUE(top_sites()->SetPageThumbnail(url2, thumbnail, high_score));
596
597  // Set on the redirect source should succeed. It should be replacable by
598  // the same score on the redirect destination, which in turn should not
599  // be replaced by the source again.
600  EXPECT_TRUE(top_sites()->SetPageThumbnail(url1a, thumbnail, medium_score));
601  EXPECT_TRUE(top_sites()->SetPageThumbnail(url1b, thumbnail, medium_score));
602  EXPECT_FALSE(top_sites()->SetPageThumbnail(url1a, thumbnail, medium_score));
603}
604
605// Makes sure a thumbnail is correctly removed when the page is removed.
606TEST_F(TopSitesImplTest, ThumbnailRemoved) {
607  GURL url("http://google.com/");
608
609  // Configure top sites with 'google.com'.
610  std::vector<MostVisitedURL> list;
611  AppendMostVisitedURL(&list, url);
612  SetTopSites(list);
613
614  // Create a dummy thumbnail.
615  gfx::Image thumbnail(CreateBitmap(SK_ColorRED));
616
617  base::Time now = base::Time::Now();
618  ThumbnailScore low_score(1.0, true, true, now);
619  ThumbnailScore medium_score(0.5, true, true, now);
620  ThumbnailScore high_score(0.0, true, true, now);
621
622  // Set the thumbnail.
623  EXPECT_TRUE(top_sites()->SetPageThumbnail(url, thumbnail, medium_score));
624
625  // Make sure the thumbnail was actually set.
626  scoped_refptr<base::RefCountedMemory> result;
627  EXPECT_TRUE(top_sites()->GetPageThumbnail(url, false, &result));
628  EXPECT_TRUE(ThumbnailEqualsBytes(thumbnail, result.get()));
629
630  // Reset the thumbnails and make sure we don't get it back.
631  SetTopSites(MostVisitedURLList());
632  RefreshTopSitesAndRecreate();
633  EXPECT_FALSE(top_sites()->GetPageThumbnail(url, false, &result));
634}
635
636// Tests GetPageThumbnail.
637TEST_F(TopSitesImplTest, GetPageThumbnail) {
638  MostVisitedURLList url_list;
639  MostVisitedURL url1;
640  url1.url = GURL("http://asdf.com");
641  url1.redirects.push_back(url1.url);
642  url_list.push_back(url1);
643
644  MostVisitedURL url2;
645  url2.url = GURL("http://gmail.com");
646  url2.redirects.push_back(url2.url);
647  url2.redirects.push_back(GURL("http://mail.google.com"));
648  url_list.push_back(url2);
649
650  SetTopSites(url_list);
651
652  // Create a dummy thumbnail.
653  gfx::Image thumbnail(CreateBitmap(SK_ColorWHITE));
654  ThumbnailScore score(0.5, true, true, base::Time::Now());
655
656  scoped_refptr<base::RefCountedMemory> result;
657  EXPECT_TRUE(top_sites()->SetPageThumbnail(url1.url, thumbnail, score));
658  EXPECT_TRUE(top_sites()->GetPageThumbnail(url1.url, false, &result));
659
660  EXPECT_TRUE(top_sites()->SetPageThumbnail(GURL("http://gmail.com"),
661                                            thumbnail, score));
662  EXPECT_TRUE(top_sites()->GetPageThumbnail(GURL("http://gmail.com"),
663                                            false,
664                                            &result));
665  // Get a thumbnail via a redirect.
666  EXPECT_TRUE(top_sites()->GetPageThumbnail(GURL("http://mail.google.com"),
667                                            false,
668                                            &result));
669
670  EXPECT_TRUE(top_sites()->SetPageThumbnail(GURL("http://mail.google.com"),
671                                            thumbnail, score));
672  EXPECT_TRUE(top_sites()->GetPageThumbnail(url2.url, false, &result));
673
674  EXPECT_TRUE(ThumbnailEqualsBytes(thumbnail, result.get()));
675}
676
677// Tests GetMostVisitedURLs.
678TEST_F(TopSitesImplTest, GetMostVisited) {
679  GURL news("http://news.google.com/");
680  GURL google("http://google.com/");
681
682  AddPageToHistory(news);
683  AddPageToHistory(google);
684
685  StartQueryForMostVisited();
686  WaitForHistory();
687
688  TopSitesQuerier querier;
689  querier.QueryTopSites(top_sites(), false);
690
691  ASSERT_EQ(1, querier.number_of_callbacks());
692
693  // 2 extra prepopulated URLs.
694  ASSERT_EQ(2u + GetPrepopulatePages().size(), querier.urls().size());
695  EXPECT_EQ(news, querier.urls()[0].url);
696  EXPECT_EQ(google, querier.urls()[1].url);
697  ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 2));
698}
699
700// Makes sure changes done to top sites get mirrored to the db.
701TEST_F(TopSitesImplTest, SaveToDB) {
702  MostVisitedURL url;
703  GURL asdf_url("http://asdf.com");
704  base::string16 asdf_title(base::ASCIIToUTF16("ASDF"));
705  GURL google_url("http://google.com");
706  base::string16 google_title(base::ASCIIToUTF16("Google"));
707  GURL news_url("http://news.google.com");
708  base::string16 news_title(base::ASCIIToUTF16("Google News"));
709
710  // Add asdf_url to history.
711  AddPageToHistory(asdf_url, asdf_title);
712
713  // Make TopSites reread from the db.
714  StartQueryForMostVisited();
715  WaitForHistory();
716
717  // Add a thumbnail.
718  gfx::Image tmp_bitmap(CreateBitmap(SK_ColorBLUE));
719  ASSERT_TRUE(top_sites()->SetPageThumbnail(asdf_url, tmp_bitmap,
720                                            ThumbnailScore()));
721
722  RecreateTopSitesAndBlock();
723
724  {
725    TopSitesQuerier querier;
726    querier.QueryTopSites(top_sites(), false);
727    ASSERT_EQ(1u + GetPrepopulatePages().size(), querier.urls().size());
728    EXPECT_EQ(asdf_url, querier.urls()[0].url);
729    EXPECT_EQ(asdf_title, querier.urls()[0].title);
730    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 1));
731
732    scoped_refptr<base::RefCountedMemory> read_data;
733    EXPECT_TRUE(top_sites()->GetPageThumbnail(asdf_url, false, &read_data));
734    EXPECT_TRUE(ThumbnailEqualsBytes(tmp_bitmap, read_data.get()));
735  }
736
737  MostVisitedURL url2;
738  url2.url = google_url;
739  url2.title = google_title;
740  url2.redirects.push_back(url2.url);
741
742  AddPageToHistory(url2.url, url2.title);
743
744  // Add new thumbnail at rank 0 and shift the other result to 1.
745  ASSERT_TRUE(top_sites()->SetPageThumbnail(google_url,
746                                            tmp_bitmap,
747                                            ThumbnailScore()));
748
749  // Make TopSites reread from the db.
750  RefreshTopSitesAndRecreate();
751
752  {
753    TopSitesQuerier querier;
754    querier.QueryTopSites(top_sites(), false);
755    ASSERT_EQ(2u + GetPrepopulatePages().size(), querier.urls().size());
756    EXPECT_EQ(asdf_url, querier.urls()[0].url);
757    EXPECT_EQ(asdf_title, querier.urls()[0].title);
758    EXPECT_EQ(google_url, querier.urls()[1].url);
759    EXPECT_EQ(google_title, querier.urls()[1].title);
760    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 2));
761  }
762}
763
764// Makes sure forced URLs in top sites get mirrored to the db.
765TEST_F(TopSitesImplTest, SaveForcedToDB) {
766  MostVisitedURL url;
767  GURL asdf_url("http://asdf.com");
768  base::string16 asdf_title(base::ASCIIToUTF16("ASDF"));
769  GURL google_url("http://google.com");
770  base::string16 google_title(base::ASCIIToUTF16("Google"));
771  GURL news_url("http://news.google.com");
772  base::string16 news_title(base::ASCIIToUTF16("Google News"));
773
774  // Add a number of forced URLs.
775  std::vector<MostVisitedURL> list;
776  AppendForcedMostVisitedURL(&list, GURL("http://forced1"), 1000);
777  list[0].title = base::ASCIIToUTF16("forced1");
778  AppendForcedMostVisitedURL(&list, GURL("http://forced2"), 2000);
779  AppendForcedMostVisitedURL(&list, GURL("http://forced3"), 3000);
780  AppendForcedMostVisitedURL(&list, GURL("http://forced4"), 4000);
781  SetTopSites(list);
782
783  // Add a thumbnail.
784  gfx::Image red_thumbnail(CreateBitmap(SK_ColorRED));
785  ASSERT_TRUE(top_sites()->SetPageThumbnail(
786                  GURL("http://forced1"), red_thumbnail, ThumbnailScore()));
787
788  // Get the original thumbnail for later comparison. Some compression can
789  // happen in |top_sites| and we don't want to depend on that.
790  SkBitmap orig_thumbnail = GetThumbnail(GURL("http://forced1"));
791
792  // Force-flush the cache to ensure we don't reread from it inadvertently.
793  EmptyThreadSafeCache();
794
795  // Make TopSites reread from the db.
796  StartQueryForMostVisited();
797  WaitForHistory();
798
799  TopSitesQuerier querier;
800  querier.QueryAllTopSites(top_sites(), true, true);
801
802  ASSERT_EQ(4u + GetPrepopulatePages().size(), querier.urls().size());
803  EXPECT_EQ(GURL("http://forced1"), querier.urls()[0].url);
804  EXPECT_EQ(base::ASCIIToUTF16("forced1"), querier.urls()[0].title);
805  SkBitmap thumbnail = GetThumbnail(GURL("http://forced1"));
806  ASSERT_EQ(orig_thumbnail.getSize(), thumbnail.getSize());
807  orig_thumbnail.lockPixels();
808  thumbnail.lockPixels();
809  EXPECT_EQ(0, memcmp(orig_thumbnail.getPixels(), thumbnail.getPixels(),
810                      orig_thumbnail.getSize()));
811  thumbnail.unlockPixels();
812  orig_thumbnail.unlockPixels();
813  EXPECT_EQ(base::Time::FromJsTime(1000), querier.urls()[0].last_forced_time);
814  EXPECT_EQ(GURL("http://forced2"), querier.urls()[1].url);
815  EXPECT_EQ(base::Time::FromJsTime(2000), querier.urls()[1].last_forced_time);
816  EXPECT_EQ(GURL("http://forced3"), querier.urls()[2].url);
817  EXPECT_EQ(base::Time::FromJsTime(3000), querier.urls()[2].last_forced_time);
818  EXPECT_EQ(GURL("http://forced4"), querier.urls()[3].url);
819  EXPECT_EQ(base::Time::FromJsTime(4000), querier.urls()[3].last_forced_time);
820
821  ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 4));
822}
823
824// More permutations of saving to db.
825TEST_F(TopSitesImplTest, RealDatabase) {
826  MostVisitedURL url;
827  GURL asdf_url("http://asdf.com");
828  base::string16 asdf_title(base::ASCIIToUTF16("ASDF"));
829  GURL google1_url("http://google.com");
830  GURL google2_url("http://google.com/redirect");
831  GURL google3_url("http://www.google.com");
832  base::string16 google_title(base::ASCIIToUTF16("Google"));
833  GURL news_url("http://news.google.com");
834  base::string16 news_title(base::ASCIIToUTF16("Google News"));
835
836  url.url = asdf_url;
837  url.title = asdf_title;
838  url.redirects.push_back(url.url);
839  gfx::Image asdf_thumbnail(CreateBitmap(SK_ColorRED));
840  ASSERT_TRUE(top_sites()->SetPageThumbnail(
841                  asdf_url, asdf_thumbnail, ThumbnailScore()));
842
843  base::Time add_time(base::Time::Now());
844  AddPageToHistory(url.url, url.title, url.redirects, add_time);
845
846  RefreshTopSitesAndRecreate();
847
848  {
849    TopSitesQuerier querier;
850    querier.QueryTopSites(top_sites(), false);
851
852    ASSERT_EQ(1u + GetPrepopulatePages().size(), querier.urls().size());
853    EXPECT_EQ(asdf_url, querier.urls()[0].url);
854    EXPECT_EQ(asdf_title, querier.urls()[0].title);
855    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 1));
856
857    scoped_refptr<base::RefCountedMemory> read_data;
858    EXPECT_TRUE(top_sites()->GetPageThumbnail(asdf_url, false, &read_data));
859    EXPECT_TRUE(ThumbnailEqualsBytes(asdf_thumbnail, read_data.get()));
860  }
861
862  MostVisitedURL url2;
863  url2.url = google3_url;
864  url2.title = google_title;
865  url2.redirects.push_back(google1_url);
866  url2.redirects.push_back(google2_url);
867  url2.redirects.push_back(google3_url);
868
869  AddPageToHistory(google3_url, url2.title, url2.redirects,
870                   add_time - base::TimeDelta::FromMinutes(1));
871  // Add google twice so that it becomes the first visited site.
872  AddPageToHistory(google3_url, url2.title, url2.redirects,
873                   add_time - base::TimeDelta::FromMinutes(2));
874
875  gfx::Image google_thumbnail(CreateBitmap(SK_ColorBLUE));
876  ASSERT_TRUE(top_sites()->SetPageThumbnail(
877                  url2.url, google_thumbnail, ThumbnailScore()));
878
879  RefreshTopSitesAndRecreate();
880
881  {
882    scoped_refptr<base::RefCountedMemory> read_data;
883    TopSitesQuerier querier;
884    querier.QueryTopSites(top_sites(), false);
885
886    ASSERT_EQ(2u + GetPrepopulatePages().size(), querier.urls().size());
887    EXPECT_EQ(google1_url, querier.urls()[0].url);
888    EXPECT_EQ(google_title, querier.urls()[0].title);
889    ASSERT_EQ(3u, querier.urls()[0].redirects.size());
890    EXPECT_TRUE(top_sites()->GetPageThumbnail(google3_url, false, &read_data));
891    EXPECT_TRUE(ThumbnailEqualsBytes(google_thumbnail, read_data.get()));
892
893    EXPECT_EQ(asdf_url, querier.urls()[1].url);
894    EXPECT_EQ(asdf_title, querier.urls()[1].title);
895    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 2));
896  }
897
898  gfx::Image weewar_bitmap(CreateBitmap(SK_ColorYELLOW));
899
900  base::Time thumbnail_time(base::Time::Now());
901  ThumbnailScore low_score(1.0, true, true, thumbnail_time);
902  ThumbnailScore medium_score(0.5, true, true, thumbnail_time);
903  ThumbnailScore high_score(0.0, true, true, thumbnail_time);
904
905  // 1. Set to weewar. (Writes the thumbnail to the DB.)
906  EXPECT_TRUE(top_sites()->SetPageThumbnail(google3_url,
907                                            weewar_bitmap,
908                                            medium_score));
909  RefreshTopSitesAndRecreate();
910  {
911    scoped_refptr<base::RefCountedMemory> read_data;
912    EXPECT_TRUE(top_sites()->GetPageThumbnail(google3_url, false, &read_data));
913    EXPECT_TRUE(ThumbnailEqualsBytes(weewar_bitmap, read_data.get()));
914  }
915
916  gfx::Image green_bitmap(CreateBitmap(SK_ColorGREEN));
917
918  // 2. Set to google - low score.
919  EXPECT_FALSE(top_sites()->SetPageThumbnail(google3_url,
920                                             green_bitmap,
921                                             low_score));
922
923  // 3. Set to google - high score.
924  EXPECT_TRUE(top_sites()->SetPageThumbnail(google1_url,
925                                            green_bitmap,
926                                            high_score));
927
928  // Check that the thumbnail was updated.
929  RefreshTopSitesAndRecreate();
930  {
931    scoped_refptr<base::RefCountedMemory> read_data;
932    EXPECT_TRUE(top_sites()->GetPageThumbnail(google3_url, false, &read_data));
933    EXPECT_FALSE(ThumbnailEqualsBytes(weewar_bitmap, read_data.get()));
934    EXPECT_TRUE(ThumbnailEqualsBytes(green_bitmap, read_data.get()));
935  }
936}
937
938TEST_F(TopSitesImplTest, DeleteNotifications) {
939  GURL google1_url("http://google.com");
940  GURL google2_url("http://google.com/redirect");
941  GURL google3_url("http://www.google.com");
942  base::string16 google_title(base::ASCIIToUTF16("Google"));
943  GURL news_url("http://news.google.com");
944  base::string16 news_title(base::ASCIIToUTF16("Google News"));
945
946  AddPageToHistory(google1_url, google_title);
947  AddPageToHistory(news_url, news_title);
948
949  RefreshTopSitesAndRecreate();
950
951  {
952    TopSitesQuerier querier;
953    querier.QueryTopSites(top_sites(), false);
954
955    ASSERT_EQ(GetPrepopulatePages().size() + 2, querier.urls().size());
956  }
957
958  DeleteURL(news_url);
959
960  // Wait for history to process the deletion.
961  WaitForHistory();
962
963  {
964    TopSitesQuerier querier;
965    querier.QueryTopSites(top_sites(), false);
966
967    ASSERT_EQ(1u + GetPrepopulatePages().size(), querier.urls().size());
968    EXPECT_EQ(google_title, querier.urls()[0].title);
969    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 1));
970  }
971
972  // Now reload. This verifies topsites actually wrote the deletion to disk.
973  RefreshTopSitesAndRecreate();
974
975  {
976    TopSitesQuerier querier;
977    querier.QueryTopSites(top_sites(), false);
978
979    ASSERT_EQ(1u + GetPrepopulatePages().size(), querier.urls().size());
980    EXPECT_EQ(google_title, querier.urls()[0].title);
981    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 1));
982  }
983
984  DeleteURL(google1_url);
985
986  // Wait for history to process the deletion.
987  WaitForHistory();
988
989  {
990    TopSitesQuerier querier;
991    querier.QueryTopSites(top_sites(), false);
992
993    ASSERT_EQ(GetPrepopulatePages().size(), querier.urls().size());
994    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 0));
995  }
996
997  // Now reload. This verifies topsites actually wrote the deletion to disk.
998  RefreshTopSitesAndRecreate();
999
1000  {
1001    TopSitesQuerier querier;
1002    querier.QueryTopSites(top_sites(), false);
1003
1004    ASSERT_EQ(GetPrepopulatePages().size(), querier.urls().size());
1005    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 0));
1006  }
1007}
1008
1009// Makes sure GetUpdateDelay is updated appropriately.
1010TEST_F(TopSitesImplTest, GetUpdateDelay) {
1011  SetLastNumUrlsChanged(0);
1012  EXPECT_EQ(30, GetUpdateDelay().InSeconds());
1013
1014  MostVisitedURLList url_list;
1015  url_list.resize(20);
1016  GURL tmp_url(GURL("http://x"));
1017  for (size_t i = 0; i < url_list.size(); ++i) {
1018    url_list[i].url = tmp_url;
1019    url_list[i].redirects.push_back(tmp_url);
1020  }
1021  SetTopSites(url_list);
1022  EXPECT_EQ(20u, last_num_urls_changed());
1023  SetLastNumUrlsChanged(0);
1024  EXPECT_EQ(60, GetUpdateDelay().InMinutes());
1025
1026  SetLastNumUrlsChanged(3);
1027  EXPECT_EQ(52, GetUpdateDelay().InMinutes());
1028
1029  SetLastNumUrlsChanged(20);
1030  EXPECT_EQ(1, GetUpdateDelay().InMinutes());
1031}
1032
1033// Verifies that callbacks are notified correctly if requested before top sites
1034// has loaded.
1035TEST_F(TopSitesImplTest, NotifyCallbacksWhenLoaded) {
1036  // Recreate top sites. It won't be loaded now.
1037  CreateTopSitesAndObserver();
1038
1039  EXPECT_FALSE(IsTopSitesLoaded());
1040
1041  TopSitesQuerier querier1;
1042  TopSitesQuerier querier2;
1043  TopSitesQuerier querier3;
1044
1045  // Starts the queries.
1046  querier1.QueryTopSites(top_sites(), false);
1047  querier2.QueryTopSites(top_sites(), false);
1048  querier3.QueryTopSites(top_sites(), false);
1049
1050  // We shouldn't have gotten a callback.
1051  EXPECT_EQ(0, querier1.number_of_callbacks());
1052  EXPECT_EQ(0, querier2.number_of_callbacks());
1053  EXPECT_EQ(0, querier3.number_of_callbacks());
1054
1055  // Wait for loading to complete.
1056  profile()->BlockUntilTopSitesLoaded();
1057
1058  // Now we should have gotten the callbacks.
1059  EXPECT_EQ(1, querier1.number_of_callbacks());
1060  EXPECT_EQ(GetPrepopulatePages().size(), querier1.urls().size());
1061  EXPECT_EQ(1, querier2.number_of_callbacks());
1062  EXPECT_EQ(GetPrepopulatePages().size(), querier2.urls().size());
1063  EXPECT_EQ(1, querier3.number_of_callbacks());
1064  EXPECT_EQ(GetPrepopulatePages().size(), querier3.urls().size());
1065
1066  // Reset the top sites.
1067  MostVisitedURLList pages;
1068  MostVisitedURL url;
1069  url.url = GURL("http://1.com/");
1070  url.redirects.push_back(url.url);
1071  pages.push_back(url);
1072  url.url = GURL("http://2.com/");
1073  url.redirects.push_back(url.url);
1074  pages.push_back(url);
1075  SetTopSites(pages);
1076
1077  // Recreate top sites. It won't be loaded now.
1078  CreateTopSitesAndObserver();
1079
1080  EXPECT_FALSE(IsTopSitesLoaded());
1081
1082  TopSitesQuerier querier4;
1083
1084  // Query again.
1085  querier4.QueryTopSites(top_sites(), false);
1086
1087  // We shouldn't have gotten a callback.
1088  EXPECT_EQ(0, querier4.number_of_callbacks());
1089
1090  // Wait for loading to complete.
1091  profile()->BlockUntilTopSitesLoaded();
1092
1093  // Now we should have gotten the callbacks.
1094  EXPECT_EQ(1, querier4.number_of_callbacks());
1095  ASSERT_EQ(2u + GetPrepopulatePages().size(), querier4.urls().size());
1096
1097  EXPECT_EQ("http://1.com/", querier4.urls()[0].url.spec());
1098  EXPECT_EQ("http://2.com/", querier4.urls()[1].url.spec());
1099  ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier4, 2));
1100
1101  // Reset the top sites again, this time don't reload.
1102  url.url = GURL("http://3.com/");
1103  url.redirects.push_back(url.url);
1104  pages.push_back(url);
1105  SetTopSites(pages);
1106
1107  // Query again.
1108  TopSitesQuerier querier5;
1109  querier5.QueryTopSites(top_sites(), true);
1110
1111  EXPECT_EQ(1, querier5.number_of_callbacks());
1112
1113  ASSERT_EQ(3u + GetPrepopulatePages().size(), querier5.urls().size());
1114  EXPECT_EQ("http://1.com/", querier5.urls()[0].url.spec());
1115  EXPECT_EQ("http://2.com/", querier5.urls()[1].url.spec());
1116  EXPECT_EQ("http://3.com/", querier5.urls()[2].url.spec());
1117  ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier5, 3));
1118}
1119
1120// Makes sure canceled requests are not notified.
1121TEST_F(TopSitesImplTest, CancelingRequestsForTopSites) {
1122  // Recreate top sites. It won't be loaded now.
1123  CreateTopSitesAndObserver();
1124
1125  EXPECT_FALSE(IsTopSitesLoaded());
1126
1127  TopSitesQuerier querier1;
1128  TopSitesQuerier querier2;
1129
1130  // Starts the queries.
1131  querier1.QueryTopSites(top_sites(), false);
1132  querier2.QueryTopSites(top_sites(), false);
1133
1134  // We shouldn't have gotten a callback.
1135  EXPECT_EQ(0, querier1.number_of_callbacks());
1136  EXPECT_EQ(0, querier2.number_of_callbacks());
1137
1138  querier2.CancelRequest();
1139
1140  // Wait for loading to complete.
1141  profile()->BlockUntilTopSitesLoaded();
1142
1143  // The first callback should succeed.
1144  EXPECT_EQ(1, querier1.number_of_callbacks());
1145  EXPECT_EQ(GetPrepopulatePages().size(), querier1.urls().size());
1146
1147  // And the canceled callback should not be notified.
1148  EXPECT_EQ(0, querier2.number_of_callbacks());
1149}
1150
1151// Makes sure temporary thumbnails are copied over correctly.
1152TEST_F(TopSitesImplTest, AddTemporaryThumbnail) {
1153  GURL unknown_url("http://news.google.com/");
1154  GURL invalid_url("chrome://thumb/http://google.com/");
1155  GURL url1a("http://google.com/");
1156  GURL url1b("http://www.google.com/");
1157
1158  // Create a dummy thumbnail.
1159  gfx::Image thumbnail(CreateBitmap(SK_ColorRED));
1160
1161  ThumbnailScore medium_score(0.5, true, true, base::Time::Now());
1162
1163  // Don't store thumbnails for Javascript URLs.
1164  EXPECT_FALSE(top_sites()->SetPageThumbnail(invalid_url,
1165                                             thumbnail,
1166                                             medium_score));
1167  // Store thumbnails for unknown (but valid) URLs temporarily - calls
1168  // AddTemporaryThumbnail.
1169  EXPECT_TRUE(top_sites()->SetPageThumbnail(unknown_url,
1170                                            thumbnail,
1171                                            medium_score));
1172
1173  // We shouldn't get the thumnail back though (the url isn't in to sites yet).
1174  scoped_refptr<base::RefCountedMemory> out;
1175  EXPECT_FALSE(top_sites()->GetPageThumbnail(unknown_url, false, &out));
1176  // But we should be able to get the temporary page thumbnail score.
1177  ThumbnailScore out_score;
1178  EXPECT_TRUE(top_sites()->GetTemporaryPageThumbnailScore(unknown_url,
1179                                                          &out_score));
1180  EXPECT_TRUE(medium_score.Equals(out_score));
1181
1182  std::vector<MostVisitedURL> list;
1183
1184  MostVisitedURL mv;
1185  mv.url = unknown_url;
1186  mv.redirects.push_back(mv.url);
1187  mv.redirects.push_back(url1a);
1188  mv.redirects.push_back(url1b);
1189  list.push_back(mv);
1190
1191  // Update URLs. This should result in using thumbnail.
1192  SetTopSites(list);
1193
1194  ASSERT_TRUE(top_sites()->GetPageThumbnail(unknown_url, false, &out));
1195  EXPECT_TRUE(ThumbnailEqualsBytes(thumbnail, out.get()));
1196}
1197
1198// Tests variations of blacklisting.
1199TEST_F(TopSitesImplTest, Blacklisting) {
1200  MostVisitedURLList pages;
1201  MostVisitedURL url, url1;
1202  url.url = GURL("http://bbc.com/");
1203  url.redirects.push_back(url.url);
1204  pages.push_back(url);
1205  url1.url = GURL("http://google.com/");
1206  url1.redirects.push_back(url1.url);
1207  pages.push_back(url1);
1208
1209  SetTopSites(pages);
1210  EXPECT_FALSE(top_sites()->IsBlacklisted(GURL("http://bbc.com/")));
1211
1212  // Blacklist google.com.
1213  top_sites()->AddBlacklistedURL(GURL("http://google.com/"));
1214
1215  GURL prepopulate_url = GetPrepopulatePages()[0].url;
1216
1217  EXPECT_TRUE(top_sites()->HasBlacklistedItems());
1218  EXPECT_TRUE(top_sites()->IsBlacklisted(GURL("http://google.com/")));
1219  EXPECT_FALSE(top_sites()->IsBlacklisted(GURL("http://bbc.com/")));
1220  EXPECT_FALSE(top_sites()->IsBlacklisted(prepopulate_url));
1221
1222  // Make sure the blacklisted site isn't returned in the results.
1223  {
1224    TopSitesQuerier q;
1225    q.QueryTopSites(top_sites(), true);
1226    ASSERT_EQ(1u + GetPrepopulatePages().size(), q.urls().size());
1227    EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
1228    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 1));
1229  }
1230
1231  // Recreate top sites and make sure blacklisted url was correctly read.
1232  RecreateTopSitesAndBlock();
1233  {
1234    TopSitesQuerier q;
1235    q.QueryTopSites(top_sites(), true);
1236    ASSERT_EQ(1u + GetPrepopulatePages().size(), q.urls().size());
1237    EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
1238    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 1));
1239  }
1240
1241  // Blacklist one of the prepopulate urls.
1242  top_sites()->AddBlacklistedURL(prepopulate_url);
1243  EXPECT_TRUE(top_sites()->HasBlacklistedItems());
1244
1245  // Make sure the blacklisted prepopulate url isn't returned.
1246  {
1247    TopSitesQuerier q;
1248    q.QueryTopSites(top_sites(), true);
1249    ASSERT_EQ(1u + GetPrepopulatePages().size() - 1, q.urls().size());
1250    EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
1251    for (size_t i = 1; i < q.urls().size(); ++i)
1252      EXPECT_NE(prepopulate_url.spec(), q.urls()[i].url.spec());
1253  }
1254
1255  // Mark google as no longer blacklisted.
1256  top_sites()->RemoveBlacklistedURL(GURL("http://google.com/"));
1257  EXPECT_TRUE(top_sites()->HasBlacklistedItems());
1258  EXPECT_FALSE(top_sites()->IsBlacklisted(GURL("http://google.com/")));
1259
1260  // Make sure google is returned now.
1261  {
1262    TopSitesQuerier q;
1263    q.QueryTopSites(top_sites(), true);
1264    ASSERT_EQ(2u + GetPrepopulatePages().size() - 1, q.urls().size());
1265    EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
1266    EXPECT_EQ("http://google.com/", q.urls()[1].url.spec());
1267    // Android has only one prepopulated page which has been blacklisted, so
1268    // only 2 urls are returned.
1269    if (q.urls().size() > 2)
1270      EXPECT_NE(prepopulate_url.spec(), q.urls()[2].url.spec());
1271    else
1272      EXPECT_EQ(1u, GetPrepopulatePages().size());
1273  }
1274
1275  // Remove all blacklisted sites.
1276  top_sites()->ClearBlacklistedURLs();
1277  EXPECT_FALSE(top_sites()->HasBlacklistedItems());
1278
1279  {
1280    TopSitesQuerier q;
1281    q.QueryTopSites(top_sites(), true);
1282    ASSERT_EQ(2u + GetPrepopulatePages().size(), q.urls().size());
1283    EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
1284    EXPECT_EQ("http://google.com/", q.urls()[1].url.spec());
1285    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 2));
1286  }
1287}
1288
1289// Makes sure prepopulated pages exist.
1290TEST_F(TopSitesImplTest, AddPrepopulatedPages) {
1291  TopSitesQuerier q;
1292  q.QueryTopSites(top_sites(), true);
1293  EXPECT_EQ(GetPrepopulatePages().size(), q.urls().size());
1294  ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 0));
1295
1296  MostVisitedURLList pages = q.urls();
1297  EXPECT_FALSE(AddPrepopulatedPages(&pages));
1298
1299  EXPECT_EQ(GetPrepopulatePages().size(), pages.size());
1300  q.set_urls(pages);
1301  ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 0));
1302}
1303
1304// Ensure calling SetTopSites with forced sites already in the DB works.
1305// This test both eviction and
1306TEST_F(TopSitesImplTest, SetForcedTopSites) {
1307  // Create forced elements in old URL list.
1308  MostVisitedURLList old_url_list;
1309  AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/0"), 1000);
1310  AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/1"), 4000);
1311  AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/2"), 7000);
1312  AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/3"), 10000);
1313  AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/4"), 11000);
1314  AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/5"), 12000);
1315  AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/6"), 13000);
1316  AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/7"), 18000);
1317  AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/8"), 21000);
1318  const size_t kNumOldForcedURLs = 9;
1319
1320  // Create forced elements in new URL list.
1321  MostVisitedURLList new_url_list;
1322  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/0"), 2000);
1323  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/1"), 3000);
1324  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/2"), 5000);
1325  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/3"), 6000);
1326  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/4"), 8000);
1327  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/5"), 9000);
1328  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/6"), 14000);
1329  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/7"), 15000);
1330  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/8"), 16000);
1331  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/9"), 17000);
1332  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/10"), 19000);
1333  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/11"), 20000);
1334  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/12"), 22000);
1335
1336  // Setup a number non-forced URLs in both old and new list.
1337  const size_t kNumNonForcedURLs = 20;  // Maximum number of non-forced URLs.
1338  for (size_t i = 0; i < kNumNonForcedURLs; ++i) {
1339    std::ostringstream url;
1340    url << "http://oldnonforced/" << i;
1341    AppendMostVisitedURL(&old_url_list, GURL(url.str()));
1342    url.str("");
1343    url << "http://newnonforced/" << i;
1344    AppendMostVisitedURL(&new_url_list, GURL(url.str()));
1345  }
1346
1347  // Set the initial list of URLs.
1348  SetTopSites(old_url_list);
1349  EXPECT_EQ(kNumOldForcedURLs + kNumNonForcedURLs, last_num_urls_changed());
1350
1351  TopSitesQuerier querier;
1352  // Query only non-forced URLs first.
1353  querier.QueryTopSites(top_sites(), false);
1354  ASSERT_EQ(kNumNonForcedURLs, querier.urls().size());
1355
1356  // Check first URL.
1357  EXPECT_EQ("http://oldnonforced/0", querier.urls()[0].url.spec());
1358
1359  // Query all URLs.
1360  querier.QueryAllTopSites(top_sites(), false, true);
1361  EXPECT_EQ(kNumOldForcedURLs + kNumNonForcedURLs, querier.urls().size());
1362
1363  // Check first URLs.
1364  EXPECT_EQ("http://oldforced/0", querier.urls()[0].url.spec());
1365  EXPECT_EQ("http://oldnonforced/0",
1366            querier.urls()[kNumOldForcedURLs].url.spec());
1367
1368  // Set the new list of URLs.
1369  SetTopSites(new_url_list);
1370
1371  // Query all URLs.
1372  querier.QueryAllTopSites(top_sites(), false, true);
1373
1374  // We should have reached the maximum of 20 forced URLs.
1375  ASSERT_EQ(20 + kNumNonForcedURLs, querier.urls().size());
1376
1377  // Check forced URLs. They follow the order of timestamps above, smaller
1378  // timestamps since they were evicted.
1379  EXPECT_EQ("http://newforced/1", querier.urls()[0].url.spec());
1380  EXPECT_EQ(3000, querier.urls()[0].last_forced_time.ToJsTime());
1381  EXPECT_EQ("http://oldforced/1", querier.urls()[1].url.spec());
1382  EXPECT_EQ(4000, querier.urls()[1].last_forced_time.ToJsTime());
1383  EXPECT_EQ("http://newforced/2", querier.urls()[2].url.spec());
1384  EXPECT_EQ(5000, querier.urls()[2].last_forced_time.ToJsTime());
1385  EXPECT_EQ("http://newforced/3", querier.urls()[3].url.spec());
1386  EXPECT_EQ(6000, querier.urls()[3].last_forced_time.ToJsTime());
1387  EXPECT_EQ("http://oldforced/2", querier.urls()[4].url.spec());
1388  EXPECT_EQ(7000, querier.urls()[4].last_forced_time.ToJsTime());
1389  EXPECT_EQ("http://newforced/4", querier.urls()[5].url.spec());
1390  EXPECT_EQ(8000, querier.urls()[5].last_forced_time.ToJsTime());
1391  EXPECT_EQ("http://newforced/5", querier.urls()[6].url.spec());
1392  EXPECT_EQ(9000, querier.urls()[6].last_forced_time.ToJsTime());
1393  EXPECT_EQ("http://oldforced/3", querier.urls()[7].url.spec());
1394  EXPECT_EQ(10000, querier.urls()[7].last_forced_time.ToJsTime());
1395  EXPECT_EQ("http://oldforced/4", querier.urls()[8].url.spec());
1396  EXPECT_EQ(11000, querier.urls()[8].last_forced_time.ToJsTime());
1397  EXPECT_EQ("http://oldforced/5", querier.urls()[9].url.spec());
1398  EXPECT_EQ(12000, querier.urls()[9].last_forced_time.ToJsTime());
1399  EXPECT_EQ("http://oldforced/6", querier.urls()[10].url.spec());
1400  EXPECT_EQ(13000, querier.urls()[10].last_forced_time.ToJsTime());
1401  EXPECT_EQ("http://newforced/6", querier.urls()[11].url.spec());
1402  EXPECT_EQ(14000, querier.urls()[11].last_forced_time.ToJsTime());
1403  EXPECT_EQ("http://newforced/7", querier.urls()[12].url.spec());
1404  EXPECT_EQ(15000, querier.urls()[12].last_forced_time.ToJsTime());
1405  EXPECT_EQ("http://newforced/8", querier.urls()[13].url.spec());
1406  EXPECT_EQ(16000, querier.urls()[13].last_forced_time.ToJsTime());
1407  EXPECT_EQ("http://newforced/9", querier.urls()[14].url.spec());
1408  EXPECT_EQ(17000, querier.urls()[14].last_forced_time.ToJsTime());
1409  EXPECT_EQ("http://oldforced/7", querier.urls()[15].url.spec());
1410  EXPECT_EQ(18000, querier.urls()[15].last_forced_time.ToJsTime());
1411  EXPECT_EQ("http://newforced/10", querier.urls()[16].url.spec());
1412  EXPECT_EQ(19000, querier.urls()[16].last_forced_time.ToJsTime());
1413  EXPECT_EQ("http://newforced/11", querier.urls()[17].url.spec());
1414  EXPECT_EQ(20000, querier.urls()[17].last_forced_time.ToJsTime());
1415  EXPECT_EQ("http://oldforced/8", querier.urls()[18].url.spec());
1416  EXPECT_EQ(21000, querier.urls()[18].last_forced_time.ToJsTime());
1417  EXPECT_EQ("http://newforced/12", querier.urls()[19].url.spec());
1418  EXPECT_EQ(22000, querier.urls()[19].last_forced_time.ToJsTime());
1419
1420  // Check first and last non-forced URLs.
1421  EXPECT_EQ("http://newnonforced/0", querier.urls()[20].url.spec());
1422  EXPECT_TRUE(querier.urls()[20].last_forced_time.is_null());
1423  EXPECT_EQ("http://newnonforced/19", querier.urls()[39].url.spec());
1424  EXPECT_TRUE(querier.urls()[39].last_forced_time.is_null());
1425}
1426
1427TEST_F(TopSitesImplTest, SetForcedTopSitesWithCollisions) {
1428
1429  // Setup an old URL list in order to generate some collisions.
1430  MostVisitedURLList old_url_list;
1431  AppendForcedMostVisitedURL(&old_url_list, GURL("http://url/0"), 1000);
1432  // The following three will be evicted.
1433  AppendForcedMostVisitedURL(&old_url_list, GURL("http://collision/0"), 4000);
1434  AppendForcedMostVisitedURL(&old_url_list, GURL("http://collision/1"), 6000);
1435  AppendForcedMostVisitedURL(&old_url_list, GURL("http://collision/2"), 7000);
1436  // The following is evicted since all non-forced URLs are, therefore it
1437  // doesn't cause a collision.
1438  AppendMostVisitedURL(&old_url_list, GURL("http://noncollision/0"));
1439  SetTopSites(old_url_list);
1440
1441  // Setup a new URL list that will cause collisions.
1442  MostVisitedURLList new_url_list;
1443  AppendForcedMostVisitedURL(&new_url_list, GURL("http://collision/1"), 2000);
1444  AppendForcedMostVisitedURL(&new_url_list, GURL("http://url/2"), 3000);
1445  AppendForcedMostVisitedURL(&new_url_list, GURL("http://collision/0"), 5000);
1446  AppendForcedMostVisitedURL(&new_url_list, GURL("http://noncollision/0"),
1447                             9000);
1448  AppendMostVisitedURL(&new_url_list, GURL("http://collision/2"));
1449  AppendMostVisitedURL(&new_url_list, GURL("http://url/3"));
1450  SetTopSites(new_url_list);
1451
1452  // Query all URLs.
1453  TopSitesQuerier querier;
1454  querier.QueryAllTopSites(top_sites(), false, true);
1455
1456  // Check URLs. When collision occurs, the incoming one is always preferred.
1457  ASSERT_EQ(7u + GetPrepopulatePages().size(), querier.urls().size());
1458  EXPECT_EQ("http://url/0", querier.urls()[0].url.spec());
1459  EXPECT_EQ(1000u, querier.urls()[0].last_forced_time.ToJsTime());
1460  EXPECT_EQ("http://collision/1", querier.urls()[1].url.spec());
1461  EXPECT_EQ(2000u, querier.urls()[1].last_forced_time.ToJsTime());
1462  EXPECT_EQ("http://url/2", querier.urls()[2].url.spec());
1463  EXPECT_EQ(3000u, querier.urls()[2].last_forced_time.ToJsTime());
1464  EXPECT_EQ("http://collision/0", querier.urls()[3].url.spec());
1465  EXPECT_EQ(5000u, querier.urls()[3].last_forced_time.ToJsTime());
1466  EXPECT_EQ("http://noncollision/0", querier.urls()[4].url.spec());
1467  EXPECT_EQ(9000u, querier.urls()[4].last_forced_time.ToJsTime());
1468  EXPECT_EQ("http://collision/2", querier.urls()[5].url.spec());
1469  EXPECT_TRUE(querier.urls()[5].last_forced_time.is_null());
1470  EXPECT_EQ("http://url/3", querier.urls()[6].url.spec());
1471  EXPECT_TRUE(querier.urls()[6].last_forced_time.is_null());
1472  ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 7));
1473}
1474
1475TEST_F(TopSitesImplTest, SetTopSitesIdentical) {
1476  // Set the initial list of URLs.
1477  MostVisitedURLList url_list;
1478  AppendForcedMostVisitedURL(&url_list, GURL("http://url/0"), 1000);
1479  AppendMostVisitedURL(&url_list, GURL("http://url/1"));
1480  AppendMostVisitedURL(&url_list, GURL("http://url/2"));
1481  SetTopSites(url_list);
1482
1483  // Set the new list of URLs to be exactly the same.
1484  SetTopSites(MostVisitedURLList(url_list));
1485
1486  // Query all URLs.
1487  TopSitesQuerier querier;
1488  querier.QueryAllTopSites(top_sites(), false, true);
1489
1490  // Check URLs. When collision occurs, the incoming one is always preferred.
1491  ASSERT_EQ(3u + GetPrepopulatePages().size(), querier.urls().size());
1492  EXPECT_EQ("http://url/0", querier.urls()[0].url.spec());
1493  EXPECT_EQ(1000u, querier.urls()[0].last_forced_time.ToJsTime());
1494  EXPECT_EQ("http://url/1", querier.urls()[1].url.spec());
1495  EXPECT_EQ("http://url/2", querier.urls()[2].url.spec());
1496  ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 3));
1497}
1498
1499TEST_F(TopSitesImplTest, SetTopSitesWithAlreadyExistingForcedURLs) {
1500  // Set the initial list of URLs.
1501  MostVisitedURLList old_url_list;
1502  AppendForcedMostVisitedURL(&old_url_list, GURL("http://url/0/redir"), 1000);
1503  AppendForcedMostVisitedURL(&old_url_list, GURL("http://url/1"), 2000);
1504  SetTopSites(old_url_list);
1505
1506  // Setup a new URL list that will cause collisions.
1507  MostVisitedURLList new_url_list;
1508  AppendMostVisitedURLWithRedirect(&new_url_list, GURL("http://url/0/redir"),
1509                                   GURL("http://url/0"));
1510  AppendMostVisitedURL(&new_url_list, GURL("http://url/1"));
1511  SetTopSites(new_url_list);
1512
1513  // Query all URLs.
1514  TopSitesQuerier querier;
1515  querier.QueryAllTopSites(top_sites(), false, true);
1516
1517  // Check URLs. When collision occurs, the non-forced one is always preferred.
1518  ASSERT_EQ(2u + GetPrepopulatePages().size(), querier.urls().size());
1519  EXPECT_EQ("http://url/0", querier.urls()[0].url.spec());
1520  EXPECT_EQ("http://url/0/redir", querier.urls()[0].redirects[0].spec());
1521  EXPECT_TRUE(querier.urls()[0].last_forced_time.is_null());
1522  EXPECT_EQ("http://url/1", querier.urls()[1].url.spec());
1523  EXPECT_TRUE(querier.urls()[1].last_forced_time.is_null());
1524  ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 2));
1525}
1526
1527TEST_F(TopSitesImplTest, AddForcedURL) {
1528  // Set the initial list of URLs.
1529  MostVisitedURLList url_list;
1530  AppendForcedMostVisitedURL(&url_list, GURL("http://forced/0"), 2000);
1531  AppendForcedMostVisitedURL(&url_list, GURL("http://forced/1"), 4000);
1532  AppendMostVisitedURL(&url_list, GURL("http://nonforced/0"));
1533  AppendMostVisitedURL(&url_list, GURL("http://nonforced/1"));
1534  AppendMostVisitedURL(&url_list, GURL("http://nonforced/2"));
1535  SetTopSites(url_list);
1536
1537  // Add forced sites here and there to exercise a couple of cases.
1538  EXPECT_TRUE(AddForcedURL(GURL("http://forced/2"),
1539                           base::Time::FromJsTime(5000)));
1540  EXPECT_TRUE(AddForcedURL(GURL("http://forced/3"),
1541                           base::Time::FromJsTime(1000)));
1542  EXPECT_TRUE(AddForcedURL(GURL("http://forced/4"),
1543                           base::Time::FromJsTime(3000)));
1544
1545  // Check URLs.
1546  TopSitesQuerier querier;
1547  querier.QueryAllTopSites(top_sites(), false, true);
1548  ASSERT_EQ(8u + GetPrepopulatePages().size(), querier.urls().size());
1549  EXPECT_EQ("http://forced/3", querier.urls()[0].url.spec());
1550  EXPECT_EQ(1000u, querier.urls()[0].last_forced_time.ToJsTime());
1551  EXPECT_EQ("http://forced/0", querier.urls()[1].url.spec());
1552  EXPECT_EQ(2000u, querier.urls()[1].last_forced_time.ToJsTime());
1553  EXPECT_EQ("http://forced/4", querier.urls()[2].url.spec());
1554  EXPECT_EQ(3000u, querier.urls()[2].last_forced_time.ToJsTime());
1555  EXPECT_EQ("http://forced/1", querier.urls()[3].url.spec());
1556  EXPECT_EQ(4000u, querier.urls()[3].last_forced_time.ToJsTime());
1557  EXPECT_EQ("http://forced/2", querier.urls()[4].url.spec());
1558  EXPECT_EQ(5000u, querier.urls()[4].last_forced_time.ToJsTime());
1559  EXPECT_EQ("http://nonforced/0", querier.urls()[5].url.spec());
1560  EXPECT_TRUE(querier.urls()[5].last_forced_time.is_null());
1561  EXPECT_EQ("http://nonforced/1", querier.urls()[6].url.spec());
1562  EXPECT_TRUE(querier.urls()[6].last_forced_time.is_null());
1563  EXPECT_EQ("http://nonforced/2", querier.urls()[7].url.spec());
1564  EXPECT_TRUE(querier.urls()[7].last_forced_time.is_null());
1565  ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 8));
1566
1567  // Add some collisions with forced and non-forced. Non-forced URLs are never
1568  // expected to move.
1569  EXPECT_TRUE(AddForcedURL(GURL("http://forced/3"),
1570                           base::Time::FromJsTime(4000)));
1571  EXPECT_TRUE(AddForcedURL(GURL("http://forced/1"),
1572                            base::Time::FromJsTime(1000)));
1573  EXPECT_FALSE(AddForcedURL(GURL("http://nonforced/0"),
1574                            base::Time::FromJsTime(6000)));
1575
1576  // Check relevant URLs.
1577  querier.QueryAllTopSites(top_sites(), false, true);
1578  ASSERT_EQ(8u + GetPrepopulatePages().size(), querier.urls().size());
1579  EXPECT_EQ("http://forced/1", querier.urls()[0].url.spec());
1580  EXPECT_EQ(1000u, querier.urls()[0].last_forced_time.ToJsTime());
1581  EXPECT_EQ("http://forced/3", querier.urls()[3].url.spec());
1582  EXPECT_EQ(4000u, querier.urls()[3].last_forced_time.ToJsTime());
1583  EXPECT_EQ("http://nonforced/0", querier.urls()[5].url.spec());
1584  EXPECT_TRUE(querier.urls()[5].last_forced_time.is_null());
1585
1586  // Add a timestamp collision and make sure things don't break.
1587  EXPECT_TRUE(AddForcedURL(GURL("http://forced/5"),
1588                           base::Time::FromJsTime(4000)));
1589  querier.QueryAllTopSites(top_sites(), false, true);
1590  ASSERT_EQ(9u + GetPrepopulatePages().size(), querier.urls().size());
1591  EXPECT_EQ(4000u, querier.urls()[3].last_forced_time.ToJsTime());
1592  EXPECT_EQ(4000u, querier.urls()[4].last_forced_time.ToJsTime());
1593  // We don't care which order they get sorted in.
1594  if (querier.urls()[3].url.spec() == "http://forced/3") {
1595    EXPECT_EQ("http://forced/3", querier.urls()[3].url.spec());
1596    EXPECT_EQ("http://forced/5", querier.urls()[4].url.spec());
1597  } else {
1598    EXPECT_EQ("http://forced/5", querier.urls()[3].url.spec());
1599    EXPECT_EQ("http://forced/3", querier.urls()[4].url.spec());
1600  }
1601
1602  // Make sure the thumbnail is not lost when the timestamp is updated.
1603  gfx::Image red_thumbnail(CreateBitmap(SK_ColorRED));
1604  ASSERT_TRUE(top_sites()->SetPageThumbnail(
1605                  GURL("http://forced/5"), red_thumbnail, ThumbnailScore()));
1606
1607  // Get the original thumbnail for later comparison. Some compression can
1608  // happen in |top_sites| and we don't want to depend on that.
1609  SkBitmap orig_thumbnail = GetThumbnail(GURL("http://forced/5"));
1610
1611  EXPECT_TRUE(AddForcedURL(GURL("http://forced/5"),
1612                           base::Time::FromJsTime(6000)));
1613
1614  // Ensure the thumbnail is still there even if the timestamp changed.
1615  querier.QueryAllTopSites(top_sites(), false, true);
1616  EXPECT_EQ("http://forced/5", querier.urls()[5].url.spec());
1617  EXPECT_EQ(6000u, querier.urls()[5].last_forced_time.ToJsTime());
1618  SkBitmap thumbnail = GetThumbnail(GURL("http://forced/5"));
1619  ASSERT_EQ(orig_thumbnail.getSize(), thumbnail.getSize());
1620  orig_thumbnail.lockPixels();
1621  thumbnail.lockPixels();
1622  EXPECT_EQ(0, memcmp(orig_thumbnail.getPixels(), thumbnail.getPixels(),
1623                      orig_thumbnail.getSize()));
1624  thumbnail.unlockPixels();
1625  orig_thumbnail.unlockPixels();
1626}
1627
1628}  // namespace history
1629