File: background_tab_loading_policy.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 (308 lines) | stat: -rw-r--r-- 12,763 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
// 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_PERFORMANCE_MANAGER_POLICIES_BACKGROUND_TAB_LOADING_POLICY_H_
#define CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_BACKGROUND_TAB_LOADING_POLICY_H_

#include <map>
#include <optional>
#include <vector>

#include "base/gtest_prod_util.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/raw_ptr.h"
#include "components/performance_manager/public/graph/graph.h"
#include "components/performance_manager/public/graph/node_data_describer.h"
#include "components/performance_manager/public/graph/page_node.h"
#include "components/performance_manager/public/graph/system_node.h"
#include "url/gurl.h"

namespace performance_manager {

namespace mechanism {
class PageLoader;
}  // namespace mechanism

FORWARD_DECLARE_TEST(BackgroundTabLoadingBrowserTest,
                     RestoredTabsAreLoadedGradually);
class BackgroundTabLoadingBrowserTest;
class SiteDataReader;

namespace policies {

// This policy manages loading of background tabs created by session restore. It
// is responsible for assigning priorities and controlling the load of
// background tab loading at all times.
class BackgroundTabLoadingPolicy : public GraphOwned,
                                   public NodeDataDescriberDefaultImpl,
                                   public PageNodeObserver,
                                   public SystemNodeObserver {
 public:
  // `all_restored_tabs_loaded_callback` is invoked when all tabs passed to
  // ScheduleLoadForRestoredTabs() are loaded.
  explicit BackgroundTabLoadingPolicy(
      base::RepeatingClosure all_restored_tabs_loaded_callback);
  ~BackgroundTabLoadingPolicy() override;
  BackgroundTabLoadingPolicy(const BackgroundTabLoadingPolicy& other) = delete;
  BackgroundTabLoadingPolicy& operator=(const BackgroundTabLoadingPolicy&) =
      delete;

  // GraphOwned implementation:
  void OnPassedToGraph(Graph* graph) override;
  void OnTakenFromGraph(Graph* graph) override;

  // PageNodeObserver implementation:
  void OnLoadingStateChanged(const PageNode* page_node,
                             PageNode::LoadingState previous_state) override;
  void OnBeforePageNodeRemoved(const PageNode* page_node) override;

  // Holds data about a PageNode being added to this policy.
  struct PageNodeData {
    explicit PageNodeData(
        base::WeakPtr<PageNode> page_node,
        GURL main_frame_url = GURL(),
        blink::mojom::PermissionStatus notification_permission_status =
            blink::mojom::PermissionStatus::ASK);
    PageNodeData(PageNodeData&& other);
    PageNodeData& operator=(PageNodeData&& other);
    PageNodeData(const PageNodeData& other);
    PageNodeData& operator=(const PageNodeData& other);
    ~PageNodeData();

    base::WeakPtr<PageNode> page_node;
    GURL main_frame_url;
    blink::mojom::PermissionStatus notification_permission_status;
    std::optional<size_t> site_engagement;
  };

  // Schedules the PageNodes in |page_node_and_permission_vector| to be loaded
  // when appropriate.
  void ScheduleLoadForRestoredTabs(
      std::vector<PageNodeData> page_node_and_permission_vector);

  void SetMockLoaderForTesting(std::unique_ptr<mechanism::PageLoader> loader);
  void SetMaxSimultaneousLoadsForTesting(size_t loading_slots);
  void SetFreeMemoryForTesting(size_t free_memory_mb);
  void ResetPolicyForTesting();

  // Returns the instance of BackgroundTabLoadingPolicy within the graph.
  static BackgroundTabLoadingPolicy* GetInstance();

 private:
  friend class ::performance_manager::BackgroundTabLoadingBrowserTest;
  friend class BackgroundTabLoadingPolicyTest;

  // Holds data about a PageNode waiting to be loaded by this policy.
  struct PageNodeToLoadData {
    PageNodeToLoadData(const PageNode* page_node,
                       std::optional<size_t> site_engagement);
    ~PageNodeToLoadData();

    // Move-only.
    PageNodeToLoadData(const PageNodeToLoadData&) = delete;
    PageNodeToLoadData& operator=(const PageNodeToLoadData&) = delete;
    PageNodeToLoadData(PageNodeToLoadData&&) = default;
    PageNodeToLoadData& operator=(PageNodeToLoadData&&) = default;

    // Returns true if the data about this PageNode indicates it uses background
    // communication.
    bool UsesBackgroundCommunication() const;

    // Keeps a pointer to the corresponding PageNode.
    raw_ptr<const PageNode> page_node;

    // A higher value here means the tab has higher priority for restoring.
    std::optional<float> score;

    // Whether the tab updates its title or favicon when backgrounded.
    // Initialized to nullopt and set asynchronously with the proper value from
    // the sites database.
    std::optional<bool> updates_title_or_favicon_in_bg;

    std::optional<size_t> site_engagement;
  };

  // Comparator used to sort PageNodeToLoadData.
  struct ScoredTabComparator;

  // NodeDataDescriber implementation:
  base::Value::Dict DescribePageNodeData(const PageNode* node) const override;
  base::Value::Dict DescribeSystemNodeData(
      const SystemNode* node) const override;

  // SystemNodeObserver:
  void OnMemoryPressure(
      base::MemoryPressureListener::MemoryPressureLevel new_level) override;

  // Returns the SiteDataReader instance for |page_node|, if any. Virtual for
  // testing.
  virtual SiteDataReader* GetSiteDataReader(const PageNode* page_node) const;

  // Determines whether or not the given PageNode should be loaded. If this
  // returns false, then the policy no longer attempts to load |page_node| and
  // removes it from the policy's internal state. This is called immediately
  // prior to trying to load the PageNode.
  bool ShouldLoad(const PageNodeToLoadData& page_node_data);

  // This will initialize |page_node_to_load_data->used_in_bg| to the proper
  // value, score the tab and call DispatchNotifyAllTabsScoredIfNeeded().
  void OnUsedInBackgroundAvailable(base::WeakPtr<PageNode> page_node);

  // Stops loading tabs by clearing |page_nodes_to_load_|.
  void StopLoadingTabs();

  // Calculates a |score| for the given tab.
  void ScoreTab(PageNodeToLoadData* page_node_to_load_data);

  // Schedule the task that will initialize |PageNodeToLoadData::used_in_bg|
  // from the local site characteristics database.
  void SetUsedInBackgroundAsync(PageNodeToLoadData* page_node_to_load_data);

  // Invoke "NotifyAllTabsScored" if all tabs are scored.
  void DispatchNotifyAllTabsScoredIfNeeded();

  // Notifying that all tabs have final scores and starts loading.
  void NotifyAllTabsScored();

  // Move the PageNode from |page_nodes_to_load_| to
  // |page_nodes_load_initiated_| and make the call to load the PageNode.
  void InitiateLoad(const PageNode* page_node);

  // Removes the PageNode from all the sets of PageNodes that the policy is
  // tracking.
  void RemovePageNode(const PageNode* page_node);

  // Initiates the load of enough tabs to fill all loading slots. No-ops if all
  // loading slots are occupied.
  void MaybeLoadSomeTabs();

  // Determines the number of tab loads that can be started at the moment to
  // avoid exceeding the number of loading slots.
  size_t GetMaxNewTabLoads() const;

  // Loads the next tab. This should only be called if there is a next tab to
  // load. This will always start loading a next tab even if the number of
  // simultaneously loading tabs is exceeded.
  void LoadNextTab();

  // Compute the amount of free memory on the system.
  size_t GetFreePhysicalMemoryMib() const;

  // If `page_node` is in the set of page nodes to load, removes it and returns
  // true.
  bool ErasePageNodeToLoadData(const PageNode* page_node);

  // Returns the `PageNodeToLoadData` for `page_node` if it exists, nullptr
  // otherwise.
  PageNodeToLoadData* FindPageNodeToLoadData(const PageNode* page_node);

  // Returns true if there are restored tabs that must be loaded by this policy
  // and aren't fully loaded yet.
  bool HasRestoredTabsToLoad() const;

  // Updates `has_restored_tabs_to_load_` to match `HasRestoredTabsToLoad()` and
  // invokes `all_restored_tabs_loaded_callback_` if needed.
  void UpdateHasRestoredTabsToLoad();

  // The callback to invoke when all restored tabs are loaded.
  const base::RepeatingClosure all_restored_tabs_loaded_callback_;

  // Whether there are restored tabs that that must be loaded by this policy and
  // aren't fully loaded yet.
  //
  // Set to true when ScheduleLoadForRestoredTabs() is invoked. Set to false
  // when HasRestoredTabsToLoad() becomes false.
  bool has_restored_tabs_to_load_ = false;

  // The mechanism used to load the pages.
  std::unique_ptr<performance_manager::mechanism::PageLoader> page_loader_;

  // The set of PageNodes that have been restored for which we need to schedule
  // loads.
  std::vector<std::unique_ptr<PageNodeToLoadData>> page_nodes_to_load_;

  // The set of PageNodes that BackgroundTabLoadingPolicy has initiated loading,
  // and for which we are waiting for the loading to actually start. This signal
  // will be received from |OnIsLoadingChanged|.
  std::vector<raw_ptr<const PageNode, VectorExperimental>>
      page_nodes_load_initiated_;

  // PageNodes that are currently loading, mapped to a boolean indicating
  // whether this policy was responsible for scheduling the load.
  std::map<const PageNode*, bool> page_nodes_loading_;

  // The number of simultaneous tab loads that are permitted by policy. This
  // is computed based on the number of cores on the machine.
  size_t max_simultaneous_tab_loads_;

  // The number of tab loads that have started. Every call to InitiateLoad
  // increments this value.
  size_t tab_loads_started_ = 0;

  // The number of tabs for which an accurate initial score has been assigned.
  // This is incremented only after all tab data is available, which
  // may happen asynchronously.
  size_t tabs_scored_ = 0;

  // Used to overwrite the amount of free memory available on the system.
  size_t free_memory_mb_for_testing_ = 0;

  // The minimum total number of restored tabs to load.
  static constexpr uint32_t kMinTabsToLoad = 4;

  // The maximum total number of restored tabs to load.
  static constexpr uint32_t kMaxTabsToLoad = 20;

  // The minimum amount of memory to keep free.
  static constexpr uint32_t kDesiredAmountOfFreeMemoryMb = 150;

  // The maximum time since last use of a tab in order for it to be loaded.
  static constexpr base::TimeDelta kMaxTimeSinceLastUseToLoad = base::Days(30);

  // Lower bound for the maximum number of tabs to load simultaneously.
  static constexpr uint32_t kMinSimultaneousTabLoads = 1;

  // Upper bound for the maximum number of tabs to load simultaneously.
  static constexpr uint32_t kMaxSimultaneousTabLoads = 4;

  // The number of CPU cores required per permitted simultaneous tab
  // load.
  static constexpr uint32_t kCoresPerSimultaneousTabLoad = 2;

  // It's possible for this policy object to be destroyed while it has posted
  // tasks. The tasks are bound to a weak pointer so that they are not executed
  // after the policy object is destroyed.
  base::WeakPtrFactory<BackgroundTabLoadingPolicy> weak_factory_{this};

  FRIEND_TEST_ALL_PREFIXES(BackgroundTabLoadingPolicyTest,
                           ShouldLoad_MaxTabsToRestore);
  FRIEND_TEST_ALL_PREFIXES(BackgroundTabLoadingPolicyTest,
                           ShouldLoad_MinTabsToRestore);
  FRIEND_TEST_ALL_PREFIXES(BackgroundTabLoadingPolicyTest,
                           ShouldLoad_FreeMemory);
  FRIEND_TEST_ALL_PREFIXES(BackgroundTabLoadingPolicyTest, ShouldLoad_OldTab);
  FRIEND_TEST_ALL_PREFIXES(BackgroundTabLoadingPolicyTest,
                           ShouldLoad_SiteEngagement);
  FRIEND_TEST_ALL_PREFIXES(BackgroundTabLoadingPolicySiteEngagementTest,
                           ShouldLoad_NoBackgroundCommunication);
  FRIEND_TEST_ALL_PREFIXES(BackgroundTabLoadingPolicySiteEngagementTest,
                           ShouldLoad_NotificationPermission);
  FRIEND_TEST_ALL_PREFIXES(BackgroundTabLoadingPolicySiteEngagementTest,
                           ShouldLoad_UpdatesTitleOrFaviconInBackground);
  FRIEND_TEST_ALL_PREFIXES(
      BackgroundTabLoadingPolicyScheduleLoadTest,
      ScheduleLoadForRestoredTabs_WithoutNotificationPermission);
  FRIEND_TEST_ALL_PREFIXES(
      BackgroundTabLoadingPolicyScheduleLoadTest,
      ScheduleLoadForRestoredTabs_WithNotificationPermission);
  FRIEND_TEST_ALL_PREFIXES(
      ::performance_manager::BackgroundTabLoadingBrowserTest,
      RestoredTabsAreLoadedGradually);
};

}  // namespace policies

}  // namespace performance_manager

#endif  // CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_BACKGROUND_TAB_LOADING_POLICY_H_