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_
|