File: most_visited_sites.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (454 lines) | stat: -rw-r--r-- 18,298 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_NTP_TILES_MOST_VISITED_SITES_H_
#define COMPONENTS_NTP_TILES_MOST_VISITED_SITES_H_

#include <stddef.h>

#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>

#include "base/callback_list.h"
#include "base/compiler_specific.h"
#include "base/functional/callback_forward.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/scoped_observation.h"
#include "components/history/core/browser/history_types.h"
#include "components/history/core/browser/top_sites.h"
#include "components/history/core/browser/top_sites_observer.h"
#include "components/ntp_tiles/custom_links_manager.h"
#include "components/ntp_tiles/ntp_tile.h"
#include "components/ntp_tiles/popular_sites.h"
#include "components/ntp_tiles/section_type.h"
#include "components/ntp_tiles/tile_source.h"
#include "components/supervised_user/core/common/buildflags.h"
#include "components/webapps/common/constants.h"
#include "url/gurl.h"

#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
#include "components/supervised_user/core/browser/supervised_user_service_observer.h"
#endif

namespace signin {
class IdentityManager;
}

namespace supervised_user {
class SupervisedUserService;
}

namespace user_prefs {
class PrefRegistrySyncable;
}

class PrefService;

namespace ntp_tiles {

class IconCacher;

// NTPTilesVector wrapper with HasUrl(), to store Custom Links.
class CustomLinksCache {
 public:
  CustomLinksCache();
  ~CustomLinksCache();

  // Adds a tile to the list.
  void PushBack(const NTPTile& tile);

  // Removes all stored tiles.
  void Clear();

  // Returns whether a tile with specified `url` exists.
  bool HasUrl(const GURL& url) const;

  // Accessor to stored tiles.
  const NTPTilesVector& GetList() const;

 private:
  // List of custom tiles, in the order of appearance, with distinct URLs.
  NTPTilesVector list_;

  // Set of URLs in |list|, for deduping.
  std::set<GURL> url_set_;
};

// Tracks the list of most visited sites.
class MostVisitedSites :
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
    public SupervisedUserServiceObserver,
#endif
    public history::TopSitesObserver {
 public:
  // LINT.IfChange(kInvalidSuggestionScore)
  // Value to indicate that a site suggestion score is unavailable.
  static constexpr double kInvalidSuggestionScore = -1.0;
  // LINT.ThenChange(//chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSites.java)

  // The observer to be notified when the list of most visited sites changes.
  class Observer : public base::CheckedObserver {
   public:
    // |is_user_triggered| specifies whether the event is caused by direct user
    // action in MV tiles. The UI can use this to decide whether MV tile updates
    // (in multiple NTPs) should be eager (for responsiveness) or deferred (for
    // tile stability).
    // |sections| must at least contain the PERSONALIZED section.
    virtual void OnURLsAvailable(
        bool is_user_triggered,
        const std::map<SectionType, NTPTilesVector>& sections) = 0;
    virtual void OnIconMadeAvailable(const GURL& site_url) = 0;
  };

  // This interface delegates the retrieval of the homepage to the
  // platform-specific implementation.
  class HomepageClient {
   public:
    using TitleCallback =
        base::OnceCallback<void(const std::optional<std::u16string>& title)>;

    virtual ~HomepageClient() = default;
    virtual bool IsHomepageTileEnabled() const = 0;
    virtual GURL GetHomepageUrl() const = 0;
    virtual void QueryHomepageTitle(TitleCallback title_callback) = 0;
  };

  // Construct a MostVisitedSites instance.
  //
  // |prefs| are required and may not be null. |top_sites|,
  // |popular_sites|, |custom_links|, |identity_manager|,
  // |supervised_user_service| and |homepage_client| are
  //  optional and if null, the associated features will be disabled.
  MostVisitedSites(
      PrefService* prefs,
      signin::IdentityManager* identity_manager,
      supervised_user::SupervisedUserService* supervised_user_service,
      scoped_refptr<history::TopSites> top_sites,
      std::unique_ptr<PopularSites> popular_sites,
      std::unique_ptr<CustomLinksManager> custom_links,
      std::unique_ptr<IconCacher> icon_cacher,
      bool is_default_chrome_app_migrated,
      bool is_custom_links_mixable);

  MostVisitedSites(const MostVisitedSites&) = delete;
  MostVisitedSites& operator=(const MostVisitedSites&) = delete;

  ~MostVisitedSites() override;

  // Returns true if this object was created with a non-null provider for the
  // given NTP tile source. That source may or may not actually provide tiles,
  // depending on its configuration and the priority of different sources.
  bool DoesSourceExist(TileSource source) const;

  // Returns the corresponding object passed at construction.
  history::TopSites* top_sites() { return top_sites_.get(); }
  PopularSites* popular_sites() { return popular_sites_.get(); }

  // Adds the observer and immediately fetches the current suggestions.
  // All observers will be notified when the suggestions are fetched.
  //
  // Note: only observers that require the same |max_num_sites| could observe
  // the same MostVisitedSites instance. Otherwise, a new Instance should be
  // created for the observer.
  //
  // Does not take ownership of |observer|, which must outlive this object and
  // must not be null. |max_num_sites| indicates the the maximum number of most
  // visited sites to return.
  virtual void AddMostVisitedURLsObserver(Observer* observer,
                                          size_t max_num_sites);

  // Removes the observer.
  virtual void RemoveMostVisitedURLsObserver(Observer* observer);

  // Sets the client that provides platform-specific homepage preferences.
  // When used to replace an existing client, the new client will first be
  // used during the construction of a new tile set.
  // |client| must not be null and outlive this object.
  void SetHomepageClient(std::unique_ptr<HomepageClient> client);

  // Requests an asynchronous refresh of the suggestions. Notifies the observer
  // if the request resulted in the set of tiles changing.
  void Refresh();

  // Forces a rebuild of the current tiles.
  void RefreshTiles();

  // Initializes custom links, which "freezes" the current MV tiles and converts
  // them to custom links. Once custom links is initialized, MostVisitedSites
  // will return only custom links. If the Most Visited tiles have not been
  // loaded yet, does nothing. Custom links must be enabled.
  void InitializeCustomLinks();

  // Uninitializes custom links and reverts back to regular MV tiles. The
  // current custom links will be deleted. Custom links must be enabled.
  void UninitializeCustomLinks();

  // Returns true if custom links has been initialized and not disabled, false
  // otherwise.
  bool IsCustomLinksInitialized();

  // Returns whether custom links should be the only data source.
  bool IsExclusivelyCustomLinks();

  // Enables or disables custom links, but does not (un)initialize them. Called
  // when the user switches between custom links and Most Visited sites on the
  // 1P Desktop NTP.
  void EnableCustomLinks(bool enable);

  // Returns whether custom links are enabled.
  bool IsCustomLinksEnabled() const;

  // Sets the visibility of the NTP tiles.
  void SetShortcutsVisible(bool visible);

  // Returns whether NTP tiles should be shown.
  bool IsShortcutsVisible() const;

  // Adds a custom link at position |pos|, bumping existing links. If the number
  // of current links is maxed, returns false and does nothing. Will initialize
  // custom links if they have not been initialized yet, unless the action
  // fails. Custom links must be enabled.
  bool AddCustomLinkTo(const GURL& url,
                       const std::u16string& title,
                       size_t pos);

  // Similar to AddCustomLinkTo(), but add to end of list.
  bool AddCustomLink(const GURL& url, const std::u16string& title);

  // Updates the URL and/or title of the custom link specified by |url|. If
  // |url| does not exist or |new_url| already exists in the custom link list,
  // returns false and does nothing. Will initialize custom links if they have
  // not been initialized yet, unless the action fails. Custom links must be
  // enabled.
  bool UpdateCustomLink(const GURL& url,
                        const GURL& new_url,
                        const std::u16string& new_title);

  // Moves the custom link specified by |url| to the index |new_pos|. If |url|
  // does not exist, or |new_pos| is invalid, returns false and does nothing.
  // Will initialize custom links if they have not been initialized yet, unless
  // the action fails. Custom links must be enabled.
  bool ReorderCustomLink(const GURL& url, size_t new_pos);

  // Deletes the custom link with the specified |url|. If |url| does not exist
  // in the custom link list, returns false and does nothing. Will initialize
  // custom links if they have not been initialized yet, unless the action
  // fails. Custom links must be enabled.
  bool DeleteCustomLink(const GURL& url);

  // Returns whether a custom link with the specified |url| exists.
  bool HasCustomLink(const GURL& url);

  // Restores the previous state of custom links before the last action that
  // modified them. If there was no action, does nothing. If this is undoing the
  // first action after initialization, uninitializes the links. Custom links
  // must be enabled.
  void UndoCustomLinkAction();

  size_t GetCustomLinkNum();

  void AddOrRemoveBlockedUrl(const GURL& url, bool add_url);
  void ClearBlockedUrls();

#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
  //  SupervisedUserServiceObserver implementation.
  void OnURLFilterChanged() override;
#endif

  // Returns the score of a tile in |current_tiles_| identified by |url|, or
  // |kInvalidSuggestionScore| if not found. Caveat: On startup,
  // |current_tiles_| may store cached values, so returned score will be 0.0.
  // In this case, the caller needs to be robust against 0.0, or first force a
  // rebuild by calling RefreshTiles().
  double GetSuggestionScore(const GURL& url) const;

  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
  static void ResetProfilePrefs(PrefService* prefs);

  // Workhorse for SaveNewTilesAndNotify. Implemented as a separate static and
  // public method for ease of testing.
  static NTPTilesVector MergeTiles(NTPTilesVector personal_tiles,
                                   NTPTilesVector popular_tiles);

  // Verifies if NTPTile App was migrated to a WebApp.
  static bool WasNtpAppMigratedToWebApp(PrefService* prefs, GURL url);

  // Verifies if NTPTile App comes from a PreInstalledApp.
  static bool IsNtpTileFromPreinstalledApp(GURL url);

 private:
  FRIEND_TEST_ALL_PREFIXES(MostVisitedSitesTest,
                           ShouldDeduplicateDomainWithNoWwwDomain);
  FRIEND_TEST_ALL_PREFIXES(MostVisitedSitesTest,
                           ShouldDeduplicateDomainByRemovingMobilePrefixes);
  FRIEND_TEST_ALL_PREFIXES(MostVisitedSitesTest,
                           ShouldDeduplicateDomainByReplacingMobilePrefixes);

  // This function tries to match the given |host| to a close fit in
  // |hosts_to_skip| by removing a prefix that is commonly used to redirect from
  // or to mobile pages (m.xyz.com --> xyz.com).
  // If this approach fails, the prefix is replaced by another prefix.
  // That way, true is returned for m.x.com if www.x.com is in |hosts_to_skip|.
  static bool IsHostOrMobilePageKnown(
      const std::set<std::string>& hosts_to_skip,
      const std::string& host);

  // Returns the maximum number of most visited sites to return. The return
  // value is |max_num_sites_| which is ntp_tiles::kMaxNumMostVisited for
  // Desktop, unless custom links are enabled in which case an additional tile
  // may be returned making up to ntp_tiles::kMaxNumCustomLinks custom links
  // including the "Add shortcut" button.
  size_t GetMaxNumSites() const;

  // Initialize the query to Top Sites.
  void InitiateTopSitesQuery(bool is_user_triggered);

  // Callback for when data is available from TopSites.
  void OnMostVisitedURLsAvailable(
      bool is_user_triggered,
      const history::MostVisitedURLList& visited_list);

  // Builds the current tileset based on available caches and notifies the
  // observer.
  void BuildCurrentTiles(bool is_user_triggered);

  // Creates tiles for all popular site sections. Uses |num_actual_tiles| and
  // |used_hosts| to restrict results for the PERSONALIZED section.
  std::map<SectionType, NTPTilesVector> CreatePopularSitesSections(
      const std::set<std::string>& used_hosts,
      size_t num_actual_tiles);

  // Creates tiles for |sites_vector|. The returned vector will neither contain
  // more than |num_max_tiles| nor include sites in |hosts_to_skip|.
  NTPTilesVector CreatePopularSitesTiles(
      const PopularSites::SitesVector& sites_vector,
      const std::set<std::string>& hosts_to_skip,
      size_t num_max_tiles);

  // Ensures |custom_links_manager_| is initialized, then runs
  // |custom_links_action|. Performs on-failure cleanup. Returns whether the
  // action was successful.
  bool ApplyCustomLinksAction(base::OnceCallback<bool()> custom_links_action);

  // Callback for when an update is reported by CustomLinksManager.
  void OnCustomLinksChanged();

  // Clears |custom_links_cache_|, then if custom links are initialized,
  // populate it with |custom_links_manager_->GetLinks()| data up to
  // |max_num_sites_|.
  void ReloadCustomLinksCache();

  // Initiates a query for the homepage tile if needed and calls
  // |SaveTilesAndNotify| in the end.
  void InitiateNotificationForNewTiles(bool is_user_triggered,
                                       NTPTilesVector new_tiles);

  // Takes the personal tiles and merges in popular tiles if appropriate. Calls
  // |SaveTilesAndNotify| at the end.
  void MergeMostVisitedTiles(bool is_user_triggered,
                             NTPTilesVector personal_tiles);

  // Removes pre installed apps which turn invalid because of migration.
  NTPTilesVector RemoveInvalidPreinstallApps(NTPTilesVector new_tiles);

  // Creates a new tiles vector consisting of |custom_links_cache_| combined
  // with |tiles|.
  NTPTilesVector ImposeCustomLinks(NTPTilesVector tiles);

  // Saves the new tiles and notifies the observer if the tiles were actually
  // changed.
  void SaveTilesAndNotify(bool is_user_triggered,
                          NTPTilesVector new_tiles,
                          std::map<SectionType, NTPTilesVector> sections);

  void OnPopularSitesDownloaded(bool success);

  void OnIconMadeAvailable(const GURL& site_url);

  // Updates the already used hosts and the total tile count based on given new
  // tiles. Enforces that the required amount of tiles is not exceeded.
  void AddToHostsAndTotalCount(const NTPTilesVector& new_tiles,
                               std::set<std::string>* hosts,
                               size_t* total_tile_count) const;

  // Adds the homepage as first tile to |tiles| and returns them as new vector.
  // Drops existing tiles with the same host as the home page and tiles that
  // would exceed the maximum.
  NTPTilesVector InsertHomeTile(NTPTilesVector tiles,
                                const std::u16string& title) const;

  void OnHomepageTitleDetermined(bool is_user_triggered,
                                 NTPTilesVector tiles,
                                 const std::optional<std::u16string>& title);

  // Returns true if there is a valid homepage that can be pinned as tile.
  bool ShouldAddHomeTile() const;

  // history::TopSitesObserver implementation.
  void TopSitesLoaded(history::TopSites* top_sites) override;
  void TopSitesChanged(history::TopSites* top_sites,
                       ChangeReason change_reason) override;

  raw_ptr<PrefService> prefs_;
  raw_ptr<signin::IdentityManager> identity_manager_;
  raw_ptr<supervised_user::SupervisedUserService> supervised_user_service_;
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
  base::ScopedObservation<supervised_user::SupervisedUserService,
                          SupervisedUserServiceObserver>
      supervised_user_service_observation_{this};
#endif

  scoped_refptr<history::TopSites> top_sites_;
  std::unique_ptr<PopularSites> const popular_sites_;
  std::unique_ptr<CustomLinksManager> const custom_links_manager_;
  std::unique_ptr<IconCacher> const icon_cacher_;
  std::unique_ptr<HomepageClient> homepage_client_;
  bool is_default_chrome_app_migrated_;
  bool is_custom_links_mixable_;

  base::ObserverList<Observer> observers_;

  // The maximum number of most visited sites to return.
  // Do not use directly. Use GetMaxNumSites() instead.
  size_t max_num_sites_;

  // Number of actions after custom link initialization. Set to -1 and not
  // incremented if custom links was not initialized during this session.
  int custom_links_action_count_ = -1;

  bool is_custom_links_enabled_ = true;
  bool is_shortcuts_visible_ = true;

  base::ScopedObservation<history::TopSites, history::TopSitesObserver>
      top_sites_observation_{this};

  base::CallbackListSubscription custom_links_subscription_;

  // Cached custom links data that also supports URL existence query.
  CustomLinksCache custom_links_cache_;

  // Current set of tiles. Optional so that the observer can be notified
  // whenever it changes, including possibily an initial change from
  // !current_tiles_.has_value() to current_tiles_->empty().
  std::optional<NTPTilesVector> current_tiles_;

  // Whether has started observing data sources.
  bool is_observing_;

  // For callbacks may be run after destruction, used exclusively for TopSites
  // (since it's used to detect whether there's a query in flight).
  base::WeakPtrFactory<MostVisitedSites> top_sites_weak_ptr_factory_{this};
};

}  // namespace ntp_tiles

#endif  // COMPONENTS_NTP_TILES_MOST_VISITED_SITES_H_