File: action_tracker.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; 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,806; 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 (220 lines) | stat: -rw-r--r-- 8,700 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
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_ACTION_TRACKER_H_
#define EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_ACTION_TRACKER_H_

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

#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "extensions/browser/api/declarative_net_request/prefs_helper.h"
#include "extensions/common/api/declarative_net_request.h"
#include "extensions/common/api/declarative_net_request/constants.h"
#include "extensions/common/extension_id.h"

namespace base {
class Clock;
class RetainingOneShotTimer;
}

namespace content {
class BrowserContext;
}

namespace extensions {

class Extension;
struct WebRequestInfo;

namespace declarative_net_request {
struct RequestAction;

class ActionTracker {
 public:
  // The lifespan of matched rules in `rules_matched_` not associated with an
  // active document,
  static constexpr base::TimeDelta kNonActiveTabRuleLifespan = base::Minutes(5);

  explicit ActionTracker(content::BrowserContext* browser_context);
  ~ActionTracker();
  ActionTracker(const ActionTracker& other) = delete;
  ActionTracker& operator=(const ActionTracker& other) = delete;

  // TODO(crbug.com/40115239): Use a task environment to avoid having to set
  // clocks just for tests.

  // Sets a custom Clock to use in tests. `clock` should be owned by the caller
  // of this function.
  void SetClockForTests(const base::Clock* clock);

  // Sets a custom RetainingOneShotTimer to use in tests, which replaces
  // `trim_rules_timer_`.
  void SetTimerForTest(
      std::unique_ptr<base::RetainingOneShotTimer> injected_trim_rules_timer);

  // Disables checking whether a tab ID corresponds to an existing tab when a
  // rule is matched. Used for unit tests where WebContents/actual tabs do not
  // exist.
  void SetCheckTabIdOnRuleMatchForTest(bool check_tab_id);

  // Called whenever a request matches with a rule.
  void OnRuleMatched(const RequestAction& request_action,
                     const WebRequestInfo& request_info);

  // Updates the action count for all tabs for the specified `extension_id`'s
  // extension action. Called when the extension calls setExtensionActionOptions
  // to enable setting the action count as badge text.
  void OnActionCountAsBadgeTextPreferenceEnabled(
      const ExtensionId& extension_id) const;

  // Clears the TrackedInfo for the specified `extension_id` for all tabs.
  // Called when an extension's ruleset is removed.
  void ClearExtensionData(const ExtensionId& extension_id);

  // Clears the TrackedInfo for every extension for the specified `tab_id`.
  // Called when the tab has been closed.
  void ClearTabData(int tab_id);

  // Clears the pending action count for every extension in
  // `pending_navigation_actions_` for the specified `navigation_id`.
  void ClearPendingNavigation(int64_t navigation_id);

  // Called when a main-frame navigation to a different document commits.
  // Updates the TrackedInfo for all extensions for the given `tab_id`.
  void ResetTrackedInfoForTab(int tab_id, int64_t navigation_id);

  // Returns all matched rules for `extension`. If `tab_id` is provided, only
  // rules matched for `tab_id` will be returned.
  std::vector<api::declarative_net_request::MatchedRuleInfo> GetMatchedRules(
      const Extension& extension,
      const std::optional<int>& tab_id,
      const base::Time& min_time_stamp);

  // Returns the number of matched rules in `rules_tracked_` for the given
  // `extension_id` and `tab_id`. If `trim_non_active_rules` is true,
  // TrimRulesFromNonActiveTabs is invoked before returning the matched rule
  // count, similar to GetMatchedRules. Should only be used for tests.
  int GetMatchedRuleCountForTest(const ExtensionId& extension_id,
                                 int tab_id,
                                 bool trim_non_active_rules);

  // Returns the number of matched rules in `pending_navigation_actions_` for
  // the given `extension_id` and `navigation_id`. Should only be used for
  // tests.
  int GetPendingRuleCountForTest(const ExtensionId& extension_id,
                                 int64_t navigation_id);

  // Increments the action count for the given `extension_id` and `tab_id`.
  // A negative value for `increment` will decrement the action count, but the
  // action count will never be less than 0.
  void IncrementActionCountForTab(const ExtensionId& extension_id,
                                  int tab_id,
                                  int increment);

 private:
  // Template key type used for TrackedInfo, specified by an extension_id and
  // another ID.
  template <typename T>
  struct TrackedInfoContextKey {
    TrackedInfoContextKey(ExtensionId extension_id, T secondary_id);
    TrackedInfoContextKey(const TrackedInfoContextKey& other) = delete;
    TrackedInfoContextKey& operator=(const TrackedInfoContextKey& other) =
        delete;
    TrackedInfoContextKey(TrackedInfoContextKey&&);
    TrackedInfoContextKey& operator=(TrackedInfoContextKey&&);

    ExtensionId extension_id;
    T secondary_id;

    bool operator<(const TrackedInfoContextKey& other) const;
  };

  using ExtensionTabIdKey = TrackedInfoContextKey<int>;
  using ExtensionNavigationIdKey = TrackedInfoContextKey<int64_t>;

  // Represents a matched rule. This is used as a lightweight version of
  // api::declarative_net_request::MatchedRuleInfo.
  struct TrackedRule {
    TrackedRule(int rule_id, RulesetID ruleset_id);
    TrackedRule(const TrackedRule& other) = delete;
    TrackedRule& operator=(const TrackedRule& other) = delete;

    const int rule_id;
    const RulesetID ruleset_id;

    // The timestamp for when the rule was matched.
    const base::Time time_stamp;
  };

  // Info tracked for each ExtensionTabIdKey or ExtensionNavigationIdKey.
  struct TrackedInfo {
    TrackedInfo();
    ~TrackedInfo();
    TrackedInfo(const TrackedInfo& other) = delete;
    TrackedInfo& operator=(const TrackedInfo& other) = delete;
    TrackedInfo(TrackedInfo&&);
    TrackedInfo& operator=(TrackedInfo&&);

    // The number of actions matched. Invalid when the corresponding
    // TrackedInfoContextKey has a tab_id of -1. Does not include allow rules.
    size_t action_count = 0;

    // The list of rules matched. Includes allow rules.
    std::list<TrackedRule> matched_rules;
  };

  // Called from OnRuleMatched. Dispatches a OnRuleMatchedDebug event to the
  // observer for the extension specified by |request_action.extension_id|.
  void DispatchOnRuleMatchedDebugIfNeeded(
      const RequestAction& request_action,
      api::declarative_net_request::RequestDetails request_details);

  // For all matched rules attributed to `tab_id`, set their tab ID to the
  // unknown tab ID (-1). Called by ClearTabData and ResetActionCountForTab.
  void TransferRulesOnTabInvalid(int tab_id);

  // Removes all rules in `rules_tracked_` older than
  // `kNonActiveTabRuleLifespan` from non active tabs (i.e. `tab_id` = -1).
  // Called periodically to ensure no rules attributed to the unknown tab ID in
  // `rules_tracked_` are older than `kNonActiveTabRuleLifespan`.
  void TrimRulesFromNonActiveTabs();

  // Schedules TrimRulesFromNonActiveTabs to be run after
  // `kNonActiveTabRuleLifespan`. Called in the constructor and whenever
  // `trim_rules_timer_` gets set.
  void StartTrimRulesTask();

  // Converts an internally represented `tracked_rule` to a MatchedRuleInfo.
  api::declarative_net_request::MatchedRuleInfo CreateMatchedRuleInfo(
      const Extension& extension,
      const TrackedRule& tracked_rule,
      int tab_id) const;

  // A timer to call TrimRulesFromNonActiveTabs with an interval of
  // `kNonActiveTabRuleLifespan`.
  std::unique_ptr<base::RetainingOneShotTimer> trim_rules_timer_ =
      std::make_unique<base::RetainingOneShotTimer>();

  // Maps a pair of (extension ID, tab ID) to the TrackedInfo for that pair.
  std::map<ExtensionTabIdKey, TrackedInfo> rules_tracked_;

  // Maps a pair of (extension ID, navigation ID) to the TrackedInfo matched for
  // the main-frame request associated with the navigation ID in the key. The
  // TrackedInfo is added to `rules_tracked_` once the navigation commits.
  std::map<ExtensionNavigationIdKey, TrackedInfo> pending_navigation_actions_;

  raw_ptr<content::BrowserContext> browser_context_;

  PrefsHelper prefs_helper_;
};

}  // namespace declarative_net_request
}  // namespace extensions

#endif  // EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_ACTION_TRACKER_H_