File: tab_search_page_handler.h

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (387 lines) | stat: -rw-r--r-- 15,844 bytes parent folder | download | duplicates (2)
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
// Copyright 2020 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_UI_WEBUI_TAB_SEARCH_TAB_SEARCH_PAGE_HANDLER_H_
#define CHROME_BROWSER_UI_WEBUI_TAB_SEARCH_TAB_SEARCH_PAGE_HANDLER_H_

#include <stdint.h>

#include "base/callback_list.h"
#include "base/memory/raw_ptr.h"
#include "chrome/browser/ui/browser_tab_strip_tracker.h"
#include "chrome/browser/ui/browser_tab_strip_tracker_delegate.h"
#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
#include "chrome/browser/ui/tabs/organization/tab_data.h"
#include "chrome/browser/ui/tabs/organization/tab_declutter_controller.h"
#include "chrome/browser/ui/tabs/organization/tab_declutter_observer.h"
#include "chrome/browser/ui/tabs/organization/tab_organization.h"
#include "chrome/browser/ui/tabs/organization/tab_organization_observer.h"
#include "chrome/browser/ui/tabs/organization/tab_organization_session.h"
#include "chrome/browser/ui/tabs/tab_group_model.h"
#include "chrome/browser/ui/tabs/tab_group_theme.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
#include "chrome/browser/ui/webui/tab_search/tab_search.mojom.h"
#include "chrome/browser/ui/webui/top_chrome/top_chrome_web_ui_controller.h"
#include "components/optimization_guide/core/model_execution/settings_enabled_observer.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/sessions/core/tab_restore_service.h"
#include "components/tabs/public/tab_group.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "url/gurl.h"

class Browser;
class MetricsReporter;
class TabOrganizationService;
class OptimizationGuideKeyedService;

namespace tabs {
class TabDeclutterController;
}

// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class TabSearchCloseAction {
  kNoAction = 0,
  kTabSwitch = 1,
  kMaxValue = kTabSwitch,
};

// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class TabSearchRecentlyClosedToggleAction {
  kExpand = 0,
  kCollapse = 1,
  kMaxValue = kCollapse,
};

class DuplicateTabsObserver : public content::WebContentsObserver {
 public:
  DuplicateTabsObserver(
      content::WebContents* web_contents,
      base::RepeatingCallback<void()> on_url_changed_callback);
  ~DuplicateTabsObserver() override;

  void PrimaryPageChanged(content::Page& page) override;

 private:
  base::RepeatingCallback<void()> on_url_changed_callback_;
};

class TabSearchPageHandler
    : public tab_search::mojom::PageHandler,
      public TabStripModelObserver,
      public BrowserTabStripTrackerDelegate,
      public TabOrganizationSession::Observer,
      public TabOrganizationObserver,
      public TabDeclutterObserver,
      public optimization_guide::SettingsEnabledObserver {
 public:
  TabSearchPageHandler(
      mojo::PendingReceiver<tab_search::mojom::PageHandler> receiver,
      mojo::PendingRemote<tab_search::mojom::Page> page,
      content::WebUI* web_ui,
      TopChromeWebUIController* webui_controller,
      MetricsReporter* metrics_reporter);
  TabSearchPageHandler(const TabSearchPageHandler&) = delete;
  TabSearchPageHandler& operator=(const TabSearchPageHandler&) = delete;
  ~TabSearchPageHandler() override;

  // tab_search::mojom::PageHandler:
  void CloseTab(int32_t tab_id) override;
  void DeclutterTabs(const std::vector<int32_t>& tab_ids,
                     const std::vector<GURL>& urls) override;
  void AcceptTabOrganization(
      int32_t session_id,
      int32_t organization_id,
      std::vector<tab_search::mojom::TabPtr> tabs) override;
  void RejectTabOrganization(int32_t session_id,
                             int32_t organization_id) override;
  void RenameTabOrganization(int32_t session_id,
                             int32_t organization_id,
                             const std::u16string& name) override;
  void ExcludeFromStaleTabs(int32_t tab_id) override;
  void ExcludeFromDuplicateTabs(const GURL& url) override;
  void GetProfileData(GetProfileDataCallback callback) override;
  void GetUnusedTabs(GetUnusedTabsCallback callback) override;
  void GetTabSearchSection(GetTabSearchSectionCallback callback) override;
  void GetTabOrganizationFeature(
      GetTabOrganizationFeatureCallback callback) override;
  void GetTabOrganizationSession(
      GetTabOrganizationSessionCallback callback) override;
  void GetTabOrganizationModelStrategy(
      GetTabOrganizationModelStrategyCallback callback) override;
  void GetIsSplit(GetIsSplitCallback callback) override;
  void SwitchToTab(
      tab_search::mojom::SwitchToTabInfoPtr switch_to_tab_info) override;
  void OpenRecentlyClosedEntry(int32_t session_id) override;
  void RequestTabOrganization() override;
  void RemoveTabFromOrganization(int32_t session_id,
                                 int32_t organization_id,
                                 tab_search::mojom::TabPtr tab) override;
  void RejectSession(int32_t session_id) override;
  void ReplaceActiveSplitTab(int32_t replacement_tab_id) override;
  void RestartSession() override;
  void SaveRecentlyClosedExpandedPref(bool expanded) override;
  void SetOrganizationFeature(
      tab_search::mojom::TabOrganizationFeature feature) override;
  void StartTabGroupTutorial() override;
  void TriggerFeedback(int32_t session_id) override;
  void TriggerSignIn() override;
  void OpenHelpPage() override;
  void SetTabOrganizationModelStrategy(
      tab_search::mojom::TabOrganizationModelStrategy strategy) override;
  void SetTabOrganizationUserInstruction(
      const std::string& user_instruction) override;
  void SetUserFeedback(int32_t session_id,
                       tab_search::mojom::UserFeedback feedback) override;
  void NotifyOrganizationUIReadyToShow() override;
  void NotifySearchUIReadyToShow() override;

  // TabStripModelObserver:
  void OnTabStripModelChanged(
      TabStripModel* tab_strip_model,
      const TabStripModelChange& change,
      const TabStripSelectionChange& selection) override;
  void TabChangedAt(content::WebContents* contents,
                    int index,
                    TabChangeType change_type) override;
  void OnSplitTabChanged(const SplitTabChange& change) override;

  // TabDeclutterObserver:
  void OnUnusedTabsProcessed(
      std::vector<tabs::TabInterface*> stale_tabs,
      std::map<GURL, std::vector<tabs::TabInterface*>> duplicate_tabs) override;

  // BrowserTabStripTrackerDelegate:
  bool ShouldTrackBrowser(Browser* browser) override;

  // Returns true if the WebContents hosting the WebUI is visible to the user
  // (in either a fully visible or partially occluded state).
  bool IsWebContentsVisible();

  // Convert TabOrganizations data to mojo serialized objects.
  tab_search::mojom::TabPtr GetMojoForTabData(TabData* tab_data) const;
  tab_search::mojom::TabOrganizationPtr GetMojoForTabOrganization(
      const TabOrganization* organization) const;
  tab_search::mojom::TabOrganizationSessionPtr GetMojoForTabOrganizationSession(
      const TabOrganizationSession* session) const;

  // TabOrganizationSession::Observer
  void OnTabOrganizationSessionUpdated(
      const TabOrganizationSession* session) override;
  void OnTabOrganizationSessionDestroyed(
      TabOrganizationSession::ID session_id) override;

  // TabOrganizationObserver
  void OnSessionCreated(const Browser* browser,
                        TabOrganizationSession* session) override;

  // SettingsEnabledObserver
  void OnChangeInFeatureCurrentlyEnabledState(bool is_now_enabled) override;

  void disable_last_active_elapsed_text_for_testing() {
    disable_last_active_time_for_testing_ = true;
  }

  std::vector<tabs::TabInterface*> stale_tabs_for_testing() {
    return stale_tabs_;
  }

  std::map<GURL, std::vector<tabs::TabInterface*>>
  duplicate_tabs_for_testing() {
    return duplicate_tabs_;
  }

  void SetTabDeclutterControllerForTesting(
      tabs::TabDeclutterController* tab_declutter_controller);

  static constexpr int kMinRecentlyClosedItemDisplayCount = 8;

 protected:
  void SetTimerForTesting(std::unique_ptr<base::RetainingOneShotTimer> timer);

 private:
  // Used to determine if a specific tab should be included or not in the
  // results of GetProfileData. Tab url/group combinations that have been
  // previously added to the ProfileData will not be added more than once by
  // leveraging DedupKey comparisons.
  typedef std::tuple<GURL, std::optional<base::Token>> DedupKey;

  enum class UnusedTabType { kInactive, kDuplicate };

  // Encapsulates tab details to facilitate performing an action on a tab.
  struct TabDetails {
    explicit TabDetails(tabs::TabInterface* tab) : tab(tab) {}

    int GetIndex() const {
      return tab->GetBrowserWindowInterface()
          ->GetTabStripModel()
          ->GetIndexOfTab(tab);
    }

    raw_ptr<tabs::TabInterface> tab;
  };

  // Show the UI if all tabs are ready to be shown.
  void MaybeShowUI();

  tab_search::mojom::ProfileDataPtr CreateProfileData();
  void UpdateUnusedTabs();

  void SetTabDeclutterController(
      tabs::TabDeclutterController* tab_declutter_controller);

  // Adds recently closed tabs and tab groups.
  void AddRecentlyClosedEntries(
      std::vector<tab_search::mojom::RecentlyClosedTabPtr>&
          recently_closed_tabs,
      std::vector<tab_search::mojom::RecentlyClosedTabGroupPtr>&
          recently_closed_tab_groups,
      std::set<tab_groups::TabGroupId>& tab_group_ids,
      std::vector<tab_search::mojom::TabGroupPtr>& tab_groups,
      std::set<DedupKey>& tab_dedup_keys);

  // Tries to add a recently closed tab to the profile data.
  // Returns true if a recently closed tab was added to `recently_closed_tabs`
  bool AddRecentlyClosedTab(
      sessions::tab_restore::Tab* tab,
      const base::Time& close_time,
      std::vector<tab_search::mojom::RecentlyClosedTabPtr>&
          recently_closed_tabs,
      std::set<DedupKey>& tab_dedup_keys,
      std::set<tab_groups::TabGroupId>& tab_group_ids,
      std::vector<tab_search::mojom::TabGroupPtr>& tab_groups);

  tab_search::mojom::TabPtr GetTab(
      const TabStripModel* tab_strip_model,
      content::WebContents* contents,
      int index,
      std::string custom_last_active_text = "") const;
  tab_search::mojom::RecentlyClosedTabPtr GetRecentlyClosedTab(
      sessions::tab_restore::Tab* tab,
      const base::Time& close_time);

  // Returns tab details required to perform an action on the tab.
  std::optional<TabDetails> GetTabDetails(int32_t tab_id);

  // Schedule a timer to call TabsChanged() when it times out
  // in order to reduce numbers of RPC.
  void ScheduleDebounce();

  // Call TabsChanged() and stop the timer if it's running.
  void NotifyTabsChanged();

  void NotifyTabIndexPrefChanged(const Profile* profile);

  void NotifyOrganizationFeaturePrefChanged(const Profile* profile);

  void NotifyShowFREPrefChanged(const Profile* profile);

  mojo::StructPtr<tab_search::mojom::UnusedTabInfo> GetMojoUnusedTabs();
  std::vector<mojo::StructPtr<tab_search::mojom::Tab>> GetMojoStaleTabs();
  base::flat_map<std::string,
                 std::vector<mojo::StructPtr<tab_search::mojom::Tab>>>
  GetMojoDuplicateTabs();

  void UnregisterTabCallbacks();
  void RegisterInactiveTabDeclutterCallbacks(tabs::TabInterface* tab);
  void RegisterDuplicateTabDeclutterCallbacks(tabs::TabInterface* tab);

  void OnStaleTabDidEnterForeground(tabs::TabInterface* tab);
  void OnDuplicateTabWillDiscardWebContents(tabs::TabInterface* tab,
                                            content::WebContents* old_content,
                                            content::WebContents* new_content);

  void OnUnusedTabWillDetach(tabs::TabInterface* tab,
                             tabs::TabInterface::DetachReason reason,
                             UnusedTabType type);
  void OnUnusedTabPinnedStateChanged(tabs::TabInterface* tab,
                                     bool new_pinned_state,
                                     UnusedTabType type);
  void OnUnusedTabGroupChanged(tabs::TabInterface* tab,
                               std::optional<tab_groups::TabGroupId> new_group,
                               UnusedTabType type);

  void RemoveStaleTab(tabs::TabInterface* tab);

  // Removes a tab from the duplicate tab list, along with its associated
  // subscriptions and observations. If the duplicate list for the tab's URL
  // contains only one remaining tab after removal, that tab is also removed,
  // and the list is erased from the map. If the tab is not found, the method
  // exits without performing any action.
  void RemoveDuplicateTab(tabs::TabInterface* tab);

  // Called when the browser window context for this WebUI has changed.
  void BrowserWindowInterfaceChanged();

  std::vector<tabs::TabInterface*> FilterDuplicateTabsFromStaleTabs(
      std::vector<tabs::TabInterface*> stale_tabs,
      std::map<GURL, std::vector<tabs::TabInterface*>> duplicate_tabs);

  mojo::Receiver<tab_search::mojom::PageHandler> receiver_;
  mojo::Remote<tab_search::mojom::Page> page_;
  const raw_ptr<content::WebUI> web_ui_;
  const raw_ptr<TopChromeWebUIController, DanglingUntriaged> webui_controller_;
  raw_ptr<Browser> browser_;
  const raw_ptr<MetricsReporter> metrics_reporter_;
  BrowserTabStripTracker browser_tab_strip_tracker_{this, this};
  std::unique_ptr<base::RetainingOneShotTimer> debounce_timer_;
  raw_ptr<TabOrganizationService> organization_service_;
  PrefChangeRegistrar pref_change_registrar_;
  raw_ptr<OptimizationGuideKeyedService> optimization_guide_keyed_service_;
  raw_ptr<tabs::TabDeclutterController> tab_declutter_controller_;

  // Tracks how many times |CloseTab()| has been evoked for the currently open
  // instance of Tab Search for logging in UMA.
  int num_tabs_closed_ = 0;

  // Tracks whether or not we have sent the initial payload to the Tab Search
  // UI for metric collection purposes.
  bool sent_initial_payload_ = false;

  // Tracks whether the user has evoked |SwitchToTab()| for metric collection
  // purposes.
  bool called_switch_to_tab_ = false;

  // Tracks whether a session restart is currently in progress.
  bool restarting_ = false;

  // Tracks whether each tab within the UI is ready to be shown. The bubble
  // will only be shown once all tabs are ready.
  bool organization_ready_to_show_ = false;
  bool search_ready_to_show_ = false;

  bool disable_last_active_time_for_testing_ = false;

  // Notifies this when the browser window context changes.
  base::CallbackListSubscription browser_window_changed_subscription_;

  // Listened TabOrganization sessions.
  std::vector<raw_ptr<TabOrganizationSession, VectorExperimental>>
      listened_sessions_;

  std::vector<tabs::TabInterface*> stale_tabs_;
  std::map<GURL, std::vector<tabs::TabInterface*>> duplicate_tabs_;

  std::map<tabs::TabInterface*, std::vector<base::CallbackListSubscription>>
      inactive_tab_subscriptions_map_;

  std::map<tabs::TabInterface*, std::vector<base::CallbackListSubscription>>
      duplicate_tab_subscriptions_map_;

  std::map<tabs::TabInterface*, std::unique_ptr<DuplicateTabsObserver>>
      duplicate_tab_webcontents_observers_;

  base::ScopedObservation<TabOrganizationService, TabOrganizationObserver>
      tab_organization_observation_{this};

  base::ScopedObservation<tabs::TabDeclutterController, TabDeclutterObserver>
      tab_declutter_observation_{this};
};

#endif  // CHROME_BROWSER_UI_WEBUI_TAB_SEARCH_TAB_SEARCH_PAGE_HANDLER_H_