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
38namespace history {
39
40namespace {
41
42// Used by WaitForHistory, see it for details.
43class 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.
62class 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.
109SkBitmap 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.
116bool 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
128class 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
326class 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.
387static 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.
397static 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.
408TEST_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.
439TEST_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.
475TEST_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.
520TEST_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.
550TEST_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.
589TEST_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.
612TEST_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.
676TEST_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
789TEST_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
860TEST_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.
914TEST_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
937TEST_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.
960TEST_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.
1046TEST_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.
1077TEST_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.
1124TEST_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.
1210TEST_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.
1289TEST_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.
1308TEST_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.
1323TEST_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