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