File: tab_load_tracker.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 (208 lines) | stat: -rw-r--r-- 8,248 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
// Copyright 2018 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_RESOURCE_COORDINATOR_TAB_LOAD_TRACKER_H_
#define CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_LOAD_TRACKER_H_

#include <array>

#include "base/containers/flat_map.h"
#include "base/functional/callback.h"
#include "base/gtest_prod_util.h"
#include "base/observer_list.h"
#include "base/process/kill.h"
#include "base/sequence_checker.h"
#include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom-shared.h"

namespace content {
class WebContents;
}  // namespace content

namespace resource_coordinator {

class ResourceCoordinatorParts;
class ResourceCoordinatorTabHelper;

// DEPRECATED. New users must observe PageNode::IsLoading() with a
// PageNodeObserver. For guidance: //components/performance_manager/OWNERS
//
// This class has the sole purpose of tracking the state of all tab-related
// WebContents, and whether or not they are in an unloaded, currently loading,
// or loaded state.
//
// This class must be bound to a given Sequence and all access to it must occur
// on that Sequence. In practice, this is intended to be on the UI thread as the
// notifications of interest occur natively on that thread. All calculations are
// very short and quick, so it is suitable for use on that thread.
//
// This class is intended to be created in early startup and persists as a
// singleton in the browser process. It is deliberately leaked at shutdown.
//
// This class isn't directly an observer of anything. An external source must
// invoke the callbacks in the protected section of the class. In the case of
// the TabManager this is done by a combination of the
// ResourceCoordinatorTabHelper and the
// TabManagerResourceCoordinatorSignalObserver.
class TabLoadTracker {
 public:
  // An observer class. This allows external classes to be notified of loading
  // state changes.
  class Observer;

  using LoadingState = ::mojom::LifecycleUnitLoadingState;

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

  // A brief note around loading states specifically as they are defined in the
  // context of a WebContents:
  //
  // An initially constructed WebContents with no loaded content is UNLOADED.
  //
  // A WebContents transitions to LOADING when network data starts being
  // received for a top-level load to a different document. This considers
  // throttled navigations as not yet loading, and will only transition to
  // loading once the throttle has been removed.
  //
  // A LOADING WebContents transitions to LOADED when it reaches an "almost
  // idle" state, based on CPU and network quiescence or after an absolute
  // timeout (see PageLoadTrackerDecorator).
  //
  // A WebContents transitions to UNLOADED when its render process is gone.

  ~TabLoadTracker();

  // Returns the singleton TabLoadTracker instance.
  static TabLoadTracker* Get();

  // Allows querying the state of a tab. The provided |web_contents| must be
  // actively tracked.
  LoadingState GetLoadingState(content::WebContents* web_contents) const;

  // Returns the total number of tabs that are being tracked by this class.
  size_t GetTabCount() const;

  // Returns the number of tabs in each state.
  size_t GetTabCount(LoadingState loading_state) const;
  size_t GetUnloadedTabCount() const;
  size_t GetLoadingTabCount() const;
  size_t GetLoadedTabCount() const;

  // Adds/removes an observer. It is up to the observer to ensure their lifetime
  // exceeds that of the TabLoadTracker, as is removed prior to its destruction.
  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

  // Exposed so that state transitions can be simulated in tests.
  void TransitionStateForTesting(content::WebContents* web_contents,
                                 LoadingState loading_state);

 protected:
  friend class ResourceCoordinatorParts;

  // For unittesting.
  friend class LocalSiteCharacteristicsWebContentsObserverTest;

  // These declarations allows the various bits of TabManager plumbing to
  // forward notifications to the TabLoadTracker.
  friend class ResourceCoordinatorTabHelper;
  friend class TabManagerResourceCoordinatorSignalObserver;

  FRIEND_TEST_ALL_PREFIXES(TabLifecycleUnitTest, CannotFreezeAFrozenTab);

  // This class is a singleton so the constructor is protected.
  TabLoadTracker();

  // Initiates tracking of a WebContents. This is fully able to determine the
  // initial state of the WebContents, even if it was created long ago
  // (is LOADING or LOADED) and only just attached to the tracker. See the
  // implementation of DetermineLoadingState for details.
  void StartTracking(content::WebContents* web_contents);

  // Stops tracking a |web_contents|.
  void StopTracking(content::WebContents* web_contents);

  // These are analogs of WebContentsObserver functions. This class is not
  // actually an observer, but the relevant events are forwarded to it from the
  // TabManager.
  //
  // In all cases, a call to PrimaryPageChanged() is expected to be followed by
  // a call to StopTracking(), RenderProcessGone() or OnPageStoppedLoading().
  void PrimaryPageChanged(content::WebContents* web_contents);
  void DidStopLoading(content::WebContents* web_contents);
  void WasDiscarded(content::WebContents* web_contents);
  void RenderProcessGone(content::WebContents* web_contents,
                         base::TerminationStatus status);

  // Notifications to this are driven by the
  // TabManagerResourceCoordinatorSignalObserver.
  void OnPageStoppedLoading(content::WebContents* web_contents);

 private:
  // For unittesting.
  friend class TestTabLoadTracker;

  // Some metadata used to track the current state of the WebContents.
  struct WebContentsData {
    LoadingState loading_state = LoadingState::UNLOADED;
  };

  using TabMap = base::flat_map<content::WebContents*, WebContentsData>;

  // Helper function for determining the current state of a |web_contents|.
  LoadingState DetermineLoadingState(content::WebContents* web_contents);

  // Transitions a web contents to the unloaded state, if not already in that
  // state.
  void TransitionToUnloaded(content::WebContents* web_contents);

  // Transitions a web contents to the given state. This updates the various
  // |state_counts_| and |tabs_| data. Setting |validate_transition| to false
  // means that valid state machine transitions aren't enforced via checks; this
  // is only used by state transitions forced via TransitionStateForTesting.
  void TransitionState(TabMap::iterator it, LoadingState loading_state);

  // The list of known WebContents and their states.
  TabMap tabs_;

  // The counts of tabs in each state.
  std::array<size_t, static_cast<size_t>(LoadingState::kMaxValue) + 1>
      state_counts_ = {};

  base::ObserverList<Observer>::UncheckedAndDanglingUntriaged observers_;

  SEQUENCE_CHECKER(sequence_checker_);
};

// A class for observing loading state changes of WebContents under observation
// by a given TabLoadTracker. All of the callbacks will be invoked on the
// sequence to which the TabLoadTracker is bound.
class TabLoadTracker::Observer {
 public:
  using LoadingState = TabLoadTracker::LoadingState;

  Observer();

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

  virtual ~Observer();

  // Called when a |web_contents| is starting to be tracked.
  virtual void OnStartTracking(content::WebContents* web_contents,
                               LoadingState loading_state) {}

  // Called for every loading state change observed on a |web_contents|.
  virtual void OnLoadingStateChange(content::WebContents* web_contents,
                                    LoadingState old_loading_state,
                                    LoadingState new_loading_state) {}

  // Called when a |web_contents| is no longer being tracked.
  virtual void OnStopTracking(content::WebContents* web_contents,
                              LoadingState loading_state) {}
};

}  // namespace resource_coordinator

#endif  // CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_LOAD_TRACKER_H_