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