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 "components/history/core/browser/top_sites_impl.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include "base/bind.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/macros.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/run_loop.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/task/cancelable_task_tracker.h"
17 #include "base/test/task_environment.h"
18 #include "build/build_config.h"
19 #include "components/history/core/browser/history_client.h"
20 #include "components/history/core/browser/history_constants.h"
21 #include "components/history/core/browser/history_database_params.h"
22 #include "components/history/core/browser/history_db_task.h"
23 #include "components/history/core/browser/history_service.h"
24 #include "components/history/core/browser/history_types.h"
25 #include "components/history/core/browser/top_sites.h"
26 #include "components/history/core/browser/top_sites_observer.h"
27 #include "components/history/core/browser/visit_delegate.h"
28 #include "components/history/core/test/history_service_test_util.h"
29 #include "components/history/core/test/history_unittest_base.h"
30 #include "components/history/core/test/test_history_database.h"
31 #include "components/history/core/test/wait_top_sites_loaded_observer.h"
32 #include "components/prefs/pref_registry_simple.h"
33 #include "components/prefs/testing_pref_service.h"
34 #include "testing/gmock/include/gmock/gmock.h"
35 #include "testing/gtest/include/gtest/gtest.h"
36 #include "url/gurl.h"
37
38 using testing::ContainerEq;
39
40 namespace history {
41
42 namespace {
43
44 const char kApplicationScheme[] = "application";
45 const char kPrepopulatedPageURL[] =
46 "http://www.google.com/int/chrome/welcome.html";
47
48 // Returns whether |url| can be added to history.
MockCanAddURLToHistory(const GURL & url)49 bool MockCanAddURLToHistory(const GURL& url) {
50 return url.is_valid() && !url.SchemeIs(kApplicationScheme);
51 }
52
53 // Used for querying top sites. Either runs sequentially, or runs a nested
54 // nested run loop until the response is complete. The later is used when
55 // TopSites is queried before it finishes loading.
56 class TopSitesQuerier {
57 public:
TopSitesQuerier()58 TopSitesQuerier() : number_of_callbacks_(0), waiting_(false) {}
59
60 // Queries top sites. If |wait| is true a nested run loop is run until the
61 // callback is notified.
QueryTopSites(TopSitesImpl * top_sites,bool wait)62 void QueryTopSites(TopSitesImpl* top_sites, bool wait) {
63 int start_number_of_callbacks = number_of_callbacks_;
64 base::RunLoop run_loop;
65 top_sites->GetMostVisitedURLs(
66 base::BindOnce(&TopSitesQuerier::OnTopSitesAvailable,
67 weak_ptr_factory_.GetWeakPtr(), &run_loop));
68 if (wait && start_number_of_callbacks == number_of_callbacks_) {
69 waiting_ = true;
70 run_loop.Run();
71 }
72 }
73
CancelRequest()74 void CancelRequest() { weak_ptr_factory_.InvalidateWeakPtrs(); }
75
set_urls(const MostVisitedURLList & urls)76 void set_urls(const MostVisitedURLList& urls) { urls_ = urls; }
urls() const77 const MostVisitedURLList& urls() const { return urls_; }
78
number_of_callbacks() const79 int number_of_callbacks() const { return number_of_callbacks_; }
80
81 private:
82 // Callback for TopSitesImpl::GetMostVisitedURLs.
OnTopSitesAvailable(base::RunLoop * run_loop,const history::MostVisitedURLList & data)83 void OnTopSitesAvailable(base::RunLoop* run_loop,
84 const history::MostVisitedURLList& data) {
85 urls_ = data;
86 number_of_callbacks_++;
87 if (waiting_) {
88 run_loop->QuitWhenIdle();
89 waiting_ = false;
90 }
91 }
92
93 MostVisitedURLList urls_;
94 int number_of_callbacks_;
95 bool waiting_;
96 base::WeakPtrFactory<TopSitesQuerier> weak_ptr_factory_{this};
97
98 DISALLOW_COPY_AND_ASSIGN(TopSitesQuerier);
99 };
100
101 } // namespace
102
103 class TopSitesImplTest : public HistoryUnitTestBase {
104 public:
TopSitesImplTest()105 TopSitesImplTest() {}
106
SetUp()107 void SetUp() override {
108 ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
109 pref_service_.reset(new TestingPrefServiceSimple);
110 TopSitesImpl::RegisterPrefs(pref_service_->registry());
111 history_service_.reset(
112 new HistoryService(nullptr, std::unique_ptr<VisitDelegate>()));
113 ASSERT_TRUE(history_service_->Init(
114 TestHistoryDatabaseParamsForPath(scoped_temp_dir_.GetPath())));
115 ResetTopSites();
116 WaitTopSitesLoaded();
117 }
118
TearDown()119 void TearDown() override {
120 DestroyTopSites();
121 history_service_->Shutdown();
122 history_service_.reset();
123 pref_service_.reset();
124 }
125
126 // Forces top sites to load top sites from history, then recreates top sites.
127 // Recreating top sites makes sure the changes from history are saved and
128 // loaded from the db.
RefreshTopSitesAndRecreate()129 void RefreshTopSitesAndRecreate() {
130 StartQueryForMostVisited();
131 WaitForHistory();
132 RecreateTopSitesAndBlock();
133 }
134
135 // Blocks the caller until history processes a task. This is useful if you
136 // need to wait until you know history has processed a task.
WaitForHistory()137 void WaitForHistory() {
138 BlockUntilHistoryProcessesPendingRequests(history_service());
139 }
140
top_sites()141 TopSitesImpl* top_sites() { return top_sites_impl_.get(); }
142
history_service()143 HistoryService* history_service() { return history_service_.get(); }
144
GetPrepopulatedPages()145 PrepopulatedPageList GetPrepopulatedPages() {
146 return top_sites()->GetPrepopulatedPages();
147 }
148
149 // Returns true if the TopSitesQuerier contains the prepopulate data starting
150 // at |start_index|.
ContainsPrepopulatePages(const TopSitesQuerier & querier,size_t start_index)151 void ContainsPrepopulatePages(const TopSitesQuerier& querier,
152 size_t start_index) {
153 PrepopulatedPageList prepopulate_pages = GetPrepopulatedPages();
154 ASSERT_LE(start_index + prepopulate_pages.size(), querier.urls().size());
155 for (size_t i = 0; i < prepopulate_pages.size(); ++i) {
156 EXPECT_EQ(prepopulate_pages[i].most_visited.url.spec(),
157 querier.urls()[start_index + i].url.spec())
158 << " @ index " << i;
159 }
160 }
161
162 // Adds a page to history.
AddPageToHistory(const GURL & url,const base::string16 & title=base::string16 (),base::Time time=base::Time::Now (),RedirectList redirects=RedirectList ())163 void AddPageToHistory(const GURL& url,
164 const base::string16& title = base::string16(),
165 base::Time time = base::Time::Now(),
166 RedirectList redirects = RedirectList()) {
167 if (redirects.empty())
168 redirects.emplace_back(url);
169 history_service()->AddPage(url, time, reinterpret_cast<ContextID>(1), 0,
170 GURL(), redirects, ui::PAGE_TRANSITION_TYPED,
171 history::SOURCE_BROWSED, false, false);
172 if (!title.empty())
173 history_service()->SetPageTitle(url, title);
174 }
175
176 // Delets a url.
DeleteURL(const GURL & url)177 void DeleteURL(const GURL& url) { history_service()->DeleteURLs({url}); }
178
179 // Recreates top sites. This forces top sites to reread from the db.
RecreateTopSitesAndBlock()180 void RecreateTopSitesAndBlock() {
181 // Recreate TopSites and wait for it to load.
182 ResetTopSites();
183 WaitTopSitesLoaded();
184 }
185
186 // Wrappers that allow private TopSites functions to be called from the
187 // individual tests without making them all be friends.
SetTopSites(const MostVisitedURLList & new_top_sites)188 void SetTopSites(const MostVisitedURLList& new_top_sites) {
189 top_sites()->SetTopSites(MostVisitedURLList(new_top_sites),
190 TopSitesImpl::CALL_LOCATION_FROM_OTHER_PLACES);
191 }
192
StartQueryForMostVisited()193 void StartQueryForMostVisited() { top_sites()->StartQueryForMostVisited(); }
194
IsTopSitesLoaded()195 bool IsTopSitesLoaded() { return top_sites()->loaded_; }
196
AddPrepopulatedPages(MostVisitedURLList * urls)197 bool AddPrepopulatedPages(MostVisitedURLList* urls) {
198 return top_sites()->AddPrepopulatedPages(urls);
199 }
200
EmptyThreadSafeCache()201 void EmptyThreadSafeCache() {
202 base::AutoLock lock(top_sites()->lock_);
203 top_sites()->thread_safe_cache_.clear();
204 }
205
ResetTopSites()206 void ResetTopSites() {
207 // TopSites shutdown takes some time as it happens on the DB thread and does
208 // not support the existence of two TopSitesImpl for a location (due to
209 // database locking). DestroyTopSites() waits for the TopSites cleanup to
210 // complete before returning.
211 DestroyTopSites();
212 DCHECK(!top_sites_impl_);
213 PrepopulatedPageList prepopulated_pages;
214 prepopulated_pages.push_back(
215 PrepopulatedPage(GURL(kPrepopulatedPageURL), base::string16(), -1, 0));
216 top_sites_impl_ = new TopSitesImpl(
217 pref_service_.get(), history_service_.get(), prepopulated_pages,
218 base::BindRepeating(MockCanAddURLToHistory));
219 top_sites_impl_->Init(scoped_temp_dir_.GetPath().Append(kTopSitesFilename));
220 }
221
DestroyTopSites()222 void DestroyTopSites() {
223 if (top_sites_impl_) {
224 top_sites_impl_->ShutdownOnUIThread();
225 top_sites_impl_ = nullptr;
226
227 task_environment_.RunUntilIdle();
228 }
229 }
230
WaitTopSitesLoaded()231 void WaitTopSitesLoaded() {
232 DCHECK(top_sites_impl_);
233 WaitTopSitesLoadedObserver wait_top_sites_loaded_observer(top_sites_impl_);
234 wait_top_sites_loaded_observer.Run();
235 }
236
237 private:
238 base::test::TaskEnvironment task_environment_;
239
240 base::ScopedTempDir scoped_temp_dir_;
241
242 std::unique_ptr<TestingPrefServiceSimple> pref_service_;
243 std::unique_ptr<HistoryService> history_service_;
244 scoped_refptr<TopSitesImpl> top_sites_impl_;
245
246 // To cancel HistoryService tasks.
247 base::CancelableTaskTracker history_tracker_;
248
249 // To cancel TopSitesBackend tasks.
250 base::CancelableTaskTracker top_sites_tracker_;
251
252 DISALLOW_COPY_AND_ASSIGN(TopSitesImplTest);
253 }; // Class TopSitesImplTest
254
255 class MockTopSitesObserver : public TopSitesObserver {
256 public:
MockTopSitesObserver()257 MockTopSitesObserver() {}
258
259 // history::TopSitesObserver:
TopSitesLoaded(TopSites * top_sites)260 void TopSitesLoaded(TopSites* top_sites) override {}
TopSitesChanged(TopSites * top_sites,ChangeReason change_reason)261 void TopSitesChanged(TopSites* top_sites,
262 ChangeReason change_reason) override {
263 is_notified_ = true;
264 }
265
ResetIsNotifiedState()266 void ResetIsNotifiedState() { is_notified_ = false; }
is_notified() const267 bool is_notified() const { return is_notified_; }
268
269 private:
270 bool is_notified_ = false;
271
272 DISALLOW_COPY_AND_ASSIGN(MockTopSitesObserver);
273 };
274
275 // Tests DoTitlesDiffer.
TEST_F(TopSitesImplTest,DoTitlesDiffer)276 TEST_F(TopSitesImplTest, DoTitlesDiffer) {
277 GURL url_1("http://url1/");
278 GURL url_2("http://url2/");
279 base::string16 title_1(base::ASCIIToUTF16("title1"));
280 base::string16 title_2(base::ASCIIToUTF16("title2"));
281
282 MockTopSitesObserver observer;
283 top_sites()->AddObserver(&observer);
284
285 // TopSites has a new list of sites and should notify its observers.
286 std::vector<MostVisitedURL> list_1;
287 list_1.emplace_back(url_1, title_1);
288 SetTopSites(list_1);
289 EXPECT_TRUE(observer.is_notified());
290 observer.ResetIsNotifiedState();
291 EXPECT_FALSE(observer.is_notified());
292
293 // list_1 and list_2 have different sizes. TopSites should notify its
294 // observers.
295 std::vector<MostVisitedURL> list_2;
296 list_2.emplace_back(url_1, title_1);
297 list_2.emplace_back(url_2, title_2);
298 SetTopSites(list_2);
299 EXPECT_TRUE(observer.is_notified());
300 observer.ResetIsNotifiedState();
301 EXPECT_FALSE(observer.is_notified());
302
303 // list_1 and list_2 are exactly the same now. TopSites should not notify its
304 // observers.
305 list_1.emplace_back(url_2, title_2);
306 SetTopSites(list_1);
307 EXPECT_FALSE(observer.is_notified());
308
309 // Change |url_2|'s title to |title_1| in list_2. The two lists are different
310 // in titles now. TopSites should notify its observers.
311 list_2.pop_back();
312 list_2.emplace_back(url_2, title_1);
313 SetTopSites(list_2);
314 EXPECT_TRUE(observer.is_notified());
315
316 top_sites()->RemoveObserver(&observer);
317 }
318
319 // Tests DiffMostVisited.
TEST_F(TopSitesImplTest,DiffMostVisited)320 TEST_F(TopSitesImplTest, DiffMostVisited) {
321 GURL stays_the_same("http://staysthesame/");
322 GURL gets_added_1("http://getsadded1/");
323 GURL gets_added_2("http://getsadded2/");
324 GURL gets_deleted_1("http://getsdeleted1/");
325 GURL gets_moved_1("http://getsmoved1/");
326
327 std::vector<MostVisitedURL> old_list;
328 old_list.emplace_back(stays_the_same, base::string16()); // 0 (unchanged)
329 old_list.emplace_back(gets_deleted_1, base::string16()); // 1 (deleted)
330 old_list.emplace_back(gets_moved_1, base::string16()); // 2 (moved to 3)
331
332 std::vector<MostVisitedURL> new_list;
333 new_list.emplace_back(stays_the_same, base::string16()); // 0 (unchanged)
334 new_list.emplace_back(gets_added_1, base::string16()); // 1 (added)
335 new_list.emplace_back(gets_added_2, base::string16()); // 2 (added)
336 new_list.emplace_back(gets_moved_1, base::string16()); // 3 (moved from 2)
337
338 history::TopSitesDelta delta;
339 TopSitesImpl::DiffMostVisited(old_list, new_list, &delta);
340
341 ASSERT_EQ(2u, delta.added.size());
342 EXPECT_TRUE(gets_added_1 == delta.added[0].url.url);
343 EXPECT_EQ(1, delta.added[0].rank);
344 EXPECT_TRUE(gets_added_2 == delta.added[1].url.url);
345 EXPECT_EQ(2, delta.added[1].rank);
346
347 ASSERT_EQ(1u, delta.deleted.size());
348 EXPECT_TRUE(gets_deleted_1 == delta.deleted[0].url);
349
350 ASSERT_EQ(1u, delta.moved.size());
351 EXPECT_TRUE(gets_moved_1 == delta.moved[0].url.url);
352 EXPECT_EQ(3, delta.moved[0].rank);
353 }
354
355 // Tests GetMostVisitedURLs.
TEST_F(TopSitesImplTest,GetMostVisited)356 TEST_F(TopSitesImplTest, GetMostVisited) {
357 GURL news("http://news.google.com/");
358 GURL google("http://google.com/");
359
360 AddPageToHistory(news);
361 AddPageToHistory(google);
362
363 StartQueryForMostVisited();
364 WaitForHistory();
365
366 TopSitesQuerier querier;
367 querier.QueryTopSites(top_sites(), false);
368
369 ASSERT_EQ(1, querier.number_of_callbacks());
370
371 // 2 extra prepopulated URLs.
372 ASSERT_EQ(2u + GetPrepopulatedPages().size(), querier.urls().size());
373 EXPECT_EQ(news, querier.urls()[0].url);
374 EXPECT_EQ(google, querier.urls()[1].url);
375 ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 2));
376 }
377
378 // Tests GetMostVisitedURLs with a redirect.
TEST_F(TopSitesImplTest,GetMostVisitedWithRedirect)379 TEST_F(TopSitesImplTest, GetMostVisitedWithRedirect) {
380 GURL bare("http://cnn.com/");
381 GURL www("https://www.cnn.com/");
382 GURL edition("https://edition.cnn.com/");
383
384 AddPageToHistory(edition, base::ASCIIToUTF16("CNN"), base::Time::Now(),
385 history::RedirectList{bare, www, edition});
386 AddPageToHistory(edition);
387
388 StartQueryForMostVisited();
389 WaitForHistory();
390
391 TopSitesQuerier querier;
392 querier.QueryTopSites(top_sites(), false);
393
394 ASSERT_EQ(1, querier.number_of_callbacks());
395
396 // This behavior is not desirable: even though edition.cnn.com is in the list
397 // of top sites, and the the bare URL cnn.com is just a redirect to it, we're
398 // returning both. Even worse, the NTP will show the same title, and icon for
399 // the site, so to the user it looks like we just have the same thing twice.
400 // (https://crbug.com/567132)
401 std::vector<GURL> expected_urls = {bare, edition}; // should be {edition}.
402
403 for (const auto& prepopulated : GetPrepopulatedPages()) {
404 expected_urls.push_back(prepopulated.most_visited.url);
405 }
406 std::vector<GURL> actual_urls;
407 for (const auto& actual : querier.urls()) {
408 actual_urls.push_back(actual.url);
409 }
410 EXPECT_THAT(actual_urls, ContainerEq(expected_urls));
411 }
412
413 // Makes sure changes done to top sites get mirrored to the db.
TEST_F(TopSitesImplTest,SaveToDB)414 TEST_F(TopSitesImplTest, SaveToDB) {
415 MostVisitedURL url;
416 GURL asdf_url("http://asdf.com");
417 base::string16 asdf_title(base::ASCIIToUTF16("ASDF"));
418 GURL google_url("http://google.com");
419 base::string16 google_title(base::ASCIIToUTF16("Google"));
420 GURL news_url("http://news.google.com");
421 base::string16 news_title(base::ASCIIToUTF16("Google News"));
422
423 // Add asdf_url to history.
424 AddPageToHistory(asdf_url, asdf_title);
425
426 // Make TopSites reread from the db.
427 StartQueryForMostVisited();
428 WaitForHistory();
429
430 RecreateTopSitesAndBlock();
431
432 {
433 TopSitesQuerier querier;
434 querier.QueryTopSites(top_sites(), false);
435 ASSERT_EQ(1u + GetPrepopulatedPages().size(), querier.urls().size());
436 EXPECT_EQ(asdf_url, querier.urls()[0].url);
437 EXPECT_EQ(asdf_title, querier.urls()[0].title);
438 ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 1));
439 }
440
441 MostVisitedURL url2;
442 url2.url = google_url;
443 url2.title = google_title;
444
445 AddPageToHistory(url2.url, url2.title);
446
447 // Make TopSites reread from the db.
448 RefreshTopSitesAndRecreate();
449
450 {
451 TopSitesQuerier querier;
452 querier.QueryTopSites(top_sites(), false);
453 ASSERT_EQ(2u + GetPrepopulatedPages().size(), querier.urls().size());
454 EXPECT_EQ(asdf_url, querier.urls()[0].url);
455 EXPECT_EQ(asdf_title, querier.urls()[0].title);
456 EXPECT_EQ(google_url, querier.urls()[1].url);
457 EXPECT_EQ(google_title, querier.urls()[1].title);
458 ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 2));
459 }
460 }
461
462 // More permutations of saving to db.
TEST_F(TopSitesImplTest,RealDatabase)463 TEST_F(TopSitesImplTest, RealDatabase) {
464 MostVisitedURL url;
465 GURL asdf_url("http://asdf.com");
466 base::string16 asdf_title(base::ASCIIToUTF16("ASDF"));
467 GURL google1_url("http://google.com");
468 GURL google2_url("http://google.com/redirect");
469 GURL google3_url("http://www.google.com");
470 base::string16 google_title(base::ASCIIToUTF16("Google"));
471 GURL news_url("http://news.google.com");
472 base::string16 news_title(base::ASCIIToUTF16("Google News"));
473
474 url.url = asdf_url;
475 url.title = asdf_title;
476
477 base::Time add_time(base::Time::Now());
478 AddPageToHistory(url.url, url.title, add_time);
479
480 RefreshTopSitesAndRecreate();
481
482 {
483 TopSitesQuerier querier;
484 querier.QueryTopSites(top_sites(), false);
485
486 ASSERT_EQ(1u + GetPrepopulatedPages().size(), querier.urls().size());
487 EXPECT_EQ(asdf_url, querier.urls()[0].url);
488 EXPECT_EQ(asdf_title, querier.urls()[0].title);
489 ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 1));
490 }
491
492 MostVisitedURL url2;
493 url2.url = google3_url;
494 url2.title = google_title;
495 history::RedirectList url2_redirects;
496 url2_redirects.push_back(google1_url);
497 url2_redirects.push_back(google2_url);
498 url2_redirects.push_back(google3_url);
499
500 AddPageToHistory(google3_url, url2.title,
501 add_time - base::TimeDelta::FromMinutes(1), url2_redirects);
502 // Add google twice so that it becomes the first visited site.
503 AddPageToHistory(google3_url, url2.title,
504 add_time - base::TimeDelta::FromMinutes(2), url2_redirects);
505
506 RefreshTopSitesAndRecreate();
507
508 {
509 scoped_refptr<base::RefCountedMemory> read_data;
510 TopSitesQuerier querier;
511 querier.QueryTopSites(top_sites(), false);
512
513 ASSERT_EQ(2u + GetPrepopulatedPages().size(), querier.urls().size());
514 EXPECT_EQ(google1_url, querier.urls()[0].url);
515 EXPECT_EQ(google_title, querier.urls()[0].title);
516
517 EXPECT_EQ(asdf_url, querier.urls()[1].url);
518 EXPECT_EQ(asdf_title, querier.urls()[1].title);
519 ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 2));
520 }
521 }
522
TEST_F(TopSitesImplTest,DeleteNotifications)523 TEST_F(TopSitesImplTest, DeleteNotifications) {
524 GURL google1_url("http://google.com");
525 GURL google2_url("http://google.com/redirect");
526 GURL google3_url("http://www.google.com");
527 base::string16 google_title(base::ASCIIToUTF16("Google"));
528 GURL news_url("http://news.google.com");
529 base::string16 news_title(base::ASCIIToUTF16("Google News"));
530
531 AddPageToHistory(google1_url, google_title);
532 AddPageToHistory(news_url, news_title);
533
534 RefreshTopSitesAndRecreate();
535
536 {
537 TopSitesQuerier querier;
538 querier.QueryTopSites(top_sites(), false);
539
540 ASSERT_EQ(GetPrepopulatedPages().size() + 2, querier.urls().size());
541 }
542
543 DeleteURL(news_url);
544
545 // Wait for history to process the deletion.
546 WaitForHistory();
547 // The deletion called back to TopSitesImpl (on the main thread), which
548 // triggers a history query. Wait for that to complete.
549 WaitForHistory();
550
551 {
552 TopSitesQuerier querier;
553 querier.QueryTopSites(top_sites(), false);
554
555 ASSERT_EQ(1u + GetPrepopulatedPages().size(), querier.urls().size());
556 EXPECT_EQ(google_title, querier.urls()[0].title);
557 ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 1));
558 }
559
560 // Now reload. This verifies topsites actually wrote the deletion to disk.
561 RefreshTopSitesAndRecreate();
562
563 {
564 TopSitesQuerier querier;
565 querier.QueryTopSites(top_sites(), false);
566
567 ASSERT_EQ(1u + GetPrepopulatedPages().size(), querier.urls().size());
568 EXPECT_EQ(google_title, querier.urls()[0].title);
569 ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 1));
570 }
571
572 DeleteURL(google1_url);
573
574 // Wait for history to process the deletion.
575 WaitForHistory();
576 // The deletion called back to TopSitesImpl (on the main thread), which
577 // triggers a history query. Wait for that to complete.
578 WaitForHistory();
579
580 {
581 TopSitesQuerier querier;
582 querier.QueryTopSites(top_sites(), false);
583
584 ASSERT_EQ(GetPrepopulatedPages().size(), querier.urls().size());
585 ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 0));
586 }
587
588 // Now reload. This verifies topsites actually wrote the deletion to disk.
589 RefreshTopSitesAndRecreate();
590
591 {
592 TopSitesQuerier querier;
593 querier.QueryTopSites(top_sites(), false);
594
595 ASSERT_EQ(GetPrepopulatedPages().size(), querier.urls().size());
596 ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 0));
597 }
598 }
599
600 // Verifies that callbacks are notified correctly if requested before top sites
601 // has loaded.
TEST_F(TopSitesImplTest,NotifyCallbacksWhenLoaded)602 TEST_F(TopSitesImplTest, NotifyCallbacksWhenLoaded) {
603 // Recreate top sites. It won't be loaded now.
604 ResetTopSites();
605
606 EXPECT_FALSE(IsTopSitesLoaded());
607
608 TopSitesQuerier querier1;
609 TopSitesQuerier querier2;
610 TopSitesQuerier querier3;
611
612 // Starts the queries.
613 querier1.QueryTopSites(top_sites(), false);
614 querier2.QueryTopSites(top_sites(), false);
615 querier3.QueryTopSites(top_sites(), false);
616
617 // We shouldn't have gotten a callback.
618 EXPECT_EQ(0, querier1.number_of_callbacks());
619 EXPECT_EQ(0, querier2.number_of_callbacks());
620 EXPECT_EQ(0, querier3.number_of_callbacks());
621
622 // Wait for loading to complete.
623 WaitTopSitesLoaded();
624
625 // Now we should have gotten the callbacks.
626 EXPECT_EQ(1, querier1.number_of_callbacks());
627 EXPECT_EQ(GetPrepopulatedPages().size(), querier1.urls().size());
628 EXPECT_EQ(1, querier2.number_of_callbacks());
629 EXPECT_EQ(GetPrepopulatedPages().size(), querier2.urls().size());
630 EXPECT_EQ(1, querier3.number_of_callbacks());
631 EXPECT_EQ(GetPrepopulatedPages().size(), querier3.urls().size());
632
633 // Reset the top sites.
634 MostVisitedURLList pages;
635 MostVisitedURL url;
636 url.url = GURL("http://1.com/");
637 pages.push_back(url);
638 url.url = GURL("http://2.com/");
639 pages.push_back(url);
640 SetTopSites(pages);
641
642 // Recreate top sites. It won't be loaded now.
643 ResetTopSites();
644
645 EXPECT_FALSE(IsTopSitesLoaded());
646
647 TopSitesQuerier querier4;
648
649 // Query again.
650 querier4.QueryTopSites(top_sites(), false);
651
652 // We shouldn't have gotten a callback.
653 EXPECT_EQ(0, querier4.number_of_callbacks());
654
655 // Wait for loading to complete.
656 WaitTopSitesLoaded();
657
658 // Now we should have gotten the callbacks.
659 EXPECT_EQ(1, querier4.number_of_callbacks());
660 ASSERT_EQ(2u + GetPrepopulatedPages().size(), querier4.urls().size());
661
662 EXPECT_EQ("http://1.com/", querier4.urls()[0].url.spec());
663 EXPECT_EQ("http://2.com/", querier4.urls()[1].url.spec());
664 ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier4, 2));
665
666 // Reset the top sites again, this time don't reload.
667 url.url = GURL("http://3.com/");
668 pages.push_back(url);
669 SetTopSites(pages);
670
671 // Query again.
672 TopSitesQuerier querier5;
673 querier5.QueryTopSites(top_sites(), true);
674
675 EXPECT_EQ(1, querier5.number_of_callbacks());
676
677 ASSERT_EQ(3u + GetPrepopulatedPages().size(), querier5.urls().size());
678 EXPECT_EQ("http://1.com/", querier5.urls()[0].url.spec());
679 EXPECT_EQ("http://2.com/", querier5.urls()[1].url.spec());
680 EXPECT_EQ("http://3.com/", querier5.urls()[2].url.spec());
681 ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier5, 3));
682 }
683
684 // Makes sure canceled requests are not notified.
TEST_F(TopSitesImplTest,CancelingRequestsForTopSites)685 TEST_F(TopSitesImplTest, CancelingRequestsForTopSites) {
686 // Recreate top sites. It won't be loaded now.
687 ResetTopSites();
688
689 EXPECT_FALSE(IsTopSitesLoaded());
690
691 TopSitesQuerier querier1;
692 TopSitesQuerier querier2;
693
694 // Starts the queries.
695 querier1.QueryTopSites(top_sites(), false);
696 querier2.QueryTopSites(top_sites(), false);
697
698 // We shouldn't have gotten a callback.
699 EXPECT_EQ(0, querier1.number_of_callbacks());
700 EXPECT_EQ(0, querier2.number_of_callbacks());
701
702 querier2.CancelRequest();
703
704 // Wait for loading to complete.
705 WaitTopSitesLoaded();
706
707 // The first callback should succeed.
708 EXPECT_EQ(1, querier1.number_of_callbacks());
709 EXPECT_EQ(GetPrepopulatedPages().size(), querier1.urls().size());
710
711 // And the canceled callback should not be notified.
712 EXPECT_EQ(0, querier2.number_of_callbacks());
713 }
714
715 // Tests variations of blocked urls.
TEST_F(TopSitesImplTest,BlockedUrlsWithoutPrepopulated)716 TEST_F(TopSitesImplTest, BlockedUrlsWithoutPrepopulated) {
717 MostVisitedURLList pages;
718 MostVisitedURL url, url1;
719 url.url = GURL("http://bbc.com/");
720 pages.push_back(url);
721 url1.url = GURL("http://google.com/");
722 pages.push_back(url1);
723
724 SetTopSites(pages);
725 EXPECT_FALSE(top_sites()->IsBlocked(GURL("http://bbc.com/")));
726
727 // Block google.com.
728 top_sites()->AddBlockedUrl(GURL("http://google.com/"));
729
730 EXPECT_TRUE(top_sites()->HasBlockedUrls());
731 EXPECT_TRUE(top_sites()->IsBlocked(GURL("http://google.com/")));
732 EXPECT_FALSE(top_sites()->IsBlocked(GURL("http://bbc.com/")));
733
734 // Make sure the blocked site isn't returned in the results.
735 {
736 TopSitesQuerier q;
737 q.QueryTopSites(top_sites(), true);
738 EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
739 }
740
741 // Recreate top sites and make sure the blocked url was correctly read.
742 RecreateTopSitesAndBlock();
743 {
744 TopSitesQuerier q;
745 q.QueryTopSites(top_sites(), true);
746 EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
747 }
748
749 // Mark google as no longer blocked.
750 top_sites()->RemoveBlockedUrl(GURL("http://google.com/"));
751 EXPECT_FALSE(top_sites()->HasBlockedUrls());
752 EXPECT_FALSE(top_sites()->IsBlocked(GURL("http://google.com/")));
753
754 // Make sure google is returned now.
755 {
756 TopSitesQuerier q;
757 q.QueryTopSites(top_sites(), true);
758 EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
759 EXPECT_EQ("http://google.com/", q.urls()[1].url.spec());
760 }
761
762 // Remove all blocked urls.
763 top_sites()->ClearBlockedUrls();
764 EXPECT_FALSE(top_sites()->HasBlockedUrls());
765
766 {
767 TopSitesQuerier q;
768 q.QueryTopSites(top_sites(), true);
769 EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
770 EXPECT_EQ("http://google.com/", q.urls()[1].url.spec());
771 ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 2));
772 }
773 }
774
775 // Tests variations of blocking including blocking prepopulated pages.
TEST_F(TopSitesImplTest,BlockingPrepopulated)776 TEST_F(TopSitesImplTest, BlockingPrepopulated) {
777 MostVisitedURLList pages;
778 MostVisitedURL url, url1;
779 url.url = GURL("http://bbc.com/");
780 pages.push_back(url);
781 url1.url = GURL("http://google.com/");
782 pages.push_back(url1);
783
784 SetTopSites(pages);
785 EXPECT_FALSE(top_sites()->IsBlocked(GURL("http://bbc.com/")));
786
787 // Block google.com.
788 top_sites()->AddBlockedUrl(GURL("http://google.com/"));
789
790 DCHECK_GE(GetPrepopulatedPages().size(), 1u);
791 GURL prepopulate_url = GetPrepopulatedPages()[0].most_visited.url;
792
793 EXPECT_TRUE(top_sites()->HasBlockedUrls());
794 EXPECT_TRUE(top_sites()->IsBlocked(GURL("http://google.com/")));
795 EXPECT_FALSE(top_sites()->IsBlocked(GURL("http://bbc.com/")));
796 EXPECT_FALSE(top_sites()->IsBlocked(prepopulate_url));
797
798 // Make sure the blocked site isn't returned in the results.
799 {
800 TopSitesQuerier q;
801 q.QueryTopSites(top_sites(), true);
802 ASSERT_EQ(1u + GetPrepopulatedPages().size(), q.urls().size());
803 EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
804 ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 1));
805 }
806
807 // Recreate top sites and make sure blocked url was correctly read.
808 RecreateTopSitesAndBlock();
809 {
810 TopSitesQuerier q;
811 q.QueryTopSites(top_sites(), true);
812 ASSERT_EQ(1u + GetPrepopulatedPages().size(), q.urls().size());
813 EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
814 ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 1));
815 }
816
817 // Block one of the prepopulate urls.
818 top_sites()->AddBlockedUrl(prepopulate_url);
819 EXPECT_TRUE(top_sites()->HasBlockedUrls());
820
821 // Make sure the blacked prepopulate url isn't returned.
822 {
823 TopSitesQuerier q;
824 q.QueryTopSites(top_sites(), true);
825 ASSERT_EQ(1u + GetPrepopulatedPages().size() - 1, q.urls().size());
826 EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
827 for (size_t i = 1; i < q.urls().size(); ++i)
828 EXPECT_NE(prepopulate_url.spec(), q.urls()[i].url.spec());
829 }
830
831 // Mark google as no longer blocked.
832 top_sites()->RemoveBlockedUrl(GURL("http://google.com/"));
833 EXPECT_TRUE(top_sites()->HasBlockedUrls());
834 EXPECT_FALSE(top_sites()->IsBlocked(GURL("http://google.com/")));
835
836 // Make sure google is returned now.
837 {
838 TopSitesQuerier q;
839 q.QueryTopSites(top_sites(), true);
840 ASSERT_EQ(2u + GetPrepopulatedPages().size() - 1, q.urls().size());
841 EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
842 EXPECT_EQ("http://google.com/", q.urls()[1].url.spec());
843 // Android has only one prepopulated page which has been blocked, so
844 // only 2 urls are returned.
845 if (q.urls().size() > 2)
846 EXPECT_NE(prepopulate_url.spec(), q.urls()[2].url.spec());
847 else
848 EXPECT_EQ(1u, GetPrepopulatedPages().size());
849 }
850
851 // Remove all blocked urls.
852 top_sites()->ClearBlockedUrls();
853 EXPECT_FALSE(top_sites()->HasBlockedUrls());
854
855 {
856 TopSitesQuerier q;
857 q.QueryTopSites(top_sites(), true);
858 ASSERT_EQ(2u + GetPrepopulatedPages().size(), q.urls().size());
859 EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
860 EXPECT_EQ("http://google.com/", q.urls()[1].url.spec());
861 ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 2));
862 }
863 }
864
865 // Makes sure prepopulated pages exist.
TEST_F(TopSitesImplTest,AddPrepopulatedPages)866 TEST_F(TopSitesImplTest, AddPrepopulatedPages) {
867 TopSitesQuerier q;
868 q.QueryTopSites(top_sites(), true);
869 EXPECT_EQ(GetPrepopulatedPages().size(), q.urls().size());
870 ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 0));
871
872 MostVisitedURLList pages = q.urls();
873 EXPECT_FALSE(AddPrepopulatedPages(&pages));
874
875 EXPECT_EQ(GetPrepopulatedPages().size(), pages.size());
876 q.set_urls(pages);
877 ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 0));
878 }
879
880 } // namespace history
881