File: rules_registry.h

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 6,122,156 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 (302 lines) | stat: -rw-r--r-- 12,527 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
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
// Copyright 2012 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_RULES_REGISTRY_H__
#define EXTENSIONS_BROWSER_API_DECLARATIVE_RULES_REGISTRY_H__

#include <stddef.h>

#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>

#include "base/compiler_specific.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/one_shot_event.h"
#include "base/time/time.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/common/api/events.h"
#include "extensions/common/extension_id.h"

namespace content {
class BrowserContext;
}

namespace base {
class Value;
}  // namespace base

namespace extensions {

class Extension;
class RulesCacheDelegate;

// A base class for RulesRegistries that takes care of storing the
// api::events::Rule objects. It contains all the methods that need to run
// on the registry thread; methods that need to run on the UI thread are
// separated in the RulesCacheDelegate object.
class RulesRegistry : public base::RefCountedThreadSafe<RulesRegistry> {
 public:
  enum Defaults { DEFAULT_PRIORITY = 100 };
  // After the RulesCacheDelegate object (the part of the registry which runs on
  // the UI thread) is created, a pointer to it is passed to |*ui_part|.
  // In tests, `browser_context` and `ui_part` can be NULL (at the same time).
  // In that case the storage functionality disabled (no RulesCacheDelegate
  // object created).
  RulesRegistry(content::BrowserContext* browser_context,
                const std::string& event_name,
                RulesCacheDelegate* cache_delegate,
                int id);

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

  const base::OneShotEvent& ready() const { return ready_; }

  // RulesRegistry implementation:

  // Registers `rules` in this RulesRegistry. If a concrete RuleRegistry does
  // not support some of the rules, it may ignore them.
  //
  // `rules` is a list of Rule instances following the definition of the
  // declarative extension APIs. It is guaranteed that each rule in `rules` has
  // a unique name within the scope of `extension_id` that has not been
  // registered before, unless it has been removed again.
  //
  // Returns an empty string if the function is successful or an error message
  // otherwise. If the function is successful, and if the `rules_out` parameter
  // is non-null, pointers to the added rules are returned.
  //
  // IMPORTANT: This function is atomic. Either all rules that are deemed
  // relevant are added or none.
  std::string AddRules(
      const ExtensionId& extension_id,
      std::vector<api::events::Rule> rules_in,
      std::vector<const api::events::Rule*>* rules_out = nullptr);

  // Unregisters all rules listed in `rule_identifiers` and owned by
  // `extension_id` from this RulesRegistry.
  // Some or all IDs in `rule_identifiers` may not be stored in this
  // RulesRegistry and are ignored.
  //
  // Returns an empty string if the function is successful or an error
  // message otherwise.
  //
  // IMPORTANT: This function is atomic. Either all rules that are deemed
  // relevant are removed or none.
  std::string RemoveRules(const ExtensionId& extension_id,
                          const std::vector<std::string>& rule_identifiers);

  // Same as RemoveAllRules but acts on all rules owned by `extension_id`.
  std::string RemoveAllRules(const ExtensionId& extension_id);

  // Returns all rules listed in `rule_identifiers` and owned by `extension_id`
  // registered in this RuleRegistry. Entries in `rule_identifiers` that
  // are unknown are ignored.
  //
  // The returned rules are stored in `out`.
  void GetRules(const ExtensionId& extension_id,
                const std::vector<std::string>& rule_identifiers,
                std::vector<const api::events::Rule*>* out);

  // Same as GetRules but returns all rules owned by `extension_id`.
  void GetAllRules(const ExtensionId& extension_id,
                   std::vector<const api::events::Rule*>* out);

  // Called to notify the RulesRegistry that the registry service is being
  // shut down.
  void OnShutdown();

  // Called to notify the RulesRegistry that the extension availability has
  // changed, so that the registry can update which rules are active.
  void OnExtensionUnloaded(const Extension* extension);
  void OnExtensionUninstalled(const Extension* extension);
  void OnExtensionLoaded(const Extension* extension);

  // Returns the number of entries in used_rule_identifiers_ for leak detection.
  // Every ExtensionId counts as one entry, even if it contains no rules.
  size_t GetNumberOfUsedRuleIdentifiersForTesting() const;

  // Returns the RulesCacheDelegate. This is used for testing.
  RulesCacheDelegate* rules_cache_delegate_for_testing() const {
    return cache_delegate_.get();
  }

  // Returns the context where the rules registry lives.
  content::BrowserContext* browser_context() const { return browser_context_; }

  // The name of the event with which rules are registered.
  const std::string& event_name() const { return event_name_; }

  // The unique identifier for this RulesRegistry object.
  int id() const { return id_; }

 protected:
  virtual ~RulesRegistry();

  // These functions need to apply the rules to the browser, while the base
  // class will handle defaulting empty fields before calling *Impl, and will
  // automatically cache the rules and re-call *Impl on browser startup.
  virtual std::string AddRulesImpl(
      const ExtensionId& extension_id,
      const std::vector<const api::events::Rule*>& rules) = 0;
  virtual std::string RemoveRulesImpl(
      const ExtensionId& extension_id,
      const std::vector<std::string>& rule_identifiers) = 0;
  virtual std::string RemoveAllRulesImpl(const ExtensionId& extension_id) = 0;

 private:
  friend class base::RefCountedThreadSafe<RulesRegistry>;
  friend class RulesCacheDelegate;

  using RuleId = std::string;
  using RulesDictionaryKey = std::pair<ExtensionId, RuleId>;

  // NOTE: The property of stability of iterators of a map during insertion is
  // relied upon here. If this type needs to change, beware that this will
  // severely complicate returning valid pointers to callers of member functions
  // of this class.
  using RulesDictionary = std::map<RulesDictionaryKey, api::events::Rule>;
  enum ProcessChangedRulesState {
    // ProcessChangedRules can never be called, `cache_delegate_` is NULL.
    NEVER_PROCESS,
    // A task to call ProcessChangedRules is scheduled for future execution.
    SCHEDULED_FOR_PROCESSING,
    // No task to call ProcessChangedRules is scheduled yet, but it is possible
    // to schedule one.
    NOT_SCHEDULED_FOR_PROCESSING
  };
  using ProcessStateMap = std::map<ExtensionId, ProcessChangedRulesState>;

  base::WeakPtr<RulesRegistry> GetWeakPtr() {
    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
    return weak_ptr_factory_.GetWeakPtr();
  }

  // Internal implementation of the AddRules interface which adds the rules to
  // the `destination` RulesDictionary. If the function is successful, and if
  // the `rules_out` parameter is non-null, pointers to the added rules are
  // returned.
  std::string AddRulesInternal(
      const ExtensionId& extension_id,
      std::vector<api::events::Rule> rules_in,
      RulesDictionary* destination,
      std::vector<const api::events::Rule*>* rules_out);

  // The precondition for calling this method is that all rules have unique IDs.
  // AddRules establishes this precondition and calls into this method.
  // Stored rules already meet this precondition and so they avoid calling
  // CheckAndFillInOptionalRules for improved performance.
  //
  // Returns an empty string if the function is successful or an error
  // message otherwise. If the function is successful, and if the
  // `rules_out` parameter is non-null, pointers to the added rules are
  // returned.
  std::string AddRulesNoFill(const ExtensionId& extension_id,
                             std::vector<api::events::Rule> rules_in,
                             RulesDictionary* destination,
                             std::vector<const api::events::Rule*>* rules_out);

  // Same as GetRules but returns all rules owned by `extension_id` for a given
  // `rules` dictionary.
  void GetRules(const ExtensionId& extension_id,
                RulesDictionary* rules,
                std::vector<const api::events::Rule*>* out);

  // Common processing after extension's rules have changed.
  void ProcessChangedRules(const ExtensionId& extension_id);

  // Calls ProcessChangedRules if
  // |process_changed_rules_requested_(extension_id)| ==
  // NOT_SCHEDULED_FOR_PROCESSING.
  void MaybeProcessChangedRules(const ExtensionId& extension_id);

  // This method implements the functionality of RemoveAllRules, except for not
  // calling MaybeProcessChangedRules. That way updating the rules store and
  // extension prefs is avoided. This method is called when an extension is
  // uninstalled, that way there is no clash with the preferences being wiped.
  // Set `remove_manifest_rules` to true if `manifest_rules_` should be cleared
  // along with `rules_`.
  std::string RemoveAllRulesNoStoreUpdate(const ExtensionId& extension_id,
                                          bool remove_manifest_rules);

  void MarkReady();

  // Deserialize the rules from the given Value object and add them to the
  // RulesRegistry.
  void DeserializeAndAddRules(const ExtensionId& extension_id,
                              std::optional<base::Value> rules);

  // Reports an internal error with the specified params to the extensions
  // client.
  void ReportInternalError(const ExtensionId& extension_id,
                           const std::string& error);

  // The context to which this rules registry belongs.
  raw_ptr<content::BrowserContext> browser_context_;

  // The name of the event with which rules are registered.
  const std::string event_name_;

  // The key that identifies the context in which these rules apply.
  int id_;

  RulesDictionary rules_;

  RulesDictionary manifest_rules_;

  // Signaled when we have finished reading from storage for all extensions that
  // are loaded on startup.
  base::OneShotEvent ready_;

  ProcessStateMap process_changed_rules_requested_;

  // Returns whether any existing rule is registered with identifier `rule_id`
  // for extension `extension_id`.
  bool IsUniqueId(const ExtensionId& extension_id,
                  const std::string& rule_id) const;

  // Creates an ID that is unique within the scope of`extension_id`.
  std::string GenerateUniqueId(const ExtensionId& extension_id);

  // Verifies that all `rules` have unique IDs or initializes them with
  // unique IDs if they don't have one. In case of duplicate IDs, this function
  // returns a non-empty error message.
  std::string CheckAndFillInOptionalRules(
      const ExtensionId& extension_id,
      std::vector<api::events::Rule>* rules);

  // Initializes the priority fields in case they have not been set.
  void FillInOptionalPriorities(std::vector<api::events::Rule>* rules);

  // Removes all `identifiers` of `extension_id` from `used_rule_identifiers_`.
  void RemoveUsedRuleIdentifiers(const ExtensionId& extension_id,
                                 const std::vector<std::string>& identifiers);

  // Same as RemoveUsedRuleIdentifiers but operates on all rules of
  // `extension_id`.
  void RemoveAllUsedRuleIdentifiers(const ExtensionId& extension_id);

  using RuleIdentifier = std::string;
  std::map<ExtensionId, std::set<RuleIdentifier>> used_rule_identifiers_;
  int last_generated_rule_identifier_id_;

  // `cache_delegate_` is owned by the registry service. If `cache_delegate_` is
  // NULL, then the storage functionality is disabled (this is used in tests).
  // This registry cannot own `cache_delegate_` because during the time after
  // rules registry service shuts down on UI thread, and the registry is
  // destroyed on its thread, the use of the `cache_delegate_` would not be
  // safe. The registry only ever associates with one RulesCacheDelegate
  // instance.
  base::WeakPtr<RulesCacheDelegate> cache_delegate_;

  base::WeakPtrFactory<RulesRegistry> weak_ptr_factory_{this};
};

}  // namespace extensions

#endif  // EXTENSIONS_BROWSER_API_DECLARATIVE_RULES_REGISTRY_H__