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
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// 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 <map>
#include <set>
#include <string>
#include <vector>
#include "base/callback_forward.h"
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "extensions/common/api/events.h"
#include "extensions/common/one_shot_event.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
// RulesRegistry::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:
typedef extensions::core_api::events::Rule Rule;
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,
content::BrowserThread::ID owner_thread,
RulesCacheDelegate* cache_delegate,
int id);
const OneShotEvent& ready() const {
return ready_;
}
// RulesRegistry implementation:
// Registers |rules|, owned by |extension_id| to 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.
// The ownership of rules remains with the caller.
//
// 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 added or none.
std::string AddRules(
const std::string& extension_id,
const std::vector<linked_ptr<RulesRegistry::Rule> >& rules);
// 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 std::string& 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 std::string& 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|. Ownership is passed to the caller.
void GetRules(const std::string& extension_id,
const std::vector<std::string>& rule_identifiers,
std::vector<linked_ptr<RulesRegistry::Rule> >* out);
// Same as GetRules but returns all rules owned by |extension_id|.
void GetAllRules(const std::string& extension_id,
std::vector<linked_ptr<RulesRegistry::Rule> >* out);
// 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_; }
// Returns the ID of the thread on which the rules registry lives.
// It is safe to call this function from any thread.
content::BrowserThread::ID owner_thread() const { return owner_thread_; }
// 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 std::string& extension_id,
const std::vector<linked_ptr<RulesRegistry::Rule> >& rules) = 0;
virtual std::string RemoveRulesImpl(
const std::string& extension_id,
const std::vector<std::string>& rule_identifiers) = 0;
virtual std::string RemoveAllRulesImpl(
const std::string& extension_id) = 0;
private:
friend class base::RefCountedThreadSafe<RulesRegistry>;
friend class RulesCacheDelegate;
typedef std::string ExtensionId;
typedef std::string RuleId;
typedef std::pair<ExtensionId, RuleId> RulesDictionaryKey;
typedef std::map<RulesDictionaryKey, linked_ptr<RulesRegistry::Rule> >
RulesDictionary;
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
};
typedef std::map<ExtensionId, ProcessChangedRulesState> ProcessStateMap;
base::WeakPtr<RulesRegistry> GetWeakPtr() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
return weak_ptr_factory_.GetWeakPtr();
}
// Internal implementation of the AddRules interface which adds
// |from_manifest| which is true when the source is the manifest.
std::string AddRulesInternal(
const std::string& extension_id,
const std::vector<linked_ptr<RulesRegistry::Rule>>& rules,
RulesDictionary* 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.
std::string AddRulesNoFill(
const std::string& extension_id,
const std::vector<linked_ptr<RulesRegistry::Rule>>& rules,
RulesDictionary* out);
// Same as GetRules but returns all rules owned by |extension_id| for a given
// |rules| dictionary.
void GetRules(const std::string& extension_id,
RulesDictionary& rules,
std::vector<linked_ptr<RulesRegistry::Rule>>* out);
// Common processing after extension's rules have changed.
void ProcessChangedRules(const std::string& extension_id);
// Calls ProcessChangedRules if
// |process_changed_rules_requested_(extension_id)| ==
// NOT_SCHEDULED_FOR_PROCESSING.
void MaybeProcessChangedRules(const std::string& 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 std::string& extension_id,
bool remove_manifest_rules);
void MarkReady(base::Time storage_init_time);
// Deserialize the rules from the given Value object and add them to the
// RulesRegistry.
void DeserializeAndAddRules(const std::string& extension_id,
scoped_ptr<base::Value> rules);
// The context to which this rules registry belongs.
content::BrowserContext* browser_context_;
// The ID of the thread on which the rules registry lives.
const content::BrowserThread::ID owner_thread_;
// 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.
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 std::string& extension_id,
const std::string& rule_id) const;
// Creates an ID that is unique within the scope of|extension_id|.
std::string GenerateUniqueId(const std::string& 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 std::string& extension_id,
const std::vector<linked_ptr<RulesRegistry::Rule> >& rules);
// Initializes the priority fields in case they have not been set.
void FillInOptionalPriorities(
const std::vector<linked_ptr<RulesRegistry::Rule> >& rules);
// Removes all |identifiers| of |extension_id| from |used_rule_identifiers_|.
void RemoveUsedRuleIdentifiers(const std::string& extension_id,
const std::vector<std::string>& identifiers);
// Same as RemoveUsedRuleIdentifiers but operates on all rules of
// |extension_id|.
void RemoveAllUsedRuleIdentifiers(const std::string& extension_id);
typedef std::string RuleIdentifier;
typedef std::map<ExtensionId, std::set<RuleIdentifier> > RuleIdentifiersMap;
RuleIdentifiersMap 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_;
DISALLOW_COPY_AND_ASSIGN(RulesRegistry);
};
} // namespace extensions
#endif // EXTENSIONS_BROWSER_API_DECLARATIVE_RULES_REGISTRY_H__
|