File: tab_model.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 (262 lines) | stat: -rw-r--r-- 10,911 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
// Copyright 2023 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_TABS_TAB_MODEL_H_
#define CHROME_BROWSER_UI_TABS_TAB_MODEL_H_

#include <memory>
#include <optional>

#include "base/callback_list.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
#include "components/tab_groups/tab_group_id.h"
#include "components/tabs/public/split_tab_id.h"
#include "components/tabs/public/tab_interface.h"
#include "third_party/perfetto/include/perfetto/tracing/traced_value_forward.h"

namespace content {
class WebContents;
}

class TabStripModel;
namespace tabs {

class TabCollection;
class TabFeatures;

class TabModel final : public TabInterface, public TabStripModelObserver {
 public:
  // Conceptually, tabs should always be a part of a normal window. There are
  // currently 2 cases where they are not:
  // (1) Tabbed PWAs is a ChromeOS_only feature that exposes Tabs to PWAs.
  // (2) Non-browser windows currently have a tab-strip and may use tabs. See
  // TODO(https://crbug.com/331031753) which tracks their eventual removal.
  // TODO(https://crbug.com/346692548): Tabs should never be constructed in
  // isolation of a model.
  TabModel(std::unique_ptr<content::WebContents> contents,
           TabStripModel* soon_to_be_owning_model);
  ~TabModel() override;

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

  void OnAddedToModel(TabStripModel* owning_model);
  void OnRemovedFromModel();

  TabStripModel* owning_model() const { return owning_model_; }
  tabs::TabInterface* opener() const { return opener_; }
  bool reset_opener_on_active_tab_change() const {
    return reset_opener_on_active_tab_change_;
  }
  bool blocked() const { return blocked_; }
  std::optional<tab_groups::TabGroupId> group() const { return group_; }

  void set_opener(tabs::TabInterface* opener) { opener_ = opener; }
  void set_reset_opener_on_active_tab_change(
      bool reset_opener_on_active_tab_change) {
    reset_opener_on_active_tab_change_ = reset_opener_on_active_tab_change;
  }

  void SetPinned(bool pinned);
  void SetGroup(std::optional<tab_groups::TabGroupId> group);

  void set_blocked(bool blocked) { blocked_ = blocked; }
  void set_split(std::optional<split_tabs::SplitTabId> split) {
    split_ = split;
  }

  void set_will_be_detaching_for_testing(bool will_be_detaching) {
    will_be_detaching_ = will_be_detaching;
  }

  void WriteIntoTrace(perfetto::TracedValue context) const;

  // https://crbug.com/331022416: Do not use this method. This is only used by
  // tab discard, which is being refactored to not need this.
  std::unique_ptr<content::WebContents> DiscardContents(
      std::unique_ptr<content::WebContents> contents);

  // This destroys the TabModel and takes ownership of the underlying
  // WebContents.
  static std::unique_ptr<content::WebContents> DestroyAndTakeWebContents(
      std::unique_ptr<TabModel> tab_model);

  // When a tab is going to be removed from the tabstrip in preparation for
  // destruction, `TabFeatures` should be destroyed first to ensure individual
  // features do not need to handle the situation of existing outside the
  // context of a tab strip.
  void DestroyTabFeatures();

  // Provides access to the parent_collection_ for testing purposes. This method
  // bypasses the PassKey mechanism, allowing tests to simulate scenarios and
  // inspect the state without needing to replicate complex authorization
  // mechanisms.
  TabCollection* GetParentCollectionForTesting() { return parent_collection_; }

  // Called by TabStripModel when a tab is going to be backgrounded (any
  // operation that makes the tab no longer visible, including removal from the
  // TabStripModel). Not called if TabStripModel is being destroyed.
  void WillEnterBackground(base::PassKey<TabStripModel>);

  // Called by TabStripModel when a tab is going to be detached for reinsertion
  // into a different tab strip.
  void WillDetach(base::PassKey<TabStripModel>,
                  tabs::TabInterface::DetachReason reason);

  // Called by TabStripModel when a tab has been inserted into a tab strip.
  void DidInsert(base::PassKey<TabStripModel>);

  // TabInterface overrides:
  base::WeakPtr<TabInterface> GetWeakPtr() override;
  content::WebContents* GetContents() const override;
  base::CallbackListSubscription RegisterWillDiscardContents(
      TabInterface::WillDiscardContentsCallback callback) override;
  bool IsActivated() const override;
  base::CallbackListSubscription RegisterDidActivate(
      TabInterface::DidActivateCallback callback) override;
  base::CallbackListSubscription RegisterWillDeactivate(
      TabInterface::WillDeactivateCallback callback) override;
  bool IsVisible() const override;
  base::CallbackListSubscription RegisterDidBecomeVisible(
      DidBecomeVisibleCallback callback) override;
  base::CallbackListSubscription RegisterWillBecomeHidden(
      WillBecomeHiddenCallback callback) override;

  base::CallbackListSubscription RegisterWillDetach(
      TabInterface::WillDetach callback) override;
  base::CallbackListSubscription RegisterDidInsert(
      TabInterface::DidInsertCallback callback) override;
  base::CallbackListSubscription RegisterPinnedStateChanged(
      TabInterface::PinnedStateChangedCallback callback) override;
  base::CallbackListSubscription RegisterGroupChanged(
      TabInterface::GroupChangedCallback callback) override;

  bool CanShowModalUI() const override;
  std::unique_ptr<ScopedTabModalUI> ShowModalUI() override;
  base::CallbackListSubscription RegisterModalUIChanged(
      TabInterfaceCallback callback) override;

  bool IsInNormalWindow() const override;
  BrowserWindowInterface* GetBrowserWindowInterface() override;
  const BrowserWindowInterface* GetBrowserWindowInterface() const override;
  tabs::TabFeatures* GetTabFeatures() override;
  const tabs::TabFeatures* GetTabFeatures() const override;
  bool IsPinned() const override;
  bool IsSplit() const override;
  std::optional<tab_groups::TabGroupId> GetGroup() const override;
  std::optional<split_tabs::SplitTabId> GetSplit() const override;
  TabCollection* GetParentCollection(
      base::PassKey<TabCollection>) const override;
  const TabCollection* GetParentCollection() const override;

  void OnReparented(TabCollection* parent,
                    base::PassKey<TabCollection>) override;
  void OnAncestorChanged(base::PassKey<TabCollection>) override;
  void Close() override;

 private:
  // Overridden from TabStripModelObserver:
  void OnTabStripModelChanged(
      TabStripModel* tab_strip_model,
      const TabStripModelChange& change,
      const TabStripSelectionChange& selection) override;

  // TODO(https://crbug.com/346692548): This will not be necessary once
  // soon_to_be_owning_model_ is removed. TabInterface logic can only be invoked
  // in contexts where a model exists.
  TabStripModel* GetModelForTabInterface() const;

  // Updates the tab's properties based on all of its ancestor collections.
  void UpdateProperties();

  // Tracks whether a tab-modal UI is showing.
  class ScopedTabModalUIImpl : public ScopedTabModalUI {
   public:
    explicit ScopedTabModalUIImpl(TabModel* tab);
    ~ScopedTabModalUIImpl() override;

   private:
    // Owns this. Some consumers may hold this beyond the lifetime of the tab.
    base::WeakPtr<TabModel> tab_;
  };

  // This must always be the first member so that it is destroyed last. This is
  // because there are some instances where a caller may want to destroy a
  // TabModel but keep the WebContents alive. There are other destructors such
  // as TabFeatures that may require a valid `contents_` during destruction.
  std::unique_ptr<content::WebContents> contents_owned_;
  raw_ptr<content::WebContents> contents_;

  // A back reference to the TabStripModel that contains this TabModel. The
  // owning model can be nullptr if the tab has been detached from it's previous
  // owning tabstrip model, and has yet to be transferred to a new tabstrip
  // model or is in the process of being closed.
  raw_ptr<TabStripModel> owning_model_ = nullptr;
  raw_ptr<TabStripModel> soon_to_be_owning_model_ = nullptr;
  bool will_be_detaching_ = false;
  raw_ptr<tabs::TabInterface> opener_ = nullptr;
  bool reset_opener_on_active_tab_change_ = false;
  bool pinned_ = false;
  bool blocked_ = false;
  // TODO(crbug.com/392951786): Remove this property, and instead determine a
  // tab's split status based on whether it is part of a split tab collection.
  std::optional<split_tabs::SplitTabId> split_ = std::nullopt;
  std::optional<tab_groups::TabGroupId> group_ = std::nullopt;
  raw_ptr<TabCollection> parent_collection_ = nullptr;

  using WillDiscardContentsCallbackList = base::RepeatingCallbackList<
      void(TabInterface*, content::WebContents*, content::WebContents*)>;
  WillDiscardContentsCallbackList will_discard_contents_callback_list_;

  using DidActivateCallbackList =
      base::RepeatingCallbackList<void(TabInterface*)>;
  DidActivateCallbackList did_enter_foreground_callback_list_;

  using WillDeactivateCallbackList =
      base::RepeatingCallbackList<void(TabInterface*)>;
  WillDeactivateCallbackList will_enter_background_callback_list_;

  using DidBecomeVisibleCallback =
      base::RepeatingCallbackList<void(TabInterface*)>;
  DidActivateCallbackList did_become_visible_callback_list_;

  using WillBecomeHiddenCallback =
      base::RepeatingCallbackList<void(TabInterface*)>;
  WillBecomeHiddenCallback will_become_hidden_callback_list_;

  using WillDetachCallbackList =
      base::RepeatingCallbackList<void(TabInterface*,
                                       tabs::TabInterface::DetachReason)>;
  WillDetachCallbackList will_detach_callback_list_;

  using DidInsertCallbackList =
      base::RepeatingCallbackList<void(TabInterface*)>;
  DidInsertCallbackList did_insert_callback_list_;

  using PinnedStateChangedCallbackList =
      base::RepeatingCallbackList<void(TabInterface*, bool new_pinned_state)>;
  PinnedStateChangedCallbackList pinned_state_changed_callback_list_;

  using GroupChangedCallbackList = base::RepeatingCallbackList<
      void(TabInterface*, std::optional<tab_groups::TabGroupId> new_group)>;
  GroupChangedCallbackList group_changed_callback_list_;

  using TabInterfaceCallbackList =
      base::RepeatingCallbackList<void(TabInterface*)>;
  TabInterfaceCallbackList modal_ui_changed_callback_list_;

  // Tracks whether a modal UI is showing.
  bool showing_modal_ui_ = false;

  // Features that are per-tab will be owned by this class.
  std::unique_ptr<TabFeatures> tab_features_;

  base::WeakPtrFactory<TabModel> weak_factory_{this};
};

}  // namespace tabs

#endif  // CHROME_BROWSER_UI_TABS_TAB_MODEL_H_