most_visited_sites.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. // 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. #ifndef COMPONENTS_NTP_TILES_MOST_VISITED_SITES_H_
  5. #define COMPONENTS_NTP_TILES_MOST_VISITED_SITES_H_
  6. #include <stddef.h>
  7. #include <map>
  8. #include <memory>
  9. #include <set>
  10. #include <string>
  11. #include <vector>
  12. #include "base/callback_forward.h"
  13. #include "base/callback_list.h"
  14. #include "base/compiler_specific.h"
  15. #include "base/gtest_prod_util.h"
  16. #include "base/memory/raw_ptr.h"
  17. #include "base/memory/weak_ptr.h"
  18. #include "base/observer_list.h"
  19. #include "base/observer_list_types.h"
  20. #include "base/scoped_observation.h"
  21. #include "components/history/core/browser/history_types.h"
  22. #include "components/history/core/browser/top_sites.h"
  23. #include "components/history/core/browser/top_sites_observer.h"
  24. #include "components/ntp_tiles/custom_links_manager.h"
  25. #include "components/ntp_tiles/ntp_tile.h"
  26. #include "components/ntp_tiles/popular_sites.h"
  27. #include "components/ntp_tiles/section_type.h"
  28. #include "components/ntp_tiles/tile_source.h"
  29. #include "components/webapps/common/constants.h"
  30. #include "third_party/abseil-cpp/absl/types/optional.h"
  31. #include "url/gurl.h"
  32. namespace user_prefs {
  33. class PrefRegistrySyncable;
  34. }
  35. class PrefService;
  36. namespace ntp_tiles {
  37. class IconCacher;
  38. // Shim interface for SupervisedUserService.
  39. class MostVisitedSitesSupervisor {
  40. public:
  41. class Observer {
  42. public:
  43. virtual void OnBlockedSitesChanged() = 0;
  44. protected:
  45. ~Observer() {}
  46. };
  47. virtual ~MostVisitedSitesSupervisor() {}
  48. // Pass non-null to set observer, or null to remove observer.
  49. // If setting observer, there must not yet be an observer set.
  50. // If removing observer, there must already be one to remove.
  51. // Does not take ownership. Observer must outlive this object.
  52. virtual void SetObserver(Observer* new_observer) = 0;
  53. // If true, |url| should not be shown on the NTP.
  54. virtual bool IsBlocked(const GURL& url) = 0;
  55. // If true, be conservative about suggesting sites from outside sources.
  56. virtual bool IsChildProfile() = 0;
  57. };
  58. // Tracks the list of most visited sites.
  59. class MostVisitedSites : public history::TopSitesObserver,
  60. public MostVisitedSitesSupervisor::Observer {
  61. public:
  62. // The observer to be notified when the list of most visited sites changes.
  63. class Observer : public base::CheckedObserver {
  64. public:
  65. // |sections| must at least contain the PERSONALIZED section.
  66. virtual void OnURLsAvailable(
  67. const std::map<SectionType, NTPTilesVector>& sections) = 0;
  68. virtual void OnIconMadeAvailable(const GURL& site_url) = 0;
  69. };
  70. // This interface delegates the retrieval of the homepage to the
  71. // platform-specific implementation.
  72. class HomepageClient {
  73. public:
  74. using TitleCallback =
  75. base::OnceCallback<void(const absl::optional<std::u16string>& title)>;
  76. virtual ~HomepageClient() = default;
  77. virtual bool IsHomepageTileEnabled() const = 0;
  78. virtual GURL GetHomepageUrl() const = 0;
  79. virtual void QueryHomepageTitle(TitleCallback title_callback) = 0;
  80. };
  81. class ExploreSitesClient {
  82. public:
  83. virtual ~ExploreSitesClient() = default;
  84. virtual GURL GetExploreSitesUrl() const = 0;
  85. virtual std::u16string GetExploreSitesTitle() const = 0;
  86. };
  87. // Construct a MostVisitedSites instance.
  88. //
  89. // |prefs| and |suggestions| are required and may not be null. |top_sites|,
  90. // |popular_sites|, |custom_links|, |supervisor| and |homepage_client| are
  91. // optional and if null, the associated features will be disabled.
  92. MostVisitedSites(PrefService* prefs,
  93. scoped_refptr<history::TopSites> top_sites,
  94. std::unique_ptr<PopularSites> popular_sites,
  95. std::unique_ptr<CustomLinksManager> custom_links,
  96. std::unique_ptr<IconCacher> icon_cacher,
  97. std::unique_ptr<MostVisitedSitesSupervisor> supervisor,
  98. bool is_default_chrome_app_migrated);
  99. MostVisitedSites(const MostVisitedSites&) = delete;
  100. MostVisitedSites& operator=(const MostVisitedSites&) = delete;
  101. ~MostVisitedSites() override;
  102. // Returns true if this object was created with a non-null provider for the
  103. // given NTP tile source. That source may or may not actually provide tiles,
  104. // depending on its configuration and the priority of different sources.
  105. bool DoesSourceExist(TileSource source) const;
  106. // Returns the corresponding object passed at construction.
  107. history::TopSites* top_sites() { return top_sites_.get(); }
  108. PopularSites* popular_sites() { return popular_sites_.get(); }
  109. MostVisitedSitesSupervisor* supervisor() { return supervisor_.get(); }
  110. // Adds the observer and immediately fetches the current suggestions.
  111. // All observers will be notified when the suggestions are fetched.
  112. //
  113. // Note: only observers that require the same |max_num_sites| could observe
  114. // the same MostVisitedSites instance. Otherwise, a new Instance should be
  115. // created for the observer.
  116. //
  117. // Does not take ownership of |observer|, which must outlive this object and
  118. // must not be null. |max_num_sites| indicates the the maximum number of most
  119. // visited sites to return.
  120. void AddMostVisitedURLsObserver(Observer* observer, size_t max_num_sites);
  121. // Removes the observer.
  122. void RemoveMostVisitedURLsObserver(Observer* observer);
  123. // Sets the client that provides platform-specific homepage preferences.
  124. // When used to replace an existing client, the new client will first be
  125. // used during the construction of a new tile set.
  126. // |client| must not be null and outlive this object.
  127. void SetHomepageClient(std::unique_ptr<HomepageClient> client);
  128. // Sets the client that provides the Explore Sites tile. Can be null if no
  129. // such tile is desirable.
  130. void SetExploreSitesClient(std::unique_ptr<ExploreSitesClient> client);
  131. // Requests an asynchronous refresh of the suggestions. Notifies the observer
  132. // if the request resulted in the set of tiles changing.
  133. void Refresh();
  134. // Forces a rebuild of the current tiles.
  135. void RefreshTiles();
  136. // Initializes custom links, which "freezes" the current MV tiles and converts
  137. // them to custom links. Once custom links is initialized, MostVisitedSites
  138. // will return only custom links. If the Most Visited tiles have not been
  139. // loaded yet, does nothing. Custom links must be enabled.
  140. void InitializeCustomLinks();
  141. // Uninitializes custom links and reverts back to regular MV tiles. The
  142. // current custom links will be deleted. Custom links must be enabled.
  143. void UninitializeCustomLinks();
  144. // Returns true if custom links has been initialized and not disabled, false
  145. // otherwise.
  146. bool IsCustomLinksInitialized();
  147. // Enables or disables custom links, but does not (un)initialize them. Called
  148. // when the user switches between custom links and Most Visited sites on the
  149. // 1P Desktop NTP.
  150. void EnableCustomLinks(bool enable);
  151. // Returns whether custom links are enabled.
  152. bool IsCustomLinksEnabled() const;
  153. // Sets the visibility of the NTP tiles.
  154. void SetShortcutsVisible(bool visible);
  155. // Returns whether NTP tiles should be shown.
  156. bool IsShortcutsVisible() const;
  157. // Adds a custom link. If the number of current links is maxed, returns false
  158. // and does nothing. Will initialize custom links if they have not been
  159. // initialized yet, unless the action fails. Custom links must be enabled.
  160. bool AddCustomLink(const GURL& url, const std::u16string& title);
  161. // Updates the URL and/or title of the custom link specified by |url|. If
  162. // |url| does not exist or |new_url| already exists in the custom link list,
  163. // returns false and does nothing. Will initialize custom links if they have
  164. // not been initialized yet, unless the action fails. Custom links must be
  165. // enabled.
  166. bool UpdateCustomLink(const GURL& url,
  167. const GURL& new_url,
  168. const std::u16string& new_title);
  169. // Moves the custom link specified by |url| to the index |new_pos|. If |url|
  170. // does not exist, or |new_pos| is invalid, returns false and does nothing.
  171. // Will initialize custom links if they have not been initialized yet, unless
  172. // the action fails. Custom links must be enabled.
  173. bool ReorderCustomLink(const GURL& url, size_t new_pos);
  174. // Deletes the custom link with the specified |url|. If |url| does not exist
  175. // in the custom link list, returns false and does nothing. Will initialize
  176. // custom links if they have not been initialized yet, unless the action
  177. // fails. Custom links must be enabled.
  178. bool DeleteCustomLink(const GURL& url);
  179. // Restores the previous state of custom links before the last action that
  180. // modified them. If there was no action, does nothing. If this is undoing the
  181. // first action after initialization, uninitializes the links. Custom links
  182. // must be enabled.
  183. void UndoCustomLinkAction();
  184. size_t GetCustomLinkNum();
  185. void AddOrRemoveBlockedUrl(const GURL& url, bool add_url);
  186. void ClearBlockedUrls();
  187. // MostVisitedSitesSupervisor::Observer implementation.
  188. void OnBlockedSitesChanged() override;
  189. static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
  190. static void ResetProfilePrefs(PrefService* prefs);
  191. // Workhorse for SaveNewTilesAndNotify. Implemented as a separate static and
  192. // public method for ease of testing.
  193. static NTPTilesVector MergeTiles(NTPTilesVector personal_tiles,
  194. NTPTilesVector popular_tiles,
  195. absl::optional<NTPTile> explore_tile);
  196. // Verifies if NTPTile App was migrated to a WebApp.
  197. static bool WasNtpAppMigratedToWebApp(PrefService* prefs, GURL url);
  198. // Verifies if NTPTile App comes from a PreInstalledApp.
  199. static bool IsNtpTileFromPreinstalledApp(GURL url);
  200. private:
  201. FRIEND_TEST_ALL_PREFIXES(MostVisitedSitesTest,
  202. ShouldDeduplicateDomainWithNoWwwDomain);
  203. FRIEND_TEST_ALL_PREFIXES(MostVisitedSitesTest,
  204. ShouldDeduplicateDomainByRemovingMobilePrefixes);
  205. FRIEND_TEST_ALL_PREFIXES(MostVisitedSitesTest,
  206. ShouldDeduplicateDomainByReplacingMobilePrefixes);
  207. // This function tries to match the given |host| to a close fit in
  208. // |hosts_to_skip| by removing a prefix that is commonly used to redirect from
  209. // or to mobile pages (m.xyz.com --> xyz.com).
  210. // If this approach fails, the prefix is replaced by another prefix.
  211. // That way, true is returned for m.x.com if www.x.com is in |hosts_to_skip|.
  212. static bool IsHostOrMobilePageKnown(
  213. const std::set<std::string>& hosts_to_skip,
  214. const std::string& host);
  215. // Returns the maximum number of most visited sites to return. The return
  216. // value is |max_num_sites_| which is ntp_tiles::kMaxNumMostVisited for
  217. // Desktop, unless custom links are enabled in which case an additional tile
  218. // may be returned making up to ntp_tiles::kMaxNumCustomLinks custom links
  219. // including the "Add shortcut" button.
  220. size_t GetMaxNumSites() const;
  221. // Initialize the query to Top Sites.
  222. void InitiateTopSitesQuery();
  223. // Callback for when data is available from TopSites.
  224. void OnMostVisitedURLsAvailable(
  225. const history::MostVisitedURLList& visited_list);
  226. // Builds the current tileset based on available caches and notifies the
  227. // observer.
  228. void BuildCurrentTiles();
  229. // Creates tiles for all popular site sections. Uses |num_actual_tiles| and
  230. // |used_hosts| to restrict results for the PERSONALIZED section.
  231. std::map<SectionType, NTPTilesVector> CreatePopularSitesSections(
  232. const std::set<std::string>& used_hosts,
  233. size_t num_actual_tiles);
  234. // Creates tiles for |sites_vector|. The returned vector will neither contain
  235. // more than |num_max_tiles| nor include sites in |hosts_to_skip|.
  236. NTPTilesVector CreatePopularSitesTiles(
  237. const PopularSites::SitesVector& sites_vector,
  238. const std::set<std::string>& hosts_to_skip,
  239. size_t num_max_tiles);
  240. // Callback for when an update is reported by CustomLinksManager.
  241. void OnCustomLinksChanged();
  242. // Creates tiles for |links| up to |max_num_sites_|. |links| will never exceed
  243. // a certain maximum.
  244. void BuildCustomLinks(const std::vector<CustomLinksManager::Link>& links);
  245. // Initiates a query for the homepage tile if needed and calls
  246. // |SaveTilesAndNotify| in the end.
  247. void InitiateNotificationForNewTiles(NTPTilesVector new_tiles);
  248. // Takes the personal tiles and merges in popular tiles if appropriate. Calls
  249. // |SaveTilesAndNotify| at the end.
  250. void MergeMostVisitedTiles(NTPTilesVector personal_tiles);
  251. // Removes pre installed apps which turn invalid because of migration.
  252. NTPTilesVector RemoveInvalidPreinstallApps(NTPTilesVector new_tiles);
  253. // Saves the new tiles and notifies the observer if the tiles were actually
  254. // changed.
  255. void SaveTilesAndNotify(NTPTilesVector new_tiles,
  256. std::map<SectionType, NTPTilesVector> sections);
  257. void OnPopularSitesDownloaded(bool success);
  258. void OnIconMadeAvailable(const GURL& site_url);
  259. // Updates the already used hosts and the total tile count based on given new
  260. // tiles. Enforces that the required amount of tiles is not exceeded.
  261. void AddToHostsAndTotalCount(const NTPTilesVector& new_tiles,
  262. std::set<std::string>* hosts,
  263. size_t* total_tile_count) const;
  264. // Adds the homepage as first tile to |tiles| and returns them as new vector.
  265. // Drops existing tiles with the same host as the home page and tiles that
  266. // would exceed the maximum.
  267. NTPTilesVector InsertHomeTile(NTPTilesVector tiles,
  268. const std::u16string& title) const;
  269. // Creates a tile for the Explore Sites page, if enabled. The tile is added to
  270. // the front of the list.
  271. absl::optional<NTPTile> CreateExploreSitesTile();
  272. void OnHomepageTitleDetermined(NTPTilesVector tiles,
  273. const absl::optional<std::u16string>& title);
  274. // Returns true if there is a valid homepage that can be pinned as tile.
  275. bool ShouldAddHomeTile() const;
  276. // history::TopSitesObserver implementation.
  277. void TopSitesLoaded(history::TopSites* top_sites) override;
  278. void TopSitesChanged(history::TopSites* top_sites,
  279. ChangeReason change_reason) override;
  280. raw_ptr<PrefService> prefs_;
  281. scoped_refptr<history::TopSites> top_sites_;
  282. std::unique_ptr<PopularSites> const popular_sites_;
  283. std::unique_ptr<CustomLinksManager> const custom_links_;
  284. std::unique_ptr<IconCacher> const icon_cacher_;
  285. std::unique_ptr<MostVisitedSitesSupervisor> supervisor_;
  286. std::unique_ptr<HomepageClient> homepage_client_;
  287. std::unique_ptr<ExploreSitesClient> explore_sites_client_;
  288. bool is_default_chrome_app_migrated_;
  289. base::ObserverList<Observer> observers_;
  290. // The maximum number of most visited sites to return.
  291. // Do not use directly. Use GetMaxNumSites() instead.
  292. size_t max_num_sites_;
  293. // Number of actions after custom link initialization. Set to -1 and not
  294. // incremented if custom links was not initialized during this session.
  295. int custom_links_action_count_ = -1;
  296. bool is_custom_links_enabled_ = true;
  297. bool is_shortcuts_visible_ = true;
  298. base::ScopedObservation<history::TopSites, history::TopSitesObserver>
  299. top_sites_observation_{this};
  300. base::CallbackListSubscription custom_links_subscription_;
  301. // The main source of personal tiles - either TOP_SITES or CUSTOM_LINKS.
  302. TileSource mv_source_;
  303. // Current set of tiles. Optional so that the observer can be notified
  304. // whenever it changes, including possibily an initial change from
  305. // !current_tiles_.has_value() to current_tiles_->empty().
  306. absl::optional<NTPTilesVector> current_tiles_;
  307. // Whether has started observing data sources.
  308. bool is_observing_;
  309. // For callbacks may be run after destruction, used exclusively for TopSites
  310. // (since it's used to detect whether there's a query in flight).
  311. base::WeakPtrFactory<MostVisitedSites> top_sites_weak_ptr_factory_{this};
  312. };
  313. } // namespace ntp_tiles
  314. #endif // COMPONENTS_NTP_TILES_MOST_VISITED_SITES_H_