top_sites_unittest.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2010 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 "app/l10n_util.h"
6#include "base/file_util.h"
7#include "base/scoped_temp_dir.h"
8#include "base/string_util.h"
9#include "base/utf_string_conversions.h"
10#include "base/values.h"
11#include "chrome/browser/chrome_thread.h"
12#include "chrome/browser/history/top_sites.h"
13#include "chrome/browser/dom_ui/most_visited_handler.h"
14#include "chrome/browser/history/history_marshaling.h"
15#include "chrome/browser/history/top_sites_database.h"
16#include "chrome/browser/history/history_notifications.h"
17#include "chrome/common/chrome_paths.h"
18#include "chrome/test/testing_profile.h"
19#include "chrome/tools/profiles/thumbnail-inl.h"
20#include "gfx/codec/jpeg_codec.h"
21#include "googleurl/src/gurl.h"
22#include "grit/chromium_strings.h"
23#include "grit/generated_resources.h"
24#include "grit/locale_settings.h"
25#include "testing/gtest/include/gtest/gtest.h"
26#include "third_party/skia/include/core/SkBitmap.h"
27
28
29namespace history {
30
31static const unsigned char kBlob[] =
32    "12346102356120394751634516591348710478123649165419234519234512349134";
33
34class TopSitesTest : public testing::Test {
35 public:
36  TopSitesTest() : number_of_callbacks_(0) {
37  }
38  ~TopSitesTest() {
39  }
40
41  TopSites& top_sites() { return *top_sites_; }
42  MostVisitedURLList& urls() { return urls_; }
43  Profile& profile() {return *profile_;}
44  FilePath& file_name() { return file_name_; }
45  RefCountedBytes* google_thumbnail() { return google_thumbnail_; }
46  RefCountedBytes* random_thumbnail() { return random_thumbnail_; }
47  RefCountedBytes* weewar_thumbnail() { return weewar_thumbnail_; }
48  CancelableRequestConsumer* consumer() { return &consumer_; }
49  size_t number_of_callbacks() {return number_of_callbacks_; }
50  // Prepopulated URLs - added at the back of TopSites.
51  GURL welcome_url() {
52    return GURL(l10n_util::GetStringUTF8(IDS_CHROME_WELCOME_URL));
53  }
54  GURL themes_url() {
55    return GURL(l10n_util::GetStringUTF8(IDS_THEMES_GALLERY_URL));
56  }
57
58  virtual void SetUp() {
59    profile_.reset(new TestingProfile);
60    top_sites_ = new TopSites(profile_.get());
61
62    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
63    file_name_ = temp_dir_.path().AppendASCII("TopSites.db");
64    EXPECT_TRUE(file_util::Delete(file_name_, false));
65
66    std::vector<unsigned char> random_data(kBlob, kBlob + sizeof(kBlob));
67    std::vector<unsigned char> google_data(kGoogleThumbnail,
68                                           kGoogleThumbnail +
69                                           sizeof(kGoogleThumbnail));
70    std::vector<unsigned char> weewar_data(kWeewarThumbnail,
71                                           kWeewarThumbnail +
72                                           sizeof(kWeewarThumbnail));
73    random_thumbnail_ = new RefCountedBytes(random_data);
74    google_thumbnail_ = new RefCountedBytes(google_data);
75    weewar_thumbnail_ = new RefCountedBytes(weewar_data);
76  }
77
78  virtual void TearDown() {
79    profile_.reset();
80    TopSites::DeleteTopSites(top_sites_);
81    EXPECT_TRUE(file_util::Delete(file_name_, false));
82  }
83
84  // Callback for TopSites::GetMostVisitedURLs.
85  void OnTopSitesAvailable(history::MostVisitedURLList data) {
86    urls_ = data;
87    number_of_callbacks_++;
88  }
89
90  // Wrappers that allow private TopSites functions to be called from the
91  // individual tests without making them all be friends.
92  GURL GetCanonicalURL(const GURL& url) const {
93    AutoLock lock(top_sites_->lock_);  // The function asserts it's in the lock.
94    return top_sites_->GetCanonicalURL(url);
95  }
96
97  void StoreMostVisited(std::vector<MostVisitedURL>* urls) {
98    top_sites_->StoreMostVisited(urls);
99  }
100
101  static void DiffMostVisited(const std::vector<MostVisitedURL>& old_list,
102                              const std::vector<MostVisitedURL>& new_list,
103                              std::vector<size_t>* added_urls,
104                              std::vector<size_t>* deleted_urls,
105                              std::vector<size_t>* moved_urls)  {
106    TopSites::DiffMostVisited(old_list, new_list,
107                              added_urls, deleted_urls, moved_urls);
108  }
109
110  Lock& lock() {
111    return top_sites_->lock_;
112  }
113
114 private:
115  scoped_refptr<TopSites> top_sites_;
116  MostVisitedURLList urls_;
117  size_t number_of_callbacks_;
118  scoped_ptr<TestingProfile> profile_;
119  ScopedTempDir temp_dir_;
120  FilePath file_name_;  // Database filename.
121  scoped_refptr<RefCountedBytes> google_thumbnail_;
122  scoped_refptr<RefCountedBytes> random_thumbnail_;
123  scoped_refptr<RefCountedBytes> weewar_thumbnail_;
124  MessageLoop message_loop_;
125  CancelableRequestConsumer consumer_;
126
127  DISALLOW_COPY_AND_ASSIGN(TopSitesTest);
128};
129
130
131// A mockup of a HistoryService used for testing TopSites.
132class MockHistoryServiceImpl : public TopSites::MockHistoryService {
133 public:
134  MockHistoryServiceImpl() : num_thumbnail_requests_(0) {}
135
136  // Calls the callback directly with the results.
137  HistoryService::Handle QueryMostVisitedURLs(
138      int result_count, int days_back,
139      CancelableRequestConsumerBase* consumer,
140      HistoryService::QueryMostVisitedURLsCallback* callback) {
141    callback->Run(CancelableRequestProvider::Handle(0),  // Handle is unused.
142                  most_visited_urls_);
143    delete callback;
144    return 0;
145  }
146
147  // Add a page to the end of the pages list.
148  void AppendMockPage(const GURL& url,
149                      const string16& title) {
150    MostVisitedURL page;
151    page.url = url;
152    page.title = title;
153    page.redirects = RedirectList();
154    page.redirects.push_back(url);
155    most_visited_urls_.push_back(page);
156  }
157
158  // Removes the last URL in the list.
159  void RemoveMostVisitedURL() {
160    most_visited_urls_.pop_back();
161  }
162
163  virtual void GetPageThumbnail(
164      const GURL& url,
165      CancelableRequestConsumerTSimple<size_t>* consumer,
166      HistoryService::ThumbnailDataCallback* callback,
167      size_t index) {
168    num_thumbnail_requests_++;
169    MostVisitedURL mvu;
170    mvu.url = url;
171    MostVisitedURLList::iterator pos = std::find(most_visited_urls_.begin(),
172                                                 most_visited_urls_.end(),
173                                                 mvu);
174    EXPECT_TRUE(pos != most_visited_urls_.end()) << url.spec();
175    scoped_refptr<RefCountedBytes> thumbnail;
176    callback->Run(index, thumbnail);
177    delete callback;
178  }
179
180  void ResetNumberOfThumbnailRequests() {
181    num_thumbnail_requests_ = 0;
182  }
183
184  int GetNumberOfThumbnailRequests() {
185    return num_thumbnail_requests_;
186  }
187
188 private:
189  MostVisitedURLList most_visited_urls_;
190  int num_thumbnail_requests_;  // Number of calls to GetPageThumbnail.
191};
192
193
194// A mockup of a TopSitesDatabase used for testing TopSites.
195class MockTopSitesDatabaseImpl : public TopSitesDatabase {
196 public:
197  virtual void GetPageThumbnails(MostVisitedURLList* urls,
198                                 std::map<GURL, Images>* thumbnails) {
199    // Return a copy of the vector.
200    *urls = top_sites_list_;
201    *thumbnails = thumbnails_map_;
202  }
203
204  virtual void SetPageThumbnail(const MostVisitedURL& url, int url_rank,
205                                const Images& thumbnail) {
206    SetPageRank(url, url_rank);
207    // Update thubmnail
208    thumbnails_map_[url.url] = thumbnail;
209  }
210
211  virtual void UpdatePageRank(const MostVisitedURL& url, int new_rank) {
212    MostVisitedURLList::iterator pos = std::find(top_sites_list_.begin(),
213                                                 top_sites_list_.end(),
214                                                 url);
215    // Is it in the right position?
216    int rank = pos - top_sites_list_.begin();
217    if (rank != new_rank) {
218      // Move the URL to a new position.
219      top_sites_list_.erase(pos);
220      top_sites_list_.insert(top_sites_list_.begin() + new_rank, url);
221    }
222  }
223
224  virtual void SetPageRank(const MostVisitedURL& url, int url_rank) {
225    // Check if this url is in the list, and at which position.
226    MostVisitedURLList::iterator pos = std::find(top_sites_list_.begin(),
227                                                 top_sites_list_.end(),
228                                                 url);
229    if (pos == top_sites_list_.end()) {
230      // Add it to the list.
231      top_sites_list_.insert(top_sites_list_.begin() + url_rank, url);
232    } else {
233      UpdatePageRank(url, url_rank);
234    }
235  }
236
237  // Get a thumbnail for a given page. Returns true iff we have the thumbnail.
238  virtual bool GetPageThumbnail(const GURL& url,
239                                Images* thumbnail) {
240    std::map<GURL, Images>::const_iterator found =
241        thumbnails_map_.find(url);
242    if (found == thumbnails_map_.end())
243      return false;  // No thumbnail for this URL.
244
245    thumbnail->thumbnail = found->second.thumbnail;
246    thumbnail->thumbnail_score = found->second.thumbnail_score;
247    return true;
248  }
249
250  virtual bool RemoveURL(const MostVisitedURL& url) {
251    // Comparison by url.
252    MostVisitedURLList::iterator pos = std::find(top_sites_list_.begin(),
253                                                 top_sites_list_.end(),
254                                                 url);
255    if (pos == top_sites_list_.end()) {
256      return false;
257    }
258    top_sites_list_.erase(pos);
259    thumbnails_map_.erase(url.url);
260    return true;
261  }
262
263 private:
264  MostVisitedURLList top_sites_list_;  // Keeps the URLs sorted by score (rank).
265  std::map<GURL, Images> thumbnails_map_;
266};
267
268
269// Helper function for appending a URL to a vector of "most visited" URLs,
270// using the default values for everything but the URL.
271static void AppendMostVisitedURL(std::vector<MostVisitedURL>* list,
272                                 const GURL& url) {
273  MostVisitedURL mv;
274  mv.url = url;
275  mv.redirects.push_back(url);
276  list->push_back(mv);
277}
278
279// Returns true if t1 and t2 contain the same data.
280static bool ThumbnailsAreEqual(RefCountedBytes* t1,
281                               RefCountedBytes* t2) {
282  if (!t1 || !t2)
283    return false;
284  if (t1->data.size() != t2->data.size())
285    return false;
286  return std::equal(t1->data.begin(),
287                    t1->data.end(),
288                    t2->data.begin());
289}
290
291// Same as AppendMostVisitedURL except that it adds a redirect from the first
292// URL to the second.
293static void AppendMostVisitedURLWithRedirect(
294    std::vector<MostVisitedURL>* list,
295    const GURL& redirect_source, const GURL& redirect_dest) {
296  MostVisitedURL mv;
297  mv.url = redirect_dest;
298  mv.redirects.push_back(redirect_source);
299  mv.redirects.push_back(redirect_dest);
300  list->push_back(mv);
301}
302
303TEST_F(TopSitesTest, GetCanonicalURL) {
304  ChromeThread db_loop(ChromeThread::DB, MessageLoop::current());
305  // Have two chains:
306  //   google.com -> www.google.com
307  //   news.google.com (no redirects)
308  GURL news("http://news.google.com/");
309  GURL source("http://google.com/");
310  GURL dest("http://www.google.com/");
311
312  std::vector<MostVisitedURL> most_visited;
313  AppendMostVisitedURLWithRedirect(&most_visited, source, dest);
314  AppendMostVisitedURL(&most_visited, news);
315  StoreMostVisited(&most_visited);
316
317  // Random URLs not in the database are returned unchanged.
318  GURL result = GetCanonicalURL(GURL("http://fark.com/"));
319  EXPECT_EQ(GURL("http://fark.com/"), result);
320
321  // Easy case, there are no redirects and the exact URL is stored.
322  result = GetCanonicalURL(news);
323  EXPECT_EQ(news, result);
324
325  // The URL in question is the source URL in a redirect list.
326  result = GetCanonicalURL(source);
327  EXPECT_EQ(dest, result);
328
329  // The URL in question is the destination of a redirect.
330  result = GetCanonicalURL(dest);
331  EXPECT_EQ(dest, result);
332}
333
334TEST_F(TopSitesTest, DiffMostVisited) {
335  GURL stays_the_same("http://staysthesame/");
336  GURL gets_added_1("http://getsadded1/");
337  GURL gets_added_2("http://getsadded2/");
338  GURL gets_deleted_1("http://getsdeleted2/");
339  GURL gets_moved_1("http://getsmoved1/");
340
341  std::vector<MostVisitedURL> old_list;
342  AppendMostVisitedURL(&old_list, stays_the_same);  // 0  (unchanged)
343  AppendMostVisitedURL(&old_list, gets_deleted_1);  // 1  (deleted)
344  AppendMostVisitedURL(&old_list, gets_moved_1);    // 2  (moved to 3)
345
346  std::vector<MostVisitedURL> new_list;
347  AppendMostVisitedURL(&new_list, stays_the_same);  // 0  (unchanged)
348  AppendMostVisitedURL(&new_list, gets_added_1);    // 1  (added)
349  AppendMostVisitedURL(&new_list, gets_added_2);    // 2  (added)
350  AppendMostVisitedURL(&new_list, gets_moved_1);    // 3  (moved from 2)
351
352  std::vector<size_t> added;
353  std::vector<size_t> deleted;
354  std::vector<size_t> moved;
355  DiffMostVisited(old_list, new_list, &added, &deleted, &moved);
356
357  ASSERT_EQ(2u, added.size());
358  ASSERT_EQ(1u, deleted.size());
359  ASSERT_EQ(1u, moved.size());
360
361  // There should be 2 URLs added, we don't assume what order they're in inside
362  // the result vector.
363  EXPECT_TRUE(added[0] == 1 || added[1] == 1);
364  EXPECT_TRUE(added[0] == 2 || added[1] == 2);
365
366  EXPECT_EQ(1u, deleted[0]);
367  EXPECT_EQ(3u, moved[0]);
368}
369
370TEST_F(TopSitesTest, SetPageThumbnail) {
371  ChromeThread db_loop(ChromeThread::DB, MessageLoop::current());
372  GURL url1a("http://google.com/");
373  GURL url1b("http://www.google.com/");
374  GURL url2("http://images.google.com/");
375  GURL invalid_url("chrome://favicon/http://google.com/");
376
377  std::vector<MostVisitedURL> list;
378  AppendMostVisitedURL(&list, url2);
379
380  MostVisitedURL mv;
381  mv.url = url1b;
382  mv.redirects.push_back(url1a);
383  mv.redirects.push_back(url1b);
384  list.push_back(mv);
385
386  // Save our most visited data containing that one site.
387  StoreMostVisited(&list);
388
389  // Create a dummy thumbnail.
390  SkBitmap thumbnail;
391  thumbnail.setConfig(SkBitmap::kARGB_8888_Config, 4, 4);
392  thumbnail.allocPixels();
393  thumbnail.eraseRGB(0x00, 0x00, 0x00);
394
395  base::Time now = base::Time::Now();
396  ThumbnailScore low_score(1.0, true, true, now);
397  ThumbnailScore medium_score(0.5, true, true, now);
398  ThumbnailScore high_score(0.0, true, true, now);
399
400  // Setting the thumbnail for invalid pages should fail.
401  EXPECT_FALSE(top_sites().SetPageThumbnail(invalid_url,
402                                            thumbnail, medium_score));
403
404  // Setting the thumbnail for url2 should succeed, lower scores shouldn't
405  // replace it, higher scores should.
406  EXPECT_TRUE(top_sites().SetPageThumbnail(url2, thumbnail, medium_score));
407  EXPECT_FALSE(top_sites().SetPageThumbnail(url2, thumbnail, low_score));
408  EXPECT_TRUE(top_sites().SetPageThumbnail(url2, thumbnail, high_score));
409
410  // Set on the redirect source should succeed. It should be replacable by
411  // the same score on the redirect destination, which in turn should not
412  // be replaced by the source again.
413  EXPECT_TRUE(top_sites().SetPageThumbnail(url1a, thumbnail, medium_score));
414  EXPECT_TRUE(top_sites().SetPageThumbnail(url1b, thumbnail, medium_score));
415  EXPECT_FALSE(top_sites().SetPageThumbnail(url1a, thumbnail, medium_score));
416}
417
418TEST_F(TopSitesTest, GetPageThumbnail) {
419  ChromeThread db_loop(ChromeThread::DB, MessageLoop::current());
420  MostVisitedURLList url_list;
421  MostVisitedURL url1 = {GURL("http://asdf.com")};
422  url1.redirects.push_back(url1.url);
423  url_list.push_back(url1);
424
425  MostVisitedURL url2 = {GURL("http://gmail.com")};
426  url2.redirects.push_back(url2.url);
427  url2.redirects.push_back(GURL("http://mail.google.com"));
428  url_list.push_back(url2);
429
430  top_sites().UpdateMostVisited(url_list);
431  MessageLoop::current()->RunAllPending();
432
433  // Create a dummy thumbnail.
434  SkBitmap thumbnail;
435  thumbnail.setConfig(SkBitmap::kARGB_8888_Config, 4, 4);
436  thumbnail.allocPixels();
437  thumbnail.eraseRGB(0x00, 0x00, 0x00);
438  ThumbnailScore score(0.5, true, true, base::Time::Now());
439
440  RefCountedBytes* result = NULL;
441  EXPECT_TRUE(top_sites().SetPageThumbnail(url1.url, thumbnail, score));
442  EXPECT_TRUE(top_sites().GetPageThumbnail(url1.url, &result));
443
444  EXPECT_TRUE(top_sites().SetPageThumbnail(GURL("http://gmail.com"),
445                                           thumbnail, score));
446  EXPECT_TRUE(top_sites().GetPageThumbnail(GURL("http://gmail.com"),
447                                           &result));
448  // Get a thumbnail via a redirect.
449  EXPECT_TRUE(top_sites().GetPageThumbnail(GURL("http://mail.google.com"),
450                                           &result));
451
452  EXPECT_TRUE(top_sites().SetPageThumbnail(GURL("http://mail.google.com"),
453                                           thumbnail, score));
454  EXPECT_TRUE(top_sites().GetPageThumbnail(url2.url, &result));
455
456  scoped_ptr<SkBitmap> out_bitmap(gfx::JPEGCodec::Decode(result->front(),
457                                                         result->size()));
458  EXPECT_EQ(0, memcmp(thumbnail.getPixels(), out_bitmap->getPixels(),
459                      thumbnail.getSize()));
460}
461
462TEST_F(TopSitesTest, GetMostVisited) {
463  ChromeThread db_loop(ChromeThread::DB, MessageLoop::current());
464  GURL news("http://news.google.com/");
465  GURL google("http://google.com/");
466
467  MockHistoryServiceImpl hs;
468  hs.AppendMockPage(news, ASCIIToUTF16("Google News"));
469  hs.AppendMockPage(google, ASCIIToUTF16("Google"));
470  top_sites().SetMockHistoryService(&hs);
471
472  top_sites().StartQueryForMostVisited();
473  MessageLoop::current()->RunAllPending();
474  top_sites().GetMostVisitedURLs(
475      consumer(),
476      NewCallback(static_cast<TopSitesTest*>(this),
477                  &TopSitesTest::OnTopSitesAvailable));
478  // 2 extra prepopulated URLs.
479  ASSERT_EQ(4u, urls().size());
480  EXPECT_EQ(news, urls()[0].url);
481  EXPECT_EQ(google, urls()[1].url);
482  EXPECT_EQ(welcome_url(), urls()[2].url);
483  EXPECT_EQ(themes_url(), urls()[3].url);
484}
485
486TEST_F(TopSitesTest, MockDatabase) {
487  ChromeThread db_loop(ChromeThread::DB, MessageLoop::current());
488  MockTopSitesDatabaseImpl* db = new MockTopSitesDatabaseImpl;
489  // |db| is destroyed when the top_sites is destroyed in TearDown.
490  top_sites().db_.reset(db);
491  MostVisitedURL url;
492  GURL asdf_url("http://asdf.com");
493  string16 asdf_title(ASCIIToUTF16("ASDF"));
494  GURL google_url("http://google.com");
495  string16 google_title(ASCIIToUTF16("Google"));
496  GURL news_url("http://news.google.com");
497  string16 news_title(ASCIIToUTF16("Google News"));
498
499  url.url = asdf_url;
500  url.title = asdf_title;
501  url.redirects.push_back(url.url);
502  Images thumbnail;
503  db->SetPageThumbnail(url, 0, thumbnail);
504
505  top_sites().ReadDatabase();
506
507  top_sites().GetMostVisitedURLs(
508      consumer(),
509      NewCallback(static_cast<TopSitesTest*>(this),
510                  &TopSitesTest::OnTopSitesAvailable));
511  ASSERT_EQ(3u, urls().size());
512  EXPECT_EQ(asdf_url, urls()[0].url);
513  EXPECT_EQ(asdf_title, urls()[0].title);
514  EXPECT_EQ(welcome_url(), urls()[1].url);
515  EXPECT_EQ(themes_url(), urls()[2].url);
516
517  MostVisitedURL url2;
518  url2.url = google_url;
519  url2.title = google_title;
520  url2.redirects.push_back(url2.url);
521
522  // Add new thumbnail at rank 0 and shift the other result to 1.
523  db->SetPageThumbnail(url2, 0, thumbnail);
524
525  top_sites().ReadDatabase();
526
527  top_sites().GetMostVisitedURLs(
528      consumer(),
529      NewCallback(static_cast<TopSitesTest*>(this),
530                  &TopSitesTest::OnTopSitesAvailable));
531  ASSERT_EQ(4u, urls().size());
532  EXPECT_EQ(google_url, urls()[0].url);
533  EXPECT_EQ(google_title, urls()[0].title);
534  EXPECT_EQ(asdf_url, urls()[1].url);
535  EXPECT_EQ(asdf_title, urls()[1].title);
536  EXPECT_EQ(welcome_url(), urls()[2].url);
537  EXPECT_EQ(themes_url(), urls()[3].url);
538
539  MockHistoryServiceImpl hs;
540  // Add one old, one new URL to the history.
541  hs.AppendMockPage(google_url, google_title);
542  hs.AppendMockPage(news_url, news_title);
543  top_sites().SetMockHistoryService(&hs);
544
545  // This writes the new data to the DB.
546  top_sites().StartQueryForMostVisited();
547  MessageLoop::current()->RunAllPending();
548
549  std::map<GURL, Images> thumbnails;
550  MostVisitedURLList result;
551  db->GetPageThumbnails(&result, &thumbnails);
552  ASSERT_EQ(4u, result.size());
553  EXPECT_EQ(google_title, result[0].title);
554  EXPECT_EQ(news_title, result[1].title);
555}
556
557// Test TopSitesDatabaseImpl.
558TEST_F(TopSitesTest, TopSitesDB) {
559  TopSitesDatabaseImpl db;
560
561  ASSERT_TRUE(db.Init(file_name()));
562
563  MostVisitedURL url;
564  GURL asdf_url("http://asdf.com");
565  string16 asdf_title(ASCIIToUTF16("ASDF"));
566  GURL google_url("http://google.com");
567  string16 google_title(ASCIIToUTF16("Google"));
568  GURL news_url("http://news.google.com");
569  string16 news_title(ASCIIToUTF16("Google News"));
570
571  url.url = asdf_url;
572  url.title = asdf_title;
573  url.redirects.push_back(url.url);
574  Images thumbnail;
575  thumbnail.thumbnail = random_thumbnail();
576  // Add asdf at rank 0.
577  db.SetPageThumbnail(url, 0, thumbnail);
578
579  Images result;
580  EXPECT_TRUE(db.GetPageThumbnail(url.url, &result));
581  EXPECT_EQ(thumbnail.thumbnail->data.size(), result.thumbnail->data.size());
582  EXPECT_TRUE(ThumbnailsAreEqual(thumbnail.thumbnail, result.thumbnail));
583
584  MostVisitedURLList urls;
585  std::map<GURL, Images> thumbnails;
586  db.GetPageThumbnails(&urls, &thumbnails);
587  ASSERT_EQ(1u, urls.size());
588  EXPECT_EQ(asdf_url, urls[0].url);
589  EXPECT_EQ(asdf_title, urls[0].title);
590
591  url.url = google_url;
592  url.title = google_title;
593
594  // Add google at rank 1 - no rank shifting.
595  db.SetPageThumbnail(url, 1, thumbnail);
596  db.GetPageThumbnails(&urls, &thumbnails);
597  ASSERT_EQ(2u, urls.size());
598  EXPECT_EQ(asdf_url, urls[0].url);
599  EXPECT_EQ(asdf_title, urls[0].title);
600  EXPECT_EQ(google_url, urls[1].url);
601  EXPECT_EQ(google_title, urls[1].title);
602
603  url.url = news_url;
604  url.title = news_title;
605
606  // Add news at rank 1 - shift google to rank 2.
607  db.SetPageThumbnail(url, 1, thumbnail);
608  db.GetPageThumbnails(&urls, &thumbnails);
609  ASSERT_EQ(3u, urls.size());
610  EXPECT_EQ(asdf_url, urls[0].url);
611  EXPECT_EQ(news_url, urls[1].url);
612  EXPECT_EQ(google_url, urls[2].url);
613
614  // Move news at rank 0 - shift the rest up.
615  db.SetPageThumbnail(url, 0, thumbnail);
616  db.GetPageThumbnails(&urls, &thumbnails);
617  ASSERT_EQ(3u, urls.size());
618  EXPECT_EQ(news_url, urls[0].url);
619  EXPECT_EQ(asdf_url, urls[1].url);
620  EXPECT_EQ(google_url, urls[2].url);
621
622  // Move news at rank 2 - shift the rest down.
623  db.SetPageThumbnail(url, 2, thumbnail);
624  db.GetPageThumbnails(&urls, &thumbnails);
625  ASSERT_EQ(3u, urls.size());
626  EXPECT_EQ(asdf_url, urls[0].url);
627  EXPECT_EQ(google_url, urls[1].url);
628  EXPECT_EQ(news_url, urls[2].url);
629
630  // Delete asdf.
631  url.url = asdf_url;
632  db.RemoveURL(url);
633
634  db.GetPageThumbnails(&urls, &thumbnails);
635  ASSERT_EQ(2u, urls.size());
636  EXPECT_EQ(google_url, urls[0].url);
637  EXPECT_EQ(news_url, urls[1].url);
638}
639
640// Test TopSites with a real database.
641TEST_F(TopSitesTest, RealDatabase) {
642  ChromeThread db_loop(ChromeThread::DB, MessageLoop::current());
643  TopSitesDatabaseImpl* db = new TopSitesDatabaseImpl;
644
645  ASSERT_TRUE(db->Init(file_name()));
646  // |db| is destroyed when the top_sites is destroyed in TearDown.
647  top_sites().db_.reset(db);
648  MostVisitedURL url;
649  GURL asdf_url("http://asdf.com");
650  string16 asdf_title(ASCIIToUTF16("ASDF"));
651  GURL google1_url("http://google.com");
652  GURL google2_url("http://google.com/redirect");
653  GURL google3_url("http://www.google.com");
654  string16 google_title(ASCIIToUTF16("Google"));
655  GURL news_url("http://news.google.com");
656  string16 news_title(ASCIIToUTF16("Google News"));
657
658  url.url = asdf_url;
659  url.title = asdf_title;
660  url.redirects.push_back(url.url);
661  Images thumbnail;
662  thumbnail.thumbnail = random_thumbnail();
663  db->SetPageThumbnail(url, 0, thumbnail);
664
665  top_sites().ReadDatabase();
666
667  top_sites().GetMostVisitedURLs(
668      consumer(),
669      NewCallback(static_cast<TopSitesTest*>(this),
670                  &TopSitesTest::OnTopSitesAvailable));
671  ASSERT_EQ(3u, urls().size());
672  EXPECT_EQ(asdf_url, urls()[0].url);
673  EXPECT_EQ(asdf_title, urls()[0].title);
674  EXPECT_EQ(welcome_url(), urls()[1].url);
675  EXPECT_EQ(themes_url(), urls()[2].url);
676
677  Images img_result;
678  db->GetPageThumbnail(asdf_url, &img_result);
679  EXPECT_TRUE(img_result.thumbnail != NULL);
680  EXPECT_TRUE(ThumbnailsAreEqual(random_thumbnail(), img_result.thumbnail));
681
682  RefCountedBytes* thumbnail_result;
683  EXPECT_TRUE(top_sites().GetPageThumbnail(asdf_url, &thumbnail_result));
684  EXPECT_TRUE(thumbnail_result != NULL);
685  EXPECT_TRUE(ThumbnailsAreEqual(random_thumbnail(), thumbnail_result));
686
687  MostVisitedURL url2;
688  url2.url = google1_url;
689  url2.title = google_title;
690  url2.redirects.push_back(google1_url);
691  url2.redirects.push_back(google2_url);
692  url2.redirects.push_back(google3_url);
693
694  // Add new thumbnail at rank 0 and shift the other result to 1.
695  Images g_thumbnail;
696  g_thumbnail.thumbnail = google_thumbnail();
697  db->SetPageThumbnail(url2, 0, g_thumbnail);
698
699  top_sites().ReadDatabase();
700
701  top_sites().GetMostVisitedURLs(
702      consumer(),
703      NewCallback(static_cast<TopSitesTest*>(this),
704                  &TopSitesTest::OnTopSitesAvailable));
705  ASSERT_EQ(4u, urls().size());
706  EXPECT_EQ(google1_url, urls()[0].url);
707  EXPECT_EQ(google_title, urls()[0].title);
708  EXPECT_TRUE(top_sites().GetPageThumbnail(google1_url, &thumbnail_result));
709  EXPECT_TRUE(ThumbnailsAreEqual(google_thumbnail(), thumbnail_result));
710  ASSERT_EQ(3u, urls()[0].redirects.size());
711  EXPECT_EQ(google1_url, urls()[0].redirects[0]);
712  EXPECT_EQ(google2_url, urls()[0].redirects[1]);
713  EXPECT_EQ(google3_url, urls()[0].redirects[2]);
714
715  EXPECT_EQ(asdf_url, urls()[1].url);
716  EXPECT_EQ(asdf_title, urls()[1].title);
717  EXPECT_EQ(welcome_url(), urls()[2].url);
718  EXPECT_EQ(themes_url(), urls()[3].url);
719
720  MockHistoryServiceImpl hs;
721  // Add one old, one new URL to the history.
722  hs.AppendMockPage(google1_url, google_title);
723  hs.AppendMockPage(news_url, news_title);
724  top_sites().SetMockHistoryService(&hs);
725
726  // This requests data from History Service and  writes it to the DB.
727  top_sites().StartQueryForMostVisited();
728  MessageLoop::current()->RunAllPending();
729
730  std::map<GURL, Images> thumbnails;
731  MostVisitedURLList results;
732  db->GetPageThumbnails(&results, &thumbnails);
733  ASSERT_EQ(4u, results.size());
734  EXPECT_EQ(google_title, results[0].title);
735  EXPECT_EQ(news_title, results[1].title);
736
737  scoped_ptr<SkBitmap> weewar_bitmap(
738      gfx::JPEGCodec::Decode(weewar_thumbnail()->front(),
739                             weewar_thumbnail()->size()));
740
741  base::Time now = base::Time::Now();
742  ThumbnailScore low_score(1.0, true, true, now);
743  ThumbnailScore medium_score(0.5, true, true, now);
744  ThumbnailScore high_score(0.0, true, true, now);
745
746  // 1. Set to weewar. (Writes the thumbnail to the DB.)
747  EXPECT_TRUE(top_sites().SetPageThumbnail(google1_url,
748                                           *weewar_bitmap,
749                                           medium_score));
750  RefCountedBytes* out_1;
751  Images out_2;
752  EXPECT_TRUE(top_sites().GetPageThumbnail(google1_url, &out_1));
753
754  MessageLoop::current()->RunAllPending();
755
756  db->GetPageThumbnail(url2.url, &out_2);
757  EXPECT_TRUE(ThumbnailsAreEqual(out_1, out_2.thumbnail));
758
759  scoped_ptr<SkBitmap> google_bitmap(
760      gfx::JPEGCodec::Decode(google_thumbnail()->front(),
761                             google_thumbnail()->size()));
762
763  // 2. Set to google - low score.
764  EXPECT_FALSE(top_sites().SetPageThumbnail(google1_url,
765                                            *google_bitmap,
766                                            low_score));
767
768  // 3. Set to google - high score.
769  EXPECT_TRUE(top_sites().SetPageThumbnail(google1_url,
770                                           *google_bitmap,
771                                           high_score));
772  // Check that the thumbnail was updated.
773  EXPECT_TRUE(top_sites().GetPageThumbnail(google1_url, &out_1));
774  EXPECT_FALSE(ThumbnailsAreEqual(out_1, out_2.thumbnail));
775  MessageLoop::current()->RunAllPending();
776
777  // Read the new thumbnail from the DB - should match what's in TopSites.
778  db->GetPageThumbnail(url2.url, &out_2);
779  EXPECT_TRUE(ThumbnailsAreEqual(out_1, out_2.thumbnail));
780  EXPECT_TRUE(high_score.Equals(out_2.thumbnail_score));
781}
782
783TEST_F(TopSitesTest, DeleteNotifications) {
784  ChromeThread db_loop(ChromeThread::DB, MessageLoop::current());
785  GURL google1_url("http://google.com");
786  GURL google2_url("http://google.com/redirect");
787  GURL google3_url("http://www.google.com");
788  string16 google_title(ASCIIToUTF16("Google"));
789  GURL news_url("http://news.google.com");
790  string16 news_title(ASCIIToUTF16("Google News"));
791
792  MockHistoryServiceImpl hs;
793
794  top_sites().Init(file_name());
795
796  hs.AppendMockPage(google1_url, google_title);
797  hs.AppendMockPage(news_url, news_title);
798  top_sites().SetMockHistoryService(&hs);
799
800  top_sites().StartQueryForMostVisited();
801  MessageLoop::current()->RunAllPending();
802
803  top_sites().GetMostVisitedURLs(
804      consumer(),
805      NewCallback(static_cast<TopSitesTest*>(this),
806                  &TopSitesTest::OnTopSitesAvailable));
807  // 2 extra prepopulated URLs.
808  ASSERT_EQ(4u, urls().size());
809
810  hs.RemoveMostVisitedURL();
811
812  history::URLsDeletedDetails history_details;
813  history_details.all_history = false;
814  Details<URLsDeletedDetails> details(&history_details);
815  top_sites().Observe(NotificationType::HISTORY_URLS_DELETED,
816                      Source<Profile> (&profile()),
817                      details);
818  MessageLoop::current()->RunAllPending();
819
820  top_sites().GetMostVisitedURLs(
821      consumer(),
822      NewCallback(static_cast<TopSitesTest*>(this),
823                  &TopSitesTest::OnTopSitesAvailable));
824  ASSERT_EQ(3u, urls().size());
825  EXPECT_EQ(google_title, urls()[0].title);
826  EXPECT_EQ(welcome_url(), urls()[1].url);
827  EXPECT_EQ(themes_url(), urls()[2].url);
828
829  hs.RemoveMostVisitedURL();
830  history_details.all_history = true;
831  details = Details<HistoryDetails>(&history_details);
832  top_sites().Observe(NotificationType::HISTORY_URLS_DELETED,
833                      Source<Profile> (&profile()),
834                      details);
835  MessageLoop::current()->RunAllPending();
836  top_sites().GetMostVisitedURLs(
837      consumer(),
838      NewCallback(static_cast<TopSitesTest*>(this),
839                  &TopSitesTest::OnTopSitesAvailable));
840  ASSERT_EQ(2u, urls().size());
841  EXPECT_EQ(welcome_url(), urls()[0].url);
842  EXPECT_EQ(themes_url(), urls()[1].url);
843}
844
845TEST_F(TopSitesTest, PinnedURLsDeleted) {
846  ChromeThread db_loop(ChromeThread::DB, MessageLoop::current());
847  GURL google1_url("http://google.com");
848  GURL google2_url("http://google.com/redirect");
849  GURL google3_url("http://www.google.com");
850  string16 google_title(ASCIIToUTF16("Google"));
851  GURL news_url("http://news.google.com");
852  string16 news_title(ASCIIToUTF16("Google News"));
853
854  MockHistoryServiceImpl hs;
855
856  top_sites().Init(file_name());
857
858  hs.AppendMockPage(google1_url, google_title);
859  hs.AppendMockPage(news_url, news_title);
860  top_sites().SetMockHistoryService(&hs);
861
862  top_sites().StartQueryForMostVisited();
863  MessageLoop::current()->RunAllPending();
864  top_sites().GetMostVisitedURLs(
865      consumer(),
866      NewCallback(static_cast<TopSitesTest*>(this),
867                  &TopSitesTest::OnTopSitesAvailable));
868  MessageLoop::current()->RunAllPending();
869  EXPECT_EQ(1u, number_of_callbacks());
870  // 2 extra prepopulated URLs.
871  ASSERT_EQ(4u, urls().size());
872
873  top_sites().AddPinnedURL(news_url, 3);
874  EXPECT_TRUE(top_sites().IsURLPinned(news_url));
875
876  hs.RemoveMostVisitedURL();
877  history::URLsDeletedDetails history_details;
878  history_details.all_history = false;
879  history_details.urls.insert(news_url);
880  Details<URLsDeletedDetails> details(&history_details);
881  top_sites().Observe(NotificationType::HISTORY_URLS_DELETED,
882                      Source<Profile> (&profile()),
883                      details);
884  MessageLoop::current()->RunAllPending();
885  top_sites().GetMostVisitedURLs(
886      consumer(),
887      NewCallback(static_cast<TopSitesTest*>(this),
888                  &TopSitesTest::OnTopSitesAvailable));
889  MessageLoop::current()->RunAllPending();
890  EXPECT_EQ(2u, number_of_callbacks());
891  ASSERT_EQ(3u, urls().size());
892  EXPECT_FALSE(top_sites().IsURLPinned(news_url));
893
894  hs.RemoveMostVisitedURL();
895  history_details.all_history = true;
896  details = Details<HistoryDetails>(&history_details);
897  top_sites().Observe(NotificationType::HISTORY_URLS_DELETED,
898                      Source<Profile> (&profile()),
899                      details);
900  MessageLoop::current()->RunAllPending();
901  top_sites().GetMostVisitedURLs(
902      consumer(),
903      NewCallback(static_cast<TopSitesTest*>(this),
904                  &TopSitesTest::OnTopSitesAvailable));
905  ASSERT_EQ(2u, urls().size());
906  MessageLoop::current()->RunAllPending();
907
908  top_sites().StartQueryForMostVisited();
909  MessageLoop::current()->RunAllPending();
910  top_sites().GetMostVisitedURLs(
911      consumer(),
912      NewCallback(static_cast<TopSitesTest*>(this),
913                  &TopSitesTest::OnTopSitesAvailable));
914  ASSERT_EQ(2u, urls().size());
915  EXPECT_EQ(welcome_url(), urls()[0].url);
916  EXPECT_EQ(themes_url(), urls()[1].url);
917}
918
919TEST_F(TopSitesTest, GetUpdateDelay) {
920  top_sites().last_num_urls_changed_ = 0;
921  EXPECT_EQ(30, top_sites().GetUpdateDelay().InSeconds());
922
923  top_sites().top_sites_.resize(20);
924  top_sites().last_num_urls_changed_ = 0;
925  EXPECT_EQ(60, top_sites().GetUpdateDelay().InMinutes());
926
927  top_sites().last_num_urls_changed_ = 3;
928  EXPECT_EQ(52, top_sites().GetUpdateDelay().InMinutes());
929
930  top_sites().last_num_urls_changed_ = 20;
931  EXPECT_EQ(1, top_sites().GetUpdateDelay().InMinutes());
932}
933
934TEST_F(TopSitesTest, Migration) {
935  ChromeThread db_loop(ChromeThread::DB, MessageLoop::current());
936  GURL google1_url("http://google.com");
937  string16 google_title(ASCIIToUTF16("Google"));
938  GURL news_url("http://news.google.com");
939  string16 news_title(ASCIIToUTF16("Google News"));
940
941  MockHistoryServiceImpl hs;
942
943  top_sites().Init(file_name());
944
945  hs.AppendMockPage(google1_url, google_title);
946  hs.AppendMockPage(news_url, news_title);
947  top_sites().SetMockHistoryService(&hs);
948  MessageLoop::current()->RunAllPending();
949
950  top_sites().StartMigration();
951  EXPECT_TRUE(top_sites().migration_in_progress_);
952  MessageLoop::current()->RunAllPending();
953  EXPECT_EQ(2, hs.GetNumberOfThumbnailRequests());
954  EXPECT_FALSE(top_sites().migration_in_progress_);
955}
956
957TEST_F(TopSitesTest, QueueingRequestsForTopSites) {
958  ChromeThread db_loop(ChromeThread::DB, MessageLoop::current());
959  CancelableRequestConsumer c1;
960  CancelableRequestConsumer c2;
961  CancelableRequestConsumer c3;
962  top_sites().GetMostVisitedURLs(
963      &c1,
964      NewCallback(static_cast<TopSitesTest*>(this),
965                  &TopSitesTest::OnTopSitesAvailable));
966
967  top_sites().GetMostVisitedURLs(
968      &c2,
969      NewCallback(static_cast<TopSitesTest*>(this),
970                  &TopSitesTest::OnTopSitesAvailable));
971
972  top_sites().GetMostVisitedURLs(
973      &c3,
974      NewCallback(static_cast<TopSitesTest*>(this),
975                  &TopSitesTest::OnTopSitesAvailable));
976
977  EXPECT_EQ(0u, number_of_callbacks());
978  EXPECT_EQ(0u, urls().size());
979
980  MostVisitedURLList pages;
981  MostVisitedURL url;
982  url.url = GURL("http://1.com/");
983  url.redirects.push_back(url.url);
984  pages.push_back(url);
985  url.url = GURL("http://2.com/");
986  url.redirects.push_back(url.url);
987  pages.push_back(url);
988  top_sites().OnTopSitesAvailable(0, pages);
989  MessageLoop::current()->RunAllPending();
990
991  EXPECT_EQ(3u, number_of_callbacks());
992
993  ASSERT_EQ(4u, urls().size());
994  EXPECT_EQ("http://1.com/", urls()[0].url.spec());
995  EXPECT_EQ("http://2.com/", urls()[1].url.spec());
996  EXPECT_EQ(welcome_url(), urls()[2].url);
997  EXPECT_EQ(themes_url(), urls()[3].url);
998
999
1000  url.url = GURL("http://3.com/");
1001  url.redirects.push_back(url.url);
1002  pages.push_back(url);
1003  top_sites().OnTopSitesAvailable(0, pages);
1004  MessageLoop::current()->RunAllPending();
1005
1006  top_sites().GetMostVisitedURLs(
1007      &c3,
1008      NewCallback(static_cast<TopSitesTest*>(this),
1009                  &TopSitesTest::OnTopSitesAvailable));
1010
1011  EXPECT_EQ(4u, number_of_callbacks());
1012
1013  ASSERT_EQ(5u, urls().size());
1014  EXPECT_EQ("http://1.com/", urls()[0].url.spec());
1015  EXPECT_EQ("http://2.com/", urls()[1].url.spec());
1016  EXPECT_EQ("http://3.com/", urls()[2].url.spec());
1017  EXPECT_EQ(welcome_url(), urls()[3].url);
1018  EXPECT_EQ(themes_url(), urls()[4].url);
1019
1020}
1021
1022TEST_F(TopSitesTest, CancelingRequestsForTopSites) {
1023  ChromeThread db_loop(ChromeThread::DB, MessageLoop::current());
1024  CancelableRequestConsumer c1;
1025  CancelableRequestConsumer c2;
1026  top_sites().GetMostVisitedURLs(
1027      &c1,
1028      NewCallback(static_cast<TopSitesTest*>(this),
1029                  &TopSitesTest::OnTopSitesAvailable));
1030
1031  top_sites().GetMostVisitedURLs(
1032      &c2,
1033      NewCallback(static_cast<TopSitesTest*>(this),
1034                  &TopSitesTest::OnTopSitesAvailable));
1035
1036  {
1037    CancelableRequestConsumer c3;
1038    top_sites().GetMostVisitedURLs(
1039        &c3,
1040        NewCallback(static_cast<TopSitesTest*>(this),
1041                    &TopSitesTest::OnTopSitesAvailable));
1042    // c3 is out of scope, and the request should be cancelled.
1043  }
1044
1045  // No requests until OnTopSitesAvailable is called.
1046  EXPECT_EQ(0u, number_of_callbacks());
1047  EXPECT_EQ(0u, urls().size());
1048
1049  MostVisitedURLList pages;
1050  MostVisitedURL url;
1051  url.url = GURL("http://1.com/");
1052  url.redirects.push_back(url.url);
1053  pages.push_back(url);
1054  url.url = GURL("http://2.com/");
1055  pages.push_back(url);
1056
1057  top_sites().OnTopSitesAvailable(0, pages);
1058  MessageLoop::current()->RunAllPending();
1059
1060  // 1 request was canceled.
1061  EXPECT_EQ(2u, number_of_callbacks());
1062
1063  // 2 extra prepopulated URLs.
1064  ASSERT_EQ(4u, urls().size());
1065  EXPECT_EQ("http://1.com/", urls()[0].url.spec());
1066  EXPECT_EQ("http://2.com/", urls()[1].url.spec());
1067}
1068
1069TEST_F(TopSitesTest, AddTemporaryThumbnail) {
1070  ChromeThread db_loop(ChromeThread::DB, MessageLoop::current());
1071  GURL unknown_url("http://news.google.com/");
1072  GURL invalid_url("chrome://thumb/http://google.com/");
1073  GURL url1a("http://google.com/");
1074  GURL url1b("http://www.google.com/");
1075
1076  // Create a dummy thumbnail.
1077  SkBitmap thumbnail;
1078  thumbnail.setConfig(SkBitmap::kARGB_8888_Config, 4, 4);
1079  thumbnail.allocPixels();
1080  thumbnail.eraseRGB(0x00, 0x00, 0x00);
1081
1082  ThumbnailScore medium_score(0.5, true, true, base::Time::Now());
1083
1084  // Don't store thumbnails for Javascript URLs.
1085  EXPECT_FALSE(top_sites().SetPageThumbnail(invalid_url,
1086                                            thumbnail, medium_score));
1087  // Store thumbnails for unknown (but valid) URLs temporarily - calls
1088  // AddTemporaryThumbnail.
1089  EXPECT_TRUE(top_sites().SetPageThumbnail(unknown_url,
1090                                           thumbnail, medium_score));
1091
1092  std::vector<MostVisitedURL> list;
1093
1094  MostVisitedURL mv;
1095  mv.url = unknown_url;
1096  mv.redirects.push_back(mv.url);
1097  mv.redirects.push_back(url1a);
1098  mv.redirects.push_back(url1b);
1099  list.push_back(mv);
1100
1101  // Update URLs - use temporary thumbnails.
1102  top_sites().UpdateMostVisited(list);
1103
1104  RefCountedBytes* out = NULL;
1105  ASSERT_TRUE(top_sites().GetPageThumbnail(unknown_url, &out));
1106  scoped_ptr<SkBitmap> out_bitmap(gfx::JPEGCodec::Decode(out->front(),
1107                                                         out->size()));
1108  EXPECT_EQ(0, memcmp(thumbnail.getPixels(), out_bitmap->getPixels(),
1109                      thumbnail.getSize()));
1110}
1111
1112TEST_F(TopSitesTest, Blacklisting) {
1113  ChromeThread db_loop(ChromeThread::DB, MessageLoop::current());
1114  MostVisitedURLList pages;
1115  MostVisitedURL url, url1;
1116  url.url = GURL("http://bbc.com/");
1117  url.redirects.push_back(url.url);
1118  pages.push_back(url);
1119  url1.url = GURL("http://google.com/");
1120  url1.redirects.push_back(url1.url);
1121  pages.push_back(url1);
1122
1123  CancelableRequestConsumer c;
1124  top_sites().GetMostVisitedURLs(
1125      &c,
1126      NewCallback(static_cast<TopSitesTest*>(this),
1127                  &TopSitesTest::OnTopSitesAvailable));
1128  top_sites().OnTopSitesAvailable(0, pages);
1129  MessageLoop::current()->RunAllPending();
1130  {
1131    Lock& l = lock();
1132    AutoLock lock(l);  // IsBlacklisted must be in a lock.
1133    EXPECT_FALSE(top_sites().IsBlacklisted(GURL("http://bbc.com/")));
1134  }
1135
1136  EXPECT_EQ(1u, number_of_callbacks());
1137
1138  ASSERT_EQ(4u, urls().size());
1139  EXPECT_EQ("http://bbc.com/", urls()[0].url.spec());
1140  EXPECT_EQ("http://google.com/", urls()[1].url.spec());
1141  EXPECT_EQ(welcome_url(), urls()[2].url);
1142  EXPECT_EQ(themes_url(), urls()[3].url);
1143  EXPECT_FALSE(top_sites().HasBlacklistedItems());
1144
1145  top_sites().AddBlacklistedURL(GURL("http://google.com/"));
1146  EXPECT_TRUE(top_sites().HasBlacklistedItems());
1147  {
1148    Lock& l = lock();
1149    AutoLock lock(l);  // IsBlacklisted must be in a lock.
1150    EXPECT_TRUE(top_sites().IsBlacklisted(GURL("http://google.com/")));
1151    EXPECT_FALSE(top_sites().IsBlacklisted(GURL("http://bbc.com/")));
1152    EXPECT_FALSE(top_sites().IsBlacklisted(welcome_url()));
1153  }
1154
1155  top_sites().GetMostVisitedURLs(
1156      &c,
1157      NewCallback(static_cast<TopSitesTest*>(this),
1158                  &TopSitesTest::OnTopSitesAvailable));
1159  MessageLoop::current()->RunAllPending();
1160  EXPECT_EQ(2u, number_of_callbacks());
1161  ASSERT_EQ(3u, urls().size());
1162  EXPECT_EQ("http://bbc.com/", urls()[0].url.spec());
1163  EXPECT_EQ(welcome_url(), urls()[1].url);
1164  EXPECT_EQ(themes_url(), urls()[2].url);
1165
1166  top_sites().AddBlacklistedURL(welcome_url());
1167  EXPECT_TRUE(top_sites().HasBlacklistedItems());
1168  top_sites().GetMostVisitedURLs(
1169      &c,
1170      NewCallback(static_cast<TopSitesTest*>(this),
1171                  &TopSitesTest::OnTopSitesAvailable));
1172  ASSERT_EQ(2u, urls().size());
1173  EXPECT_EQ("http://bbc.com/", urls()[0].url.spec());
1174  EXPECT_EQ(themes_url(), urls()[1].url);
1175
1176  top_sites().RemoveBlacklistedURL(GURL("http://google.com/"));
1177  EXPECT_TRUE(top_sites().HasBlacklistedItems());
1178  {
1179    Lock& l = lock();
1180    AutoLock lock(l);  // IsBlacklisted must be in a lock.
1181    EXPECT_FALSE(top_sites().IsBlacklisted(GURL("http://google.com/")));
1182  }
1183
1184  top_sites().GetMostVisitedURLs(
1185      &c,
1186      NewCallback(static_cast<TopSitesTest*>(this),
1187                  &TopSitesTest::OnTopSitesAvailable));
1188  ASSERT_EQ(3u, urls().size());
1189  EXPECT_EQ("http://bbc.com/", urls()[0].url.spec());
1190  EXPECT_EQ("http://google.com/", urls()[1].url.spec());
1191  EXPECT_EQ(themes_url(), urls()[2].url);
1192
1193  top_sites().ClearBlacklistedURLs();
1194  EXPECT_FALSE(top_sites().HasBlacklistedItems());
1195  top_sites().GetMostVisitedURLs(
1196      &c,
1197      NewCallback(static_cast<TopSitesTest*>(this),
1198                  &TopSitesTest::OnTopSitesAvailable));
1199  ASSERT_EQ(4u, urls().size());
1200  EXPECT_EQ("http://bbc.com/", urls()[0].url.spec());
1201  EXPECT_EQ("http://google.com/", urls()[1].url.spec());
1202  EXPECT_EQ(welcome_url(), urls()[2].url);
1203  EXPECT_EQ(themes_url(), urls()[3].url);
1204}
1205
1206TEST_F(TopSitesTest, PinnedURLs) {
1207  ChromeThread db_loop(ChromeThread::DB, MessageLoop::current());
1208  MostVisitedURLList pages;
1209  MostVisitedURL url, url1;
1210  url.url = GURL("http://bbc.com/");
1211  url.redirects.push_back(url.url);
1212  pages.push_back(url);
1213  url1.url = GURL("http://google.com/");
1214  url1.redirects.push_back(url1.url);
1215  pages.push_back(url1);
1216
1217  CancelableRequestConsumer c;
1218  top_sites().GetMostVisitedURLs(
1219      &c,
1220      NewCallback(static_cast<TopSitesTest*>(this),
1221                  &TopSitesTest::OnTopSitesAvailable));
1222  top_sites().OnTopSitesAvailable(0, pages);
1223  MessageLoop::current()->RunAllPending();
1224  EXPECT_FALSE(top_sites().IsURLPinned(GURL("http://bbc.com/")));
1225
1226  ASSERT_EQ(4u, urls().size());
1227  EXPECT_EQ("http://bbc.com/", urls()[0].url.spec());
1228  EXPECT_EQ("http://google.com/", urls()[1].url.spec());
1229  EXPECT_EQ(welcome_url(), urls()[2].url);
1230  EXPECT_EQ(themes_url(), urls()[3].url);
1231
1232  top_sites().AddPinnedURL(GURL("http://google.com/"), 3);
1233  EXPECT_FALSE(top_sites().IsURLPinned(GURL("http://bbc.com/")));
1234  EXPECT_FALSE(top_sites().IsURLPinned(welcome_url()));
1235
1236  top_sites().GetMostVisitedURLs(
1237      &c,
1238      NewCallback(static_cast<TopSitesTest*>(this),
1239                  &TopSitesTest::OnTopSitesAvailable));
1240  EXPECT_EQ(2u, number_of_callbacks());
1241  ASSERT_EQ(4u, urls().size());
1242  EXPECT_EQ("http://bbc.com/", urls()[0].url.spec());
1243  EXPECT_EQ(welcome_url(), urls()[1].url);
1244  EXPECT_EQ(themes_url(), urls()[2].url);
1245  EXPECT_EQ("http://google.com/", urls()[3].url.spec());
1246
1247  top_sites().RemovePinnedURL(GURL("http://google.com/"));
1248  EXPECT_FALSE(top_sites().IsURLPinned(GURL("http://google.com/")));
1249  top_sites().GetMostVisitedURLs(
1250      &c,
1251      NewCallback(static_cast<TopSitesTest*>(this),
1252                  &TopSitesTest::OnTopSitesAvailable));
1253
1254  ASSERT_EQ(4u, urls().size());
1255  EXPECT_EQ("http://bbc.com/", urls()[0].url.spec());
1256  EXPECT_EQ("http://google.com/", urls()[1].url.spec());
1257  EXPECT_EQ(welcome_url(), urls()[2].url);
1258  EXPECT_EQ(themes_url(), urls()[3].url);
1259
1260  top_sites().AddPinnedURL(GURL("http://bbc.com"), 1);
1261  top_sites().AddPinnedURL(themes_url(), 0);
1262  top_sites().GetMostVisitedURLs(
1263      &c,
1264      NewCallback(static_cast<TopSitesTest*>(this),
1265                  &TopSitesTest::OnTopSitesAvailable));
1266
1267  ASSERT_EQ(4u, urls().size());
1268  EXPECT_EQ(themes_url(), urls()[0].url);
1269  EXPECT_EQ("http://bbc.com/", urls()[1].url.spec());
1270  EXPECT_EQ("http://google.com/", urls()[2].url.spec());
1271  EXPECT_EQ(welcome_url(), urls()[3].url);
1272
1273  top_sites().RemovePinnedURL(GURL("http://bbc.com"));
1274  top_sites().RemovePinnedURL(themes_url());
1275
1276  top_sites().AddPinnedURL(welcome_url(), 1);
1277  top_sites().AddPinnedURL(GURL("http://bbc.com"), 3);
1278
1279  top_sites().GetMostVisitedURLs(
1280      &c,
1281      NewCallback(static_cast<TopSitesTest*>(this),
1282                  &TopSitesTest::OnTopSitesAvailable));
1283
1284  ASSERT_EQ(4u, urls().size());
1285  EXPECT_EQ("http://google.com/", urls()[0].url.spec());
1286  EXPECT_EQ(welcome_url(), urls()[1].url);
1287  EXPECT_EQ(themes_url(), urls()[2].url);
1288  EXPECT_EQ("http://bbc.com/", urls()[3].url.spec());
1289}
1290
1291TEST_F(TopSitesTest, BlacklistingAndPinnedURLs) {
1292  ChromeThread db_loop(ChromeThread::DB, MessageLoop::current());
1293  MostVisitedURLList pages;
1294  CancelableRequestConsumer c;
1295  top_sites().GetMostVisitedURLs(
1296      &c,
1297      NewCallback(static_cast<TopSitesTest*>(this),
1298                  &TopSitesTest::OnTopSitesAvailable));
1299  top_sites().OnTopSitesAvailable(0, pages);
1300  MessageLoop::current()->RunAllPending();
1301
1302  ASSERT_EQ(2u, urls().size());
1303  EXPECT_EQ(welcome_url(), urls()[0].url);
1304  EXPECT_EQ(themes_url(), urls()[1].url);
1305
1306  top_sites().AddPinnedURL(themes_url(), 1);
1307  top_sites().AddBlacklistedURL(welcome_url());
1308
1309  top_sites().GetMostVisitedURLs(
1310      &c,
1311      NewCallback(static_cast<TopSitesTest*>(this),
1312                  &TopSitesTest::OnTopSitesAvailable));
1313
1314  ASSERT_EQ(2u, urls().size());
1315  EXPECT_EQ(GURL(), urls()[0].url);
1316  EXPECT_EQ(themes_url(), urls()[1].url);
1317
1318}
1319
1320TEST_F(TopSitesTest, AddPrepopulatedPages) {
1321  MostVisitedURLList pages;
1322  top_sites().AddPrepopulatedPages(&pages);
1323  ASSERT_EQ(2u, pages.size());
1324  EXPECT_EQ(welcome_url(), pages[0].url);
1325  EXPECT_EQ(themes_url(), pages[1].url);
1326
1327  pages.clear();
1328
1329  MostVisitedURL url = {themes_url()};
1330  pages.push_back(url);
1331
1332  top_sites().AddPrepopulatedPages(&pages);
1333
1334  // Themes URL is already in pages; should not be added twice.
1335  ASSERT_EQ(2u, pages.size());
1336  EXPECT_EQ(themes_url(), pages[0].url);
1337  EXPECT_EQ(welcome_url(), pages[1].url);
1338}
1339
1340}  // namespace history
1341