blob: 1e1057bb5d76216ff5a2da482784549d1a38a12f [file] [log] [blame]
[email protected]c764b2822013-07-03 04:16:481// Copyright 2013 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
sfiera3ff01c0d2016-06-13 15:33:385#include "components/ntp_tiles/most_visited_sites.h"
[email protected]c764b2822013-07-03 04:16:486
sfiera3ff01c0d2016-06-13 15:33:387#include <algorithm>
Friedrich Horschigb1733402017-08-28 17:06:118#include <iterator>
dchengbc6125d2015-12-30 01:54:079#include <utility>
10
mastiz73693f12017-01-27 15:52:5711#include "base/bind.h"
[email protected]d33adb40d2014-06-03 21:38:4612#include "base/callback.h"
mastizf3468a82016-06-15 11:05:4113#include "base/feature_list.h"
dgnf6500c12017-05-09 17:05:3114#include "base/metrics/user_metrics.h"
Weilun Shi354a46242018-09-25 06:51:0315#include "base/strings/string_split.h"
Friedrich Horschigb1733402017-08-28 17:06:1116#include "base/strings/string_util.h"
[email protected]bc093e82014-03-04 21:49:1117#include "base/strings/utf_string_conversions.h"
sdefresne0da3bc02015-01-29 18:26:3518#include "components/history/core/browser/top_sites.h"
treibdb416392016-06-29 17:20:5019#include "components/ntp_tiles/constants.h"
sfieraae1ae692016-10-24 18:19:1520#include "components/ntp_tiles/icon_cacher.h"
sfiera0dc4da52016-04-29 09:23:0521#include "components/ntp_tiles/pref_names.h"
22#include "components/ntp_tiles/switches.h"
knncbbd754d2015-09-09 15:43:4023#include "components/pref_registry/pref_registry_syncable.h"
brettwb1fc1b82016-02-02 00:19:0824#include "components/prefs/pref_service.h"
[email protected]c764b2822013-07-03 04:16:4825
[email protected]c764b2822013-07-03 04:16:4826using history::TopSites;
[email protected]bc093e82014-03-04 21:49:1127using suggestions::ChromeSuggestion;
28using suggestions::SuggestionsProfile;
sfiera7e952d42016-05-04 17:56:3329using suggestions::SuggestionsService;
[email protected]c764b2822013-07-03 04:16:4830
sfiera08009fe2016-06-15 17:07:2631namespace ntp_tiles {
32
[email protected]c764b2822013-07-03 04:16:4833namespace {
34
kristiparkc16800962018-07-31 20:05:2935// The maximum number of custom links that can be shown. This is independent of
36// the maximum number of Most Visited sites that can be shown.
37const size_t kMaxNumCustomLinks = 10;
38
mastizf3468a82016-06-15 11:05:4139const base::Feature kDisplaySuggestionsServiceTiles{
40 "DisplaySuggestionsServiceTiles", base::FEATURE_ENABLED_BY_DEFAULT};
41
Friedrich Horschigb1733402017-08-28 17:06:1142// URL host prefixes. Hosts with these prefixes often redirect to each other, or
43// have the same content.
44// Popular sites are excluded if the user has visited a page whose host only
45// differs by one of these prefixes. Even if the URL does not point to the exact
46// same page, the user will have a personalized suggestion that is more likely
47// to be of use for them.
48// A cleaner way could be checking the history for redirects but this requires
49// the page to be visited on the device.
50const char* kKnownGenericPagePrefixes[] = {
51 "m.", "mobile.", // Common prefixes among popular sites.
52 "edition.", // Used among news papers (CNN, Independent, ...)
53 "www.", // Usually no-www domains redirect to www or vice-versa.
54 // The following entry MUST REMAIN LAST as it is prefix of every string!
55 ""}; // The no-www domain matches domains on same level .
56
sfiera635d21d2016-08-04 07:56:0957// Determine whether we need any tiles from PopularSites to fill up a grid of
Friedrich Horschig9e8749f02017-08-10 09:17:3158// |num_tiles| tiles. If exploration sections are used, we need popular sites
59// regardless of how many tiles we already have.
treibcd3d2ef2016-07-13 16:53:3160bool NeedPopularSites(const PrefService* prefs, int num_tiles) {
Nicolas Dossou-gbete56f37dc2017-08-10 16:14:0461 return base::FeatureList::IsEnabled(kSiteExplorationUiFeature) ||
Friedrich Horschig9e8749f02017-08-10 09:17:3162 prefs->GetInteger(prefs::kNumPersonalTiles) < num_tiles;
treibf79ed40d2015-09-22 12:38:0663}
64
atanasova9c0dda602016-03-22 17:41:1365bool AreURLsEquivalent(const GURL& url1, const GURL& url2) {
csharrison88b3b712016-11-14 23:12:3566 return url1.host_piece() == url2.host_piece() &&
67 url1.path_piece() == url2.path_piece();
atanasova9c0dda602016-03-22 17:41:1368}
69
Yafei Duan3797cf42018-07-14 01:03:5870bool HasHomeTile(const NTPTilesVector& tiles) {
71 for (const auto& tile : tiles) {
72 if (tile.source == TileSource::HOMEPAGE)
73 return true;
74 }
75 return false;
76}
77
Friedrich Horschigb1733402017-08-28 17:06:1178std::string StripFirstGenericPrefix(const std::string& host) {
79 for (const char* prefix : kKnownGenericPagePrefixes) {
80 if (base::StartsWith(host, prefix, base::CompareCase::INSENSITIVE_ASCII)) {
81 return std::string(
82 base::TrimString(host, prefix, base::TrimPositions::TRIM_LEADING));
83 }
84 }
85 return host;
86}
87
Friedrich Horschigf738ab92018-02-14 10:10:1088bool ShouldShowPopularSites() {
89 return base::FeatureList::IsEnabled(kUsePopularSitesSuggestions);
90}
91
Weilun Shi354a46242018-09-25 06:51:0392// Generate a short title for Most Visited items before they're converted to
93// custom links.
94base::string16 GenerateShortTitle(const base::string16& title) {
95 // Empty title only happened in the unittests.
96 if (title.empty())
97 return base::string16();
98 std::vector<base::string16> short_title_list =
99 SplitString(title, base::UTF8ToUTF16("-:|;"), base::TRIM_WHITESPACE,
100 base::SPLIT_WANT_NONEMPTY);
101 // Make sure it doesn't crash when the title only contains spaces.
102 if (short_title_list.empty())
103 return base::string16();
104 base::string16 short_title_front = short_title_list.front();
105 base::string16 short_title_back = short_title_list.back();
106 base::string16 short_title = short_title_front;
107 if (short_title_front != short_title_back) {
108 int words_in_front =
109 SplitString(short_title_front, base::kWhitespaceASCIIAs16,
110 base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)
111 .size();
112 int words_in_back =
113 SplitString(short_title_back, base::kWhitespaceASCIIAs16,
114 base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)
115 .size();
116 if (words_in_front >= 3 && words_in_back >= 1 && words_in_back <= 3) {
117 short_title = short_title_back;
118 }
119 }
120 return short_title;
121}
122
sfiera8df7b382016-04-26 14:06:33123} // namespace
124
sfierac35d2722016-12-14 09:41:45125MostVisitedSites::MostVisitedSites(
126 PrefService* prefs,
127 scoped_refptr<history::TopSites> top_sites,
128 SuggestionsService* suggestions,
129 std::unique_ptr<PopularSites> popular_sites,
kristiparkc0199772018-07-18 05:25:42130 std::unique_ptr<CustomLinksManager> custom_links,
sfierac35d2722016-12-14 09:41:45131 std::unique_ptr<IconCacher> icon_cacher,
fhorschig3fc1f812017-06-01 12:28:28132 std::unique_ptr<MostVisitedSitesSupervisor> supervisor)
sfiera79e643b2016-05-13 16:52:49133 : prefs_(prefs),
sfiera685a987e2016-05-12 17:08:47134 top_sites_(top_sites),
135 suggestions_service_(suggestions),
sfiera96c03252016-09-14 18:58:16136 popular_sites_(std::move(popular_sites)),
kristiparkc0199772018-07-18 05:25:42137 custom_links_(std::move(custom_links)),
sfieraae1ae692016-10-24 18:19:15138 icon_cacher_(std::move(icon_cacher)),
sfierac35d2722016-12-14 09:41:45139 supervisor_(std::move(supervisor)),
sfiera685a987e2016-05-12 17:08:47140 observer_(nullptr),
kristiparkc0199772018-07-18 05:25:42141 max_num_sites_(0u),
treibbaada0f2016-08-01 11:30:33142 top_sites_observer_(this),
treib231212e2017-04-04 17:09:22143 mv_source_(TileSource::TOP_SITES),
mastizd0da75e2017-01-09 11:36:48144 top_sites_weak_ptr_factory_(this) {
sfiera87db8582016-08-05 10:46:42145 DCHECK(prefs_);
sfieraaa1b8862016-10-04 16:09:23146 // top_sites_ can be null in tests.
147 // TODO(sfiera): have iOS use a dummy TopSites in its tests.
mastizc60d74e2016-06-14 14:02:49148 DCHECK(suggestions_service_);
sfiera87db8582016-08-05 10:46:42149 if (supervisor_)
150 supervisor_->SetObserver(this);
[email protected]7ceb4e32013-12-06 04:13:04151}
[email protected]c764b2822013-07-03 04:16:48152
[email protected]7ceb4e32013-12-06 04:13:04153MostVisitedSites::~MostVisitedSites() {
sfiera87db8582016-08-05 10:46:42154 if (supervisor_)
155 supervisor_->SetObserver(nullptr);
[email protected]7ceb4e32013-12-06 04:13:04156}
[email protected]c764b2822013-07-03 04:16:48157
Friedrich Horschigb1733402017-08-28 17:06:11158// static
159bool MostVisitedSites::IsHostOrMobilePageKnown(
160 const std::set<std::string>& hosts_to_skip,
161 const std::string& host) {
162 std::string no_prefix_host = StripFirstGenericPrefix(host);
163 for (const char* prefix : kKnownGenericPagePrefixes) {
164 if (hosts_to_skip.count(prefix + no_prefix_host) ||
165 hosts_to_skip.count(prefix + host)) {
166 return true;
167 }
168 }
169 return false;
170}
171
treib231212e2017-04-04 17:09:22172bool MostVisitedSites::DoesSourceExist(TileSource source) const {
sfiera65cefe9d2017-02-07 11:02:50173 switch (source) {
treib231212e2017-04-04 17:09:22174 case TileSource::TOP_SITES:
sfiera65cefe9d2017-02-07 11:02:50175 return top_sites_ != nullptr;
treib231212e2017-04-04 17:09:22176 case TileSource::SUGGESTIONS_SERVICE:
sfiera65cefe9d2017-02-07 11:02:50177 return suggestions_service_ != nullptr;
Friedrich Horschig7706ef62017-08-25 08:20:00178 case TileSource::POPULAR_BAKED_IN:
treib231212e2017-04-04 17:09:22179 case TileSource::POPULAR:
sfiera65cefe9d2017-02-07 11:02:50180 return popular_sites_ != nullptr;
Yafei Duan3797cf42018-07-14 01:03:58181 case TileSource::HOMEPAGE:
182 return homepage_client_ != nullptr;
treib231212e2017-04-04 17:09:22183 case TileSource::WHITELIST:
sfiera65cefe9d2017-02-07 11:02:50184 return supervisor_ != nullptr;
kristiparkc0199772018-07-18 05:25:42185 case TileSource::CUSTOM_LINKS:
186 return custom_links_ != nullptr;
sfiera65cefe9d2017-02-07 11:02:50187 }
188 NOTREACHED();
189 return false;
190}
191
Yafei Duan3797cf42018-07-14 01:03:58192void MostVisitedSites::SetHomepageClient(
193 std::unique_ptr<HomepageClient> client) {
194 DCHECK(client);
195 homepage_client_ = std::move(client);
196}
197
treib5a59f542016-05-18 12:17:29198void MostVisitedSites::SetMostVisitedURLsObserver(Observer* observer,
fhorschigd3222452017-05-22 08:36:44199 size_t num_sites) {
treibc1bd1f12016-04-29 15:06:05200 DCHECK(observer);
sfiera929502f32016-04-21 12:52:48201 observer_ = observer;
kristiparkc0199772018-07-18 05:25:42202 max_num_sites_ = num_sites;
[email protected]852fc792013-10-04 04:15:12203
treib99f6b992016-11-23 13:59:50204 // The order for this condition is important, ShouldShowPopularSites() should
Eric Noyau4793d932016-11-16 16:19:23205 // always be called last to keep metrics as relevant as possible.
kristiparkc0199772018-07-18 05:25:42206 if (popular_sites_ && NeedPopularSites(prefs_, max_num_sites_) &&
Eric Noyau4793d932016-11-16 16:19:23207 ShouldShowPopularSites()) {
mastizfd2c7ab2017-01-27 19:35:00208 popular_sites_->MaybeStartFetch(
209 false, base::Bind(&MostVisitedSites::OnPopularSitesDownloaded,
sfiera00a58ab2016-07-28 10:20:49210 base::Unretained(this)));
treibf79ed40d2015-09-22 12:38:06211 }
212
treibf7d11512016-06-29 09:06:15213 if (top_sites_) {
treibf7d11512016-06-29 09:06:15214 // Register as TopSitesObserver so that we can update ourselves when the
215 // TopSites changes.
treibbaada0f2016-08-01 11:30:33216 top_sites_observer_.Add(top_sites_.get());
treibf7d11512016-06-29 09:06:15217 }
treibcb9c93b2016-04-01 13:22:52218
kristiparke79bcc32018-08-29 19:02:31219 if (custom_links_) {
220 custom_links_subscription_ =
221 custom_links_->RegisterCallbackForOnChanged(base::BindRepeating(
222 &MostVisitedSites::OnCustomLinksChanged, base::Unretained(this)));
223 }
224
mastizbad28af2017-01-30 16:04:37225 suggestions_subscription_ = suggestions_service_->AddCallback(base::Bind(
226 &MostVisitedSites::OnSuggestionsProfileChanged, base::Unretained(this)));
treibcb9c93b2016-04-01 13:22:52227
sfiera635d21d2016-08-04 07:56:09228 // Immediately build the current set of tiles, getting suggestions from the
229 // SuggestionsService's cache or, if that is empty, sites from TopSites.
230 BuildCurrentTiles();
treibcb9c93b2016-04-01 13:22:52231 // Also start a request for fresh suggestions.
treibbb0c5af52016-12-09 17:34:15232 Refresh();
233}
234
235void MostVisitedSites::Refresh() {
Mikel Astiz1d90c812017-07-21 13:52:51236 if (top_sites_) {
237 // TopSites updates itself after a delay. To ensure up-to-date results,
238 // force an update now.
239 // TODO(mastiz): Is seems unnecessary to refresh TopSites if we will end up
240 // using server-side suggestions.
241 top_sites_->SyncWithHistory();
242 }
243
sfiera728962f2016-04-29 11:04:02244 suggestions_service_->FetchSuggestionsData();
[email protected]c764b2822013-07-03 04:16:48245}
246
Kristi Parkdb8138f2018-10-22 17:06:37247void MostVisitedSites::RefreshTiles() {
Yafei Duan3797cf42018-07-14 01:03:58248 BuildCurrentTiles();
249}
250
kristiparkc0199772018-07-18 05:25:42251void MostVisitedSites::InitializeCustomLinks() {
kristiparkf8fa4132018-09-13 18:07:29252 if (!custom_links_ || !current_tiles_.has_value() || !custom_links_enabled_)
kristiparkc0199772018-07-18 05:25:42253 return;
254
Kristi Parkdb8138f2018-10-22 17:06:37255 if (custom_links_->Initialize(current_tiles_.value()))
Kristi Parkc1fc3542018-10-12 22:57:04256 custom_links_action_count_ = 0;
kristiparkc0199772018-07-18 05:25:42257}
258
259void MostVisitedSites::UninitializeCustomLinks() {
kristiparkf8fa4132018-09-13 18:07:29260 if (!custom_links_ || !custom_links_enabled_)
kristiparkc0199772018-07-18 05:25:42261 return;
262
Kristi Parkc1fc3542018-10-12 22:57:04263 custom_links_action_count_ = -1;
kristiparkc0199772018-07-18 05:25:42264 custom_links_->Uninitialize();
265 BuildCurrentTiles();
266 Refresh();
267}
268
kristiparka52a3892018-07-24 18:46:44269bool MostVisitedSites::IsCustomLinksInitialized() {
kristiparkf8fa4132018-09-13 18:07:29270 if (!custom_links_ || !custom_links_enabled_)
kristiparka52a3892018-07-24 18:46:44271 return false;
272
273 return custom_links_->IsInitialized();
274}
275
kristiparkf8fa4132018-09-13 18:07:29276void MostVisitedSites::EnableCustomLinks(bool enable) {
277 if (custom_links_enabled_ != enable) {
278 custom_links_enabled_ = enable;
279 BuildCurrentTiles();
280 }
281}
282
kristiparkbe00c6562018-08-01 21:30:27283bool MostVisitedSites::AddCustomLink(const GURL& url,
kristiparkc0199772018-07-18 05:25:42284 const base::string16& title) {
kristiparkf8fa4132018-09-13 18:07:29285 if (!custom_links_ || !custom_links_enabled_)
kristiparkbe00c6562018-08-01 21:30:27286 return false;
kristiparkc0199772018-07-18 05:25:42287
Kristi Parkc1fc3542018-10-12 22:57:04288 // Initialize custom links if they have not been initialized yet.
289 InitializeCustomLinks();
290
kristiparkbe00c6562018-08-01 21:30:27291 bool success = custom_links_->AddLink(url, title);
Kristi Parkc1fc3542018-10-12 22:57:04292 if (success) {
293 if (custom_links_action_count_ != -1)
294 custom_links_action_count_++;
kristipark0e19d3a2018-07-30 07:08:02295 BuildCurrentTiles();
Kristi Parkc1fc3542018-10-12 22:57:04296 }
kristiparkbe00c6562018-08-01 21:30:27297 return success;
kristiparkc0199772018-07-18 05:25:42298}
299
kristiparkbe00c6562018-08-01 21:30:27300bool MostVisitedSites::UpdateCustomLink(const GURL& url,
kristipark940dc202018-07-30 18:29:55301 const GURL& new_url,
Kristi Park6d2d9982018-10-25 00:16:58302 const base::string16& new_title) {
kristiparkf8fa4132018-09-13 18:07:29303 if (!custom_links_ || !custom_links_enabled_)
kristiparkbe00c6562018-08-01 21:30:27304 return false;
kristipark940dc202018-07-30 18:29:55305
Kristi Parkc1fc3542018-10-12 22:57:04306 // Initialize custom links if they have not been initialized yet.
307 InitializeCustomLinks();
308
Kristi Park6d2d9982018-10-25 00:16:58309 bool success = custom_links_->UpdateLink(url, new_url, new_title);
Kristi Parkc1fc3542018-10-12 22:57:04310 if (success) {
Kristi Park6d2d9982018-10-25 00:16:58311 if (custom_links_action_count_ != -1)
Kristi Parkc1fc3542018-10-12 22:57:04312 custom_links_action_count_++;
kristipark940dc202018-07-30 18:29:55313 BuildCurrentTiles();
Kristi Parkc1fc3542018-10-12 22:57:04314 }
kristiparkbe00c6562018-08-01 21:30:27315 return success;
kristipark940dc202018-07-30 18:29:55316}
317
kristiparkbe00c6562018-08-01 21:30:27318bool MostVisitedSites::DeleteCustomLink(const GURL& url) {
kristiparkf8fa4132018-09-13 18:07:29319 if (!custom_links_ || !custom_links_enabled_)
kristiparkbe00c6562018-08-01 21:30:27320 return false;
321
Kristi Parkc1fc3542018-10-12 22:57:04322 // Initialize custom links if they have not been initialized yet.
323 InitializeCustomLinks();
324
kristiparkbe00c6562018-08-01 21:30:27325 bool success = custom_links_->DeleteLink(url);
Kristi Parkc1fc3542018-10-12 22:57:04326 if (success) {
327 if (custom_links_action_count_ != -1)
328 custom_links_action_count_++;
kristiparkbe00c6562018-08-01 21:30:27329 BuildCurrentTiles();
Kristi Parkc1fc3542018-10-12 22:57:04330 }
kristiparkbe00c6562018-08-01 21:30:27331 return success;
332}
333
334void MostVisitedSites::UndoCustomLinkAction() {
kristiparkf8fa4132018-09-13 18:07:29335 if (!custom_links_ || !custom_links_enabled_)
kristiparkc0199772018-07-18 05:25:42336 return;
337
Kristi Parkc1fc3542018-10-12 22:57:04338 // If this is undoing the first action after initialization, uninitialize
339 // custom links.
340 if (custom_links_action_count_-- == 1)
341 UninitializeCustomLinks();
342 else if (custom_links_->UndoAction())
kristipark0e19d3a2018-07-30 07:08:02343 BuildCurrentTiles();
kristiparka52a3892018-07-24 18:46:44344}
345
treib5a59f542016-05-18 12:17:29346void MostVisitedSites::AddOrRemoveBlacklistedUrl(const GURL& url,
347 bool add_url) {
dgnf6500c12017-05-09 17:05:31348 if (add_url) {
349 base::RecordAction(base::UserMetricsAction("Suggestions.Site.Removed"));
350 } else {
351 base::RecordAction(
352 base::UserMetricsAction("Suggestions.Site.RemovalUndone"));
353 }
354
treibf7d11512016-06-29 09:06:15355 if (top_sites_) {
356 // Always blacklist in the local TopSites.
357 if (add_url)
358 top_sites_->AddBlacklistedURL(url);
359 else
360 top_sites_->RemoveBlacklistedURL(url);
361 }
[email protected]d4975242014-06-02 18:16:20362
treibfac75192015-08-17 13:21:24363 // Only blacklist in the server-side suggestions service if it's active.
treib231212e2017-04-04 17:09:22364 if (mv_source_ == TileSource::SUGGESTIONS_SERVICE) {
treib16070ce2016-03-11 11:57:40365 if (add_url)
sfiera728962f2016-04-29 11:04:02366 suggestions_service_->BlacklistURL(url);
treib16070ce2016-03-11 11:57:40367 else
sfiera728962f2016-04-29 11:04:02368 suggestions_service_->UndoBlacklistURL(url);
[email protected]d4975242014-06-02 18:16:20369 }
[email protected]a4c2f282013-07-20 05:26:05370}
[email protected]7ceb4e32013-12-06 04:13:04371
treibbb0c5af52016-12-09 17:34:15372void MostVisitedSites::ClearBlacklistedUrls() {
373 if (top_sites_) {
374 // Always update the blacklist in the local TopSites.
375 top_sites_->ClearBlacklistedURLs();
376 }
377
378 // Only update the server-side blacklist if it's active.
treib231212e2017-04-04 17:09:22379 if (mv_source_ == TileSource::SUGGESTIONS_SERVICE) {
treibbb0c5af52016-12-09 17:34:15380 suggestions_service_->ClearBlacklist();
381 }
382}
383
sfiera79e643b2016-05-13 16:52:49384void MostVisitedSites::OnBlockedSitesChanged() {
sfiera635d21d2016-08-04 07:56:09385 BuildCurrentTiles();
atanasova9572aaf2016-02-26 18:08:26386}
387
[email protected]7ceb4e32013-12-06 04:13:04388// static
knncbbd754d2015-09-09 15:43:40389void MostVisitedSites::RegisterProfilePrefs(
390 user_prefs::PrefRegistrySyncable* registry) {
sfiera635d21d2016-08-04 07:56:09391 registry->RegisterIntegerPref(prefs::kNumPersonalTiles, 0);
knncbbd754d2015-09-09 15:43:40392}
393
[email protected]bc093e82014-03-04 21:49:11394void MostVisitedSites::InitiateTopSitesQuery() {
treibf7d11512016-06-29 09:06:15395 if (!top_sites_)
396 return;
mastizd0da75e2017-01-09 11:36:48397 if (top_sites_weak_ptr_factory_.HasWeakPtrs())
398 return; // Ongoing query.
sfiera728962f2016-04-29 11:04:02399 top_sites_->GetMostVisitedURLs(
knn6cf777fc2015-05-06 13:21:48400 base::Bind(&MostVisitedSites::OnMostVisitedURLsAvailable,
mastizd0da75e2017-01-09 11:36:48401 top_sites_weak_ptr_factory_.GetWeakPtr()),
[email protected]7ceb4e32013-12-06 04:13:04402 false);
403}
404
atanasova9c0dda602016-03-22 17:41:13405base::FilePath MostVisitedSites::GetWhitelistLargeIconPath(const GURL& url) {
sfiera87db8582016-08-05 10:46:42406 if (supervisor_) {
thestigcff6d872017-06-08 18:30:35407 for (const auto& whitelist : supervisor_->GetWhitelists()) {
sfiera87db8582016-08-05 10:46:42408 if (AreURLsEquivalent(whitelist.entry_point, url))
409 return whitelist.large_icon_path;
410 }
atanasova9c0dda602016-03-22 17:41:13411 }
412 return base::FilePath();
413}
414
[email protected]d4975242014-06-02 18:16:20415void MostVisitedSites::OnMostVisitedURLsAvailable(
[email protected]d4975242014-06-02 18:16:20416 const history::MostVisitedURLList& visited_list) {
kristipark90b244e2018-08-02 19:08:07417 // Ignore the event if tiles are provided by the Suggestions Service or custom
418 // links, which take precedence.
kristiparkf8fa4132018-09-13 18:07:29419 if (IsCustomLinksInitialized() ||
kristipark90b244e2018-08-02 19:08:07420 mv_source_ == TileSource::SUGGESTIONS_SERVICE) {
mastiz64840862017-01-05 12:42:31421 return;
422 }
423
sfiera635d21d2016-08-04 07:56:09424 NTPTilesVector tiles;
kristiparkc0199772018-07-18 05:25:42425 size_t num_tiles = std::min(visited_list.size(), max_num_sites_);
knncbbd754d2015-09-09 15:43:40426 for (size_t i = 0; i < num_tiles; ++i) {
knn6cf777fc2015-05-06 13:21:48427 const history::MostVisitedURL& visited = visited_list[i];
vitaliii875bfee2017-02-08 10:54:53428 if (visited.url.is_empty())
knn6cf777fc2015-05-06 13:21:48429 break; // This is the signal that there are no more real visited sites.
sfiera87db8582016-08-05 10:46:42430 if (supervisor_ && supervisor_->IsBlocked(visited.url))
atanasova9514b302016-02-26 23:09:28431 continue;
atanasova9514b302016-02-26 23:09:28432
sfiera635d21d2016-08-04 07:56:09433 NTPTile tile;
Weilun Shi354a46242018-09-25 06:51:03434 tile.title = IsCustomLinksEnabled() ? GenerateShortTitle(visited.title)
435 : visited.title;
sfiera635d21d2016-08-04 07:56:09436 tile.url = visited.url;
treib231212e2017-04-04 17:09:22437 tile.source = TileSource::TOP_SITES;
sfiera635d21d2016-08-04 07:56:09438 tile.whitelist_icon_path = GetWhitelistLargeIconPath(visited.url);
Friedrich Horschigefec0812017-09-28 18:50:17439 // MostVisitedURL.title is either the title or the URL which is treated
440 // exactly as the title. Differentiating here is not worth the overhead.
441 tile.title_source = TileTitleSource::TITLE_TAG;
Mikel Astiza0f98cc2017-10-12 19:48:48442 // TODO(crbug.com/773278): Populate |data_generation_time| here in order to
443 // log UMA metrics of age.
sfiera635d21d2016-08-04 07:56:09444 tiles.push_back(std::move(tile));
knn6cf777fc2015-05-06 13:21:48445 }
[email protected]d4975242014-06-02 18:16:20446
treib231212e2017-04-04 17:09:22447 mv_source_ = TileSource::TOP_SITES;
Yafei Duan3797cf42018-07-14 01:03:58448 InitiateNotificationForNewTiles(std::move(tiles));
[email protected]d4975242014-06-02 18:16:20449}
450
mastizbad28af2017-01-30 16:04:37451void MostVisitedSites::OnSuggestionsProfileChanged(
[email protected]bc093e82014-03-04 21:49:11452 const SuggestionsProfile& suggestions_profile) {
kristipark90b244e2018-08-02 19:08:07453 // Ignore the event if tiles are provided by custom links, which take
454 // precedence.
kristiparkf8fa4132018-09-13 18:07:29455 if (IsCustomLinksInitialized() ||
kristipark90b244e2018-08-02 19:08:07456 (suggestions_profile.suggestions_size() == 0 &&
457 mv_source_ != TileSource::SUGGESTIONS_SERVICE)) {
mastizbad28af2017-01-30 16:04:37458 return;
459 }
460
461 BuildCurrentTilesGivenSuggestionsProfile(suggestions_profile);
462}
463
464void MostVisitedSites::BuildCurrentTiles() {
kristiparkf8fa4132018-09-13 18:07:29465 if (IsCustomLinksInitialized()) {
kristiparkc0199772018-07-18 05:25:42466 BuildCustomLinks(custom_links_->GetLinks());
467 return;
468 }
469
mastizbad28af2017-01-30 16:04:37470 BuildCurrentTilesGivenSuggestionsProfile(
471 suggestions_service_->GetSuggestionsDataFromCache().value_or(
472 SuggestionsProfile()));
473}
474
475void MostVisitedSites::BuildCurrentTilesGivenSuggestionsProfile(
476 const suggestions::SuggestionsProfile& suggestions_profile) {
fhorschigd3222452017-05-22 08:36:44477 size_t num_tiles = suggestions_profile.suggestions_size();
treibc1bd1f12016-04-29 15:06:05478 // With no server suggestions, fall back to local TopSites.
mastizf3468a82016-06-15 11:05:41479 if (num_tiles == 0 ||
480 !base::FeatureList::IsEnabled(kDisplaySuggestionsServiceTiles)) {
treib231212e2017-04-04 17:09:22481 mv_source_ = TileSource::TOP_SITES;
[email protected]bc093e82014-03-04 21:49:11482 InitiateTopSitesQuery();
483 return;
484 }
kristiparkc0199772018-07-18 05:25:42485 if (max_num_sites_ < num_tiles)
486 num_tiles = max_num_sites_;
[email protected]bc093e82014-03-04 21:49:11487
Mikel Astiza0f98cc2017-10-12 19:48:48488 const base::Time profile_timestamp =
489 base::Time::UnixEpoch() +
490 base::TimeDelta::FromMicroseconds(suggestions_profile.timestamp());
491
sfiera635d21d2016-08-04 07:56:09492 NTPTilesVector tiles;
fhorschigd3222452017-05-22 08:36:44493 for (size_t i = 0; i < num_tiles; ++i) {
treibd2698222016-07-14 11:32:44494 const ChromeSuggestion& suggestion_pb = suggestions_profile.suggestions(i);
495 GURL url(suggestion_pb.url());
sfiera87db8582016-08-05 10:46:42496 if (supervisor_ && supervisor_->IsBlocked(url))
atanasova9514b302016-02-26 23:09:28497 continue;
atanasova9514b302016-02-26 23:09:28498
sfiera635d21d2016-08-04 07:56:09499 NTPTile tile;
Weilun Shi354a46242018-09-25 06:51:03500 tile.title =
501 IsCustomLinksEnabled()
502 ? GenerateShortTitle(base::UTF8ToUTF16(suggestion_pb.title()))
503 : base::UTF8ToUTF16(suggestion_pb.title());
sfiera635d21d2016-08-04 07:56:09504 tile.url = url;
treib231212e2017-04-04 17:09:22505 tile.source = TileSource::SUGGESTIONS_SERVICE;
Friedrich Horschigefec0812017-09-28 18:50:17506 // The title is an aggregation of multiple history entries of one site.
507 tile.title_source = TileTitleSource::INFERRED;
sfiera635d21d2016-08-04 07:56:09508 tile.whitelist_icon_path = GetWhitelistLargeIconPath(url);
treibbb0c5af52016-12-09 17:34:15509 tile.thumbnail_url = GURL(suggestion_pb.thumbnail());
510 tile.favicon_url = GURL(suggestion_pb.favicon_url());
Mikel Astiza0f98cc2017-10-12 19:48:48511 tile.data_generation_time = profile_timestamp;
512
Jan Krcalace93322017-11-22 12:33:54513 icon_cacher_->StartFetchMostLikely(
Yafei Duan3797cf42018-07-14 01:03:58514 url, base::BindRepeating(&MostVisitedSites::OnIconMadeAvailable,
515 base::Unretained(this), url));
atanasovac3c25d12016-03-17 18:33:57516
sfiera635d21d2016-08-04 07:56:09517 tiles.push_back(std::move(tile));
[email protected]bc093e82014-03-04 21:49:11518 }
treib783a3372015-08-25 16:24:39519
treib231212e2017-04-04 17:09:22520 mv_source_ = TileSource::SUGGESTIONS_SERVICE;
Yafei Duan3797cf42018-07-14 01:03:58521 InitiateNotificationForNewTiles(std::move(tiles));
knn6cf777fc2015-05-06 13:21:48522}
[email protected]d4975242014-06-02 18:16:20523
sfiera635d21d2016-08-04 07:56:09524NTPTilesVector MostVisitedSites::CreateWhitelistEntryPointTiles(
fhorschigd3222452017-05-22 08:36:44525 const std::set<std::string>& used_hosts,
526 size_t num_actual_tiles) {
sfiera87db8582016-08-05 10:46:42527 if (!supervisor_) {
528 return NTPTilesVector();
529 }
530
sfiera635d21d2016-08-04 07:56:09531 NTPTilesVector whitelist_tiles;
thestigcff6d872017-06-08 18:30:35532 for (const auto& whitelist : supervisor_->GetWhitelists()) {
kristiparkc0199772018-07-18 05:25:42533 if (whitelist_tiles.size() + num_actual_tiles >= max_num_sites_)
sfierae56d2a02017-02-07 09:40:09534 break;
535
atanasova9514b302016-02-26 23:09:28536 // Skip blacklisted sites.
treibf7d11512016-06-29 09:06:15537 if (top_sites_ && top_sites_->IsBlacklisted(whitelist.entry_point))
atanasova9514b302016-02-26 23:09:28538 continue;
539
sfiera635d21d2016-08-04 07:56:09540 // Skip tiles already present.
fhorschigd3222452017-05-22 08:36:44541 if (used_hosts.find(whitelist.entry_point.host()) != used_hosts.end())
atanasova9514b302016-02-26 23:09:28542 continue;
543
544 // Skip whitelist entry points that are manually blocked.
sfiera79e643b2016-05-13 16:52:49545 if (supervisor_->IsBlocked(whitelist.entry_point))
atanasova9514b302016-02-26 23:09:28546 continue;
atanasova9514b302016-02-26 23:09:28547
sfiera635d21d2016-08-04 07:56:09548 NTPTile tile;
549 tile.title = whitelist.title;
550 tile.url = whitelist.entry_point;
treib231212e2017-04-04 17:09:22551 tile.source = TileSource::WHITELIST;
Friedrich Horschigefec0812017-09-28 18:50:17552 // User-set. Might be the title but we cannot be sure.
553 tile.title_source = TileTitleSource::UNKNOWN;
sfiera635d21d2016-08-04 07:56:09554 tile.whitelist_icon_path = whitelist.large_icon_path;
sfiera635d21d2016-08-04 07:56:09555 whitelist_tiles.push_back(std::move(tile));
atanasova9572aaf2016-02-26 18:08:26556 }
557
sfiera635d21d2016-08-04 07:56:09558 return whitelist_tiles;
atanasova9572aaf2016-02-26 18:08:26559}
560
Friedrich Horschig9e8749f02017-08-10 09:17:31561std::map<SectionType, NTPTilesVector>
562MostVisitedSites::CreatePopularSitesSections(
fhorschigd3222452017-05-22 08:36:44563 const std::set<std::string>& used_hosts,
564 size_t num_actual_tiles) {
Friedrich Horschig9e8749f02017-08-10 09:17:31565 std::map<SectionType, NTPTilesVector> sections = {
566 std::make_pair(SectionType::PERSONALIZED, NTPTilesVector())};
sfiera635d21d2016-08-04 07:56:09567 // For child accounts popular sites tiles will not be added.
fhorschigd3222452017-05-22 08:36:44568 if (supervisor_ && supervisor_->IsChildProfile()) {
Friedrich Horschig9e8749f02017-08-10 09:17:31569 return sections;
fhorschigd3222452017-05-22 08:36:44570 }
atanasova9514b302016-02-26 23:09:28571
fhorschigd3222452017-05-22 08:36:44572 if (!popular_sites_ || !ShouldShowPopularSites()) {
Friedrich Horschig9e8749f02017-08-10 09:17:31573 return sections;
fhorschigd3222452017-05-22 08:36:44574 }
atanasova9572aaf2016-02-26 18:08:26575
Friedrich Horschig9e8749f02017-08-10 09:17:31576 const std::set<std::string> no_hosts;
577 for (const auto& section_type_and_sites : popular_sites()->sections()) {
578 SectionType type = section_type_and_sites.first;
579 const PopularSites::SitesVector& sites = section_type_and_sites.second;
580 if (type == SectionType::PERSONALIZED) {
kristiparkc0199772018-07-18 05:25:42581 size_t num_required_tiles = max_num_sites_ - num_actual_tiles;
Friedrich Horschig9e8749f02017-08-10 09:17:31582 sections[type] =
583 CreatePopularSitesTiles(/*popular_sites=*/sites,
584 /*hosts_to_skip=*/used_hosts,
585 /*num_max_tiles=*/num_required_tiles);
586 } else {
kristiparkc0199772018-07-18 05:25:42587 sections[type] =
588 CreatePopularSitesTiles(/*popular_sites=*/sites,
589 /*hosts_to_skip=*/no_hosts,
590 /*num_max_tiles=*/max_num_sites_);
Friedrich Horschig9e8749f02017-08-10 09:17:31591 }
592 }
593 return sections;
594}
595
596NTPTilesVector MostVisitedSites::CreatePopularSitesTiles(
597 const PopularSites::SitesVector& sites_vector,
598 const std::set<std::string>& hosts_to_skip,
599 size_t num_max_tiles) {
knncbbd754d2015-09-09 15:43:40600 // Collect non-blacklisted popular suggestions, skipping those already present
601 // in the personal suggestions.
sfiera635d21d2016-08-04 07:56:09602 NTPTilesVector popular_sites_tiles;
Friedrich Horschig9e8749f02017-08-10 09:17:31603 for (const PopularSites::Site& popular_site : sites_vector) {
604 if (popular_sites_tiles.size() >= num_max_tiles) {
fhorschigd3222452017-05-22 08:36:44605 break;
Friedrich Horschig9e8749f02017-08-10 09:17:31606 }
treibcffa6502015-08-06 09:12:27607
fhorschigd3222452017-05-22 08:36:44608 // Skip blacklisted sites.
609 if (top_sites_ && top_sites_->IsBlacklisted(popular_site.url))
610 continue;
treibcffa6502015-08-06 09:12:27611
fhorschigd3222452017-05-22 08:36:44612 const std::string& host = popular_site.url.host();
Friedrich Horschigb1733402017-08-28 17:06:11613 if (IsHostOrMobilePageKnown(hosts_to_skip, host)) {
fhorschigd3222452017-05-22 08:36:44614 continue;
Friedrich Horschig9e8749f02017-08-10 09:17:31615 }
atanasovac3c25d12016-03-17 18:33:57616
fhorschigd3222452017-05-22 08:36:44617 NTPTile tile;
618 tile.title = popular_site.title;
619 tile.url = GURL(popular_site.url);
Friedrich Horschigefec0812017-09-28 18:50:17620 tile.title_source = popular_site.title_source;
Friedrich Horschig7706ef62017-08-25 08:20:00621 tile.source = popular_site.baked_in ? TileSource::POPULAR_BAKED_IN
622 : TileSource::POPULAR;
fhorschigd3222452017-05-22 08:36:44623 popular_sites_tiles.push_back(std::move(tile));
624 base::Closure icon_available =
625 base::Bind(&MostVisitedSites::OnIconMadeAvailable,
626 base::Unretained(this), popular_site.url);
627 icon_cacher_->StartFetchPopularSites(popular_site, icon_available,
628 icon_available);
treibcffa6502015-08-06 09:12:27629 }
sfiera635d21d2016-08-04 07:56:09630 return popular_sites_tiles;
atanasova9572aaf2016-02-26 18:08:26631}
632
Yafei Duan3797cf42018-07-14 01:03:58633void MostVisitedSites::OnHomepageTitleDetermined(
634 NTPTilesVector tiles,
635 const base::Optional<base::string16>& title) {
636 if (!title.has_value())
637 return; // If there is no title, the most recent tile was already sent out.
638
kristiparkc0199772018-07-18 05:25:42639 MergeMostVisitedTiles(InsertHomeTile(std::move(tiles), title.value()));
Yafei Duan3797cf42018-07-14 01:03:58640}
641
642NTPTilesVector MostVisitedSites::InsertHomeTile(
643 NTPTilesVector tiles,
644 const base::string16& title) const {
645 DCHECK(homepage_client_);
kristiparkc0199772018-07-18 05:25:42646 DCHECK_GT(max_num_sites_, 0u);
Yafei Duan3797cf42018-07-14 01:03:58647
648 const GURL& homepage_url = homepage_client_->GetHomepageUrl();
649 NTPTilesVector new_tiles;
650 bool homepage_tile_added = false;
651
652 for (auto& tile : tiles) {
kristiparkc0199772018-07-18 05:25:42653 if (new_tiles.size() >= max_num_sites_) {
Yafei Duan3797cf42018-07-14 01:03:58654 break;
655 }
656
657 // If there's a tile has the same host name with homepage, insert the tile
658 // to the first position of the list. This is also a deduplication.
659 if (tile.url.host() == homepage_url.host() && !homepage_tile_added) {
660 tile.source = TileSource::HOMEPAGE;
661 homepage_tile_added = true;
662 new_tiles.insert(new_tiles.begin(), std::move(tile));
663 continue;
664 }
665 new_tiles.push_back(std::move(tile));
666 }
667
668 if (!homepage_tile_added) {
669 // Make room for the homepage tile.
kristiparkc0199772018-07-18 05:25:42670 if (new_tiles.size() >= max_num_sites_) {
Yafei Duan3797cf42018-07-14 01:03:58671 new_tiles.pop_back();
672 }
673 NTPTile homepage_tile;
674 homepage_tile.url = homepage_url;
675 homepage_tile.title = title;
676 homepage_tile.source = TileSource::HOMEPAGE;
677 homepage_tile.title_source = TileTitleSource::TITLE_TAG;
678
679 // Always insert |homepage_tile| to the front of |new_tiles| to ensure it's
680 // the first tile.
681 new_tiles.insert(new_tiles.begin(), std::move(homepage_tile));
682 }
683 return new_tiles;
684}
685
kristiparke79bcc32018-08-29 19:02:31686void MostVisitedSites::OnCustomLinksChanged() {
687 DCHECK(custom_links_);
688 DCHECK(custom_links_->IsInitialized());
kristiparkf8fa4132018-09-13 18:07:29689 if (custom_links_enabled_)
690 BuildCustomLinks(custom_links_->GetLinks());
kristiparke79bcc32018-08-29 19:02:31691}
692
kristiparkc0199772018-07-18 05:25:42693void MostVisitedSites::BuildCustomLinks(
694 const std::vector<CustomLinksManager::Link>& links) {
kristipark6d3d90d32018-07-19 03:28:01695 DCHECK(IsCustomLinksEnabled());
kristiparkc0199772018-07-18 05:25:42696
697 NTPTilesVector tiles;
kristiparkc16800962018-07-31 20:05:29698 size_t num_tiles = std::min(links.size(), kMaxNumCustomLinks);
kristiparkc0199772018-07-18 05:25:42699 for (size_t i = 0; i < num_tiles; ++i) {
700 const CustomLinksManager::Link& link = links.at(i);
701 if (supervisor_ && supervisor_->IsBlocked(link.url))
702 continue;
703
704 NTPTile tile;
705 tile.title = link.title;
706 tile.url = link.url;
707 tile.source = TileSource::CUSTOM_LINKS;
708 // TODO(crbug.com/773278): Populate |data_generation_time| here in order to
709 // log UMA metrics of age.
710 tiles.push_back(std::move(tile));
711 }
712
713 mv_source_ = TileSource::CUSTOM_LINKS;
714 SaveTilesAndNotify(std::move(tiles), std::map<SectionType, NTPTilesVector>());
715}
716
Yafei Duan3797cf42018-07-14 01:03:58717void MostVisitedSites::InitiateNotificationForNewTiles(
718 NTPTilesVector new_tiles) {
719 if (ShouldAddHomeTile() && !HasHomeTile(new_tiles)) {
720 homepage_client_->QueryHomepageTitle(
721 base::BindOnce(&MostVisitedSites::OnHomepageTitleDetermined,
722 base::Unretained(this), new_tiles));
723 GURL homepage_url = homepage_client_->GetHomepageUrl();
724 icon_cacher_->StartFetchMostLikely(
725 homepage_url,
726 base::BindRepeating(&MostVisitedSites::OnIconMadeAvailable,
727 base::Unretained(this), homepage_url));
728
729 // Don't wait for the homepage title from history but immediately serve a
730 // copy of new tiles.
731 new_tiles = InsertHomeTile(std::move(new_tiles), base::string16());
732 }
kristiparkc0199772018-07-18 05:25:42733 MergeMostVisitedTiles(std::move(new_tiles));
Yafei Duan3797cf42018-07-14 01:03:58734}
735
kristiparkc0199772018-07-18 05:25:42736void MostVisitedSites::MergeMostVisitedTiles(NTPTilesVector personal_tiles) {
fhorschigd3222452017-05-22 08:36:44737 std::set<std::string> used_hosts;
738 size_t num_actual_tiles = 0u;
fhorschigd3222452017-05-22 08:36:44739 AddToHostsAndTotalCount(personal_tiles, &used_hosts, &num_actual_tiles);
740
741 NTPTilesVector whitelist_tiles =
742 CreateWhitelistEntryPointTiles(used_hosts, num_actual_tiles);
743 AddToHostsAndTotalCount(whitelist_tiles, &used_hosts, &num_actual_tiles);
744
Friedrich Horschig9e8749f02017-08-10 09:17:31745 std::map<SectionType, NTPTilesVector> sections =
746 CreatePopularSitesSections(used_hosts, num_actual_tiles);
747 AddToHostsAndTotalCount(sections[SectionType::PERSONALIZED], &used_hosts,
748 &num_actual_tiles);
treib5a59f542016-05-18 12:17:29749
sfiera3140e142017-03-07 16:00:48750 NTPTilesVector new_tiles =
sfiera635d21d2016-08-04 07:56:09751 MergeTiles(std::move(personal_tiles), std::move(whitelist_tiles),
Friedrich Horschig9e8749f02017-08-10 09:17:31752 std::move(sections[SectionType::PERSONALIZED]));
sfiera3140e142017-03-07 16:00:48753
kristiparkc0199772018-07-18 05:25:42754 SaveTilesAndNotify(std::move(new_tiles), std::move(sections));
755}
756
757void MostVisitedSites::SaveTilesAndNotify(
758 NTPTilesVector new_tiles,
759 std::map<SectionType, NTPTilesVector> sections) {
760 if (current_tiles_.has_value() && (*current_tiles_ == new_tiles))
761 return;
sfiera3140e142017-03-07 16:00:48762 current_tiles_.emplace(std::move(new_tiles));
treib5a59f542016-05-18 12:17:29763
sfiera635d21d2016-08-04 07:56:09764 int num_personal_tiles = 0;
sfiera3140e142017-03-07 16:00:48765 for (const auto& tile : *current_tiles_) {
Friedrich Horschig764f2902018-01-22 14:28:48766 if (tile.source != TileSource::POPULAR &&
767 tile.source != TileSource::POPULAR_BAKED_IN) {
sfiera635d21d2016-08-04 07:56:09768 num_personal_tiles++;
Friedrich Horschig764f2902018-01-22 14:28:48769 }
treibcd3d2ef2016-07-13 16:53:31770 }
sfiera635d21d2016-08-04 07:56:09771 prefs_->SetInteger(prefs::kNumPersonalTiles, num_personal_tiles);
sfiera3140e142017-03-07 16:00:48772 if (!observer_)
773 return;
Friedrich Horschig9e8749f02017-08-10 09:17:31774 sections[SectionType::PERSONALIZED] = *current_tiles_;
775 observer_->OnURLsAvailable(sections);
treibcf674e62015-08-17 15:43:01776}
777
778// static
sfiera635d21d2016-08-04 07:56:09779NTPTilesVector MostVisitedSites::MergeTiles(NTPTilesVector personal_tiles,
780 NTPTilesVector whitelist_tiles,
781 NTPTilesVector popular_tiles) {
782 NTPTilesVector merged_tiles;
783 std::move(personal_tiles.begin(), personal_tiles.end(),
784 std::back_inserter(merged_tiles));
785 std::move(whitelist_tiles.begin(), whitelist_tiles.end(),
786 std::back_inserter(merged_tiles));
787 std::move(popular_tiles.begin(), popular_tiles.end(),
788 std::back_inserter(merged_tiles));
789 return merged_tiles;
treibcffa6502015-08-06 09:12:27790}
791
mastizfd2c7ab2017-01-27 19:35:00792void MostVisitedSites::OnPopularSitesDownloaded(bool success) {
treibcffa6502015-08-06 09:12:27793 if (!success) {
794 LOG(WARNING) << "Download of popular sites failed";
795 return;
796 }
bauerb21e371e2017-03-03 18:48:29797
Friedrich Horschig9e8749f02017-08-10 09:17:31798 for (const auto& section : popular_sites_->sections()) {
799 for (const PopularSites::Site& site : section.second) {
800 // Ignore callback; these icons will be seen on the *next* NTP.
801 icon_cacher_->StartFetchPopularSites(site, base::Closure(),
802 base::Closure());
803 }
bauerb21e371e2017-03-03 18:48:29804 }
treibcffa6502015-08-06 09:12:27805}
806
fhorschigfed34be2017-03-02 23:16:09807void MostVisitedSites::OnIconMadeAvailable(const GURL& site_url) {
808 observer_->OnIconMadeAvailable(site_url);
sfieraae1ae692016-10-24 18:19:15809}
810
treib16070ce2016-03-11 11:57:40811void MostVisitedSites::TopSitesLoaded(TopSites* top_sites) {}
sdefresneedf9e01f2015-01-13 19:45:41812
treib16070ce2016-03-11 11:57:40813void MostVisitedSites::TopSitesChanged(TopSites* top_sites,
fserbdb575112015-06-29 21:31:59814 ChangeReason change_reason) {
treib231212e2017-04-04 17:09:22815 if (mv_source_ == TileSource::TOP_SITES) {
sfiera635d21d2016-08-04 07:56:09816 // The displayed tiles are invalidated.
newt2a47ce72015-10-01 20:09:49817 InitiateTopSitesQuery();
sdefresneedf9e01f2015-01-13 19:45:41818 }
819}
sfiera08009fe2016-06-15 17:07:26820
Yafei Duan3797cf42018-07-14 01:03:58821bool MostVisitedSites::ShouldAddHomeTile() const {
kristiparkc0199772018-07-18 05:25:42822 return max_num_sites_ > 0u &&
Yafei Duan3797cf42018-07-14 01:03:58823 homepage_client_ && // No platform-specific implementation - no tile.
Yafei Duanddf0db02018-07-18 17:21:47824 homepage_client_->IsHomepageTileEnabled() &&
Yafei Duan3797cf42018-07-14 01:03:58825 !homepage_client_->GetHomepageUrl().is_empty() &&
826 !(top_sites_ &&
827 top_sites_->IsBlacklisted(homepage_client_->GetHomepageUrl()));
828}
829
fhorschigd3222452017-05-22 08:36:44830void MostVisitedSites::AddToHostsAndTotalCount(const NTPTilesVector& new_tiles,
831 std::set<std::string>* hosts,
832 size_t* total_tile_count) const {
833 for (const auto& tile : new_tiles) {
834 hosts->insert(tile.url.host());
835 }
836 *total_tile_count += new_tiles.size();
kristiparkc0199772018-07-18 05:25:42837 DCHECK_LE(*total_tile_count, max_num_sites_);
fhorschigd3222452017-05-22 08:36:44838}
839
sfiera08009fe2016-06-15 17:07:26840} // namespace ntp_tiles