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