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
|
// 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 CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_RULES_REGISTRY_H__
#define CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_RULES_REGISTRY_H__
#include "chrome/browser/extensions/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 "chrome/common/extensions/api/events.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/one_shot_event.h"
class Profile;
namespace base {
class Value;
} // namespace base
namespace extensions {
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::api::events::Rule Rule;
struct WebViewKey {
int embedder_process_id;
int webview_instance_id;
WebViewKey(int embedder_process_id, int webview_instance_id)
: embedder_process_id(embedder_process_id),
webview_instance_id(webview_instance_id) {}
bool operator<(const WebViewKey& other) const {
return embedder_process_id < other.embedder_process_id ||
((embedder_process_id == other.embedder_process_id) &&
(webview_instance_id < other.webview_instance_id));
}
};
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, |profile| and |ui_part| can be NULL (at the same time). In that
// case the storage functionality disabled (no RulesCacheDelegate object
// created).
RulesRegistry(Profile* profile,
const std::string& event_name,
content::BrowserThread::ID owner_thread,
RulesCacheDelegate* cache_delegate,
const WebViewKey& webview_key);
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 std::string& extension_id);
void OnExtensionUninstalled(const std::string& extension_id);
void OnExtensionLoaded(const std::string& extension_id);
// 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 profile where the rules registry lives.
Profile* profile() const { return profile_; }
// 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 key that identifies the webview (or tabs) in which these rules apply.
// If the rules apply to the main browser, then this returns the tuple (0, 0).
const WebViewKey& webview_key() const {
return webview_key_;
}
protected:
virtual ~RulesRegistry();
// 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);
// 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(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
return weak_ptr_factory_.GetWeakPtr();
}
// 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.
std::string RemoveAllRulesNoStoreUpdate(const std::string& extension_id);
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 profile to which this rules registry belongs.
Profile* profile_;
// 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.
WebViewKey webview_key_;
RulesDictionary rules_;
// Signaled when we have finished reading from storage for all extensions that
// are loaded on startup.
OneShotEvent ready_;
// The factory needs to be declared before |cache_delegate_|, so that it can
// produce a pointer as a construction argument for |cache_delegate_|.
base::WeakPtrFactory<RulesRegistry> weak_ptr_factory_;
// |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_;
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_;
DISALLOW_COPY_AND_ASSIGN(RulesRegistry);
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_RULES_REGISTRY_H__
|