File: jumplist.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 (361 lines) | stat: -rw-r--r-- 15,073 bytes parent folder | download | duplicates (5)
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
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_WIN_JUMPLIST_H_
#define CHROME_BROWSER_WIN_JUMPLIST_H_

#include <stddef.h>

#include <list>
#include <memory>
#include <string>
#include <utility>

#include "base/containers/flat_map.h"
#include "base/files/file_path.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/task/cancelable_task_tracker.h"
#include "base/timer/timer.h"
#include "chrome/browser/prefs/incognito_mode_prefs.h"
#include "chrome/browser/win/jumplist_updater.h"
#include "components/favicon_base/favicon_types.h"
#include "components/history/core/browser/history_types.h"
#include "components/history/core/browser/top_sites_observer.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/sessions/core/tab_restore_service.h"
#include "components/sessions/core/tab_restore_service_observer.h"

namespace base {
class SingleThreadTaskRunner;
class SequencedTaskRunner;
}

namespace chrome {
struct FaviconImageResult;
}

class JumpListFactory;
class PrefChangeRegistrar;
class Profile;

// A class which implements an application JumpList.
//
// This class observes the recently closed tabs, topsites, and policies of the
// given Profile. It tries to update the JumpList whenever a change is detected.
//
// The states that the JumpList machine can be in between UI thread tasks are:
// 1. Idle.
// 2. Notification from TabRetore and/or TopSites services arrived, waiting for
//    quiesence via a timer.
// 3. Most-visited data async fetch started, waiting for data. (Tab restore data
//    is fetched synchronously, so it doesn't have a state.)
// 4. Tab restore data or most-visited data has been fetched; favicons load
//    started (one at a time), waiting for results.
// 5. All favicon loaded, JumpList update started.
//
// The policy for how to handle notifications while any state of an update is in
// progress is:
//   "Prohibit overlapping updates by queueing up inbound notifications that
// arrive after an update has started but before it has finished. On update
// completion, restart the timer to start another update if any notifications
// were queued."
//
// Updating a JumpList as mentioned in state 5 requires some file operations and
// it is not good to run it in the UI thread. To solve this problem, this class
// posts the update task to a non-UI thread.
//
// Updating a JumpList consists of the following steps:
// 1. Tell the OS to begin an update transaction. If this fails or times out,
//    abort this update run.
// 2. Create new icon files if not in the cache.
// 3. Assemble an updated JumpList with most-visited, recently-closed and tasks
//    (never change) categories. If this fails or times out, go to step 5.
// 4. Commit the update to the OS.
// 5. Delete any obsolete icon files. If step 3 or 4 fails or times out, delete
//    icons newly created in step 2, otherwise delete icons from the previous
//    JumpList but aren't reused by the new one.
// 6. Update the icon cache.
//
// Step 1, 3 and 4 are basically Windows API calls. Normally they are pretty
// fast (within a few hundred milliseconds), but can take minutes in slow
// machines. To prevent those machines from being bogged down by JumpList
// updates, this class skips the next few updates if a timeout is detected in
// any of those steps.
class JumpList : public sessions::TabRestoreServiceObserver,
                 public history::TopSitesObserver,
                 public KeyedService {
 public:
  JumpList(const JumpList&) = delete;
  JumpList& operator=(const JumpList&) = delete;

  ~JumpList() override;

  // Returns true if the custom JumpList is enabled.
  static bool Enabled();

  // KeyedService:
  void Shutdown() override;

 private:
  using UrlAndLinkItem = std::pair<std::string, scoped_refptr<ShellLinkItem>>;
  using URLIconCache = base::flat_map<std::string, base::FilePath>;

  // Holds results of a RunUpdateJumpList run.
  // In-out params:
  //   |most_visited_icons|, |recently_closed_icons|
  // Out params:
  //   |update_success|, |update_timeout|
  struct UpdateTransaction {
    UpdateTransaction();
    ~UpdateTransaction();

    // Icon file paths of the most visited links, indexed by tab url.
    // Holding a copy of most_visited_icons_ initially, it's updated by the
    // JumpList update run. If the update run succeeds, it overwrites
    // most_visited_icons_.
    URLIconCache most_visited_icons;

    // Icon file paths of the recently closed links, indexed by tab url.
    // Holding a copy of recently_closed_icons_ initially, it's updated by the
    // JumpList update run. If the update run succeeds, it overwrites
    // recently_closed_icons_.
    URLIconCache recently_closed_icons;

    // A flag indicating if a JumpList update run is successful.
    bool update_success = false;

    // A flag indicating if there is a timeout in notifying the JumpList update
    // to shell. Note that this variable is independent of update_success.
    bool update_timeout = false;
  };

  friend JumpListFactory;
  explicit JumpList(Profile* profile);  // Use JumpListFactory instead

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

  // sessions::TabRestoreServiceObserver:
  void TabRestoreServiceChanged(sessions::TabRestoreService* service) override;
  void TabRestoreServiceDestroyed(
      sessions::TabRestoreService* service) override;

  // Callback for changes to the incognito mode availability pref.
  void OnIncognitoAvailabilityChanged();

  // Initializes the one-shot timer to update the JumpList in a while. If there
  // is already a request queued then cancel it and post the new request. This
  // ensures that JumpList update won't happen until there has been a brief
  // quiet period, thus avoiding update storms.
  void InitializeTimerForUpdate();

  // Processes update notifications. Calls APIs ProcessTopSitesNotification and
  // ProcessTabRestoreNotification on demand to do the actual work.
  void ProcessNotifications();

  // Processes notifications from TopSites service.
  void ProcessTopSitesNotification();

  // Processes notifications from TabRestore service.
  void ProcessTabRestoreServiceNotification();

  // Callback for TopSites that notifies when |data|, the "Most Visited" list,
  // is available. This function updates the ShellLinkItemList objects and
  // begins the process of fetching favicons for the URLs.
  void OnMostVisitedURLsAvailable(const history::MostVisitedURLList& data);

  // Adds a new ShellLinkItem for |tab| to the JumpList data provided that doing
  // so will not exceed |max_items|. If |cmd_line_profile_dir| is not empty,
  // it will be added to the command line switch --profile-directory.
  bool AddTab(const sessions::tab_restore::Tab& tab,
              const base::FilePath& cmd_line_profile_dir,
              size_t max_items);

  // Adds a new ShellLinkItem for each tab in |window| to the JumpList data
  // provided that doing so will not exceed |max_items|. If
  // |cmd_line_profile_dir| is not empty, it will be added to the command line
  // switch --profile-directory.
  void AddWindow(const sessions::tab_restore::Window& window,
                 const base::FilePath& cmd_line_profile_dir,
                 size_t max_items);

  // Adds a new ShellLinkItem for each tab in |group| to the JumpList data
  // provided that doing so will not exceed |max_items|. If
  // |cmd_line_profile_dir| is not empty, it will be added to the command line
  // switch --profile-directory.
  void AddGroup(const sessions::tab_restore::Group& group,
                const base::FilePath& cmd_line_profile_dir,
                size_t max_items);

  // Starts loading a favicon for each URL in |icon_urls_|.
  // This function sends a query to HistoryService.
  // When finishing loading all favicons, this function posts a task that
  // decompresses collected favicons and updates a JumpList.
  void StartLoadingFavicon();

  // Callback for HistoryService that notifies when a requested favicon is
  // available. To avoid file operations, this function just attaches the given
  // |image_result| to a ShellLinkItem object.
  void OnFaviconDataAvailable(
      const favicon_base::FaviconImageResult& image_result);

  // Posts tasks to update the JumpList and delete any obsolete JumpList related
  // folders.
  void PostRunUpdate();

  // Handles the completion of an update by incorporating its results in
  // |update_transaction| back into this instance. Additionally, a new update is
  // triggered as needed to process notifications that arrived while the
  // now-completed update was running.
  void OnRunUpdateCompletion(
      std::unique_ptr<UpdateTransaction> update_transaction);

  // Cancels a pending JumpList update.
  void CancelPendingUpdate();

  // Terminates the JumpList, which includes cancelling any pending updates and
  // stopping observing the Profile and its services. This must be called before
  // the |profile_| is destroyed.
  void Terminate();

  // Updates the application JumpList, which consists of 1) create a new
  // JumpList along with any icons that are not in the cache; 2) notify the OS;
  // 3) delete obsolete icon files. Any error along the way results in the old
  // JumpList being left as-is.
  static void RunUpdateJumpList(
      const std::wstring& app_id,
      const base::FilePath& profile_dir,
      const ShellLinkItemList& most_visited_pages,
      const ShellLinkItemList& recently_closed_pages,
      const base::FilePath& cmd_line_profile_dir,
      bool most_visited_should_update,
      bool recently_closed_should_update,
      policy::IncognitoModeAvailability incognito_availability,
      UpdateTransaction* update_transaction);

  // Creates a new JumpList along with any icons that are not in the cache,
  // and notifies the OS.
  static void CreateNewJumpListAndNotifyOS(
      const std::wstring& app_id,
      const base::FilePath& most_visited_icon_dir,
      const base::FilePath& recently_closed_icon_dir,
      const ShellLinkItemList& most_visited_pages,
      const ShellLinkItemList& recently_closed_pages,
      const base::FilePath& cmd_line_profile_dir,
      bool most_visited_should_update,
      bool recently_closed_should_update,
      policy::IncognitoModeAvailability incognito_availability,
      UpdateTransaction* update_transaction);

  // Updates icon files for |item_list| in |icon_dir|, which consists of
  // 1) If certain safe conditions are not met, clean the folder at |icon_dir|.
  // If folder cleaning fails, skip step 2. Besides, clear |icon_cur| and
  // |icon_next|.
  // 2) Create at most |max_items| icon files which are not in |icon_cur| for
  // the asynchrounously loaded icons stored in |item_list|.
  static int UpdateIconFiles(const base::FilePath& icon_dir,
                             const ShellLinkItemList& item_list,
                             size_t max_items,
                             URLIconCache* icon_cur,
                             URLIconCache* icon_next);

  // In |icon_dir|, creates at most |max_items| icon files which are not in
  // |icon_cur| for the asynchrounously loaded icons stored in |item_list|.
  // |icon_next| is updated based on the reusable icons and the newly created
  // icons. Returns the number of new icon files created.
  static int CreateIconFiles(const base::FilePath& icon_dir,
                             const ShellLinkItemList& item_list,
                             size_t max_items,
                             const URLIconCache& icon_cur,
                             URLIconCache* icon_next);

  // Deletes icon files in |icon_dir| which are not in |icon_cache|.
  static void DeleteIconFiles(const base::FilePath& icon_dir,
                              const URLIconCache& icons_cache);

  // Gets the basename of the profile directory for |profile_|, suitable for
  // appending --profile-directory=<profile name> to jumplist items' command
  // lines. If the user has only one profile, this returns an empty FilePath.
  base::FilePath GetCmdLineProfileDir();

  // Tracks FaviconService tasks.
  base::CancelableTaskTracker cancelable_task_tracker_;

  // The Profile object is used to listen for events.
  raw_ptr<Profile> profile_;

  // Manages the registration of pref change observers.
  std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;

  // App id to associate with the JumpList.
  std::wstring app_id_;

  // Timer for requesting delayed JumpList updates.
  base::OneShotTimer timer_;

  // A list of URLs we need to retrieve their favicons,
  std::list<UrlAndLinkItem> icon_urls_;

  // Items in the "Most Visited" category of the JumpList.
  ShellLinkItemList most_visited_pages_;

  // Items in the "Recently Closed" category of the JumpList.
  ShellLinkItemList recently_closed_pages_;

  // The icon file paths of the most visited links, indexed by tab url.
  URLIconCache most_visited_icons_;

  // The icon file paths of the recently closed links, indexed by tab url.
  URLIconCache recently_closed_icons_;

  // A flag indicating if TopSites service has notifications.
  bool top_sites_has_pending_notification_ = false;

  // A flag indicating if TabRestore service has notifications.
  bool tab_restore_has_pending_notification_ = false;

  // A flag indicating if "Most Visited" category should be updated.
  bool most_visited_should_update_ = false;

  // A flag indicating if "Recently Closed" category should be updated.
  bool recently_closed_should_update_ = false;

  // A flag indicating if there's a JumpList update task already posted or
  // currently running.
  bool update_in_progress_ = false;

  // A flag indicating if a session has at least one tab closed.
  bool has_tab_closed_ = false;

  // A flag indicating if a session has at least one top sites sync.
  bool has_topsites_sync = false;

  // Number of updates to skip to alleviate the machine when a previous update
  // was too slow. Updates will be resumed when this reaches 0 again.
  int updates_to_skip_ = 0;

  // Id of last favicon task. It's used to cancel current task if a new one
  // comes in before it finishes.
  base::CancelableTaskTracker::TaskId task_id_ =
      base::CancelableTaskTracker::kBadTaskId;

  // A task runner running tasks to update the JumpList.
  scoped_refptr<base::SingleThreadTaskRunner> update_jumplist_task_runner_;

  // A task runner running tasks to delete the JumpListIcons and
  // JumpListIconsOld folders.
  scoped_refptr<base::SequencedTaskRunner> delete_jumplisticons_task_runner_;

  SEQUENCE_CHECKER(sequence_checker_);

  // For callbacks may run after destruction.
  base::WeakPtrFactory<JumpList> weak_ptr_factory_{this};
};

#endif  // CHROME_BROWSER_WIN_JUMPLIST_H_