1 // Copyright 2015 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/ntp_tiles/most_visited_sites.h"
6 
7 #include <stddef.h>
8 
9 #include <map>
10 #include <memory>
11 #include <ostream>
12 #include <string>
13 #include <tuple>
14 #include <utility>
15 #include <vector>
16 
17 #include "base/bind.h"
18 #include "base/callback_list.h"
19 #include "base/command_line.h"
20 #include "base/macros.h"
21 #include "base/run_loop.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "base/task/cancelable_task_tracker.h"
24 #include "base/test/scoped_feature_list.h"
25 #include "base/test/task_environment.h"
26 #include "base/threading/thread_task_runner_handle.h"
27 #include "build/build_config.h"
28 #include "components/history/core/browser/top_sites.h"
29 #include "components/history/core/browser/top_sites_observer.h"
30 #include "components/ntp_tiles/custom_links_manager.h"
31 #include "components/ntp_tiles/features.h"
32 #include "components/ntp_tiles/icon_cacher.h"
33 #include "components/ntp_tiles/popular_sites_impl.h"
34 #include "components/ntp_tiles/pref_names.h"
35 #include "components/ntp_tiles/section_type.h"
36 #include "components/ntp_tiles/switches.h"
37 #include "components/sync_preferences/testing_pref_service_syncable.h"
38 #include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
39 #include "services/network/public/cpp/shared_url_loader_factory.h"
40 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
41 #include "services/network/test/test_url_loader_factory.h"
42 #include "testing/gmock/include/gmock/gmock.h"
43 #include "testing/gtest/include/gtest/gtest.h"
44 
45 namespace ntp_tiles {
46 
47 // Defined for googletest. Must be defined in the same namespace.
PrintTo(const NTPTile & tile,std::ostream * os)48 void PrintTo(const NTPTile& tile, std::ostream* os) {
49   *os << "{\"" << tile.title << "\", \"" << tile.url << "\", "
50       << static_cast<int>(tile.source) << "}";
51 }
52 
53 namespace {
54 
55 using history::MostVisitedURL;
56 using history::MostVisitedURLList;
57 using history::TopSites;
58 using suggestions::ChromeSuggestion;
59 using suggestions::SuggestionsProfile;
60 using suggestions::SuggestionsService;
61 using testing::AtLeast;
62 using testing::AllOf;
63 using testing::AnyNumber;
64 using testing::ByMove;
65 using testing::Contains;
66 using testing::ElementsAre;
67 using testing::Eq;
68 using testing::Ge;
69 using testing::InSequence;
70 using testing::Invoke;
71 using testing::IsEmpty;
72 using testing::Key;
73 using testing::Mock;
74 using testing::Not;
75 using testing::Pair;
76 using testing::Return;
77 using testing::ReturnRef;
78 using testing::SaveArg;
79 using testing::SizeIs;
80 using testing::StrictMock;
81 using testing::_;
82 
83 const char kHomepageUrl[] = "http://homepa.ge/";
84 const char kHomepageTitle[] = "Homepage";
85 const char kTestExploreUrl[] = "https://example.com/";
86 const char kTestExploreTitle[] = "Example";
87 
PrintTile(const std::string & title,const std::string & url,TileSource source)88 std::string PrintTile(const std::string& title,
89                       const std::string& url,
90                       TileSource source) {
91   return std::string("has title \"") + title + std::string("\" and url \"") +
92          url + std::string("\" and source ") +
93          testing::PrintToString(static_cast<int>(source));
94 }
95 
MATCHER_P3(MatchesTile,title,url,source,PrintTile (title,url,source))96 MATCHER_P3(MatchesTile, title, url, source, PrintTile(title, url, source)) {
97   return arg.title == base::ASCIIToUTF16(title) && arg.url == GURL(url) &&
98          arg.source == source;
99 }
100 
PrintTileSource(TileSource source)101 std::string PrintTileSource(TileSource source) {
102   return std::string("has source ") +
103          testing::PrintToString(static_cast<int>(source));
104 }
105 
MATCHER_P(TileWithSource,source,PrintTileSource (source))106 MATCHER_P(TileWithSource, source, PrintTileSource(source)) {
107   return arg.source == source;
108 }
109 
110 MATCHER_P3(LastTileIs,
111            title,
112            url,
113            source,
114            std::string("last tile ") + PrintTile(title, url, source)) {
115   const NTPTilesVector& tiles = arg.at(SectionType::PERSONALIZED);
116   if (tiles.empty())
117     return false;
118 
119   const NTPTile& last = tiles.back();
120   return last.title == base::ASCIIToUTF16(title) && last.url == GURL(url) &&
121          last.source == source;
122 }
123 
124 MATCHER_P3(FirstPersonalizedTileIs,
125            title,
126            url,
127            source,
128            std::string("first tile ") + PrintTile(title, url, source)) {
129   if (arg.count(SectionType::PERSONALIZED) == 0) {
130     return false;
131   }
132   const NTPTilesVector& tiles = arg.at(SectionType::PERSONALIZED);
133   return !tiles.empty() && tiles[0].title == base::ASCIIToUTF16(title) &&
134          tiles[0].url == GURL(url) && tiles[0].source == source;
135 }
136 
137 // testing::InvokeArgument<N> does not work with base::Callback, fortunately
138 // gmock makes it simple to create action templates that do for the various
139 // possible numbers of arguments.
ACTION_TEMPLATE(InvokeCallbackArgument,HAS_1_TEMPLATE_PARAMS (int,k),AND_1_VALUE_PARAMS (p0))140 ACTION_TEMPLATE(InvokeCallbackArgument,
141                 HAS_1_TEMPLATE_PARAMS(int, k),
142                 AND_1_VALUE_PARAMS(p0)) {
143   std::move(std::get<k>(args)).Run(p0);
144 }
145 
MakeTile(const std::string & title,const std::string & url,TileSource source)146 NTPTile MakeTile(const std::string& title,
147                  const std::string& url,
148                  TileSource source) {
149   NTPTile tile;
150   tile.title = base::ASCIIToUTF16(title);
151   tile.url = GURL(url);
152   tile.source = source;
153   return tile;
154 }
155 
MakeSuggestion(const std::string & title,const std::string & url)156 ChromeSuggestion MakeSuggestion(const std::string& title,
157                                 const std::string& url) {
158   ChromeSuggestion suggestion;
159   suggestion.set_title(title);
160   suggestion.set_url(url);
161   return suggestion;
162 }
163 
MakeProfile(const std::vector<ChromeSuggestion> & suggestions)164 SuggestionsProfile MakeProfile(
165     const std::vector<ChromeSuggestion>& suggestions) {
166   SuggestionsProfile profile;
167   for (const ChromeSuggestion& suggestion : suggestions) {
168     *profile.add_suggestions() = suggestion;
169   }
170   return profile;
171 }
172 
MakeMostVisitedURL(const std::string & title,const std::string & url)173 MostVisitedURL MakeMostVisitedURL(const std::string& title,
174                                   const std::string& url) {
175   MostVisitedURL result;
176   result.title = base::ASCIIToUTF16(title);
177   result.url = GURL(url);
178   return result;
179 }
180 
181 class MockTopSites : public TopSites {
182  public:
183   MOCK_METHOD0(ShutdownOnUIThread, void());
GetMostVisitedURLs(GetMostVisitedURLsCallback callback)184   void GetMostVisitedURLs(GetMostVisitedURLsCallback callback) override {
185     GetMostVisitedURLs_(callback);
186   }
187   MOCK_METHOD1(GetMostVisitedURLs_, void(GetMostVisitedURLsCallback& callback));
188   MOCK_METHOD0(SyncWithHistory, void());
189   MOCK_CONST_METHOD0(HasBlacklistedItems, bool());
190   MOCK_METHOD1(AddBlacklistedURL, void(const GURL& url));
191   MOCK_METHOD1(RemoveBlacklistedURL, void(const GURL& url));
192   MOCK_METHOD1(IsBlacklisted, bool(const GURL& url));
193   MOCK_METHOD0(ClearBlacklistedURLs, void());
194   MOCK_METHOD0(StartQueryForMostVisited, base::CancelableTaskTracker::TaskId());
195   MOCK_METHOD1(IsKnownURL, bool(const GURL& url));
196   MOCK_CONST_METHOD1(GetCanonicalURLString,
197                      const std::string&(const GURL& url));
198   MOCK_METHOD0(IsFull, bool());
199   MOCK_CONST_METHOD0(loaded, bool());
200   MOCK_METHOD0(GetPrepopulatedPages, history::PrepopulatedPageList());
201   MOCK_METHOD1(OnNavigationCommitted, void(const GURL& url));
202 
203   // Publicly expose notification to observers, since the implementation cannot
204   // be overriden.
205   using TopSites::NotifyTopSitesChanged;
206 
207  protected:
208   ~MockTopSites() override = default;
209 };
210 
211 class MockSuggestionsService : public SuggestionsService {
212  public:
213   MOCK_METHOD0(FetchSuggestionsData, bool());
214   MOCK_CONST_METHOD0(GetSuggestionsDataFromCache,
215                      base::Optional<SuggestionsProfile>());
216   MOCK_METHOD1(AddCallback,
217                std::unique_ptr<ResponseCallbackList::Subscription>(
218                    const ResponseCallback& callback));
219   MOCK_METHOD1(BlacklistURL, bool(const GURL& candidate_url));
220   MOCK_METHOD1(UndoBlacklistURL, bool(const GURL& url));
221   MOCK_METHOD0(ClearBlacklist, void());
222 };
223 
224 class MockMostVisitedSitesObserver : public MostVisitedSites::Observer {
225  public:
226   MOCK_METHOD1(OnURLsAvailable,
227                void(const std::map<SectionType, NTPTilesVector>& sections));
228   MOCK_METHOD1(OnIconMadeAvailable, void(const GURL& site_url));
229 };
230 
231 class FakeHomepageClient : public MostVisitedSites::HomepageClient {
232  public:
FakeHomepageClient()233   FakeHomepageClient()
234       : homepage_tile_enabled_(false), homepage_url_(kHomepageUrl) {}
~FakeHomepageClient()235   ~FakeHomepageClient() override {}
236 
IsHomepageTileEnabled() const237   bool IsHomepageTileEnabled() const override { return homepage_tile_enabled_; }
238 
GetHomepageUrl() const239   GURL GetHomepageUrl() const override { return homepage_url_; }
240 
QueryHomepageTitle(TitleCallback title_callback)241   void QueryHomepageTitle(TitleCallback title_callback) override {
242     std::move(title_callback).Run(homepage_title_);
243   }
244 
SetHomepageTileEnabled(bool homepage_tile_enabled)245   void SetHomepageTileEnabled(bool homepage_tile_enabled) {
246     homepage_tile_enabled_ = homepage_tile_enabled;
247   }
248 
SetHomepageUrl(GURL homepage_url)249   void SetHomepageUrl(GURL homepage_url) { homepage_url_ = homepage_url; }
250 
SetHomepageTitle(const base::Optional<base::string16> & homepage_title)251   void SetHomepageTitle(const base::Optional<base::string16>& homepage_title) {
252     homepage_title_ = homepage_title;
253   }
254 
255  private:
256   bool homepage_tile_enabled_;
257   GURL homepage_url_;
258   base::Optional<base::string16> homepage_title_;
259 };
260 
261 class FakeExploreSitesClient : public MostVisitedSites::ExploreSitesClient {
262  public:
263   ~FakeExploreSitesClient() override = default;
264 
GetExploreSitesUrl() const265   GURL GetExploreSitesUrl() const override { return GURL(kTestExploreUrl); }
266 
GetExploreSitesTitle() const267   base::string16 GetExploreSitesTitle() const override {
268     return base::ASCIIToUTF16(kTestExploreTitle);
269   }
270 };
271 
272 class MockIconCacher : public IconCacher {
273  public:
274   MOCK_METHOD3(StartFetchPopularSites,
275                void(PopularSites::Site site,
276                     base::OnceClosure icon_available,
277                     base::OnceClosure preliminary_icon_available));
278   MOCK_METHOD2(StartFetchMostLikely,
279                void(const GURL& page_url, base::OnceClosure icon_available));
280 };
281 
282 class MockCustomLinksManager : public CustomLinksManager {
283  public:
284   MOCK_METHOD1(Initialize, bool(const NTPTilesVector& tiles));
285   MOCK_METHOD0(Uninitialize, void());
286   MOCK_CONST_METHOD0(IsInitialized, bool());
287   MOCK_CONST_METHOD0(GetLinks, const std::vector<CustomLinksManager::Link>&());
288   MOCK_METHOD2(AddLink, bool(const GURL& url, const base::string16& title));
289   MOCK_METHOD3(UpdateLink,
290                bool(const GURL& url,
291                     const GURL& new_url,
292                     const base::string16& new_title));
293   MOCK_METHOD2(ReorderLink, bool(const GURL& url, size_t new_pos));
294   MOCK_METHOD1(DeleteLink, bool(const GURL& url));
295   MOCK_METHOD0(UndoAction, bool());
296   MOCK_METHOD1(RegisterCallbackForOnChanged,
297                std::unique_ptr<base::CallbackList<void()>::Subscription>(
298                    base::RepeatingClosure callback));
299 };
300 
301 class PopularSitesFactoryForTest {
302  public:
PopularSitesFactoryForTest(sync_preferences::TestingPrefServiceSyncable * pref_service)303   PopularSitesFactoryForTest(
304       sync_preferences::TestingPrefServiceSyncable* pref_service)
305       : prefs_(pref_service) {
306     test_shared_loader_factory_ =
307         base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
308             &test_url_loader_factory_);
309     PopularSitesImpl::RegisterProfilePrefs(pref_service->registry());
310   }
311 
SeedWithSampleData()312   void SeedWithSampleData() {
313     prefs_->SetString(prefs::kPopularSitesOverrideCountry, "IN");
314     prefs_->SetString(prefs::kPopularSitesOverrideVersion, "5");
315 
316     test_url_loader_factory_.ClearResponses();
317     test_url_loader_factory_.AddResponse(
318         "https://www.gstatic.com/chrome/ntp/suggested_sites_IN_5.json",
319         R"([{
320               "title": "PopularSite1",
321               "url": "http://popularsite1/",
322               "favicon_url": "http://popularsite1/favicon.ico"
323             },
324             {
325               "title": "PopularSite2",
326               "url": "http://popularsite2/",
327               "favicon_url": "http://popularsite2/favicon.ico"
328             }
329            ])");
330 
331     test_url_loader_factory_.AddResponse(
332         "https://www.gstatic.com/chrome/ntp/suggested_sites_US_5.json",
333         R"([{
334               "title": "ESPN",
335               "url": "http://www.espn.com",
336               "favicon_url": "http://www.espn.com/favicon.ico"
337             }, {
338               "title": "Mobile",
339               "url": "http://www.mobile.de",
340               "favicon_url": "http://www.mobile.de/favicon.ico"
341             }, {
342               "title": "Google News",
343               "url": "http://news.google.com",
344               "favicon_url": "http://news.google.com/favicon.ico"
345             }
346            ])");
347 
348     test_url_loader_factory_.AddResponse(
349         "https://www.gstatic.com/chrome/ntp/suggested_sites_IN_6.json",
350         R"([{
351               "section": 1, // PERSONALIZED
352               "sites": [{
353                   "title": "PopularSite1",
354                   "url": "http://popularsite1/",
355                   "favicon_url": "http://popularsite1/favicon.ico"
356                 },
357                 {
358                   "title": "PopularSite2",
359                   "url": "http://popularsite2/",
360                   "favicon_url": "http://popularsite2/favicon.ico"
361                 },
362                ]
363             },
364             {
365                 "section": 4,  // NEWS
366                 "sites": [{
367                     "large_icon_url": "https://news.google.com/icon.ico",
368                     "title": "Google News",
369                     "url": "https://news.google.com/"
370                 },
371                 {
372                     "favicon_url": "https://news.google.com/icon.ico",
373                     "title": "Google News Germany",
374                     "url": "https://news.google.de/"
375                 }]
376             },
377             {
378                 "section": 2,  // SOCIAL
379                 "sites": [{
380                     "large_icon_url": "https://ssl.gstatic.com/icon.png",
381                     "title": "Google+",
382                     "url": "https://plus.google.com/"
383                 }]
384             },
385             {
386                 "section": 3,  // ENTERTAINMENT
387                 "sites": [
388                     // Intentionally empty site list.
389                 ]
390             }
391         ])");
392   }
393 
New()394   std::unique_ptr<PopularSites> New() {
395     return std::make_unique<PopularSitesImpl>(prefs_,
396                                               /*template_url_service=*/nullptr,
397                                               /*variations_service=*/nullptr,
398                                               test_shared_loader_factory_);
399   }
400 
401  private:
402   PrefService* prefs_;
403   network::TestURLLoaderFactory test_url_loader_factory_;
404   scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
405 };
406 
407 // CallbackList-like container without Subscription, mimicking the
408 // implementation in TopSites (which doesn't use base::CallbackList).
409 class TopSitesCallbackList {
410  public:
411   void Add(TopSites::GetMostVisitedURLsCallback& callback) {
412     callbacks_.push_back(std::move(callback));
413   }
414 
415   void ClearAndNotify(const MostVisitedURLList& list) {
416     std::vector<TopSites::GetMostVisitedURLsCallback> callbacks;
417     callbacks.swap(callbacks_);
418     for (auto& callback : callbacks)
419       std::move(callback).Run(list);
420   }
421 
422   bool empty() const { return callbacks_.empty(); }
423 
424  private:
425   std::vector<TopSites::GetMostVisitedURLsCallback> callbacks_;
426 };
427 
428 }  // namespace
429 
430 // Param is a tuple with two components:
431 // * The first specifies whether Popular Sites is enabled via variations.
432 // * The second specifies whether Suggestions Service tiles are enabled via
433 //   variations.
434 class MostVisitedSitesTest
435     : public ::testing::TestWithParam<std::tuple<bool, bool>> {
436  protected:
437   MostVisitedSitesTest()
438       : is_custom_links_enabled_(false),
439         popular_sites_factory_(&pref_service_),
440         mock_top_sites_(new StrictMock<MockTopSites>()) {
441     MostVisitedSites::RegisterProfilePrefs(pref_service_.registry());
442 
443     std::vector<base::Feature> enabled_features;
444     // Disable FaviconServer in most tests and override in specific tests.
445     std::vector<base::Feature> disabled_features = {
446         kNtpMostLikelyFaviconsFromServerFeature};
447     if (IsPopularSitesFeatureEnabled()) {
448       enabled_features.push_back(kUsePopularSitesSuggestions);
449     } else {
450       disabled_features.push_back(kUsePopularSitesSuggestions);
451     }
452     if (IsDisplaySuggestionsServiceTilesEnabled()) {
453       enabled_features.push_back(kDisplaySuggestionsServiceTiles);
454     } else {
455       disabled_features.push_back(kDisplaySuggestionsServiceTiles);
456     }
457 
458     feature_list_.InitWithFeatures(enabled_features, disabled_features);
459     if (IsPopularSitesFeatureEnabled())
460       popular_sites_factory_.SeedWithSampleData();
461 
462     RecreateMostVisitedSites();
463   }
464 
465   void RecreateMostVisitedSites() {
466     // We use StrictMock to make sure the object is not used unless Popular
467     // Sites is enabled.
468     auto icon_cacher = std::make_unique<StrictMock<MockIconCacher>>();
469     icon_cacher_ = icon_cacher.get();
470 
471     // Custom links needs to be nullptr when MostVisitedSites is created, unless
472     // the custom links feature is enabled. Custom links is disabled for
473     // Android, iOS, and third-party NTPs.
474     std::unique_ptr<StrictMock<MockCustomLinksManager>> mock_custom_links;
475     if (is_custom_links_enabled_) {
476       mock_custom_links =
477           std::make_unique<StrictMock<MockCustomLinksManager>>();
478       mock_custom_links_ = mock_custom_links.get();
479     }
480 
481     if (IsPopularSitesFeatureEnabled()) {
482       // Populate Popular Sites' internal cache by mimicking a past usage of
483       // PopularSitesImpl.
484       auto tmp_popular_sites = popular_sites_factory_.New();
485       base::RunLoop loop;
486       bool save_success = false;
487       tmp_popular_sites->MaybeStartFetch(
488           /*force_download=*/true,
489           base::BindOnce(
490               [](bool* save_success, base::RunLoop* loop, bool success) {
491                 *save_success = success;
492                 loop->Quit();
493               },
494               &save_success, &loop));
495       loop.Run();
496       EXPECT_TRUE(save_success);
497 
498       // With PopularSites enabled, blacklist is exercised.
499       EXPECT_CALL(*mock_top_sites_, IsBlacklisted(_))
500           .WillRepeatedly(Return(false));
501       // Mock icon cacher never replies, and we also don't verify whether the
502       // code uses it correctly.
503       EXPECT_CALL(*icon_cacher, StartFetchPopularSites(_, _, _))
504           .Times(AtLeast(0));
505     }
506 
507     EXPECT_CALL(*icon_cacher, StartFetchMostLikely(_, _)).Times(AtLeast(0));
508 
509     most_visited_sites_ = std::make_unique<MostVisitedSites>(
510         &pref_service_, mock_top_sites_, &mock_suggestions_service_,
511         popular_sites_factory_.New(), std::move(mock_custom_links),
512         std::move(icon_cacher),
513         /*supervisor=*/nullptr);
514   }
515 
516   bool IsPopularSitesFeatureEnabled() const { return std::get<0>(GetParam()); }
517   bool IsDisplaySuggestionsServiceTilesEnabled() const {
518     return std::get<1>(GetParam());
519   }
520 
521   bool VerifyAndClearExpectations() {
522     base::RunLoop().RunUntilIdle();
523     const bool success =
524         Mock::VerifyAndClearExpectations(mock_top_sites_.get()) &&
525         Mock::VerifyAndClearExpectations(&mock_suggestions_service_) &&
526         Mock::VerifyAndClearExpectations(&mock_observer_);
527     // For convenience, restore the expectations for IsBlacklisted().
528     if (IsPopularSitesFeatureEnabled()) {
529       EXPECT_CALL(*mock_top_sites_, IsBlacklisted(_))
530           .WillRepeatedly(Return(false));
531     }
532     return success;
533   }
534 
535   FakeHomepageClient* RegisterNewHomepageClient() {
536     auto homepage_client = std::make_unique<FakeHomepageClient>();
537     FakeHomepageClient* raw_client_ptr = homepage_client.get();
538     most_visited_sites_->SetHomepageClient(std::move(homepage_client));
539     return raw_client_ptr;
540   }
541 
542   FakeExploreSitesClient* RegisterNewExploreSitesClient() {
543     auto explore_sites_client = std::make_unique<FakeExploreSitesClient>();
544     FakeExploreSitesClient* raw_client_ptr = explore_sites_client.get();
545     most_visited_sites_->SetExploreSitesClient(std::move(explore_sites_client));
546     return raw_client_ptr;
547   }
548 
549   void DisableRemoteSuggestions() {
550     EXPECT_CALL(mock_suggestions_service_, AddCallback(_))
551         .Times(AnyNumber())
552         .WillRepeatedly(Invoke(&suggestions_service_callbacks_,
553                                &SuggestionsService::ResponseCallbackList::Add));
554     EXPECT_CALL(mock_suggestions_service_, GetSuggestionsDataFromCache())
555         .Times(AnyNumber())
556         .WillRepeatedly(Return(SuggestionsProfile()));  // Empty cache.
557     EXPECT_CALL(mock_suggestions_service_, FetchSuggestionsData())
558         .Times(AnyNumber())
559         .WillRepeatedly(Return(true));
560   }
561 
562   void EnableCustomLinks() { is_custom_links_enabled_ = true; }
563 
564   bool is_custom_links_enabled_;
565   base::CallbackList<SuggestionsService::ResponseCallback::RunType>
566       suggestions_service_callbacks_;
567   TopSitesCallbackList top_sites_callbacks_;
568 
569   base::test::SingleThreadTaskEnvironment task_environment_;
570   data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
571   sync_preferences::TestingPrefServiceSyncable pref_service_;
572   PopularSitesFactoryForTest popular_sites_factory_;
573   scoped_refptr<StrictMock<MockTopSites>> mock_top_sites_;
574   StrictMock<MockSuggestionsService> mock_suggestions_service_;
575   StrictMock<MockMostVisitedSitesObserver> mock_observer_;
576   std::unique_ptr<MostVisitedSites> most_visited_sites_;
577   base::test::ScopedFeatureList feature_list_;
578   MockCustomLinksManager* mock_custom_links_;
579   MockIconCacher* icon_cacher_;
580 };
581 
582 TEST_P(MostVisitedSitesTest, ShouldStartNoCallInConstructor) {
583   // No call to mocks expected by the mere fact of instantiating
584   // MostVisitedSites.
585   base::RunLoop().RunUntilIdle();
586 }
587 
588 TEST_P(MostVisitedSitesTest, ShouldRefreshBothBackends) {
589   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
590   EXPECT_CALL(mock_suggestions_service_, FetchSuggestionsData());
591   most_visited_sites_->Refresh();
592 }
593 
594 TEST_P(MostVisitedSitesTest, ShouldIncludeTileForHomepage) {
595   FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
596   homepage_client->SetHomepageTileEnabled(true);
597   DisableRemoteSuggestions();
598   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
599       .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{}));
600   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
601   EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
602       .Times(AnyNumber())
603       .WillRepeatedly(Return(false));
604   EXPECT_CALL(mock_observer_, OnURLsAvailable(FirstPersonalizedTileIs(
605                                   "", kHomepageUrl, TileSource::HOMEPAGE)));
606   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
607                                                   /*num_sites=*/3);
608   base::RunLoop().RunUntilIdle();
609 }
610 
611 TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomepageWithoutClient) {
612   DisableRemoteSuggestions();
613   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
614       .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{}));
615   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
616   EXPECT_CALL(mock_observer_,
617               OnURLsAvailable(Contains(
618                   Pair(SectionType::PERSONALIZED,
619                        Not(Contains(MatchesTile("", kHomepageUrl,
620                                                 TileSource::HOMEPAGE)))))));
621   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
622                                                   /*num_sites=*/3);
623   base::RunLoop().RunUntilIdle();
624 }
625 
626 TEST_P(MostVisitedSitesTest, ShouldIncludeHomeTileWithUrlBeforeQueryingName) {
627   // Because the query time for the real name might take a while, provide the
628   // home tile with URL as title immediately and update the tiles as soon as the
629   // real title was found.
630   FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
631   homepage_client->SetHomepageTileEnabled(true);
632   homepage_client->SetHomepageTitle(base::UTF8ToUTF16(kHomepageTitle));
633   DisableRemoteSuggestions();
634   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
635       .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{}));
636   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
637   EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
638       .Times(AnyNumber())
639       .WillRepeatedly(Return(false));
640   {
641     testing::Sequence seq;
642     EXPECT_CALL(mock_observer_,
643                 OnURLsAvailable(Contains(
644                     Pair(SectionType::PERSONALIZED,
645                          Not(Contains(MatchesTile("", kHomepageUrl,
646                                                   TileSource::HOMEPAGE)))))));
647     EXPECT_CALL(mock_observer_,
648                 OnURLsAvailable(Contains(
649                     Pair(SectionType::PERSONALIZED,
650                          Not(Contains(MatchesTile(kHomepageTitle, kHomepageUrl,
651                                                   TileSource::HOMEPAGE)))))));
652   }
653   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
654                                                   /*num_sites=*/3);
655   base::RunLoop().RunUntilIdle();
656 }
657 
658 TEST_P(MostVisitedSitesTest, ShouldUpdateHomepageTileWhenRefreshHomepageTile) {
659   FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
660   homepage_client->SetHomepageTileEnabled(true);
661   DisableRemoteSuggestions();
662 
663   // Ensure that home tile is available as usual.
664   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
665       .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{}));
666   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
667   EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
668       .Times(AnyNumber())
669       .WillRepeatedly(Return(false));
670   EXPECT_CALL(mock_observer_, OnURLsAvailable(FirstPersonalizedTileIs(
671                                   "", kHomepageUrl, TileSource::HOMEPAGE)));
672   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
673                                                   /*num_sites=*/3);
674   base::RunLoop().RunUntilIdle();
675   VerifyAndClearExpectations();
676 
677   // Disable home page and rebuild _without_ Resync. The tile should be gone.
678   homepage_client->SetHomepageTileEnabled(false);
679   DisableRemoteSuggestions();
680   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
681       .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{}));
682   EXPECT_CALL(*mock_top_sites_, SyncWithHistory()).Times(0);
683   EXPECT_CALL(mock_observer_, OnURLsAvailable(Not(FirstPersonalizedTileIs(
684                                   "", kHomepageUrl, TileSource::HOMEPAGE))));
685   most_visited_sites_->RefreshTiles();
686   base::RunLoop().RunUntilIdle();
687 }
688 
689 TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomepageIfNoTileRequested) {
690   FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
691   homepage_client->SetHomepageTileEnabled(true);
692   DisableRemoteSuggestions();
693   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
694       .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{}));
695   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
696   EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
697       .Times(AnyNumber())
698       .WillRepeatedly(Return(false));
699   EXPECT_CALL(
700       mock_observer_,
701       OnURLsAvailable(Contains(Pair(SectionType::PERSONALIZED, IsEmpty()))));
702   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
703                                                   /*num_sites=*/0);
704   base::RunLoop().RunUntilIdle();
705 }
706 
707 TEST_P(MostVisitedSitesTest, ShouldReturnHomepageIfOneTileRequested) {
708   FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
709   homepage_client->SetHomepageTileEnabled(true);
710   DisableRemoteSuggestions();
711   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
712       .WillRepeatedly(InvokeCallbackArgument<0>(
713           (MostVisitedURLList{MakeMostVisitedURL("Site 1", "http://site1/")})));
714   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
715   EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
716       .Times(AnyNumber())
717       .WillRepeatedly(Return(false));
718   EXPECT_CALL(
719       mock_observer_,
720       OnURLsAvailable(Contains(Pair(
721           SectionType::PERSONALIZED,
722           ElementsAre(MatchesTile("", kHomepageUrl, TileSource::HOMEPAGE))))));
723   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
724                                                   /*num_sites=*/1);
725   base::RunLoop().RunUntilIdle();
726 }
727 
TEST_P(MostVisitedSitesTest,ShouldHaveHomepageFirstInListWhenFull)728 TEST_P(MostVisitedSitesTest, ShouldHaveHomepageFirstInListWhenFull) {
729   FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
730   homepage_client->SetHomepageTileEnabled(true);
731   DisableRemoteSuggestions();
732   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
733       .WillRepeatedly(InvokeCallbackArgument<0>((MostVisitedURLList{
734           MakeMostVisitedURL("Site 1", "http://site1/"),
735           MakeMostVisitedURL("Site 2", "http://site2/"),
736           MakeMostVisitedURL("Site 3", "http://site3/"),
737           MakeMostVisitedURL("Site 4", "http://site4/"),
738           MakeMostVisitedURL("Site 5", "http://site5/"),
739       })));
740   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
741   EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
742       .Times(AnyNumber())
743       .WillRepeatedly(Return(false));
744   std::map<SectionType, NTPTilesVector> sections;
745   EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
746       .WillOnce(SaveArg<0>(&sections));
747   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
748                                                   /*num_sites=*/4);
749   base::RunLoop().RunUntilIdle();
750   ASSERT_THAT(sections, Contains(Key(SectionType::PERSONALIZED)));
751   NTPTilesVector tiles = sections.at(SectionType::PERSONALIZED);
752   ASSERT_THAT(tiles.size(), Ge(4ul));
753   // Assert that the home page is appended as the final tile.
754   EXPECT_THAT(tiles[0], MatchesTile("", kHomepageUrl, TileSource::HOMEPAGE));
755 }
756 
TEST_P(MostVisitedSitesTest,ShouldHaveHomepageFirstInListWhenNotFull)757 TEST_P(MostVisitedSitesTest, ShouldHaveHomepageFirstInListWhenNotFull) {
758   FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
759   homepage_client->SetHomepageTileEnabled(true);
760   DisableRemoteSuggestions();
761   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
762       .WillRepeatedly(InvokeCallbackArgument<0>((MostVisitedURLList{
763           MakeMostVisitedURL("Site 1", "http://site1/"),
764           MakeMostVisitedURL("Site 2", "http://site2/"),
765           MakeMostVisitedURL("Site 3", "http://site3/"),
766           MakeMostVisitedURL("Site 4", "http://site4/"),
767           MakeMostVisitedURL("Site 5", "http://site5/"),
768       })));
769   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
770   EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
771       .Times(AnyNumber())
772       .WillRepeatedly(Return(false));
773   std::map<SectionType, NTPTilesVector> sections;
774   EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
775       .WillOnce(SaveArg<0>(&sections));
776   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
777                                                   /*num_sites=*/8);
778   base::RunLoop().RunUntilIdle();
779   ASSERT_THAT(sections, Contains(Key(SectionType::PERSONALIZED)));
780   NTPTilesVector tiles = sections.at(SectionType::PERSONALIZED);
781   ASSERT_THAT(tiles.size(), Ge(6ul));
782   // Assert that the home page is the first tile.
783   EXPECT_THAT(tiles[0], MatchesTile("", kHomepageUrl, TileSource::HOMEPAGE));
784 }
785 
TEST_P(MostVisitedSitesTest,ShouldDeduplicateHomepageWithTopSites)786 TEST_P(MostVisitedSitesTest, ShouldDeduplicateHomepageWithTopSites) {
787   FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
788   homepage_client->SetHomepageTileEnabled(true);
789   DisableRemoteSuggestions();
790   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
791       .WillRepeatedly(InvokeCallbackArgument<0>(
792           (MostVisitedURLList{MakeMostVisitedURL("Site 1", "http://site1/"),
793                               MakeMostVisitedURL("", kHomepageUrl)})));
794   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
795   EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
796       .Times(AnyNumber())
797       .WillRepeatedly(Return(false));
798   EXPECT_CALL(
799       mock_observer_,
800       OnURLsAvailable(Contains(Pair(
801           SectionType::PERSONALIZED,
802           AllOf(Contains(MatchesTile("", kHomepageUrl, TileSource::HOMEPAGE)),
803                 Not(Contains(
804                     MatchesTile("", kHomepageUrl, TileSource::TOP_SITES))))))));
805   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
806                                                   /*num_sites=*/3);
807   base::RunLoop().RunUntilIdle();
808 }
809 
TEST_P(MostVisitedSitesTest,ShouldNotIncludeHomepageIfThereIsNone)810 TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomepageIfThereIsNone) {
811   FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
812   homepage_client->SetHomepageTileEnabled(false);
813   DisableRemoteSuggestions();
814   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
815       .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{}));
816   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
817   EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
818       .Times(AnyNumber())
819       .WillRepeatedly(Return(false));
820   EXPECT_CALL(mock_observer_,
821               OnURLsAvailable(Contains(
822                   Pair(SectionType::PERSONALIZED,
823                        Not(Contains(MatchesTile("", kHomepageUrl,
824                                                 TileSource::HOMEPAGE)))))));
825   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
826                                                   /*num_sites=*/3);
827   base::RunLoop().RunUntilIdle();
828 }
829 
TEST_P(MostVisitedSitesTest,ShouldNotIncludeHomepageIfEmptyUrl)830 TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomepageIfEmptyUrl) {
831   const std::string kEmptyHomepageUrl;
832   FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
833   homepage_client->SetHomepageTileEnabled(true);
834   homepage_client->SetHomepageUrl(GURL(kEmptyHomepageUrl));
835   DisableRemoteSuggestions();
836   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
837       .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{}));
838   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
839   EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(kEmptyHomepageUrl)))
840       .Times(AnyNumber())
841       .WillRepeatedly(Return(false));
842   EXPECT_CALL(mock_observer_,
843               OnURLsAvailable(Not(FirstPersonalizedTileIs(
844                   "", kEmptyHomepageUrl, TileSource::HOMEPAGE))));
845   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
846                                                   /*num_sites=*/3);
847   base::RunLoop().RunUntilIdle();
848 }
849 
TEST_P(MostVisitedSitesTest,ShouldNotIncludeHomepageIfBlacklisted)850 TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomepageIfBlacklisted) {
851   FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
852   homepage_client->SetHomepageTileEnabled(true);
853   DisableRemoteSuggestions();
854   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
855       .WillRepeatedly(InvokeCallbackArgument<0>(
856           (MostVisitedURLList{MakeMostVisitedURL("", kHomepageUrl)})));
857   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
858   EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
859       .Times(AnyNumber())
860       .WillRepeatedly(Return(false));
861 
862   EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
863       .Times(AtLeast(1))
864       .WillRepeatedly(Return(true));
865   EXPECT_CALL(mock_observer_,
866               OnURLsAvailable(Contains(
867                   Pair(SectionType::PERSONALIZED,
868                        Not(Contains(MatchesTile("", kHomepageUrl,
869                                                 TileSource::HOMEPAGE)))))));
870 
871   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
872                                                   /*num_sites=*/3);
873   base::RunLoop().RunUntilIdle();
874 }
875 
TEST_P(MostVisitedSitesTest,ShouldPinHomepageAgainIfBlacklistingUndone)876 TEST_P(MostVisitedSitesTest, ShouldPinHomepageAgainIfBlacklistingUndone) {
877   FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
878   homepage_client->SetHomepageTileEnabled(true);
879 
880   DisableRemoteSuggestions();
881   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
882       .WillOnce(InvokeCallbackArgument<0>(
883           (MostVisitedURLList{MakeMostVisitedURL("", kHomepageUrl)})));
884   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
885   EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
886       .Times(AtLeast(1))
887       .WillRepeatedly(Return(true));
888   EXPECT_CALL(mock_observer_,
889               OnURLsAvailable(Contains(
890                   Pair(SectionType::PERSONALIZED,
891                        Not(Contains(MatchesTile("", kHomepageUrl,
892                                                 TileSource::HOMEPAGE)))))));
893 
894   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
895                                                   /*num_sites=*/3);
896   base::RunLoop().RunUntilIdle();
897   VerifyAndClearExpectations();
898 
899   DisableRemoteSuggestions();
900   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
901       .WillOnce(InvokeCallbackArgument<0>(MostVisitedURLList{}));
902   EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
903       .Times(AtLeast(1))
904       .WillRepeatedly(Return(false));
905   EXPECT_CALL(
906       mock_observer_,
907       OnURLsAvailable(Contains(Pair(
908           SectionType::PERSONALIZED,
909           Contains(MatchesTile("", kHomepageUrl, TileSource::HOMEPAGE))))));
910 
911   most_visited_sites_->OnBlockedSitesChanged();
912   base::RunLoop().RunUntilIdle();
913 }
914 
TEST_P(MostVisitedSitesTest,ShouldNotIncludeTileForExploreSitesIfNoClient)915 TEST_P(MostVisitedSitesTest, ShouldNotIncludeTileForExploreSitesIfNoClient) {
916   // Does not register an explore sites client.
917 
918   DisableRemoteSuggestions();
919   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
920       .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{
921           MakeMostVisitedURL("ESPN", "http://espn.com/"),
922           MakeMostVisitedURL("Mobile", "http://m.mobile.de/"),
923           MakeMostVisitedURL("Google", "http://www.google.com/")}));
924   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
925   EXPECT_CALL(mock_observer_,
926               OnURLsAvailable(Not(Contains(
927                   Pair(SectionType::PERSONALIZED,
928                        Contains(TileWithSource(TileSource::EXPLORE)))))));
929   // Note that 5 sites are requested, this means that there should be the 3 from
930   // top sites and two from popular sites.
931   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
932                                                   /*num_sites=*/5);
933   base::RunLoop().RunUntilIdle();
934 }
935 
936 // Tests that the explore sites tile appears when there is a mix of top sites
937 // and popular sites.
TEST_P(MostVisitedSitesTest,ShouldIncludeTileForExploreSites)938 TEST_P(MostVisitedSitesTest, ShouldIncludeTileForExploreSites) {
939   RegisterNewExploreSitesClient();
940   DisableRemoteSuggestions();
941   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
942       .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{
943           MakeMostVisitedURL("ESPN", "http://espn.com/"),
944           MakeMostVisitedURL("Mobile", "http://m.mobile.de/"),
945           MakeMostVisitedURL("Google", "http://www.google.com/")}));
946   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
947   EXPECT_CALL(mock_observer_,
948               OnURLsAvailable(LastTileIs(kTestExploreTitle, kTestExploreUrl,
949                                          TileSource::EXPLORE)));
950   // Note that 5 sites are requested, this means that there should be the 3 from
951   // top sites, one from popular sites, and one explore tile.
952   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
953                                                   /*num_sites=*/5);
954   base::RunLoop().RunUntilIdle();
955 }
956 
TEST_P(MostVisitedSitesTest,RemovesPersonalSiteIfExploreSitesTilePresent)957 TEST_P(MostVisitedSitesTest, RemovesPersonalSiteIfExploreSitesTilePresent) {
958   RegisterNewExploreSitesClient();
959   DisableRemoteSuggestions();
960   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
961       .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{
962           MakeMostVisitedURL("ESPN", "http://espn.com/"),
963           MakeMostVisitedURL("Mobile", "http://m.mobile.de/"),
964           MakeMostVisitedURL("Google", "http://www.google.com/")}));
965   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
966   EXPECT_CALL(mock_observer_,
967               OnURLsAvailable(Contains(Pair(
968                   SectionType::PERSONALIZED,
969                   ElementsAre(MatchesTile("ESPN", "http://espn.com/",
970                                           TileSource::TOP_SITES),
971                               MatchesTile("Mobile", "http://m.mobile.de/",
972                                           TileSource::TOP_SITES),
973                               MatchesTile(kTestExploreTitle, kTestExploreUrl,
974                                           TileSource::EXPLORE))))));
975   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
976                                                   /*num_sites=*/3);
977   base::RunLoop().RunUntilIdle();
978 }
979 
TEST_P(MostVisitedSitesTest,ShouldInformSuggestionSourcesWhenBlacklisting)980 TEST_P(MostVisitedSitesTest, ShouldInformSuggestionSourcesWhenBlacklisting) {
981   EXPECT_CALL(*mock_top_sites_, AddBlacklistedURL(Eq(GURL(kHomepageUrl))))
982       .Times(1);
983   EXPECT_CALL(mock_suggestions_service_, BlacklistURL(Eq(GURL(kHomepageUrl))))
984       .Times(AnyNumber());
985   most_visited_sites_->AddOrRemoveBlacklistedUrl(GURL(kHomepageUrl),
986                                                  /*add_url=*/true);
987   EXPECT_CALL(*mock_top_sites_, RemoveBlacklistedURL(Eq(GURL(kHomepageUrl))))
988       .Times(1);
989   EXPECT_CALL(mock_suggestions_service_,
990               UndoBlacklistURL(Eq(GURL(kHomepageUrl))))
991       .Times(AnyNumber());
992   most_visited_sites_->AddOrRemoveBlacklistedUrl(GURL(kHomepageUrl),
993                                                  /*add_url=*/false);
994 }
995 
TEST_P(MostVisitedSitesTest,ShouldDeduplicatePopularSitesWithMostVisitedIffHostAndTitleMatches)996 TEST_P(MostVisitedSitesTest,
997        ShouldDeduplicatePopularSitesWithMostVisitedIffHostAndTitleMatches) {
998   pref_service_.SetString(prefs::kPopularSitesOverrideCountry, "US");
999   RecreateMostVisitedSites();  // Refills cache with ESPN and Google News.
1000   DisableRemoteSuggestions();
1001   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
1002       .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{
1003           MakeMostVisitedURL("ESPN", "http://espn.com/"),
1004           MakeMostVisitedURL("Mobile", "http://m.mobile.de/"),
1005           MakeMostVisitedURL("Google", "http://www.google.com/")}));
1006   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
1007   std::map<SectionType, NTPTilesVector> sections;
1008   EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1009       .WillOnce(SaveArg<0>(&sections));
1010 
1011   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1012                                                   /*num_sites=*/6);
1013   base::RunLoop().RunUntilIdle();
1014   ASSERT_THAT(sections, Contains(Key(SectionType::PERSONALIZED)));
1015   EXPECT_THAT(sections.at(SectionType::PERSONALIZED),
1016               Contains(MatchesTile("Google", "http://www.google.com/",
1017                                    TileSource::TOP_SITES)));
1018   if (IsPopularSitesFeatureEnabled()) {
1019     EXPECT_THAT(sections.at(SectionType::PERSONALIZED),
1020                 Contains(MatchesTile("Google News", "http://news.google.com/",
1021                                      TileSource::POPULAR)));
1022   }
1023   EXPECT_THAT(sections.at(SectionType::PERSONALIZED),
1024               AllOf(Contains(MatchesTile("ESPN", "http://espn.com/",
1025                                          TileSource::TOP_SITES)),
1026                     Contains(MatchesTile("Mobile", "http://m.mobile.de/",
1027                                          TileSource::TOP_SITES)),
1028                     Not(Contains(MatchesTile("ESPN", "http://www.espn.com/",
1029                                              TileSource::POPULAR))),
1030                     Not(Contains(MatchesTile("Mobile", "http://www.mobile.de/",
1031                                              TileSource::POPULAR)))));
1032 }
1033 
TEST_P(MostVisitedSitesTest,ShouldHandleTopSitesCacheHit)1034 TEST_P(MostVisitedSitesTest, ShouldHandleTopSitesCacheHit) {
1035   // If cached, TopSites returns the tiles synchronously, running the callback
1036   // even before the function returns.
1037   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
1038       .WillRepeatedly(InvokeCallbackArgument<0>(
1039           MostVisitedURLList{MakeMostVisitedURL("Site 1", "http://site1/")}));
1040 
1041   InSequence seq;
1042   EXPECT_CALL(mock_suggestions_service_, AddCallback(_))
1043       .WillOnce(Invoke(&suggestions_service_callbacks_,
1044                        &SuggestionsService::ResponseCallbackList::Add));
1045   EXPECT_CALL(mock_suggestions_service_, GetSuggestionsDataFromCache())
1046       .WillOnce(Return(SuggestionsProfile()));  // Empty cache.
1047   if (IsPopularSitesFeatureEnabled()) {
1048     EXPECT_CALL(
1049         mock_observer_,
1050         OnURLsAvailable(Contains(Pair(
1051             SectionType::PERSONALIZED,
1052             ElementsAre(
1053                 MatchesTile("Site 1", "http://site1/", TileSource::TOP_SITES),
1054                 MatchesTile("PopularSite1", "http://popularsite1/",
1055                             TileSource::POPULAR),
1056                 MatchesTile("PopularSite2", "http://popularsite2/",
1057                             TileSource::POPULAR))))));
1058   } else {
1059     EXPECT_CALL(mock_observer_,
1060                 OnURLsAvailable(Contains(
1061                     Pair(SectionType::PERSONALIZED,
1062                          ElementsAre(MatchesTile("Site 1", "http://site1/",
1063                                                  TileSource::TOP_SITES))))));
1064   }
1065   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
1066   EXPECT_CALL(mock_suggestions_service_, FetchSuggestionsData())
1067       .WillOnce(Return(true));
1068 
1069   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1070                                                   /*num_sites=*/3);
1071   VerifyAndClearExpectations();
1072   EXPECT_FALSE(suggestions_service_callbacks_.empty());
1073   CHECK(top_sites_callbacks_.empty());
1074 
1075   // Update by TopSites is propagated.
1076   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
1077       .WillOnce(InvokeCallbackArgument<0>(
1078           MostVisitedURLList{MakeMostVisitedURL("Site 2", "http://site2/")}));
1079   if (IsPopularSitesFeatureEnabled()) {
1080     EXPECT_CALL(*mock_top_sites_, IsBlacklisted(_))
1081         .WillRepeatedly(Return(false));
1082   }
1083   EXPECT_CALL(mock_observer_, OnURLsAvailable(_));
1084   mock_top_sites_->NotifyTopSitesChanged(
1085       history::TopSitesObserver::ChangeReason::MOST_VISITED);
1086   base::RunLoop().RunUntilIdle();
1087 }
1088 
1089 INSTANTIATE_TEST_SUITE_P(MostVisitedSitesTest,
1090                          MostVisitedSitesTest,
1091                          ::testing::Combine(::testing::Bool(),
1092                                             ::testing::Bool()));
1093 
TEST(MostVisitedSitesTest,ShouldDeduplicateDomainWithNoWwwDomain)1094 TEST(MostVisitedSitesTest, ShouldDeduplicateDomainWithNoWwwDomain) {
1095   EXPECT_TRUE(MostVisitedSites::IsHostOrMobilePageKnown({"www.mobile.de"},
1096                                                         "mobile.de"));
1097   EXPECT_TRUE(MostVisitedSites::IsHostOrMobilePageKnown({"mobile.de"},
1098                                                         "www.mobile.de"));
1099   EXPECT_TRUE(MostVisitedSites::IsHostOrMobilePageKnown({"mobile.co.uk"},
1100                                                         "www.mobile.co.uk"));
1101 }
1102 
TEST(MostVisitedSitesTest,ShouldDeduplicateDomainByRemovingMobilePrefixes)1103 TEST(MostVisitedSitesTest, ShouldDeduplicateDomainByRemovingMobilePrefixes) {
1104   EXPECT_TRUE(
1105       MostVisitedSites::IsHostOrMobilePageKnown({"bbc.co.uk"}, "m.bbc.co.uk"));
1106   EXPECT_TRUE(
1107       MostVisitedSites::IsHostOrMobilePageKnown({"m.bbc.co.uk"}, "bbc.co.uk"));
1108   EXPECT_TRUE(MostVisitedSites::IsHostOrMobilePageKnown({"cnn.com"},
1109                                                         "edition.cnn.com"));
1110   EXPECT_TRUE(MostVisitedSites::IsHostOrMobilePageKnown({"edition.cnn.com"},
1111                                                         "cnn.com"));
1112   EXPECT_TRUE(
1113       MostVisitedSites::IsHostOrMobilePageKnown({"cnn.com"}, "mobile.cnn.com"));
1114   EXPECT_TRUE(
1115       MostVisitedSites::IsHostOrMobilePageKnown({"mobile.cnn.com"}, "cnn.com"));
1116 }
1117 
TEST(MostVisitedSitesTest,ShouldDeduplicateDomainByReplacingMobilePrefixes)1118 TEST(MostVisitedSitesTest, ShouldDeduplicateDomainByReplacingMobilePrefixes) {
1119   EXPECT_TRUE(MostVisitedSites::IsHostOrMobilePageKnown({"www.bbc.co.uk"},
1120                                                         "m.bbc.co.uk"));
1121   EXPECT_TRUE(MostVisitedSites::IsHostOrMobilePageKnown({"m.mobile.de"},
1122                                                         "www.mobile.de"));
1123   EXPECT_TRUE(MostVisitedSites::IsHostOrMobilePageKnown({"www.cnn.com"},
1124                                                         "edition.cnn.com"));
1125   EXPECT_TRUE(MostVisitedSites::IsHostOrMobilePageKnown({"mobile.cnn.com"},
1126                                                         "www.cnn.com"));
1127 }
1128 
1129 #if !defined(OS_ANDROID) && !defined(OS_IOS)
1130 class MostVisitedSitesWithCustomLinksTest : public MostVisitedSitesTest {
1131  public:
MostVisitedSitesWithCustomLinksTest()1132   MostVisitedSitesWithCustomLinksTest() {
1133     EnableCustomLinks();
1134     RecreateMostVisitedSites();
1135   }
1136 
ExpectBuildWithTopSites(const MostVisitedURLList & expected_list,std::map<SectionType,NTPTilesVector> * sections)1137   void ExpectBuildWithTopSites(
1138       const MostVisitedURLList& expected_list,
1139       std::map<SectionType, NTPTilesVector>* sections) {
1140     EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
1141         .WillRepeatedly(InvokeCallbackArgument<0>(expected_list));
1142     EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
1143     EXPECT_CALL(*mock_custom_links_, IsInitialized())
1144         .WillRepeatedly(Return(false));
1145     EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1146         .WillOnce(SaveArg<0>(sections));
1147   }
1148 
ExpectBuildWithSuggestions(const std::vector<ChromeSuggestion> & suggestions,std::map<SectionType,NTPTilesVector> * sections)1149   void ExpectBuildWithSuggestions(
1150       const std::vector<ChromeSuggestion>& suggestions,
1151       std::map<SectionType, NTPTilesVector>* sections) {
1152     EXPECT_CALL(mock_suggestions_service_, AddCallback(_))
1153         .WillOnce(Invoke(&suggestions_service_callbacks_,
1154                          &SuggestionsService::ResponseCallbackList::Add));
1155     EXPECT_CALL(mock_suggestions_service_, GetSuggestionsDataFromCache())
1156         .WillOnce(Return(MakeProfile(suggestions)));
1157     EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
1158     EXPECT_CALL(mock_suggestions_service_, FetchSuggestionsData())
1159         .WillOnce(Return(true));
1160     EXPECT_CALL(*mock_custom_links_, IsInitialized())
1161         .WillRepeatedly(Return(false));
1162     EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1163         .WillOnce(SaveArg<0>(sections));
1164   }
1165 
ExpectBuildWithCustomLinks(const std::vector<CustomLinksManager::Link> & expected_links,std::map<SectionType,NTPTilesVector> * sections)1166   void ExpectBuildWithCustomLinks(
1167       const std::vector<CustomLinksManager::Link>& expected_links,
1168       std::map<SectionType, NTPTilesVector>* sections) {
1169     EXPECT_CALL(*mock_custom_links_, IsInitialized())
1170         .WillRepeatedly(Return(true));
1171     EXPECT_CALL(*mock_custom_links_, GetLinks())
1172         .WillOnce(ReturnRef(expected_links));
1173     EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1174         .WillOnce(SaveArg<0>(sections));
1175   }
1176 };
1177 
TEST_P(MostVisitedSitesWithCustomLinksTest,ShouldOnlyBuildCustomLinksWhenInitialized)1178 TEST_P(MostVisitedSitesWithCustomLinksTest,
1179        ShouldOnlyBuildCustomLinksWhenInitialized) {
1180   const char kTestUrl[] = "http://site1/";
1181   const char kTestTitle[] = "Site 1";
1182   std::vector<CustomLinksManager::Link> expected_links(
1183       {CustomLinksManager::Link{GURL(kTestUrl),
1184                                 base::UTF8ToUTF16(kTestTitle)}});
1185   std::map<SectionType, NTPTilesVector> sections;
1186   DisableRemoteSuggestions();
1187 
1188   // Build tiles when custom links is not initialized. Tiles should be Top
1189   // Sites.
1190   EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1191   ExpectBuildWithTopSites(
1192       MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, &sections);
1193   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1194                                                   /*num_sites=*/1);
1195   base::RunLoop().RunUntilIdle();
1196   EXPECT_THAT(
1197       sections.at(SectionType::PERSONALIZED),
1198       ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::TOP_SITES)));
1199 
1200   // Initialize custom links and rebuild tiles. Tiles should be custom links.
1201   EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
1202   ExpectBuildWithCustomLinks(expected_links, &sections);
1203   most_visited_sites_->InitializeCustomLinks();
1204   most_visited_sites_->RefreshTiles();
1205   base::RunLoop().RunUntilIdle();
1206   EXPECT_THAT(
1207       sections.at(SectionType::PERSONALIZED),
1208       ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::CUSTOM_LINKS)));
1209 
1210   // Uninitialize custom links and rebuild tiles. Tiles should be Top Sites.
1211   EXPECT_CALL(*mock_custom_links_, Uninitialize());
1212   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
1213       .WillRepeatedly(InvokeCallbackArgument<0>(
1214           MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}));
1215   EXPECT_CALL(*mock_custom_links_, IsInitialized())
1216       .WillRepeatedly(Return(false));
1217   EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1218       .WillOnce(SaveArg<0>(&sections));
1219   most_visited_sites_->UninitializeCustomLinks();
1220   base::RunLoop().RunUntilIdle();
1221   EXPECT_THAT(
1222       sections.at(SectionType::PERSONALIZED),
1223       ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::TOP_SITES)));
1224 }
1225 
TEST_P(MostVisitedSitesWithCustomLinksTest,ShouldFavorCustomLinksOverTopSites)1226 TEST_P(MostVisitedSitesWithCustomLinksTest,
1227        ShouldFavorCustomLinksOverTopSites) {
1228   const char kTestUrl[] = "http://site1/";
1229   const char kTestTitle[] = "Site 1";
1230   std::vector<CustomLinksManager::Link> expected_links(
1231       {CustomLinksManager::Link{GURL(kTestUrl),
1232                                 base::UTF8ToUTF16(kTestTitle)}});
1233   std::map<SectionType, NTPTilesVector> sections;
1234   DisableRemoteSuggestions();
1235 
1236   // Build tiles when custom links is not initialized. Tiles should be Top
1237   // Sites.
1238   EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1239   ExpectBuildWithTopSites(
1240       MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, &sections);
1241   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1242                                                   /*num_sites=*/1);
1243   base::RunLoop().RunUntilIdle();
1244   ASSERT_THAT(
1245       sections.at(SectionType::PERSONALIZED),
1246       ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::TOP_SITES)));
1247 
1248   // Initialize custom links and rebuild tiles. Tiles should be custom links.
1249   EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
1250   ExpectBuildWithCustomLinks(expected_links, &sections);
1251   most_visited_sites_->InitializeCustomLinks();
1252   most_visited_sites_->RefreshTiles();
1253   base::RunLoop().RunUntilIdle();
1254   ASSERT_THAT(
1255       sections.at(SectionType::PERSONALIZED),
1256       ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::CUSTOM_LINKS)));
1257 
1258   // Initiate notification for new Top Sites. This should be ignored.
1259   EXPECT_CALL(*mock_custom_links_, IsInitialized()).WillOnce(Return(true));
1260   // Notify with an empty SuggestionsProfile first to trigger a query for
1261   // TopSites.
1262   suggestions_service_callbacks_.Notify(SuggestionsProfile());
1263   VerifyAndClearExpectations();
1264   EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(0);
1265   top_sites_callbacks_.ClearAndNotify(
1266       {MakeMostVisitedURL("Site 2", "http://site2/")});
1267   base::RunLoop().RunUntilIdle();
1268 }
1269 
TEST_P(MostVisitedSitesWithCustomLinksTest,ShouldFavorCustomLinksOverSuggestions)1270 TEST_P(MostVisitedSitesWithCustomLinksTest,
1271        ShouldFavorCustomLinksOverSuggestions) {
1272   const char kTestUrl[] = "http://site1/";
1273   const char kTestTitle[] = "Site 1";
1274   std::vector<CustomLinksManager::Link> expected_links(
1275       {CustomLinksManager::Link{GURL(kTestUrl),
1276                                 base::UTF8ToUTF16(kTestTitle)}});
1277   std::map<SectionType, NTPTilesVector> sections;
1278 
1279   // Build tiles when custom links is not initialized. Tiles should be from
1280   // suggestions.
1281   EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1282   ExpectBuildWithSuggestions({MakeSuggestion(kTestTitle, kTestUrl)}, &sections);
1283   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1284                                                   /*num_sites=*/1);
1285   base::RunLoop().RunUntilIdle();
1286   ASSERT_THAT(sections.at(SectionType::PERSONALIZED),
1287               ElementsAre(MatchesTile(kTestTitle, kTestUrl,
1288                                       TileSource::SUGGESTIONS_SERVICE)));
1289 
1290   // Initialize custom links and rebuild tiles. Tiles should be custom links.
1291   EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
1292   ExpectBuildWithCustomLinks(expected_links, &sections);
1293   most_visited_sites_->InitializeCustomLinks();
1294   most_visited_sites_->RefreshTiles();
1295   base::RunLoop().RunUntilIdle();
1296   ASSERT_THAT(
1297       sections.at(SectionType::PERSONALIZED),
1298       ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::CUSTOM_LINKS)));
1299 
1300   // Initiate notification for new suggestions. This should be ignored.
1301   EXPECT_CALL(*mock_custom_links_, IsInitialized())
1302       .WillRepeatedly(Return(true));
1303   EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(0);
1304   suggestions_service_callbacks_.Notify(
1305       MakeProfile({MakeSuggestion("Site 2", "http://site2/")}));
1306   base::RunLoop().RunUntilIdle();
1307 }
1308 
TEST_P(MostVisitedSitesWithCustomLinksTest,DisableCustomLinksWhenNotInitialized)1309 TEST_P(MostVisitedSitesWithCustomLinksTest,
1310        DisableCustomLinksWhenNotInitialized) {
1311   const char kTestUrl[] = "http://site1/";
1312   const char kTestTitle[] = "Site 1";
1313   std::vector<CustomLinksManager::Link> expected_links(
1314       {CustomLinksManager::Link{GURL(kTestUrl),
1315                                 base::UTF8ToUTF16(kTestTitle)}});
1316   std::map<SectionType, NTPTilesVector> sections;
1317 
1318   // Build tiles when custom links is not initialized. Tiles should be from
1319   // suggestions.
1320   EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1321   ExpectBuildWithSuggestions({MakeSuggestion(kTestTitle, kTestUrl)}, &sections);
1322   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1323                                                   /*num_sites=*/1);
1324   base::RunLoop().RunUntilIdle();
1325   ASSERT_THAT(sections.at(SectionType::PERSONALIZED),
1326               ElementsAre(MatchesTile(kTestTitle, kTestUrl,
1327                                       TileSource::SUGGESTIONS_SERVICE)));
1328 
1329   // Disable custom links. Tiles should rebuild but not send an update.
1330   EXPECT_CALL(mock_suggestions_service_, GetSuggestionsDataFromCache())
1331       .WillOnce(Return(MakeProfile({MakeSuggestion(kTestTitle, kTestUrl)})));
1332   EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(0);
1333   most_visited_sites_->EnableCustomLinks(false);
1334   base::RunLoop().RunUntilIdle();
1335 
1336   // Try to disable custom links again. This should not rebuild the tiles.
1337   EXPECT_CALL(mock_suggestions_service_, GetSuggestionsDataFromCache())
1338       .Times(0);
1339   EXPECT_CALL(*mock_custom_links_, GetLinks()).Times(0);
1340   most_visited_sites_->EnableCustomLinks(false);
1341   base::RunLoop().RunUntilIdle();
1342 }
1343 
TEST_P(MostVisitedSitesWithCustomLinksTest,DisableCustomLinksWhenInitialized)1344 TEST_P(MostVisitedSitesWithCustomLinksTest, DisableCustomLinksWhenInitialized) {
1345   const char kTestUrl[] = "http://site1/";
1346   const char kTestTitle[] = "Site 1";
1347   std::vector<CustomLinksManager::Link> expected_links(
1348       {CustomLinksManager::Link{GURL(kTestUrl),
1349                                 base::UTF8ToUTF16(kTestTitle)}});
1350   std::map<SectionType, NTPTilesVector> sections;
1351 
1352   // Build tiles when custom links is initialized and not disabled. Tiles should
1353   // be custom links.
1354   EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1355   EXPECT_CALL(mock_suggestions_service_, AddCallback(_))
1356       .WillOnce(Invoke(&suggestions_service_callbacks_,
1357                        &SuggestionsService::ResponseCallbackList::Add));
1358   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
1359   EXPECT_CALL(mock_suggestions_service_, FetchSuggestionsData())
1360       .WillOnce(Return(false));
1361   ExpectBuildWithCustomLinks(expected_links, &sections);
1362   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1363                                                   /*num_sites=*/1);
1364   base::RunLoop().RunUntilIdle();
1365   ASSERT_THAT(
1366       sections.at(SectionType::PERSONALIZED),
1367       ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::CUSTOM_LINKS)));
1368 
1369   // Disable custom links. Tiles should rebuild and return suggestions.
1370   EXPECT_CALL(mock_suggestions_service_, GetSuggestionsDataFromCache())
1371       .WillOnce(Return(MakeProfile({MakeSuggestion(kTestTitle, kTestUrl)})));
1372   EXPECT_CALL(*mock_custom_links_, IsInitialized())
1373       .WillRepeatedly(Return(false));
1374   EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1375       .WillOnce(SaveArg<0>(&sections));
1376   most_visited_sites_->EnableCustomLinks(false);
1377   base::RunLoop().RunUntilIdle();
1378   EXPECT_THAT(sections.at(SectionType::PERSONALIZED),
1379               ElementsAre(MatchesTile(kTestTitle, kTestUrl,
1380                                       TileSource::SUGGESTIONS_SERVICE)));
1381 
1382   // Re-enable custom links. Tiles should rebuild and return custom links.
1383   ExpectBuildWithCustomLinks(expected_links, &sections);
1384   most_visited_sites_->EnableCustomLinks(true);
1385   base::RunLoop().RunUntilIdle();
1386   ASSERT_THAT(
1387       sections.at(SectionType::PERSONALIZED),
1388       ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::CUSTOM_LINKS)));
1389 }
1390 
TEST_P(MostVisitedSitesWithCustomLinksTest,ShouldGenerateShortTitleForTopSites)1391 TEST_P(MostVisitedSitesWithCustomLinksTest,
1392        ShouldGenerateShortTitleForTopSites) {
1393   std::string kTestUrl1 = "https://www.imdb.com/";
1394   std::string kTestTitle1 = "IMDb - Movies, TV and Celebrities - IMDb";
1395   std::string kTestUrl2 = "https://drive.google.com/";
1396   std::string kTestTitle2 =
1397       "Google Drive - Cloud Storage & File Backup for Photos, Docs & More";
1398   std::string kTestUrl3 = "https://amazon.com/";
1399   std::string kTestTitle3 =
1400       "Amazon.com: Online Shopping for Electronics, Apparel, Computers, Books, "
1401       "DVDs & more";
1402   std::map<SectionType, NTPTilesVector> sections;
1403   DisableRemoteSuggestions();
1404 
1405   // Build tiles from Top Sites. The tiles should have short titles.
1406   EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1407   ExpectBuildWithTopSites(
1408       MostVisitedURLList{MakeMostVisitedURL(kTestTitle1, kTestUrl1),
1409                          MakeMostVisitedURL(kTestTitle2, kTestUrl2),
1410                          MakeMostVisitedURL(kTestTitle3, kTestUrl3)},
1411       &sections);
1412   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1413                                                   /*num_sites=*/3);
1414   base::RunLoop().RunUntilIdle();
1415 
1416   EXPECT_THAT(
1417       sections.at(SectionType::PERSONALIZED),
1418       ElementsAre(
1419           MatchesTile(/* The short title generated by the heuristic */ "IMDb",
1420                       kTestUrl1, TileSource::TOP_SITES),
1421           MatchesTile(
1422               /* The short title generated by the heuristic */ "Google Drive",
1423               kTestUrl2, TileSource::TOP_SITES),
1424           MatchesTile(
1425               /* The short title generated by the heuristic */ "Amazon.com",
1426               kTestUrl3, TileSource::TOP_SITES)));
1427 }
1428 
TEST_P(MostVisitedSitesWithCustomLinksTest,ShouldGenerateShortTitleForSuggestions)1429 TEST_P(MostVisitedSitesWithCustomLinksTest,
1430        ShouldGenerateShortTitleForSuggestions) {
1431   std::string kTestUrl1 = "https://www.imdb.com/";
1432   std::string kTestTitle1 = "IMDb - Movies, TV and Celebrities - IMDb";
1433   std::string kTestUrl2 = "https://drive.google.com/";
1434   std::string kTestTitle2 =
1435       "Google Drive - Cloud Storage & File Backup for Photos, Docs & More";
1436   std::string kTestUrl3 = "https://amazon.com/";
1437   std::string kTestTitle3 =
1438       "Amazon.com: Online Shopping for Electronics, Apparel, Computers, Books, "
1439       "DVDs & more";
1440   std::map<SectionType, NTPTilesVector> sections;
1441 
1442   // Build tiles from Suggestions. The tiles should have short titles.
1443   EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1444   ExpectBuildWithSuggestions({MakeSuggestion(kTestTitle1, kTestUrl1),
1445                               MakeSuggestion(kTestTitle2, kTestUrl2),
1446                               MakeSuggestion(kTestTitle3, kTestUrl3)},
1447                              &sections);
1448   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1449                                                   /*num_sites=*/3);
1450   base::RunLoop().RunUntilIdle();
1451 
1452   EXPECT_THAT(
1453       sections.at(SectionType::PERSONALIZED),
1454       ElementsAre(
1455           MatchesTile(/* The short title generated by the heuristic */ "IMDb",
1456                       kTestUrl1, TileSource::SUGGESTIONS_SERVICE),
1457           MatchesTile(
1458               /* The short title generated by the heuristic */ "Google Drive",
1459               kTestUrl2, TileSource::SUGGESTIONS_SERVICE),
1460           MatchesTile(
1461               /* The short title generated by the heuristic */ "Amazon.com",
1462               kTestUrl3, TileSource::SUGGESTIONS_SERVICE)));
1463 }
1464 
TEST_P(MostVisitedSitesWithCustomLinksTest,ShouldNotCrashIfReceiveAnEmptyTitle)1465 TEST_P(MostVisitedSitesWithCustomLinksTest,
1466        ShouldNotCrashIfReceiveAnEmptyTitle) {
1467   std::string kTestUrl1 = "https://site1/";
1468   std::string kTestTitle1 = "";  // Empty title
1469   std::string kTestUrl2 = "https://site2/";
1470   std::string kTestTitle2 = "       ";  // Title only contains spaces
1471   std::map<SectionType, NTPTilesVector> sections;
1472   DisableRemoteSuggestions();
1473 
1474   // Build tiles from Top Sites. The tiles should have short titles.
1475   EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1476   ExpectBuildWithTopSites(
1477       MostVisitedURLList{MakeMostVisitedURL(kTestTitle1, kTestUrl1),
1478                          MakeMostVisitedURL(kTestTitle2, kTestUrl2)},
1479       &sections);
1480   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1481                                                   /*num_sites=*/2);
1482   base::RunLoop().RunUntilIdle();
1483 
1484   // Both cases should not crash and generate an empty title tile.
1485   EXPECT_THAT(sections.at(SectionType::PERSONALIZED),
1486               ElementsAre(MatchesTile("", kTestUrl1, TileSource::TOP_SITES),
1487                           MatchesTile("", kTestUrl2, TileSource::TOP_SITES)));
1488 }
1489 
TEST_P(MostVisitedSitesWithCustomLinksTest,UninitializeCustomLinksOnUndoAfterFirstAction)1490 TEST_P(MostVisitedSitesWithCustomLinksTest,
1491        UninitializeCustomLinksOnUndoAfterFirstAction) {
1492   const char kTestUrl[] = "http://site1/";
1493   const char kTestTitle[] = "Site 1";
1494   std::vector<CustomLinksManager::Link> expected_links(
1495       {CustomLinksManager::Link{GURL(kTestUrl),
1496                                 base::UTF8ToUTF16(kTestTitle)}});
1497   std::map<SectionType, NTPTilesVector> sections;
1498   DisableRemoteSuggestions();
1499 
1500   // Build initial tiles with Top Sites.
1501   EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1502   ExpectBuildWithTopSites(
1503       MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, &sections);
1504   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1505                                                   /*num_sites=*/1);
1506   base::RunLoop().RunUntilIdle();
1507   ASSERT_THAT(
1508       sections.at(SectionType::PERSONALIZED),
1509       ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::TOP_SITES)));
1510 
1511   // Initialize custom links and complete a custom link action.
1512   EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
1513   EXPECT_CALL(*mock_custom_links_, AddLink(_, _)).WillOnce(Return(true));
1514   EXPECT_CALL(*mock_custom_links_, IsInitialized())
1515       .WillRepeatedly(Return(true));
1516   EXPECT_CALL(*mock_custom_links_, GetLinks())
1517       .WillRepeatedly(ReturnRef(expected_links));
1518   EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1519       .WillOnce(SaveArg<0>(&sections));
1520   most_visited_sites_->AddCustomLink(GURL("test.com"),
1521                                      base::UTF8ToUTF16("test"));
1522   base::RunLoop().RunUntilIdle();
1523   ASSERT_THAT(
1524       sections.at(SectionType::PERSONALIZED),
1525       ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::CUSTOM_LINKS)));
1526 
1527   // Undo the action. This should uninitialize custom links.
1528   EXPECT_CALL(*mock_custom_links_, UndoAction()).Times(0);
1529   EXPECT_CALL(*mock_custom_links_, Uninitialize());
1530   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
1531       .WillRepeatedly(InvokeCallbackArgument<0>(
1532           MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}));
1533   EXPECT_CALL(*mock_custom_links_, IsInitialized())
1534       .WillRepeatedly(Return(false));
1535   EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1536       .WillOnce(SaveArg<0>(&sections));
1537   most_visited_sites_->UndoCustomLinkAction();
1538   base::RunLoop().RunUntilIdle();
1539   ASSERT_THAT(
1540       sections.at(SectionType::PERSONALIZED),
1541       ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::TOP_SITES)));
1542 }
1543 
TEST_P(MostVisitedSitesWithCustomLinksTest,DontUninitializeCustomLinksOnUndoAfterMultipleActions)1544 TEST_P(MostVisitedSitesWithCustomLinksTest,
1545        DontUninitializeCustomLinksOnUndoAfterMultipleActions) {
1546   const char kTestUrl[] = "http://site1/";
1547   const char kTestTitle[] = "Site 1";
1548   std::vector<CustomLinksManager::Link> expected_links(
1549       {CustomLinksManager::Link{GURL(kTestUrl),
1550                                 base::UTF8ToUTF16(kTestTitle)}});
1551   std::map<SectionType, NTPTilesVector> sections;
1552   DisableRemoteSuggestions();
1553 
1554   // Build initial tiles with Top Sites.
1555   EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1556   ExpectBuildWithTopSites(
1557       MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, &sections);
1558   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1559                                                   /*num_sites=*/1);
1560   base::RunLoop().RunUntilIdle();
1561   ASSERT_THAT(
1562       sections.at(SectionType::PERSONALIZED),
1563       ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::TOP_SITES)));
1564 
1565   // Initialize custom links and complete a custom link action.
1566   EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
1567   EXPECT_CALL(*mock_custom_links_, UpdateLink(_, _, _)).WillOnce(Return(true));
1568   EXPECT_CALL(*mock_custom_links_, IsInitialized())
1569       .WillRepeatedly(Return(true));
1570   EXPECT_CALL(*mock_custom_links_, GetLinks())
1571       .WillRepeatedly(ReturnRef(expected_links));
1572   EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1573       .WillOnce(SaveArg<0>(&sections));
1574   most_visited_sites_->UpdateCustomLink(GURL("test.com"), GURL("test.com"),
1575                                         base::UTF8ToUTF16("test"));
1576   base::RunLoop().RunUntilIdle();
1577   ASSERT_THAT(
1578       sections.at(SectionType::PERSONALIZED),
1579       ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::CUSTOM_LINKS)));
1580 
1581   // Complete a second custom link action.
1582   EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(false));
1583   EXPECT_CALL(*mock_custom_links_, DeleteLink(_)).WillOnce(Return(true));
1584   EXPECT_CALL(*mock_custom_links_, IsInitialized())
1585       .WillRepeatedly(Return(true));
1586   EXPECT_CALL(*mock_custom_links_, GetLinks())
1587       .WillOnce(ReturnRef(expected_links));
1588   most_visited_sites_->DeleteCustomLink(GURL("test.com"));
1589   base::RunLoop().RunUntilIdle();
1590 
1591   // Undo the second action. This should not uninitialize custom links.
1592   EXPECT_CALL(*mock_custom_links_, UndoAction()).WillOnce(Return(true));
1593   EXPECT_CALL(*mock_custom_links_, Uninitialize()).Times(0);
1594   EXPECT_CALL(*mock_custom_links_, IsInitialized()).WillOnce(Return(true));
1595   EXPECT_CALL(*mock_custom_links_, GetLinks())
1596       .WillOnce(ReturnRef(expected_links));
1597   most_visited_sites_->UndoCustomLinkAction();
1598   base::RunLoop().RunUntilIdle();
1599 }
1600 
TEST_P(MostVisitedSitesWithCustomLinksTest,UninitializeCustomLinksIfFirstActionFails)1601 TEST_P(MostVisitedSitesWithCustomLinksTest,
1602        UninitializeCustomLinksIfFirstActionFails) {
1603   const char kTestUrl[] = "http://site1/";
1604   const char kTestTitle[] = "Site 1";
1605   std::vector<CustomLinksManager::Link> expected_links(
1606       {CustomLinksManager::Link{GURL(kTestUrl),
1607                                 base::UTF8ToUTF16(kTestTitle)}});
1608   std::map<SectionType, NTPTilesVector> sections;
1609   DisableRemoteSuggestions();
1610 
1611   // Build initial tiles with Top Sites.
1612   EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1613   ExpectBuildWithTopSites(
1614       MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, &sections);
1615   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1616                                                   /*num_sites=*/1);
1617   base::RunLoop().RunUntilIdle();
1618   ASSERT_THAT(
1619       sections.at(SectionType::PERSONALIZED),
1620       ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::TOP_SITES)));
1621 
1622   // Fail to add a custom link. This should not initialize custom links nor
1623   // notify.
1624   EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
1625   EXPECT_CALL(*mock_custom_links_, AddLink(_, _)).WillOnce(Return(false));
1626   EXPECT_CALL(*mock_custom_links_, IsInitialized())
1627       .WillRepeatedly(Return(false));
1628   EXPECT_CALL(*mock_custom_links_, Uninitialize());
1629   EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(0);
1630   most_visited_sites_->AddCustomLink(GURL(kTestUrl), base::UTF8ToUTF16("test"));
1631   base::RunLoop().RunUntilIdle();
1632 
1633   // Fail to edit a custom link. This should not initialize custom links nor
1634   // notify.
1635   EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
1636   EXPECT_CALL(*mock_custom_links_, UpdateLink(_, _, _)).WillOnce(Return(false));
1637   EXPECT_CALL(*mock_custom_links_, IsInitialized())
1638       .WillRepeatedly(Return(false));
1639   EXPECT_CALL(*mock_custom_links_, Uninitialize());
1640   EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(0);
1641   most_visited_sites_->UpdateCustomLink(GURL("test.com"), GURL("test2.com"),
1642                                         base::UTF8ToUTF16("test"));
1643   base::RunLoop().RunUntilIdle();
1644 
1645   // Fail to reorder a custom link. This should not initialize custom links nor
1646   // notify.
1647   EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
1648   EXPECT_CALL(*mock_custom_links_, ReorderLink(_, _)).WillOnce(Return(false));
1649   EXPECT_CALL(*mock_custom_links_, IsInitialized())
1650       .WillRepeatedly(Return(false));
1651   EXPECT_CALL(*mock_custom_links_, Uninitialize());
1652   EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(0);
1653   most_visited_sites_->ReorderCustomLink(GURL("test.com"), 1);
1654   base::RunLoop().RunUntilIdle();
1655 
1656   // Fail to delete a custom link. This should not initialize custom links nor
1657   // notify.
1658   EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
1659   EXPECT_CALL(*mock_custom_links_, DeleteLink(_)).WillOnce(Return(false));
1660   EXPECT_CALL(*mock_custom_links_, IsInitialized())
1661       .WillRepeatedly(Return(false));
1662   EXPECT_CALL(*mock_custom_links_, Uninitialize());
1663   EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(0);
1664   most_visited_sites_->DeleteCustomLink(GURL("test.com"));
1665   base::RunLoop().RunUntilIdle();
1666 }
1667 
TEST_P(MostVisitedSitesWithCustomLinksTest,RebuildTilesOnCustomLinksChanged)1668 TEST_P(MostVisitedSitesWithCustomLinksTest, RebuildTilesOnCustomLinksChanged) {
1669   const char kTestUrl1[] = "http://site1/";
1670   const char kTestUrl2[] = "http://site2/";
1671   const char kTestTitle1[] = "Site 1";
1672   const char kTestTitle2[] = "Site 2";
1673   std::vector<CustomLinksManager::Link> expected_links(
1674       {CustomLinksManager::Link{GURL(kTestUrl2),
1675                                 base::UTF8ToUTF16(kTestTitle2)}});
1676   std::map<SectionType, NTPTilesVector> sections;
1677   DisableRemoteSuggestions();
1678 
1679   // Build initial tiles with Top Sites.
1680   base::RepeatingClosure custom_links_callback;
1681   EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_))
1682       .WillOnce(
1683           DoAll(SaveArg<0>(&custom_links_callback), Return(ByMove(nullptr))));
1684   ExpectBuildWithTopSites(
1685       MostVisitedURLList{MakeMostVisitedURL(kTestTitle1, kTestUrl1)},
1686       &sections);
1687   most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1688                                                   /*num_sites=*/1);
1689   base::RunLoop().RunUntilIdle();
1690   ASSERT_THAT(
1691       sections.at(SectionType::PERSONALIZED),
1692       ElementsAre(MatchesTile(kTestTitle1, kTestUrl1, TileSource::TOP_SITES)));
1693 
1694   // Notify that there is a new set of custom links. This should replace the
1695   // current tiles with custom links.
1696   EXPECT_CALL(*mock_custom_links_, IsInitialized())
1697       .WillRepeatedly(Return(true));
1698   EXPECT_CALL(*mock_custom_links_, GetLinks())
1699       .WillRepeatedly(ReturnRef(expected_links));
1700   EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1701       .WillOnce(SaveArg<0>(&sections));
1702   custom_links_callback.Run();
1703   base::RunLoop().RunUntilIdle();
1704   EXPECT_THAT(sections.at(SectionType::PERSONALIZED),
1705               ElementsAre(MatchesTile(kTestTitle2, kTestUrl2,
1706                                       TileSource::CUSTOM_LINKS)));
1707 
1708   // Notify that custom links have been uninitialized. This should rebuild the
1709   // tiles with Top Sites.
1710   EXPECT_CALL(*mock_custom_links_, IsInitialized())
1711       .WillRepeatedly(Return(false));
1712   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
1713       .WillRepeatedly(InvokeCallbackArgument<0>(
1714           MostVisitedURLList{MakeMostVisitedURL(kTestTitle1, kTestUrl1)}));
1715   EXPECT_CALL(*mock_custom_links_, IsInitialized())
1716       .WillRepeatedly(Return(false));
1717   EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1718       .WillOnce(SaveArg<0>(&sections));
1719   custom_links_callback.Run();
1720   base::RunLoop().RunUntilIdle();
1721   EXPECT_THAT(
1722       sections.at(SectionType::PERSONALIZED),
1723       ElementsAre(MatchesTile(kTestTitle1, kTestUrl1, TileSource::TOP_SITES)));
1724 }
1725 
1726 // These tests expect Most Likely to be enabled, and exclude Android and iOS,
1727 // so this will continue to be the case.
1728 INSTANTIATE_TEST_SUITE_P(MostVisitedSitesWithCustomLinksTest,
1729                          MostVisitedSitesWithCustomLinksTest,
1730                          ::testing::Combine(::testing::Bool(),
1731                                             ::testing::Values(true)));
1732 #endif
1733 
1734 class MostVisitedSitesWithCacheHitTest : public MostVisitedSitesTest {
1735  public:
1736   // Constructor sets the common expectations for the case where suggestions
1737   // service has cached results when the observer is registered.
MostVisitedSitesWithCacheHitTest()1738   MostVisitedSitesWithCacheHitTest() {
1739     InSequence seq;
1740     EXPECT_CALL(mock_suggestions_service_, AddCallback(_))
1741         .WillOnce(Invoke(&suggestions_service_callbacks_,
1742                          &SuggestionsService::ResponseCallbackList::Add));
1743     EXPECT_CALL(mock_suggestions_service_, GetSuggestionsDataFromCache())
1744         .WillOnce(Return(MakeProfile({
1745             MakeSuggestion("Site 1", "http://site1/"),
1746             MakeSuggestion("Site 2", "http://site2/"),
1747             MakeSuggestion("Site 3", "http://site3/"),
1748         })));
1749 
1750     if (IsPopularSitesFeatureEnabled()) {
1751       EXPECT_CALL(
1752           mock_observer_,
1753           OnURLsAvailable(Contains(Pair(
1754               SectionType::PERSONALIZED,
1755               ElementsAre(MatchesTile("Site 1", "http://site1/",
1756                                       TileSource::SUGGESTIONS_SERVICE),
1757                           MatchesTile("Site 2", "http://site2/",
1758                                       TileSource::SUGGESTIONS_SERVICE),
1759                           MatchesTile("Site 3", "http://site3/",
1760                                       TileSource::SUGGESTIONS_SERVICE),
1761                           MatchesTile("PopularSite1", "http://popularsite1/",
1762                                       TileSource::POPULAR))))));
1763     } else {
1764       EXPECT_CALL(
1765           mock_observer_,
1766           OnURLsAvailable(Contains(Pair(
1767               SectionType::PERSONALIZED,
1768               ElementsAre(MatchesTile("Site 1", "http://site1/",
1769                                       TileSource::SUGGESTIONS_SERVICE),
1770                           MatchesTile("Site 2", "http://site2/",
1771                                       TileSource::SUGGESTIONS_SERVICE),
1772                           MatchesTile("Site 3", "http://site3/",
1773                                       TileSource::SUGGESTIONS_SERVICE))))));
1774     }
1775     EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
1776     EXPECT_CALL(mock_suggestions_service_, FetchSuggestionsData())
1777         .WillOnce(Return(true));
1778 
1779     most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1780                                                     /*num_sites=*/4);
1781     VerifyAndClearExpectations();
1782 
1783     EXPECT_FALSE(suggestions_service_callbacks_.empty());
1784     EXPECT_TRUE(top_sites_callbacks_.empty());
1785   }
1786 };
1787 
TEST_P(MostVisitedSitesWithCacheHitTest,ShouldFavorSuggestionsServiceCache)1788 TEST_P(MostVisitedSitesWithCacheHitTest, ShouldFavorSuggestionsServiceCache) {
1789   // Constructor sets basic expectations for a suggestions service cache hit.
1790 }
1791 
TEST_P(MostVisitedSitesWithCacheHitTest,ShouldPropagateUpdateBySuggestionsService)1792 TEST_P(MostVisitedSitesWithCacheHitTest,
1793        ShouldPropagateUpdateBySuggestionsService) {
1794   EXPECT_CALL(mock_observer_,
1795               OnURLsAvailable(Contains(Pair(
1796                   SectionType::PERSONALIZED,
1797                   ElementsAre(MatchesTile("Site 4", "http://site4/",
1798                                           TileSource::SUGGESTIONS_SERVICE),
1799                               MatchesTile("Site 5", "http://site5/",
1800                                           TileSource::SUGGESTIONS_SERVICE),
1801                               MatchesTile("Site 6", "http://site6/",
1802                                           TileSource::SUGGESTIONS_SERVICE),
1803                               MatchesTile("Site 7", "http://site7/",
1804                                           TileSource::SUGGESTIONS_SERVICE))))));
1805   suggestions_service_callbacks_.Notify(
1806       MakeProfile({MakeSuggestion("Site 4", "http://site4/"),
1807                    MakeSuggestion("Site 5", "http://site5/"),
1808                    MakeSuggestion("Site 6", "http://site6/"),
1809                    MakeSuggestion("Site 7", "http://site7/")}));
1810   base::RunLoop().RunUntilIdle();
1811 }
1812 
TEST_P(MostVisitedSitesWithCacheHitTest,ShouldTruncateList)1813 TEST_P(MostVisitedSitesWithCacheHitTest, ShouldTruncateList) {
1814   EXPECT_CALL(
1815       mock_observer_,
1816       OnURLsAvailable(Contains(Pair(SectionType::PERSONALIZED, SizeIs(4)))));
1817   suggestions_service_callbacks_.Notify(
1818       MakeProfile({MakeSuggestion("Site 4", "http://site4/"),
1819                    MakeSuggestion("Site 5", "http://site5/"),
1820                    MakeSuggestion("Site 6", "http://site6/"),
1821                    MakeSuggestion("Site 7", "http://site7/"),
1822                    MakeSuggestion("Site 8", "http://site8/")}));
1823   base::RunLoop().RunUntilIdle();
1824 }
1825 
TEST_P(MostVisitedSitesWithCacheHitTest,ShouldCompleteWithPopularSitesIffEnabled)1826 TEST_P(MostVisitedSitesWithCacheHitTest,
1827        ShouldCompleteWithPopularSitesIffEnabled) {
1828   if (IsPopularSitesFeatureEnabled()) {
1829     EXPECT_CALL(
1830         mock_observer_,
1831         OnURLsAvailable(Contains(
1832             Pair(SectionType::PERSONALIZED,
1833                  ElementsAre(MatchesTile("Site 4", "http://site4/",
1834                                          TileSource::SUGGESTIONS_SERVICE),
1835                              MatchesTile("PopularSite1", "http://popularsite1/",
1836                                          TileSource::POPULAR),
1837                              MatchesTile("PopularSite2", "http://popularsite2/",
1838                                          TileSource::POPULAR))))));
1839   } else {
1840     EXPECT_CALL(
1841         mock_observer_,
1842         OnURLsAvailable(Contains(
1843             Pair(SectionType::PERSONALIZED,
1844                  ElementsAre(MatchesTile("Site 4", "http://site4/",
1845                                          TileSource::SUGGESTIONS_SERVICE))))));
1846   }
1847   suggestions_service_callbacks_.Notify(
1848       MakeProfile({MakeSuggestion("Site 4", "http://site4/")}));
1849   base::RunLoop().RunUntilIdle();
1850 }
1851 
TEST_P(MostVisitedSitesWithCacheHitTest,ShouldSwitchToTopSitesIfEmptyUpdateBySuggestionsService)1852 TEST_P(MostVisitedSitesWithCacheHitTest,
1853        ShouldSwitchToTopSitesIfEmptyUpdateBySuggestionsService) {
1854   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
1855       .WillOnce(Invoke(&top_sites_callbacks_, &TopSitesCallbackList::Add));
1856   suggestions_service_callbacks_.Notify(SuggestionsProfile());
1857   VerifyAndClearExpectations();
1858 
1859   EXPECT_CALL(
1860       mock_observer_,
1861       OnURLsAvailable(Contains(Pair(
1862           SectionType::PERSONALIZED,
1863           ElementsAre(
1864               MatchesTile("Site 4", "http://site4/", TileSource::TOP_SITES),
1865               MatchesTile("Site 5", "http://site5/", TileSource::TOP_SITES),
1866               MatchesTile("Site 6", "http://site6/", TileSource::TOP_SITES),
1867               MatchesTile("Site 7", "http://site7/",
1868                           TileSource::TOP_SITES))))));
1869   top_sites_callbacks_.ClearAndNotify(
1870       {MakeMostVisitedURL("Site 4", "http://site4/"),
1871        MakeMostVisitedURL("Site 5", "http://site5/"),
1872        MakeMostVisitedURL("Site 6", "http://site6/"),
1873        MakeMostVisitedURL("Site 7", "http://site7/")});
1874   base::RunLoop().RunUntilIdle();
1875 }
1876 
TEST_P(MostVisitedSitesWithCacheHitTest,ShouldFetchFaviconsIfEnabled)1877 TEST_P(MostVisitedSitesWithCacheHitTest, ShouldFetchFaviconsIfEnabled) {
1878   base::test::ScopedFeatureList feature_list;
1879   feature_list.InitAndEnableFeature(kNtpMostLikelyFaviconsFromServerFeature);
1880 
1881   EXPECT_CALL(mock_observer_, OnURLsAvailable(_));
1882   EXPECT_CALL(*icon_cacher_, StartFetchMostLikely(GURL("http://site4/"), _));
1883 
1884   suggestions_service_callbacks_.Notify(
1885       MakeProfile({MakeSuggestion("Site 4", "http://site4/")}));
1886   base::RunLoop().RunUntilIdle();
1887 }
1888 
1889 // Tests only apply when the suggestions service is enabled.
1890 INSTANTIATE_TEST_SUITE_P(MostVisitedSitesWithCacheHitTest,
1891                          MostVisitedSitesWithCacheHitTest,
1892                          ::testing::Combine(::testing::Bool(),
1893                                             testing::Values(true)));
1894 
1895 class MostVisitedSitesWithEmptyCacheTest : public MostVisitedSitesTest {
1896  public:
1897   // Constructor sets the common expectations for the case where suggestions
1898   // service doesn't have cached results when the observer is registered.
MostVisitedSitesWithEmptyCacheTest()1899   MostVisitedSitesWithEmptyCacheTest() {
1900     InSequence seq;
1901     EXPECT_CALL(mock_suggestions_service_, AddCallback(_))
1902         .WillOnce(Invoke(&suggestions_service_callbacks_,
1903                          &SuggestionsService::ResponseCallbackList::Add));
1904     EXPECT_CALL(mock_suggestions_service_, GetSuggestionsDataFromCache())
1905         .WillOnce(Return(SuggestionsProfile()));  // Empty cache.
1906     EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
1907         .WillOnce(Invoke(&top_sites_callbacks_, &TopSitesCallbackList::Add));
1908     EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
1909     EXPECT_CALL(mock_suggestions_service_, FetchSuggestionsData())
1910         .WillOnce(Return(true));
1911 
1912     most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1913                                                     /*num_sites=*/3);
1914     VerifyAndClearExpectations();
1915 
1916     EXPECT_FALSE(suggestions_service_callbacks_.empty());
1917     EXPECT_FALSE(top_sites_callbacks_.empty());
1918   }
1919 };
1920 
TEST_P(MostVisitedSitesWithEmptyCacheTest,ShouldQueryTopSitesAndSuggestionsService)1921 TEST_P(MostVisitedSitesWithEmptyCacheTest,
1922        ShouldQueryTopSitesAndSuggestionsService) {
1923   // Constructor sets basic expectations for a suggestions service cache miss.
1924 }
1925 
TEST_P(MostVisitedSitesWithEmptyCacheTest,ShouldCompleteWithPopularSitesIffEnabled)1926 TEST_P(MostVisitedSitesWithEmptyCacheTest,
1927        ShouldCompleteWithPopularSitesIffEnabled) {
1928   if (IsPopularSitesFeatureEnabled()) {
1929     EXPECT_CALL(
1930         mock_observer_,
1931         OnURLsAvailable(Contains(
1932             Pair(SectionType::PERSONALIZED,
1933                  ElementsAre(MatchesTile("Site 4", "http://site4/",
1934                                          TileSource::SUGGESTIONS_SERVICE),
1935                              MatchesTile("PopularSite1", "http://popularsite1/",
1936                                          TileSource::POPULAR),
1937                              MatchesTile("PopularSite2", "http://popularsite2/",
1938                                          TileSource::POPULAR))))));
1939   } else {
1940     EXPECT_CALL(
1941         mock_observer_,
1942         OnURLsAvailable(Contains(
1943             Pair(SectionType::PERSONALIZED,
1944                  ElementsAre(MatchesTile("Site 4", "http://site4/",
1945                                          TileSource::SUGGESTIONS_SERVICE))))));
1946   }
1947   suggestions_service_callbacks_.Notify(
1948       MakeProfile({MakeSuggestion("Site 4", "http://site4/")}));
1949   base::RunLoop().RunUntilIdle();
1950 }
1951 
TEST_P(MostVisitedSitesWithEmptyCacheTest,ShouldIgnoreTopSitesIfSuggestionsServiceFaster)1952 TEST_P(MostVisitedSitesWithEmptyCacheTest,
1953        ShouldIgnoreTopSitesIfSuggestionsServiceFaster) {
1954   // Reply from suggestions service triggers and update to our observer.
1955   EXPECT_CALL(mock_observer_,
1956               OnURLsAvailable(Contains(Pair(
1957                   SectionType::PERSONALIZED,
1958                   ElementsAre(MatchesTile("Site 1", "http://site1/",
1959                                           TileSource::SUGGESTIONS_SERVICE),
1960                               MatchesTile("Site 2", "http://site2/",
1961                                           TileSource::SUGGESTIONS_SERVICE),
1962                               MatchesTile("Site 3", "http://site3/",
1963                                           TileSource::SUGGESTIONS_SERVICE))))));
1964   suggestions_service_callbacks_.Notify(
1965       MakeProfile({MakeSuggestion("Site 1", "http://site1/"),
1966                    MakeSuggestion("Site 2", "http://site2/"),
1967                    MakeSuggestion("Site 3", "http://site3/")}));
1968   VerifyAndClearExpectations();
1969 
1970   // Reply from top sites is ignored (i.e. not reported to observer).
1971   top_sites_callbacks_.ClearAndNotify(
1972       {MakeMostVisitedURL("Site 4", "http://site4/")});
1973   VerifyAndClearExpectations();
1974 
1975   // Update by TopSites is also ignored.
1976   mock_top_sites_->NotifyTopSitesChanged(
1977       history::TopSitesObserver::ChangeReason::MOST_VISITED);
1978   base::RunLoop().RunUntilIdle();
1979 }
1980 
TEST_P(MostVisitedSitesWithEmptyCacheTest,ShouldExposeTopSitesIfSuggestionsServiceFasterButEmpty)1981 TEST_P(MostVisitedSitesWithEmptyCacheTest,
1982        ShouldExposeTopSitesIfSuggestionsServiceFasterButEmpty) {
1983   // Empty reply from suggestions service causes no update to our observer.
1984   suggestions_service_callbacks_.Notify(SuggestionsProfile());
1985   VerifyAndClearExpectations();
1986 
1987   // Reply from top sites is propagated to observer.
1988   EXPECT_CALL(
1989       mock_observer_,
1990       OnURLsAvailable(Contains(Pair(
1991           SectionType::PERSONALIZED,
1992           ElementsAre(
1993               MatchesTile("Site 1", "http://site1/", TileSource::TOP_SITES),
1994               MatchesTile("Site 2", "http://site2/", TileSource::TOP_SITES),
1995               MatchesTile("Site 3", "http://site3/",
1996                           TileSource::TOP_SITES))))));
1997   top_sites_callbacks_.ClearAndNotify(
1998       {MakeMostVisitedURL("Site 1", "http://site1/"),
1999        MakeMostVisitedURL("Site 2", "http://site2/"),
2000        MakeMostVisitedURL("Site 3", "http://site3/")});
2001   base::RunLoop().RunUntilIdle();
2002 }
2003 
TEST_P(MostVisitedSitesWithEmptyCacheTest,ShouldFavorSuggestionsServiceAlthoughSlower)2004 TEST_P(MostVisitedSitesWithEmptyCacheTest,
2005        ShouldFavorSuggestionsServiceAlthoughSlower) {
2006   // Reply from top sites is propagated to observer.
2007   EXPECT_CALL(
2008       mock_observer_,
2009       OnURLsAvailable(Contains(Pair(
2010           SectionType::PERSONALIZED,
2011           ElementsAre(
2012               MatchesTile("Site 1", "http://site1/", TileSource::TOP_SITES),
2013               MatchesTile("Site 2", "http://site2/", TileSource::TOP_SITES),
2014               MatchesTile("Site 3", "http://site3/",
2015                           TileSource::TOP_SITES))))));
2016   top_sites_callbacks_.ClearAndNotify(
2017       {MakeMostVisitedURL("Site 1", "http://site1/"),
2018        MakeMostVisitedURL("Site 2", "http://site2/"),
2019        MakeMostVisitedURL("Site 3", "http://site3/")});
2020   VerifyAndClearExpectations();
2021 
2022   // Reply from suggestions service overrides top sites.
2023   InSequence seq;
2024   EXPECT_CALL(mock_observer_,
2025               OnURLsAvailable(Contains(Pair(
2026                   SectionType::PERSONALIZED,
2027                   ElementsAre(MatchesTile("Site 4", "http://site4/",
2028                                           TileSource::SUGGESTIONS_SERVICE),
2029                               MatchesTile("Site 5", "http://site5/",
2030                                           TileSource::SUGGESTIONS_SERVICE),
2031                               MatchesTile("Site 6", "http://site6/",
2032                                           TileSource::SUGGESTIONS_SERVICE))))));
2033   suggestions_service_callbacks_.Notify(
2034       MakeProfile({MakeSuggestion("Site 4", "http://site4/"),
2035                    MakeSuggestion("Site 5", "http://site5/"),
2036                    MakeSuggestion("Site 6", "http://site6/")}));
2037   base::RunLoop().RunUntilIdle();
2038 }
2039 
TEST_P(MostVisitedSitesWithEmptyCacheTest,ShouldIgnoreSuggestionsServiceIfSlowerAndEmpty)2040 TEST_P(MostVisitedSitesWithEmptyCacheTest,
2041        ShouldIgnoreSuggestionsServiceIfSlowerAndEmpty) {
2042   // Reply from top sites is propagated to observer.
2043   EXPECT_CALL(
2044       mock_observer_,
2045       OnURLsAvailable(Contains(Pair(
2046           SectionType::PERSONALIZED,
2047           ElementsAre(
2048               MatchesTile("Site 1", "http://site1/", TileSource::TOP_SITES),
2049               MatchesTile("Site 2", "http://site2/", TileSource::TOP_SITES),
2050               MatchesTile("Site 3", "http://site3/",
2051                           TileSource::TOP_SITES))))));
2052   top_sites_callbacks_.ClearAndNotify(
2053       {MakeMostVisitedURL("Site 1", "http://site1/"),
2054        MakeMostVisitedURL("Site 2", "http://site2/"),
2055        MakeMostVisitedURL("Site 3", "http://site3/")});
2056   VerifyAndClearExpectations();
2057 
2058   // Reply from suggestions service is empty and thus ignored.
2059   suggestions_service_callbacks_.Notify(SuggestionsProfile());
2060   base::RunLoop().RunUntilIdle();
2061 }
2062 
TEST_P(MostVisitedSitesWithEmptyCacheTest,ShouldPropagateUpdateByTopSites)2063 TEST_P(MostVisitedSitesWithEmptyCacheTest, ShouldPropagateUpdateByTopSites) {
2064   // Reply from top sites is propagated to observer.
2065   EXPECT_CALL(
2066       mock_observer_,
2067       OnURLsAvailable(Contains(Pair(
2068           SectionType::PERSONALIZED,
2069           ElementsAre(
2070               MatchesTile("Site 1", "http://site1/", TileSource::TOP_SITES),
2071               MatchesTile("Site 2", "http://site2/", TileSource::TOP_SITES),
2072               MatchesTile("Site 3", "http://site3/",
2073                           TileSource::TOP_SITES))))));
2074   top_sites_callbacks_.ClearAndNotify(
2075       {MakeMostVisitedURL("Site 1", "http://site1/"),
2076        MakeMostVisitedURL("Site 2", "http://site2/"),
2077        MakeMostVisitedURL("Site 3", "http://site3/")});
2078   VerifyAndClearExpectations();
2079 
2080   // Reply from suggestions service is empty and thus ignored.
2081   suggestions_service_callbacks_.Notify(SuggestionsProfile());
2082   VerifyAndClearExpectations();
2083   EXPECT_TRUE(top_sites_callbacks_.empty());
2084 
2085   // Update from top sites is propagated to observer.
2086   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
2087       .WillOnce(InvokeCallbackArgument<0>(
2088           MostVisitedURLList{MakeMostVisitedURL("Site 4", "http://site4/"),
2089                              MakeMostVisitedURL("Site 5", "http://site5/"),
2090                              MakeMostVisitedURL("Site 6", "http://site6/")}));
2091   EXPECT_CALL(
2092       mock_observer_,
2093       OnURLsAvailable(Contains(Pair(
2094           SectionType::PERSONALIZED,
2095           ElementsAre(
2096               MatchesTile("Site 4", "http://site4/", TileSource::TOP_SITES),
2097               MatchesTile("Site 5", "http://site5/", TileSource::TOP_SITES),
2098               MatchesTile("Site 6", "http://site6/",
2099                           TileSource::TOP_SITES))))));
2100   mock_top_sites_->NotifyTopSitesChanged(
2101       history::TopSitesObserver::ChangeReason::MOST_VISITED);
2102   base::RunLoop().RunUntilIdle();
2103 }
2104 
TEST_P(MostVisitedSitesWithEmptyCacheTest,ShouldSendEmptyListIfBothTopSitesAndSuggestionsServiceEmpty)2105 TEST_P(MostVisitedSitesWithEmptyCacheTest,
2106        ShouldSendEmptyListIfBothTopSitesAndSuggestionsServiceEmpty) {
2107   if (IsPopularSitesFeatureEnabled()) {
2108     EXPECT_CALL(
2109         mock_observer_,
2110         OnURLsAvailable(Contains(
2111             Pair(SectionType::PERSONALIZED,
2112                  ElementsAre(MatchesTile("PopularSite1", "http://popularsite1/",
2113                                          TileSource::POPULAR),
2114                              MatchesTile("PopularSite2", "http://popularsite2/",
2115                                          TileSource::POPULAR))))));
2116   } else {
2117     // The Android NTP doesn't finish initialization until it gets tiles, so a
2118     // 0-tile notification is always needed.
2119     EXPECT_CALL(mock_observer_, OnURLsAvailable(ElementsAre(Pair(
2120                                     SectionType::PERSONALIZED, IsEmpty()))));
2121   }
2122   suggestions_service_callbacks_.Notify(SuggestionsProfile());
2123   top_sites_callbacks_.ClearAndNotify(MostVisitedURLList{});
2124 
2125   base::RunLoop().RunUntilIdle();
2126 }
2127 
TEST_P(MostVisitedSitesWithEmptyCacheTest,ShouldNotifyOnceIfTopSitesUnchanged)2128 TEST_P(MostVisitedSitesWithEmptyCacheTest,
2129        ShouldNotifyOnceIfTopSitesUnchanged) {
2130   EXPECT_CALL(
2131       mock_observer_,
2132       OnURLsAvailable(Contains(Pair(
2133           SectionType::PERSONALIZED,
2134           ElementsAre(
2135               MatchesTile("Site 1", "http://site1/", TileSource::TOP_SITES),
2136               MatchesTile("Site 2", "http://site2/", TileSource::TOP_SITES),
2137               MatchesTile("Site 3", "http://site3/",
2138                           TileSource::TOP_SITES))))));
2139 
2140   suggestions_service_callbacks_.Notify(SuggestionsProfile());
2141 
2142   top_sites_callbacks_.ClearAndNotify(
2143       {MakeMostVisitedURL("Site 1", "http://site1/"),
2144        MakeMostVisitedURL("Site 2", "http://site2/"),
2145        MakeMostVisitedURL("Site 3", "http://site3/")});
2146   base::RunLoop().RunUntilIdle();
2147 
2148   for (int i = 0; i < 4; ++i) {
2149     EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
2150         .WillOnce(Invoke(&top_sites_callbacks_, &TopSitesCallbackList::Add));
2151     mock_top_sites_->NotifyTopSitesChanged(
2152         history::TopSitesObserver::ChangeReason::MOST_VISITED);
2153     EXPECT_FALSE(top_sites_callbacks_.empty());
2154     top_sites_callbacks_.ClearAndNotify(
2155         {MakeMostVisitedURL("Site 1", "http://site1/"),
2156          MakeMostVisitedURL("Site 2", "http://site2/"),
2157          MakeMostVisitedURL("Site 3", "http://site3/")});
2158     base::RunLoop().RunUntilIdle();
2159   }
2160 }
2161 
TEST_P(MostVisitedSitesWithEmptyCacheTest,ShouldNotifyOnceIfSuggestionsUnchanged)2162 TEST_P(MostVisitedSitesWithEmptyCacheTest,
2163        ShouldNotifyOnceIfSuggestionsUnchanged) {
2164   EXPECT_CALL(mock_observer_,
2165               OnURLsAvailable(Contains(Pair(
2166                   SectionType::PERSONALIZED,
2167                   ElementsAre(MatchesTile("Site 1", "http://site1/",
2168                                           TileSource::SUGGESTIONS_SERVICE),
2169                               MatchesTile("Site 2", "http://site2/",
2170                                           TileSource::SUGGESTIONS_SERVICE),
2171                               MatchesTile("Site 3", "http://site3/",
2172                                           TileSource::SUGGESTIONS_SERVICE))))));
2173 
2174   for (int i = 0; i < 5; ++i) {
2175     suggestions_service_callbacks_.Notify(
2176         MakeProfile({MakeSuggestion("Site 1", "http://site1/"),
2177                      MakeSuggestion("Site 2", "http://site2/"),
2178                      MakeSuggestion("Site 3", "http://site3/")}));
2179   }
2180 }
2181 
2182 // Tests only apply when the suggestions service is enabled.
2183 INSTANTIATE_TEST_SUITE_P(MostVisitedSitesWithEmptyCacheTest,
2184                          MostVisitedSitesWithEmptyCacheTest,
2185                          ::testing::Combine(::testing::Bool(),
2186                                             testing::Values(true)));
2187 
2188 // This a test for MostVisitedSites::MergeTiles(...) method, and thus has the
2189 // same scope as the method itself. This tests merging popular sites with
2190 // personal tiles.
2191 // More important things out of the scope of testing presently:
2192 // - Removing blacklisted tiles.
2193 // - Correct host extraction from the URL.
2194 // - Ensuring personal tiles are not duplicated in popular tiles.
TEST(MostVisitedSitesMergeTest,ShouldMergeTilesWithPersonalOnly)2195 TEST(MostVisitedSitesMergeTest, ShouldMergeTilesWithPersonalOnly) {
2196   std::vector<NTPTile> personal_tiles{
2197       MakeTile("Site 1", "https://www.site1.com/", TileSource::TOP_SITES),
2198       MakeTile("Site 2", "https://www.site2.com/", TileSource::TOP_SITES),
2199       MakeTile("Site 3", "https://www.site3.com/", TileSource::TOP_SITES),
2200       MakeTile("Site 4", "https://www.site4.com/", TileSource::TOP_SITES),
2201   };
2202   // Without any popular tiles, the result after merge should be the personal
2203   // tiles.
2204   EXPECT_THAT(MostVisitedSites::MergeTiles(std::move(personal_tiles),
2205                                            /*whitelist_tiles=*/NTPTilesVector(),
2206                                            /*popular_tiles=*/NTPTilesVector(),
2207                                            /*explore_tile=*/base::nullopt),
2208               ElementsAre(MatchesTile("Site 1", "https://www.site1.com/",
2209                                       TileSource::TOP_SITES),
2210                           MatchesTile("Site 2", "https://www.site2.com/",
2211                                       TileSource::TOP_SITES),
2212                           MatchesTile("Site 3", "https://www.site3.com/",
2213                                       TileSource::TOP_SITES),
2214                           MatchesTile("Site 4", "https://www.site4.com/",
2215                                       TileSource::TOP_SITES)));
2216 }
2217 
TEST(MostVisitedSitesMergeTest,ShouldMergeTilesWithPopularOnly)2218 TEST(MostVisitedSitesMergeTest, ShouldMergeTilesWithPopularOnly) {
2219   std::vector<NTPTile> popular_tiles{
2220       MakeTile("Site 1", "https://www.site1.com/", TileSource::POPULAR),
2221       MakeTile("Site 2", "https://www.site2.com/", TileSource::POPULAR),
2222       MakeTile("Site 3", "https://www.site3.com/", TileSource::POPULAR),
2223       MakeTile("Site 4", "https://www.site4.com/", TileSource::POPULAR),
2224   };
2225   // Without any personal tiles, the result after merge should be the popular
2226   // tiles.
2227   EXPECT_THAT(
2228       MostVisitedSites::MergeTiles(/*personal_tiles=*/NTPTilesVector(),
2229                                    /*whitelist_tiles=*/NTPTilesVector(),
2230                                    /*popular_tiles=*/std::move(popular_tiles),
2231                                    /*explore_tile=*/base::nullopt),
2232       ElementsAre(
2233           MatchesTile("Site 1", "https://www.site1.com/", TileSource::POPULAR),
2234           MatchesTile("Site 2", "https://www.site2.com/", TileSource::POPULAR),
2235           MatchesTile("Site 3", "https://www.site3.com/", TileSource::POPULAR),
2236           MatchesTile("Site 4", "https://www.site4.com/",
2237                       TileSource::POPULAR)));
2238 }
2239 
TEST(MostVisitedSitesMergeTest,ShouldMergeTilesFavoringPersonalOverPopular)2240 TEST(MostVisitedSitesMergeTest, ShouldMergeTilesFavoringPersonalOverPopular) {
2241   std::vector<NTPTile> popular_tiles{
2242       MakeTile("Site 1", "https://www.site1.com/", TileSource::POPULAR),
2243       MakeTile("Site 2", "https://www.site2.com/", TileSource::POPULAR),
2244   };
2245   std::vector<NTPTile> personal_tiles{
2246       MakeTile("Site 3", "https://www.site3.com/", TileSource::TOP_SITES),
2247       MakeTile("Site 4", "https://www.site4.com/", TileSource::TOP_SITES),
2248   };
2249   base::Optional<NTPTile> explore_tile{
2250       MakeTile("Explore", "https://explore.example.com/", TileSource::EXPLORE),
2251   };
2252   EXPECT_THAT(
2253       MostVisitedSites::MergeTiles(std::move(personal_tiles),
2254                                    /*whitelist_tiles=*/NTPTilesVector(),
2255                                    /*popular_tiles=*/std::move(popular_tiles),
2256                                    /*explore_tiles=*/explore_tile),
2257       ElementsAre(
2258           MatchesTile("Site 3", "https://www.site3.com/",
2259                       TileSource::TOP_SITES),
2260           MatchesTile("Site 4", "https://www.site4.com/",
2261                       TileSource::TOP_SITES),
2262           MatchesTile("Site 1", "https://www.site1.com/", TileSource::POPULAR),
2263           MatchesTile("Site 2", "https://www.site2.com/", TileSource::POPULAR),
2264           MatchesTile("Explore", "https://explore.example.com/",
2265                       TileSource::EXPLORE)));
2266 }
2267 
2268 }  // namespace ntp_tiles
2269