Home | History | Annotate | Download | only in history
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/command_line.h"
      6 #include "base/file_util.h"
      7 #include "base/format_macros.h"
      8 #include "base/memory/scoped_temp_dir.h"
      9 #include "base/path_service.h"
     10 #include "base/string_util.h"
     11 #include "base/utf_string_conversions.h"
     12 #include "base/values.h"
     13 #include "chrome/browser/history/history_backend.h"
     14 #include "chrome/browser/history/history_database.h"
     15 #include "chrome/browser/history/history_marshaling.h"
     16 #include "chrome/browser/history/history_notifications.h"
     17 #include "chrome/browser/history/history_unittest_base.h"
     18 #include "chrome/browser/history/top_sites.h"
     19 #include "chrome/browser/history/top_sites_backend.h"
     20 #include "chrome/browser/history/top_sites_cache.h"
     21 #include "chrome/browser/history/top_sites_database.h"
     22 #include "chrome/browser/ui/webui/most_visited_handler.h"
     23 #include "chrome/common/chrome_constants.h"
     24 #include "chrome/common/chrome_paths.h"
     25 #include "chrome/common/chrome_switches.h"
     26 #include "chrome/test/testing_profile.h"
     27 #include "chrome/tools/profiles/thumbnail-inl.h"
     28 #include "content/browser/browser_thread.h"
     29 #include "googleurl/src/gurl.h"
     30 #include "grit/chromium_strings.h"
     31 #include "grit/generated_resources.h"
     32 #include "grit/locale_settings.h"
     33 #include "testing/gtest/include/gtest/gtest.h"
     34 #include "third_party/skia/include/core/SkBitmap.h"
     35 #include "ui/base/l10n/l10n_util.h"
     36 #include "ui/gfx/codec/jpeg_codec.h"
     37 
     38 namespace history {
     39 
     40 namespace {
     41 
     42 // Used by WaitForHistory, see it for details.
     43 class WaitForHistoryTask : public HistoryDBTask {
     44  public:
     45   WaitForHistoryTask() {}
     46 
     47   virtual bool RunOnDBThread(HistoryBackend* backend, HistoryDatabase* db) {
     48     return true;
     49   }
     50 
     51   virtual void DoneRunOnMainThread() {
     52     MessageLoop::current()->Quit();
     53   }
     54 
     55  private:
     56   DISALLOW_COPY_AND_ASSIGN(WaitForHistoryTask);
     57 };
     58 
     59 // Used for querying top sites. Either runs sequentially, or runs a nested
     60 // nested message loop until the response is complete. The later is used when
     61 // TopSites is queried before it finishes loading.
     62 class TopSitesQuerier {
     63  public:
     64   TopSitesQuerier() : number_of_callbacks_(0), waiting_(false) {}
     65 
     66   // Queries top sites. If |wait| is true a nested message loop is run until the
     67   // callback is notified.
     68   void QueryTopSites(TopSites* top_sites, bool wait) {
     69     int start_number_of_callbacks = number_of_callbacks_;
     70     top_sites->GetMostVisitedURLs(
     71         &consumer_,
     72         NewCallback(this, &TopSitesQuerier::OnTopSitesAvailable));
     73     if (wait && start_number_of_callbacks == number_of_callbacks_) {
     74       waiting_ = true;
     75       MessageLoop::current()->Run();
     76     }
     77   }
     78 
     79   void CancelRequest() {
     80     consumer_.CancelAllRequests();
     81   }
     82 
     83   void set_urls(const MostVisitedURLList& urls) { urls_ = urls; }
     84   const MostVisitedURLList& urls() const { return urls_; }
     85 
     86   int number_of_callbacks() const { return number_of_callbacks_; }
     87 
     88  private:
     89   // Callback for TopSites::GetMostVisitedURLs.
     90   void OnTopSitesAvailable(const history::MostVisitedURLList& data) {
     91     urls_ = data;
     92     number_of_callbacks_++;
     93     if (waiting_) {
     94       MessageLoop::current()->Quit();
     95       waiting_ = false;
     96     }
     97   }
     98 
     99   CancelableRequestConsumer consumer_;
    100   MostVisitedURLList urls_;
    101   int number_of_callbacks_;
    102   bool waiting_;
    103 
    104   DISALLOW_COPY_AND_ASSIGN(TopSitesQuerier);
    105 };
    106 
    107 // Extracts the data from |t1| into a SkBitmap. This is intended for usage of
    108 // thumbnail data, which is stored as jpgs.
    109 SkBitmap ExtractThumbnail(const RefCountedBytes& t1) {
    110   scoped_ptr<SkBitmap> image(gfx::JPEGCodec::Decode(t1.front(),
    111                                                     t1.data.size()));
    112   return image.get() ? *image : SkBitmap();
    113 }
    114 
    115 // Returns true if t1 and t2 contain the same data.
    116 bool ThumbnailsAreEqual(RefCountedBytes* t1, RefCountedBytes* t2) {
    117   if (!t1 || !t2)
    118     return false;
    119   if (t1->data.size() != t2->data.size())
    120     return false;
    121   return std::equal(t1->data.begin(),
    122                     t1->data.end(),
    123                     t2->data.begin());
    124 }
    125 
    126 }  // namespace
    127 
    128 class TopSitesTest : public HistoryUnitTestBase {
    129  public:
    130   TopSitesTest()
    131       : ui_thread_(BrowserThread::UI, &message_loop_),
    132         db_thread_(BrowserThread::DB, &message_loop_),
    133         original_command_line_(*CommandLine::ForCurrentProcess()) {
    134   }
    135 
    136   virtual void SetUp() {
    137     profile_.reset(new TestingProfile);
    138     if (CreateHistoryAndTopSites()) {
    139       profile_->CreateHistoryService(false, false);
    140       profile_->CreateTopSites();
    141       profile_->BlockUntilTopSitesLoaded();
    142     }
    143   }
    144 
    145   virtual void TearDown() {
    146     profile_.reset();
    147     *CommandLine::ForCurrentProcess() = original_command_line_;
    148   }
    149 
    150   // Returns true if history and top sites should be created in SetUp.
    151   virtual bool CreateHistoryAndTopSites() {
    152     return true;
    153   }
    154 
    155   // Gets the thumbnail for |url| from TopSites.
    156   SkBitmap GetThumbnail(const GURL& url) {
    157     scoped_refptr<RefCountedBytes> data;
    158     return top_sites()->GetPageThumbnail(url, &data) ?
    159         ExtractThumbnail(*data.get()) : SkBitmap();
    160   }
    161 
    162   // Creates a bitmap of the specified color.
    163   SkBitmap CreateBitmap(SkColor color) {
    164     SkBitmap thumbnail;
    165     thumbnail.setConfig(SkBitmap::kARGB_8888_Config, 4, 4);
    166     thumbnail.allocPixels();
    167     thumbnail.eraseColor(color);
    168     return thumbnail;
    169   }
    170 
    171   // Forces top sites to load top sites from history, then recreates top sites.
    172   // Recreating top sites makes sure the changes from history are saved and
    173   // loaded from the db.
    174   void RefreshTopSitesAndRecreate() {
    175     StartQueryForMostVisited();
    176     WaitForHistory();
    177     RecreateTopSitesAndBlock();
    178   }
    179 
    180   // Blocks the caller until history processes a task. This is useful if you
    181   // need to wait until you know history has processed a task.
    182   void WaitForHistory() {
    183     history_service()->ScheduleDBTask(new WaitForHistoryTask(), &consumer_);
    184     MessageLoop::current()->Run();
    185   }
    186 
    187   // Waits for top sites to finish processing a task. This is useful if you need
    188   // to wait until top sites finishes processing a task.
    189   void WaitForTopSites() {
    190     top_sites()->backend_->DoEmptyRequest(
    191         &consumer_,
    192         NewCallback(this, &TopSitesTest::QuitCallback));
    193     MessageLoop::current()->Run();
    194   }
    195 
    196   TopSites* top_sites() { return profile_->GetTopSites(); }
    197   CancelableRequestConsumer* consumer() { return &consumer_; }
    198   TestingProfile* profile() {return profile_.get();}
    199   HistoryService* history_service() {
    200     return profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
    201   }
    202 
    203   MostVisitedURLList GetPrepopulatePages() {
    204     return TopSites::GetPrepopulatePages();
    205   }
    206 
    207   // Returns true if the TopSitesQuerier contains the prepopulate data starting
    208   // at |start_index|.
    209   void ContainsPrepopulatePages(const TopSitesQuerier& querier,
    210                                 size_t start_index) {
    211     MostVisitedURLList prepopulate_urls = GetPrepopulatePages();
    212     ASSERT_LE(start_index + prepopulate_urls.size(), querier.urls().size());
    213     for (size_t i = 0; i < prepopulate_urls.size(); ++i) {
    214       EXPECT_EQ(prepopulate_urls[i].url.spec(),
    215                 querier.urls()[start_index + i].url.spec()) << " @ index " <<
    216           i;
    217     }
    218   }
    219 
    220   // Used for callbacks from history.
    221   void EmptyCallback() {
    222   }
    223 
    224   // Quit the current message loop when invoked. Useful when running a nested
    225   // message loop.
    226   void QuitCallback(TopSitesBackend::Handle handle) {
    227     MessageLoop::current()->Quit();
    228   }
    229 
    230   // Adds a page to history.
    231   void AddPageToHistory(const GURL& url) {
    232     RedirectList redirects;
    233     redirects.push_back(url);
    234     history_service()->AddPage(
    235         url, static_cast<void*>(this), 0, GURL(), PageTransition::TYPED,
    236         redirects, history::SOURCE_BROWSED, false);
    237   }
    238 
    239   // Adds a page to history.
    240   void AddPageToHistory(const GURL& url, const string16& title) {
    241     RedirectList redirects;
    242     redirects.push_back(url);
    243     history_service()->AddPage(
    244         url, static_cast<void*>(this), 0, GURL(), PageTransition::TYPED,
    245         redirects, history::SOURCE_BROWSED, false);
    246     history_service()->SetPageTitle(url, title);
    247   }
    248 
    249   // Adds a page to history.
    250   void AddPageToHistory(const GURL& url,
    251                         const string16& title,
    252                         const history::RedirectList& redirects,
    253                         base::Time time) {
    254     history_service()->AddPage(
    255         url, time, static_cast<void*>(this), 0, GURL(), PageTransition::TYPED,
    256         redirects, history::SOURCE_BROWSED, false);
    257     history_service()->SetPageTitle(url, title);
    258   }
    259 
    260   // Delets a url.
    261   void DeleteURL(const GURL& url) {
    262     history_service()->DeleteURL(url);
    263   }
    264 
    265   // Returns true if the thumbnail equals the specified bytes.
    266   bool ThumbnailEqualsBytes(const SkBitmap& image, RefCountedBytes* bytes) {
    267     scoped_refptr<RefCountedBytes> encoded_image;
    268     EncodeBitmap(image, &encoded_image);
    269     return ThumbnailsAreEqual(encoded_image, bytes);
    270   }
    271 
    272   // Recreates top sites. This forces top sites to reread from the db.
    273   void RecreateTopSitesAndBlock() {
    274     // Recreate TopSites and wait for it to load.
    275     profile()->CreateTopSites();
    276     // As history already loaded we have to fake this call.
    277     profile()->BlockUntilTopSitesLoaded();
    278   }
    279 
    280   // Wrappers that allow private TopSites functions to be called from the
    281   // individual tests without making them all be friends.
    282   GURL GetCanonicalURL(const GURL& url) {
    283     return top_sites()->cache_->GetCanonicalURL(url);
    284   }
    285 
    286   void SetTopSites(const MostVisitedURLList& new_top_sites) {
    287     top_sites()->SetTopSites(new_top_sites);
    288   }
    289 
    290   void StartQueryForMostVisited() {
    291     top_sites()->StartQueryForMostVisited();
    292   }
    293 
    294   bool EncodeBitmap(const SkBitmap& image,
    295                     scoped_refptr<RefCountedBytes>* bytes) {
    296     return TopSites::EncodeBitmap(image, bytes);
    297   }
    298 
    299   void SetLastNumUrlsChanged(size_t value) {
    300     top_sites()->last_num_urls_changed_ = value;
    301   }
    302 
    303   size_t last_num_urls_changed() { return top_sites()->last_num_urls_changed_; }
    304 
    305   base::TimeDelta GetUpdateDelay() {
    306     return top_sites()->GetUpdateDelay();
    307   }
    308 
    309   bool IsTopSitesLoaded() { return top_sites()->loaded_; }
    310 
    311   bool AddPrepopulatedPages(MostVisitedURLList* urls) {
    312     return TopSites::AddPrepopulatedPages(urls);
    313   }
    314 
    315  private:
    316   MessageLoopForUI message_loop_;
    317   BrowserThread ui_thread_;
    318   BrowserThread db_thread_;
    319   scoped_ptr<TestingProfile> profile_;
    320   CancelableRequestConsumer consumer_;
    321   CommandLine original_command_line_;
    322 
    323   DISALLOW_COPY_AND_ASSIGN(TopSitesTest);
    324 };  // Class TopSitesTest
    325 
    326 class TopSitesMigrationTest : public TopSitesTest {
    327  public:
    328   TopSitesMigrationTest() {}
    329 
    330   virtual void SetUp() {
    331     TopSitesTest::SetUp();
    332 
    333     FilePath data_path;
    334     ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path));
    335     data_path = data_path.AppendASCII("top_sites");
    336 
    337     // Set up history and thumbnails as they would be before migration.
    338     ASSERT_NO_FATAL_FAILURE(ExecuteSQLScript(
    339         data_path.AppendASCII("history.19.sql"),
    340         profile()->GetPath().Append(chrome::kHistoryFilename)));
    341     ASSERT_NO_FATAL_FAILURE(ExecuteSQLScript(
    342         data_path.AppendASCII("thumbnails.3.sql"),
    343         profile()->GetPath().Append(chrome::kThumbnailsFilename)));
    344 
    345     profile()->CreateHistoryService(false, false);
    346     profile()->CreateTopSites();
    347     profile()->BlockUntilTopSitesLoaded();
    348   }
    349 
    350   // Returns true if history and top sites should be created in SetUp.
    351   virtual bool CreateHistoryAndTopSites() {
    352     return false;
    353   }
    354 
    355  protected:
    356   // Assertions for the migration test. This is extracted into a standalone
    357   // method so that it can be invoked twice.
    358   void MigrationAssertions() {
    359     TopSitesQuerier querier;
    360     querier.QueryTopSites(top_sites(), false);
    361 
    362     // We shouldn't have gotten a callback.
    363     EXPECT_EQ(1, querier.number_of_callbacks());
    364 
    365     // The data we loaded should contain google and yahoo.
    366     ASSERT_EQ(2u + GetPrepopulatePages().size(), querier.urls().size());
    367     EXPECT_EQ(GURL("http://google.com/"), querier.urls()[0].url);
    368     EXPECT_EQ(GURL("http://yahoo.com/"), querier.urls()[1].url);
    369     ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 2));
    370 
    371     SkBitmap goog_thumbnail = GetThumbnail(GURL("http://google.com/"));
    372     EXPECT_EQ(1, goog_thumbnail.width());
    373 
    374     SkBitmap yahoo_thumbnail = GetThumbnail(GURL("http://yahoo.com/"));
    375     EXPECT_EQ(2, yahoo_thumbnail.width());
    376 
    377     // Favicon assertions are handled in ThumbnailDatabase.
    378   }
    379 
    380  private:
    381 
    382   DISALLOW_COPY_AND_ASSIGN(TopSitesMigrationTest);
    383 };
    384 
    385 // Helper function for appending a URL to a vector of "most visited" URLs,
    386 // using the default values for everything but the URL.
    387 static void AppendMostVisitedURL(std::vector<MostVisitedURL>* list,
    388                                  const GURL& url) {
    389   MostVisitedURL mv;
    390   mv.url = url;
    391   mv.redirects.push_back(url);
    392   list->push_back(mv);
    393 }
    394 
    395 // Same as AppendMostVisitedURL except that it adds a redirect from the first
    396 // URL to the second.
    397 static void AppendMostVisitedURLWithRedirect(
    398     std::vector<MostVisitedURL>* list,
    399     const GURL& redirect_source, const GURL& redirect_dest) {
    400   MostVisitedURL mv;
    401   mv.url = redirect_dest;
    402   mv.redirects.push_back(redirect_source);
    403   mv.redirects.push_back(redirect_dest);
    404   list->push_back(mv);
    405 }
    406 
    407 // Tests GetCanonicalURL.
    408 TEST_F(TopSitesTest, GetCanonicalURL) {
    409   // Have two chains:
    410   //   google.com -> www.google.com
    411   //   news.google.com (no redirects)
    412   GURL news("http://news.google.com/");
    413   GURL source("http://google.com/");
    414   GURL dest("http://www.google.com/");
    415 
    416   std::vector<MostVisitedURL> most_visited;
    417   AppendMostVisitedURLWithRedirect(&most_visited, source, dest);
    418   AppendMostVisitedURL(&most_visited, news);
    419   SetTopSites(most_visited);
    420 
    421   // Random URLs not in the database are returned unchanged.
    422   GURL result = GetCanonicalURL(GURL("http://fark.com/"));
    423   EXPECT_EQ(GURL("http://fark.com/"), result);
    424 
    425   // Easy case, there are no redirects and the exact URL is stored.
    426   result = GetCanonicalURL(news);
    427   EXPECT_EQ(news, result);
    428 
    429   // The URL in question is the source URL in a redirect list.
    430   result = GetCanonicalURL(source);
    431   EXPECT_EQ(dest, result);
    432 
    433   // The URL in question is the destination of a redirect.
    434   result = GetCanonicalURL(dest);
    435   EXPECT_EQ(dest, result);
    436 }
    437 
    438 // Tests DiffMostVisited.
    439 TEST_F(TopSitesTest, DiffMostVisited) {
    440   GURL stays_the_same("http://staysthesame/");
    441   GURL gets_added_1("http://getsadded1/");
    442   GURL gets_added_2("http://getsadded2/");
    443   GURL gets_deleted_1("http://getsdeleted2/");
    444   GURL gets_moved_1("http://getsmoved1/");
    445 
    446   std::vector<MostVisitedURL> old_list;
    447   AppendMostVisitedURL(&old_list, stays_the_same);  // 0  (unchanged)
    448   AppendMostVisitedURL(&old_list, gets_deleted_1);  // 1  (deleted)
    449   AppendMostVisitedURL(&old_list, gets_moved_1);    // 2  (moved to 3)
    450 
    451   std::vector<MostVisitedURL> new_list;
    452   AppendMostVisitedURL(&new_list, stays_the_same);  // 0  (unchanged)
    453   AppendMostVisitedURL(&new_list, gets_added_1);    // 1  (added)
    454   AppendMostVisitedURL(&new_list, gets_added_2);    // 2  (added)
    455   AppendMostVisitedURL(&new_list, gets_moved_1);    // 3  (moved from 2)
    456 
    457   history::TopSitesDelta delta;
    458   history::TopSites::DiffMostVisited(old_list, new_list, &delta);
    459 
    460   ASSERT_EQ(2u, delta.added.size());
    461   ASSERT_TRUE(gets_added_1 == delta.added[0].url.url);
    462   ASSERT_EQ(1, delta.added[0].rank);
    463   ASSERT_TRUE(gets_added_2 == delta.added[1].url.url);
    464   ASSERT_EQ(2, delta.added[1].rank);
    465 
    466   ASSERT_EQ(1u, delta.deleted.size());
    467   ASSERT_TRUE(gets_deleted_1 == delta.deleted[0].url);
    468 
    469   ASSERT_EQ(1u, delta.moved.size());
    470   ASSERT_TRUE(gets_moved_1 == delta.moved[0].url.url);
    471   ASSERT_EQ(3, delta.moved[0].rank);
    472 }
    473 
    474 // Tests SetPageThumbnail.
    475 TEST_F(TopSitesTest, SetPageThumbnail) {
    476   GURL url1a("http://google.com/");
    477   GURL url1b("http://www.google.com/");
    478   GURL url2("http://images.google.com/");
    479   GURL invalid_url("chrome://favicon/http://google.com/");
    480 
    481   std::vector<MostVisitedURL> list;
    482   AppendMostVisitedURL(&list, url2);
    483 
    484   MostVisitedURL mv;
    485   mv.url = url1b;
    486   mv.redirects.push_back(url1a);
    487   mv.redirects.push_back(url1b);
    488   list.push_back(mv);
    489 
    490   // Save our most visited data containing that one site.
    491   SetTopSites(list);
    492 
    493   // Create a dummy thumbnail.
    494   SkBitmap thumbnail(CreateBitmap(SK_ColorWHITE));
    495 
    496   base::Time now = base::Time::Now();
    497   ThumbnailScore low_score(1.0, true, true, now);
    498   ThumbnailScore medium_score(0.5, true, true, now);
    499   ThumbnailScore high_score(0.0, true, true, now);
    500 
    501   // Setting the thumbnail for invalid pages should fail.
    502   EXPECT_FALSE(top_sites()->SetPageThumbnail(invalid_url,
    503                                              thumbnail, medium_score));
    504 
    505   // Setting the thumbnail for url2 should succeed, lower scores shouldn't
    506   // replace it, higher scores should.
    507   EXPECT_TRUE(top_sites()->SetPageThumbnail(url2, thumbnail, medium_score));
    508   EXPECT_FALSE(top_sites()->SetPageThumbnail(url2, thumbnail, low_score));
    509   EXPECT_TRUE(top_sites()->SetPageThumbnail(url2, thumbnail, high_score));
    510 
    511   // Set on the redirect source should succeed. It should be replacable by
    512   // the same score on the redirect destination, which in turn should not
    513   // be replaced by the source again.
    514   EXPECT_TRUE(top_sites()->SetPageThumbnail(url1a, thumbnail, medium_score));
    515   EXPECT_TRUE(top_sites()->SetPageThumbnail(url1b, thumbnail, medium_score));
    516   EXPECT_FALSE(top_sites()->SetPageThumbnail(url1a, thumbnail, medium_score));
    517 }
    518 
    519 // Makes sure a thumbnail is correctly removed when the page is removed.
    520 TEST_F(TopSitesTest, ThumbnailRemoved) {
    521   GURL url("http://google.com/");
    522 
    523   // Configure top sites with 'google.com'.
    524   std::vector<MostVisitedURL> list;
    525   AppendMostVisitedURL(&list, url);
    526   SetTopSites(list);
    527 
    528   // Create a dummy thumbnail.
    529   SkBitmap thumbnail(CreateBitmap(SK_ColorRED));
    530 
    531   base::Time now = base::Time::Now();
    532   ThumbnailScore low_score(1.0, true, true, now);
    533   ThumbnailScore medium_score(0.5, true, true, now);
    534   ThumbnailScore high_score(0.0, true, true, now);
    535 
    536   // Set the thumbnail.
    537   EXPECT_TRUE(top_sites()->SetPageThumbnail(url, thumbnail, medium_score));
    538 
    539   // Make sure the thumbnail was actually set.
    540   scoped_refptr<RefCountedBytes> result;
    541   EXPECT_TRUE(top_sites()->GetPageThumbnail(url, &result));
    542   EXPECT_TRUE(ThumbnailEqualsBytes(thumbnail, result.get()));
    543 
    544   // Reset the thumbnails and make sure we don't get it back.
    545   SetTopSites(MostVisitedURLList());
    546   EXPECT_FALSE(top_sites()->GetPageThumbnail(url, &result));
    547 }
    548 
    549 // Tests GetPageThumbnail.
    550 TEST_F(TopSitesTest, GetPageThumbnail) {
    551   MostVisitedURLList url_list;
    552   MostVisitedURL url1;
    553   url1.url = GURL("http://asdf.com");
    554   url1.redirects.push_back(url1.url);
    555   url_list.push_back(url1);
    556 
    557   MostVisitedURL url2;
    558   url2.url = GURL("http://gmail.com");
    559   url2.redirects.push_back(url2.url);
    560   url2.redirects.push_back(GURL("http://mail.google.com"));
    561   url_list.push_back(url2);
    562 
    563   SetTopSites(url_list);
    564 
    565   // Create a dummy thumbnail.
    566   SkBitmap thumbnail(CreateBitmap(SK_ColorWHITE));
    567   ThumbnailScore score(0.5, true, true, base::Time::Now());
    568 
    569   scoped_refptr<RefCountedBytes> result;
    570   EXPECT_TRUE(top_sites()->SetPageThumbnail(url1.url, thumbnail, score));
    571   EXPECT_TRUE(top_sites()->GetPageThumbnail(url1.url, &result));
    572 
    573   EXPECT_TRUE(top_sites()->SetPageThumbnail(GURL("http://gmail.com"),
    574                                            thumbnail, score));
    575   EXPECT_TRUE(top_sites()->GetPageThumbnail(GURL("http://gmail.com"),
    576                                             &result));
    577   // Get a thumbnail via a redirect.
    578   EXPECT_TRUE(top_sites()->GetPageThumbnail(GURL("http://mail.google.com"),
    579                                             &result));
    580 
    581   EXPECT_TRUE(top_sites()->SetPageThumbnail(GURL("http://mail.google.com"),
    582                                            thumbnail, score));
    583   EXPECT_TRUE(top_sites()->GetPageThumbnail(url2.url, &result));
    584 
    585   EXPECT_TRUE(ThumbnailEqualsBytes(thumbnail, result.get()));
    586 }
    587 
    588 // Tests GetMostVisitedURLs.
    589 TEST_F(TopSitesTest, GetMostVisited) {
    590   GURL news("http://news.google.com/");
    591   GURL google("http://google.com/");
    592 
    593   AddPageToHistory(news);
    594   AddPageToHistory(google);
    595 
    596   StartQueryForMostVisited();
    597   WaitForHistory();
    598 
    599   TopSitesQuerier querier;
    600   querier.QueryTopSites(top_sites(), false);
    601 
    602   ASSERT_EQ(1, querier.number_of_callbacks());
    603 
    604   // 2 extra prepopulated URLs.
    605   ASSERT_EQ(2u + GetPrepopulatePages().size(), querier.urls().size());
    606   EXPECT_EQ(news, querier.urls()[0].url);
    607   EXPECT_EQ(google, querier.urls()[1].url);
    608   ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 2));
    609 }
    610 
    611 // Makes sure changes done to top sites get mirrored to the db.
    612 TEST_F(TopSitesTest, SaveToDB) {
    613   MostVisitedURL url;
    614   GURL asdf_url("http://asdf.com");
    615   string16 asdf_title(ASCIIToUTF16("ASDF"));
    616   GURL google_url("http://google.com");
    617   string16 google_title(ASCIIToUTF16("Google"));
    618   GURL news_url("http://news.google.com");
    619   string16 news_title(ASCIIToUTF16("Google News"));
    620 
    621   // Add asdf_url to history.
    622   AddPageToHistory(asdf_url, asdf_title);
    623 
    624   // Make TopSites reread from the db.
    625   StartQueryForMostVisited();
    626   WaitForHistory();
    627 
    628   // Add a thumbnail.
    629   SkBitmap tmp_bitmap(CreateBitmap(SK_ColorBLUE));
    630   ASSERT_TRUE(top_sites()->SetPageThumbnail(asdf_url, tmp_bitmap,
    631                                             ThumbnailScore()));
    632 
    633   RecreateTopSitesAndBlock();
    634 
    635   {
    636     TopSitesQuerier querier;
    637     querier.QueryTopSites(top_sites(), false);
    638     ASSERT_EQ(1u + GetPrepopulatePages().size(), querier.urls().size());
    639     EXPECT_EQ(asdf_url, querier.urls()[0].url);
    640     EXPECT_EQ(asdf_title, querier.urls()[0].title);
    641     ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 1));
    642 
    643     scoped_refptr<RefCountedBytes> read_data;
    644     EXPECT_TRUE(top_sites()->GetPageThumbnail(asdf_url, &read_data));
    645     EXPECT_TRUE(ThumbnailEqualsBytes(tmp_bitmap, read_data.get()));
    646   }
    647 
    648   MostVisitedURL url2;
    649   url2.url = google_url;
    650   url2.title = google_title;
    651   url2.redirects.push_back(url2.url);
    652 
    653   AddPageToHistory(url2.url, url2.title);
    654 
    655   // Add new thumbnail at rank 0 and shift the other result to 1.
    656   ASSERT_TRUE(top_sites()->SetPageThumbnail(google_url,
    657                                             tmp_bitmap,
    658                                             ThumbnailScore()));
    659 
    660   // Make TopSites reread from the db.
    661   RefreshTopSitesAndRecreate();
    662 
    663   {
    664     TopSitesQuerier querier;
    665     querier.QueryTopSites(top_sites(), false);
    666     ASSERT_EQ(2u + GetPrepopulatePages().size(), querier.urls().size());
    667     EXPECT_EQ(asdf_url, querier.urls()[0].url);
    668     EXPECT_EQ(asdf_title, querier.urls()[0].title);
    669     EXPECT_EQ(google_url, querier.urls()[1].url);
    670     EXPECT_EQ(google_title, querier.urls()[1].title);
    671     ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 2));
    672   }
    673 }
    674 
    675 // More permutations of saving to db.
    676 TEST_F(TopSitesTest, RealDatabase) {
    677   MostVisitedURL url;
    678   GURL asdf_url("http://asdf.com");
    679   string16 asdf_title(ASCIIToUTF16("ASDF"));
    680   GURL google1_url("http://google.com");
    681   GURL google2_url("http://google.com/redirect");
    682   GURL google3_url("http://www.google.com");
    683   string16 google_title(ASCIIToUTF16("Google"));
    684   GURL news_url("http://news.google.com");
    685   string16 news_title(ASCIIToUTF16("Google News"));
    686 
    687   url.url = asdf_url;
    688   url.title = asdf_title;
    689   url.redirects.push_back(url.url);
    690   SkBitmap asdf_thumbnail(CreateBitmap(SK_ColorRED));
    691   ASSERT_TRUE(top_sites()->SetPageThumbnail(
    692                   asdf_url, asdf_thumbnail, ThumbnailScore()));
    693 
    694   base::Time add_time(base::Time::Now());
    695   AddPageToHistory(url.url, url.title, url.redirects, add_time);
    696 
    697   RefreshTopSitesAndRecreate();
    698 
    699   {
    700     TopSitesQuerier querier;
    701     querier.QueryTopSites(top_sites(), false);
    702 
    703     ASSERT_EQ(1u + GetPrepopulatePages().size(), querier.urls().size());
    704     EXPECT_EQ(asdf_url, querier.urls()[0].url);
    705     EXPECT_EQ(asdf_title, querier.urls()[0].title);
    706     ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 1));
    707 
    708     scoped_refptr<RefCountedBytes> read_data;
    709     EXPECT_TRUE(top_sites()->GetPageThumbnail(asdf_url, &read_data));
    710     EXPECT_TRUE(ThumbnailEqualsBytes(asdf_thumbnail, read_data.get()));
    711   }
    712 
    713   MostVisitedURL url2;
    714   url2.url = google3_url;
    715   url2.title = google_title;
    716   url2.redirects.push_back(google1_url);
    717   url2.redirects.push_back(google2_url);
    718   url2.redirects.push_back(google3_url);
    719 
    720   AddPageToHistory(google3_url, url2.title, url2.redirects,
    721                    add_time - base::TimeDelta::FromMinutes(1));
    722   // Add google twice so that it becomes the first visited site.
    723   AddPageToHistory(google3_url, url2.title, url2.redirects,
    724                    add_time - base::TimeDelta::FromMinutes(2));
    725 
    726   SkBitmap google_thumbnail(CreateBitmap(SK_ColorBLUE));
    727   ASSERT_TRUE(top_sites()->SetPageThumbnail(
    728                   url2.url, google_thumbnail, ThumbnailScore()));
    729 
    730   RefreshTopSitesAndRecreate();
    731 
    732   {
    733     scoped_refptr<RefCountedBytes> read_data;
    734     TopSitesQuerier querier;
    735     querier.QueryTopSites(top_sites(), false);
    736 
    737     ASSERT_EQ(2u + GetPrepopulatePages().size(), querier.urls().size());
    738     EXPECT_EQ(google1_url, querier.urls()[0].url);
    739     EXPECT_EQ(google_title, querier.urls()[0].title);
    740     ASSERT_EQ(3u, querier.urls()[0].redirects.size());
    741     EXPECT_TRUE(top_sites()->GetPageThumbnail(google3_url, &read_data));
    742     EXPECT_TRUE(ThumbnailEqualsBytes(google_thumbnail, read_data.get()));
    743 
    744     EXPECT_EQ(asdf_url, querier.urls()[1].url);
    745     EXPECT_EQ(asdf_title, querier.urls()[1].title);
    746     ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 2));
    747   }
    748 
    749   SkBitmap weewar_bitmap(CreateBitmap(SK_ColorYELLOW));
    750 
    751   base::Time thumbnail_time(base::Time::Now());
    752   ThumbnailScore low_score(1.0, true, true, thumbnail_time);
    753   ThumbnailScore medium_score(0.5, true, true, thumbnail_time);
    754   ThumbnailScore high_score(0.0, true, true, thumbnail_time);
    755 
    756   // 1. Set to weewar. (Writes the thumbnail to the DB.)
    757   EXPECT_TRUE(top_sites()->SetPageThumbnail(google3_url,
    758                                             weewar_bitmap,
    759                                             medium_score));
    760   RefreshTopSitesAndRecreate();
    761   {
    762     scoped_refptr<RefCountedBytes> read_data;
    763     EXPECT_TRUE(top_sites()->GetPageThumbnail(google3_url, &read_data));
    764     EXPECT_TRUE(ThumbnailEqualsBytes(weewar_bitmap, read_data.get()));
    765   }
    766 
    767   SkBitmap google_bitmap(CreateBitmap(SK_ColorGREEN));
    768 
    769   // 2. Set to google - low score.
    770   EXPECT_FALSE(top_sites()->SetPageThumbnail(google3_url,
    771                                              google_bitmap,
    772                                              low_score));
    773 
    774   // 3. Set to google - high score.
    775   EXPECT_TRUE(top_sites()->SetPageThumbnail(google1_url,
    776                                             google_bitmap,
    777                                             high_score));
    778 
    779   // Check that the thumbnail was updated.
    780   RefreshTopSitesAndRecreate();
    781   {
    782     scoped_refptr<RefCountedBytes> read_data;
    783     EXPECT_TRUE(top_sites()->GetPageThumbnail(google3_url, &read_data));
    784     EXPECT_FALSE(ThumbnailEqualsBytes(weewar_bitmap, read_data.get()));
    785     EXPECT_TRUE(ThumbnailEqualsBytes(google_bitmap, read_data.get()));
    786   }
    787 }
    788 
    789 TEST_F(TopSitesTest, DeleteNotifications) {
    790   GURL google1_url("http://google.com");
    791   GURL google2_url("http://google.com/redirect");
    792   GURL google3_url("http://www.google.com");
    793   string16 google_title(ASCIIToUTF16("Google"));
    794   GURL news_url("http://news.google.com");
    795   string16 news_title(ASCIIToUTF16("Google News"));
    796 
    797   AddPageToHistory(google1_url, google_title);
    798   AddPageToHistory(news_url, news_title);
    799 
    800   RefreshTopSitesAndRecreate();
    801 
    802   {
    803     TopSitesQuerier querier;
    804     querier.QueryTopSites(top_sites(), false);
    805 
    806     ASSERT_EQ(4u, querier.urls().size());
    807   }
    808 
    809   DeleteURL(news_url);
    810 
    811   // Wait for history to process the deletion.
    812   WaitForHistory();
    813 
    814   {
    815     TopSitesQuerier querier;
    816     querier.QueryTopSites(top_sites(), false);
    817 
    818     ASSERT_EQ(1u + GetPrepopulatePages().size(), querier.urls().size());
    819     EXPECT_EQ(google_title, querier.urls()[0].title);
    820     ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 1));
    821   }
    822 
    823   // Now reload. This verifies topsites actually wrote the deletion to disk.
    824   RefreshTopSitesAndRecreate();
    825 
    826   {
    827     TopSitesQuerier querier;
    828     querier.QueryTopSites(top_sites(), false);
    829 
    830     ASSERT_EQ(1u + GetPrepopulatePages().size(), querier.urls().size());
    831     EXPECT_EQ(google_title, querier.urls()[0].title);
    832     ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 1));
    833   }
    834 
    835   DeleteURL(google1_url);
    836 
    837   // Wait for history to process the deletion.
    838   WaitForHistory();
    839 
    840   {
    841     TopSitesQuerier querier;
    842     querier.QueryTopSites(top_sites(), false);
    843 
    844     ASSERT_EQ(GetPrepopulatePages().size(), querier.urls().size());
    845     ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 0));
    846   }
    847 
    848   // Now reload. This verifies topsites actually wrote the deletion to disk.
    849   RefreshTopSitesAndRecreate();
    850 
    851   {
    852     TopSitesQuerier querier;
    853     querier.QueryTopSites(top_sites(), false);
    854 
    855     ASSERT_EQ(GetPrepopulatePages().size(), querier.urls().size());
    856     ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 0));
    857   }
    858 }
    859 
    860 TEST_F(TopSitesTest, PinnedURLsDeleted) {
    861   GURL google1_url("http://google.com");
    862   GURL google2_url("http://google.com/redirect");
    863   GURL google3_url("http://www.google.com");
    864   string16 google_title(ASCIIToUTF16("Google"));
    865   GURL news_url("http://news.google.com");
    866   string16 news_title(ASCIIToUTF16("Google News"));
    867 
    868   AddPageToHistory(google1_url, google_title);
    869   AddPageToHistory(news_url, news_title);
    870 
    871   RefreshTopSitesAndRecreate();
    872 
    873   {
    874     TopSitesQuerier querier;
    875     querier.QueryTopSites(top_sites(), false);
    876 
    877     // 2 extra prepopulated URLs.
    878     ASSERT_EQ(4u, querier.urls().size());
    879   }
    880 
    881   top_sites()->AddPinnedURL(news_url, 3);
    882   EXPECT_TRUE(top_sites()->IsURLPinned(news_url));
    883 
    884   DeleteURL(news_url);
    885   WaitForHistory();
    886 
    887   {
    888     TopSitesQuerier querier;
    889     querier.QueryTopSites(top_sites(), false);
    890 
    891     // 2 extra prepopulated URLs.
    892     ASSERT_EQ(3u, querier.urls().size());
    893     EXPECT_FALSE(top_sites()->IsURLPinned(news_url));
    894   }
    895 
    896   history_service()->ExpireHistoryBetween(
    897       std::set<GURL>(), base::Time(), base::Time(),
    898       consumer(), NewCallback(static_cast<TopSitesTest*>(this),
    899                               &TopSitesTest::EmptyCallback)),
    900   WaitForHistory();
    901 
    902   {
    903     TopSitesQuerier querier;
    904     querier.QueryTopSites(top_sites(), false);
    905 
    906     // 2 extra prepopulated URLs.
    907     ASSERT_EQ(GetPrepopulatePages().size(), querier.urls().size());
    908     EXPECT_FALSE(top_sites()->IsURLPinned(google1_url));
    909     ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 0));
    910   }
    911 }
    912 
    913 // Makes sure GetUpdateDelay is updated appropriately.
    914 TEST_F(TopSitesTest, GetUpdateDelay) {
    915   SetLastNumUrlsChanged(0);
    916   EXPECT_EQ(30, GetUpdateDelay().InSeconds());
    917 
    918   MostVisitedURLList url_list;
    919   url_list.resize(20);
    920   GURL tmp_url(GURL("http://x"));
    921   for (size_t i = 0; i < url_list.size(); ++i) {
    922     url_list[i].url = tmp_url;
    923     url_list[i].redirects.push_back(tmp_url);
    924   }
    925   SetTopSites(url_list);
    926   EXPECT_EQ(20u, last_num_urls_changed());
    927   SetLastNumUrlsChanged(0);
    928   EXPECT_EQ(60, GetUpdateDelay().InMinutes());
    929 
    930   SetLastNumUrlsChanged(3);
    931   EXPECT_EQ(52, GetUpdateDelay().InMinutes());
    932 
    933   SetLastNumUrlsChanged(20);
    934   EXPECT_EQ(1, GetUpdateDelay().InMinutes());
    935 }
    936 
    937 TEST_F(TopSitesMigrationTest, Migrate) {
    938   EXPECT_TRUE(IsTopSitesLoaded());
    939 
    940   // Make sure the data was migrated to top sites.
    941   ASSERT_NO_FATAL_FAILURE(MigrationAssertions());
    942 
    943   // We need to wait for top sites and history to finish processing requests.
    944   WaitForTopSites();
    945   WaitForHistory();
    946 
    947   // Make sure there is no longer a Thumbnails file on disk.
    948   ASSERT_FALSE(file_util::PathExists(
    949                    profile()->GetPath().Append(chrome::kThumbnailsFilename)));
    950 
    951   // Recreate top sites and make sure everything is still there.
    952   profile()->CreateHistoryService(false, false);
    953   RecreateTopSitesAndBlock();
    954 
    955   ASSERT_NO_FATAL_FAILURE(MigrationAssertions());
    956 }
    957 
    958 // Verifies that callbacks are notified correctly if requested before top sites
    959 // has loaded.
    960 TEST_F(TopSitesTest, NotifyCallbacksWhenLoaded) {
    961   // Recreate top sites. It won't be loaded now.
    962   profile()->CreateTopSites();
    963 
    964   EXPECT_FALSE(IsTopSitesLoaded());
    965 
    966   TopSitesQuerier querier1;
    967   TopSitesQuerier querier2;
    968   TopSitesQuerier querier3;
    969 
    970   // Starts the queries.
    971   querier1.QueryTopSites(top_sites(), false);
    972   querier2.QueryTopSites(top_sites(), false);
    973   querier3.QueryTopSites(top_sites(), false);
    974 
    975   // We shouldn't have gotten a callback.
    976   EXPECT_EQ(0, querier1.number_of_callbacks());
    977   EXPECT_EQ(0, querier2.number_of_callbacks());
    978   EXPECT_EQ(0, querier3.number_of_callbacks());
    979 
    980   // Wait for loading to complete.
    981   profile()->BlockUntilTopSitesLoaded();
    982 
    983   // Now we should have gotten the callbacks.
    984   EXPECT_EQ(1, querier1.number_of_callbacks());
    985   EXPECT_EQ(GetPrepopulatePages().size(), querier1.urls().size());
    986   EXPECT_EQ(1, querier2.number_of_callbacks());
    987   EXPECT_EQ(GetPrepopulatePages().size(), querier2.urls().size());
    988   EXPECT_EQ(1, querier3.number_of_callbacks());
    989   EXPECT_EQ(GetPrepopulatePages().size(), querier3.urls().size());
    990 
    991   // Reset the top sites.
    992   MostVisitedURLList pages;
    993   MostVisitedURL url;
    994   url.url = GURL("http://1.com/");
    995   url.redirects.push_back(url.url);
    996   pages.push_back(url);
    997   url.url = GURL("http://2.com/");
    998   url.redirects.push_back(url.url);
    999   pages.push_back(url);
   1000   SetTopSites(pages);
   1001 
   1002   // Recreate top sites. It won't be loaded now.
   1003   profile()->CreateTopSites();
   1004 
   1005   EXPECT_FALSE(IsTopSitesLoaded());
   1006 
   1007   TopSitesQuerier querier4;
   1008 
   1009   // Query again.
   1010   querier4.QueryTopSites(top_sites(), false);
   1011 
   1012   // We shouldn't have gotten a callback.
   1013   EXPECT_EQ(0, querier4.number_of_callbacks());
   1014 
   1015   // Wait for loading to complete.
   1016   profile()->BlockUntilTopSitesLoaded();
   1017 
   1018   // Now we should have gotten the callbacks.
   1019   EXPECT_EQ(1, querier4.number_of_callbacks());
   1020   ASSERT_EQ(2u + GetPrepopulatePages().size(), querier4.urls().size());
   1021 
   1022   EXPECT_EQ("http://1.com/", querier4.urls()[0].url.spec());
   1023   EXPECT_EQ("http://2.com/", querier4.urls()[1].url.spec());
   1024   ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier4, 2));
   1025 
   1026   // Reset the top sites again, this time don't reload.
   1027   url.url = GURL("http://3.com/");
   1028   url.redirects.push_back(url.url);
   1029   pages.push_back(url);
   1030   SetTopSites(pages);
   1031 
   1032   // Query again.
   1033   TopSitesQuerier querier5;
   1034   querier5.QueryTopSites(top_sites(), true);
   1035 
   1036   EXPECT_EQ(1, querier5.number_of_callbacks());
   1037 
   1038   ASSERT_EQ(3u + GetPrepopulatePages().size(), querier5.urls().size());
   1039   EXPECT_EQ("http://1.com/", querier5.urls()[0].url.spec());
   1040   EXPECT_EQ("http://2.com/", querier5.urls()[1].url.spec());
   1041   EXPECT_EQ("http://3.com/", querier5.urls()[2].url.spec());
   1042   ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier5, 3));
   1043 }
   1044 
   1045 // Makes sure canceled requests are not notified.
   1046 TEST_F(TopSitesTest, CancelingRequestsForTopSites) {
   1047   // Recreate top sites. It won't be loaded now.
   1048   profile()->CreateTopSites();
   1049 
   1050   EXPECT_FALSE(IsTopSitesLoaded());
   1051 
   1052   TopSitesQuerier querier1;
   1053   TopSitesQuerier querier2;
   1054 
   1055   // Starts the queries.
   1056   querier1.QueryTopSites(top_sites(), false);
   1057   querier2.QueryTopSites(top_sites(), false);
   1058 
   1059   // We shouldn't have gotten a callback.
   1060   EXPECT_EQ(0, querier1.number_of_callbacks());
   1061   EXPECT_EQ(0, querier2.number_of_callbacks());
   1062 
   1063   querier2.CancelRequest();
   1064 
   1065   // Wait for loading to complete.
   1066   profile()->BlockUntilTopSitesLoaded();
   1067 
   1068   // The first callback should succeed.
   1069   EXPECT_EQ(1, querier1.number_of_callbacks());
   1070   EXPECT_EQ(GetPrepopulatePages().size(), querier1.urls().size());
   1071 
   1072   // And the canceled callback should not be notified.
   1073   EXPECT_EQ(0, querier2.number_of_callbacks());
   1074 }
   1075 
   1076 // Makes sure temporary thumbnails are copied over correctly.
   1077 TEST_F(TopSitesTest, AddTemporaryThumbnail) {
   1078   GURL unknown_url("http://news.google.com/");
   1079   GURL invalid_url("chrome://thumb/http://google.com/");
   1080   GURL url1a("http://google.com/");
   1081   GURL url1b("http://www.google.com/");
   1082 
   1083   // Create a dummy thumbnail.
   1084   SkBitmap thumbnail(CreateBitmap(SK_ColorRED));
   1085 
   1086   ThumbnailScore medium_score(0.5, true, true, base::Time::Now());
   1087 
   1088   // Don't store thumbnails for Javascript URLs.
   1089   EXPECT_FALSE(top_sites()->SetPageThumbnail(invalid_url,
   1090                                              thumbnail,
   1091                                              medium_score));
   1092   // Store thumbnails for unknown (but valid) URLs temporarily - calls
   1093   // AddTemporaryThumbnail.
   1094   EXPECT_TRUE(top_sites()->SetPageThumbnail(unknown_url,
   1095                                             thumbnail,
   1096                                             medium_score));
   1097 
   1098   // We shouldn't get the thumnail back though (the url isn't in to sites yet).
   1099   scoped_refptr<RefCountedBytes> out;
   1100   EXPECT_FALSE(top_sites()->GetPageThumbnail(unknown_url, &out));
   1101   // But we should be able to get the temporary page thumbnail score.
   1102   ThumbnailScore out_score;
   1103   EXPECT_TRUE(top_sites()->GetTemporaryPageThumbnailScore(unknown_url,
   1104                                                           &out_score));
   1105   EXPECT_TRUE(medium_score.Equals(out_score));
   1106 
   1107   std::vector<MostVisitedURL> list;
   1108 
   1109   MostVisitedURL mv;
   1110   mv.url = unknown_url;
   1111   mv.redirects.push_back(mv.url);
   1112   mv.redirects.push_back(url1a);
   1113   mv.redirects.push_back(url1b);
   1114   list.push_back(mv);
   1115 
   1116   // Update URLs. This should result in using thumbnail.
   1117   SetTopSites(list);
   1118 
   1119   ASSERT_TRUE(top_sites()->GetPageThumbnail(unknown_url, &out));
   1120   EXPECT_TRUE(ThumbnailEqualsBytes(thumbnail, out.get()));
   1121 }
   1122 
   1123 // Tests variations of blacklisting.
   1124 TEST_F(TopSitesTest, Blacklisting) {
   1125   MostVisitedURLList pages;
   1126   MostVisitedURL url, url1;
   1127   url.url = GURL("http://bbc.com/");
   1128   url.redirects.push_back(url.url);
   1129   pages.push_back(url);
   1130   url1.url = GURL("http://google.com/");
   1131   url1.redirects.push_back(url1.url);
   1132   pages.push_back(url1);
   1133 
   1134   SetTopSites(pages);
   1135   EXPECT_FALSE(top_sites()->IsBlacklisted(GURL("http://bbc.com/")));
   1136 
   1137   // Blacklist google.com.
   1138   top_sites()->AddBlacklistedURL(GURL("http://google.com/"));
   1139 
   1140   GURL prepopulate_url = GetPrepopulatePages()[0].url;
   1141 
   1142   EXPECT_TRUE(top_sites()->HasBlacklistedItems());
   1143   EXPECT_TRUE(top_sites()->IsBlacklisted(GURL("http://google.com/")));
   1144   EXPECT_FALSE(top_sites()->IsBlacklisted(GURL("http://bbc.com/")));
   1145   EXPECT_FALSE(top_sites()->IsBlacklisted(prepopulate_url));
   1146 
   1147   // Make sure the blacklisted site isn't returned in the results.
   1148   {
   1149     TopSitesQuerier q;
   1150     q.QueryTopSites(top_sites(), true);
   1151     ASSERT_EQ(1u + GetPrepopulatePages().size(), q.urls().size());
   1152     EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
   1153     ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 1));
   1154   }
   1155 
   1156   // Recreate top sites and make sure blacklisted url was correctly read.
   1157   RecreateTopSitesAndBlock();
   1158   {
   1159     TopSitesQuerier q;
   1160     q.QueryTopSites(top_sites(), true);
   1161     ASSERT_EQ(1u + GetPrepopulatePages().size(), q.urls().size());
   1162     EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
   1163     ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 1));
   1164   }
   1165 
   1166   // Blacklist one of the prepopulate urls.
   1167   top_sites()->AddBlacklistedURL(prepopulate_url);
   1168   EXPECT_TRUE(top_sites()->HasBlacklistedItems());
   1169 
   1170   // Make sure the blacklisted prepopulate url isn't returned.
   1171   {
   1172     TopSitesQuerier q;
   1173     q.QueryTopSites(top_sites(), true);
   1174     ASSERT_EQ(1u + GetPrepopulatePages().size() - 1, q.urls().size());
   1175     EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
   1176     for (size_t i = 1; i < q.urls().size(); ++i)
   1177       EXPECT_NE(prepopulate_url.spec(), q.urls()[i].url.spec());
   1178   }
   1179 
   1180   // Mark google as no longer blacklisted.
   1181   top_sites()->RemoveBlacklistedURL(GURL("http://google.com/"));
   1182   EXPECT_TRUE(top_sites()->HasBlacklistedItems());
   1183   EXPECT_FALSE(top_sites()->IsBlacklisted(GURL("http://google.com/")));
   1184 
   1185   // Make sure google is returned now.
   1186   {
   1187     TopSitesQuerier q;
   1188     q.QueryTopSites(top_sites(), true);
   1189     ASSERT_EQ(2u + GetPrepopulatePages().size() - 1, q.urls().size());
   1190     EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
   1191     EXPECT_EQ("http://google.com/", q.urls()[1].url.spec());
   1192     EXPECT_NE(prepopulate_url.spec(), q.urls()[2].url.spec());
   1193   }
   1194 
   1195   // Remove all blacklisted sites.
   1196   top_sites()->ClearBlacklistedURLs();
   1197   EXPECT_FALSE(top_sites()->HasBlacklistedItems());
   1198 
   1199   {
   1200     TopSitesQuerier q;
   1201     q.QueryTopSites(top_sites(), true);
   1202     ASSERT_EQ(2u + GetPrepopulatePages().size(), q.urls().size());
   1203     EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
   1204     EXPECT_EQ("http://google.com/", q.urls()[1].url.spec());
   1205     ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 2));
   1206   }
   1207 }
   1208 
   1209 // Tests variations of pinning/unpinning urls.
   1210 TEST_F(TopSitesTest, PinnedURLs) {
   1211   MostVisitedURLList pages;
   1212   MostVisitedURL url, url1;
   1213   url.url = GURL("http://bbc.com/");
   1214   url.redirects.push_back(url.url);
   1215   pages.push_back(url);
   1216   url1.url = GURL("http://google.com/");
   1217   url1.redirects.push_back(url1.url);
   1218   pages.push_back(url1);
   1219 
   1220   SetTopSites(pages);
   1221 
   1222   EXPECT_FALSE(top_sites()->IsURLPinned(GURL("http://bbc.com/")));
   1223 
   1224   {
   1225     TopSitesQuerier q;
   1226     q.QueryTopSites(top_sites(), true);
   1227     ASSERT_EQ(2u + GetPrepopulatePages().size(), q.urls().size());
   1228     EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
   1229     EXPECT_EQ("http://google.com/", q.urls()[1].url.spec());
   1230     ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 2));
   1231   }
   1232 
   1233   top_sites()->AddPinnedURL(GURL("http://google.com/"), 3);
   1234   EXPECT_FALSE(top_sites()->IsURLPinned(GURL("http://bbc.com/")));
   1235   EXPECT_FALSE(top_sites()->IsURLPinned(GetPrepopulatePages()[0].url));
   1236 
   1237   {
   1238     TopSitesQuerier q;
   1239     q.QueryTopSites(top_sites(), true);
   1240     ASSERT_EQ(4u, q.urls().size());
   1241     EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
   1242     ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 1));
   1243     EXPECT_EQ("http://google.com/", q.urls()[3].url.spec());
   1244   }
   1245 
   1246   top_sites()->RemovePinnedURL(GURL("http://google.com/"));
   1247   EXPECT_FALSE(top_sites()->IsURLPinned(GURL("http://google.com/")));
   1248   {
   1249     TopSitesQuerier q;
   1250     q.QueryTopSites(top_sites(), true);
   1251 
   1252     ASSERT_EQ(2u + GetPrepopulatePages().size(), q.urls().size());
   1253     EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
   1254     EXPECT_EQ("http://google.com/", q.urls()[1].url.spec());
   1255     ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 2));
   1256   }
   1257 
   1258   GURL prepopulate_url = GetPrepopulatePages()[0].url;
   1259   top_sites()->AddPinnedURL(GURL("http://bbc.com"), 1);
   1260   top_sites()->AddPinnedURL(prepopulate_url, 0);
   1261   {
   1262     TopSitesQuerier q;
   1263     q.QueryTopSites(top_sites(), true);
   1264 
   1265     ASSERT_EQ(3u + GetPrepopulatePages().size() - 1, q.urls().size());
   1266     EXPECT_EQ(prepopulate_url, q.urls()[0].url);
   1267     EXPECT_EQ("http://bbc.com/", q.urls()[1].url.spec());
   1268     EXPECT_EQ("http://google.com/", q.urls()[2].url.spec());
   1269     if (GetPrepopulatePages().size() > 1)
   1270       EXPECT_EQ(GetPrepopulatePages()[1].url, q.urls()[3].url);
   1271   }
   1272 
   1273   // Recreate and make sure state remains the same.
   1274   RecreateTopSitesAndBlock();
   1275   {
   1276     TopSitesQuerier q;
   1277     q.QueryTopSites(top_sites(), true);
   1278 
   1279     ASSERT_EQ(3u + GetPrepopulatePages().size() - 1, q.urls().size());
   1280     EXPECT_EQ(prepopulate_url, q.urls()[0].url);
   1281     EXPECT_EQ("http://bbc.com/", q.urls()[1].url.spec());
   1282     EXPECT_EQ("http://google.com/", q.urls()[2].url.spec());
   1283     if (GetPrepopulatePages().size() > 1)
   1284       EXPECT_EQ(GetPrepopulatePages()[1].url, q.urls()[3].url);
   1285   }
   1286 }
   1287 
   1288 // Tests blacklisting and pinning.
   1289 TEST_F(TopSitesTest, BlacklistingAndPinnedURLs) {
   1290   MostVisitedURLList prepopulate_urls = GetPrepopulatePages();
   1291   if (prepopulate_urls.size() < 2)
   1292     return;
   1293 
   1294   top_sites()->AddPinnedURL(prepopulate_urls[0].url, 1);
   1295   top_sites()->AddBlacklistedURL(prepopulate_urls[1].url);
   1296 
   1297   {
   1298     TopSitesQuerier q;
   1299     q.QueryTopSites(top_sites(), true);
   1300 
   1301     ASSERT_LE(2u, q.urls().size());
   1302     EXPECT_EQ(GURL(), q.urls()[0].url);
   1303     EXPECT_EQ(prepopulate_urls[0].url, q.urls()[1].url);
   1304   }
   1305 }
   1306 
   1307 // Makes sure prepopulated pages exist.
   1308 TEST_F(TopSitesTest, AddPrepopulatedPages) {
   1309   TopSitesQuerier q;
   1310   q.QueryTopSites(top_sites(), true);
   1311   EXPECT_EQ(GetPrepopulatePages().size(), q.urls().size());
   1312   ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 0));
   1313 
   1314   MostVisitedURLList pages = q.urls();
   1315   EXPECT_FALSE(AddPrepopulatedPages(&pages));
   1316 
   1317   EXPECT_EQ(GetPrepopulatePages().size(), pages.size());
   1318   q.set_urls(pages);
   1319   ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 0));
   1320 }
   1321 
   1322 // Makes sure creating top sites before history is created works.
   1323 TEST_F(TopSitesTest, CreateTopSitesThenHistory) {
   1324   profile()->DestroyTopSites();
   1325   profile()->DestroyHistoryService();
   1326 
   1327   // Remove the TopSites file. This forces TopSites to wait until history loads
   1328   // before TopSites is considered loaded.
   1329   file_util::Delete(profile()->GetPath().Append(chrome::kTopSitesFilename),
   1330                     false);
   1331 
   1332   // Create TopSites, but not History.
   1333   profile()->CreateTopSites();
   1334   WaitForTopSites();
   1335   EXPECT_FALSE(IsTopSitesLoaded());
   1336 
   1337   // Load history, which should make TopSites finish loading too.
   1338   profile()->CreateHistoryService(false, false);
   1339   profile()->BlockUntilTopSitesLoaded();
   1340   EXPECT_TRUE(IsTopSitesLoaded());
   1341 }
   1342 
   1343 }  // namespace history
   1344