Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(687)

Side by Side Diff: chrome/browser/extensions/api/declarative/rules_registry.cc

Issue 49693003: Refactor RulesRegistryWithCache to RulesRegistry (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Similarity matching Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/declarative/rules_registry_with_cache.h" 5 #include "chrome/browser/extensions/api/declarative/rules_registry.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h" 9 #include "base/message_loop/message_loop.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 #include "base/strings/stringprintf.h" 11 #include "base/strings/stringprintf.h"
12 #include "base/time/time.h" 12 #include "base/time/time.h"
13 #include "base/values.h" 13 #include "base/values.h"
14 #include "chrome/browser/chrome_notification_types.h" 14 #include "chrome/browser/chrome_notification_types.h"
15 #include "chrome/browser/extensions/api/declarative/rules_cache_delegate.h"
15 #include "chrome/browser/extensions/extension_info_map.h" 16 #include "chrome/browser/extensions/extension_info_map.h"
16 #include "chrome/browser/extensions/extension_prefs.h" 17 #include "chrome/browser/extensions/extension_prefs.h"
17 #include "chrome/browser/extensions/extension_service.h" 18 #include "chrome/browser/extensions/extension_service.h"
18 #include "chrome/browser/extensions/extension_system.h" 19 #include "chrome/browser/extensions/extension_system.h"
19 #include "chrome/browser/extensions/extension_util.h" 20 #include "chrome/browser/extensions/extension_util.h"
20 #include "chrome/browser/extensions/state_store.h" 21 #include "chrome/browser/extensions/state_store.h"
21 #include "chrome/browser/profiles/profile.h" 22 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/common/extensions/extension.h" 23 #include "chrome/common/extensions/extension.h"
23 #include "content/public/browser/browser_thread.h" 24 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/notification_details.h" 25 #include "content/public/browser/notification_details.h"
(...skipping 27 matching lines...) Expand all
52 continue; 53 continue;
53 linked_ptr<extensions::RulesRegistry::Rule> rule( 54 linked_ptr<extensions::RulesRegistry::Rule> rule(
54 new extensions::RulesRegistry::Rule()); 55 new extensions::RulesRegistry::Rule());
55 if (extensions::RulesRegistry::Rule::Populate(*dict, rule.get())) 56 if (extensions::RulesRegistry::Rule::Populate(*dict, rule.get()))
56 rules.push_back(rule); 57 rules.push_back(rule);
57 } 58 }
58 59
59 return rules; 60 return rules;
60 } 61 }
61 62
62 // Returns the key to use for storing declarative rules in the state store. 63 std::string ToId(int identifier) {
63 std::string GetDeclarativeRuleStorageKey(const std::string& event_name, 64 return base::StringPrintf("_%d_", identifier);
64 bool incognito) {
65 if (incognito)
66 return "declarative_rules.incognito." + event_name;
67 else
68 return "declarative_rules." + event_name;
69 } 65 }
70 66
71 } // namespace 67 } // namespace
72 68
73 69
74 namespace extensions { 70 namespace extensions {
75 71
76 // RulesRegistryWithCache 72 // RulesRegistry
77 73
78 RulesRegistryWithCache::RulesRegistryWithCache( 74 RulesRegistry::RulesRegistry(
79 Profile* profile, 75 Profile* profile,
80 const std::string& event_name, 76 const std::string& event_name,
81 content::BrowserThread::ID owner_thread, 77 content::BrowserThread::ID owner_thread,
82 bool log_storage_init_delay, 78 bool log_storage_init_delay,
83 scoped_ptr<RuleStorageOnUI>* ui_part) 79 scoped_ptr<RulesCacheDelegate>* ui_part)
84 : RulesRegistry(owner_thread, event_name), 80 : owner_thread_(owner_thread),
81 event_name_(event_name),
85 weak_ptr_factory_(profile ? this : NULL), 82 weak_ptr_factory_(profile ? this : NULL),
86 storage_on_ui_( 83 cache_delegate_(
87 (profile ? (new RuleStorageOnUI(profile, 84 (profile ? (new RulesCacheDelegate(profile,
88 event_name, 85 event_name,
89 owner_thread, 86 owner_thread,
90 weak_ptr_factory_.GetWeakPtr(), 87 weak_ptr_factory_.GetWeakPtr(),
91 log_storage_init_delay))->GetWeakPtr() 88 log_storage_init_delay))->GetWeakPtr()
92 : base::WeakPtr<RuleStorageOnUI>())), 89 : base::WeakPtr<RulesCacheDelegate>())),
93 process_changed_rules_requested_(profile ? NOT_SCHEDULED_FOR_PROCESSING 90 process_changed_rules_requested_(profile ? NOT_SCHEDULED_FOR_PROCESSING
94 : NEVER_PROCESS) { 91 : NEVER_PROCESS),
92 last_generated_rule_identifier_id_(0) {
95 if (!profile) { 93 if (!profile) {
96 CHECK(!ui_part); 94 CHECK(!ui_part);
97 return; 95 return;
98 } 96 }
99 97
100 ui_part->reset(storage_on_ui_.get()); 98 ui_part->reset(cache_delegate_.get());
101 99
102 storage_on_ui_->Init(); 100 cache_delegate_->Init();
103 } 101 }
104 102
105 std::string RulesRegistryWithCache::AddRules( 103 std::string RulesRegistry::AddRules(
106 const std::string& extension_id, 104 const std::string& extension_id,
107 const std::vector<linked_ptr<Rule> >& rules) { 105 const std::vector<linked_ptr<Rule> >& rules) {
108 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); 106 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
109 107
108 std::string error = CheckAndFillInOptionalRules(extension_id, rules);
Jeffrey Yasskin 2013/10/30 22:30:48 This is probably fine, but note that, now that Ini
Fady Samuel 2013/10/31 14:02:24 OK. This is one time operation on browser startup
vabr (Chromium) 2013/10/31 16:35:05 Actually, the start-up time is a critical point. W
109 if (!error.empty())
110 return error;
111 FillInOptionalPriorities(rules);
112
110 // Verify that all rule IDs are new. 113 // Verify that all rule IDs are new.
111 for (std::vector<linked_ptr<Rule> >::const_iterator i = 114 for (std::vector<linked_ptr<Rule> >::const_iterator i =
112 rules.begin(); i != rules.end(); ++i) { 115 rules.begin(); i != rules.end(); ++i) {
113 const RuleId& rule_id = *((*i)->id); 116 const RuleId& rule_id = *((*i)->id);
114 RulesDictionaryKey key(extension_id, rule_id); 117 RulesDictionaryKey key(extension_id, rule_id);
115 if (rules_.find(key) != rules_.end()) 118 if (rules_.find(key) != rules_.end())
116 return base::StringPrintf(kDuplicateRuleId, rule_id.c_str()); 119 return base::StringPrintf(kDuplicateRuleId, rule_id.c_str());
117 } 120 }
118 121
119 std::string error = AddRulesImpl(extension_id, rules); 122 error = AddRulesImpl(extension_id, rules);
120 123
121 if (!error.empty()) 124 if (!error.empty())
122 return error; 125 return error;
123 126
124 // Commit all rules into |rules_| on success. 127 // Commit all rules into |rules_| on success.
125 for (std::vector<linked_ptr<Rule> >::const_iterator i = 128 for (std::vector<linked_ptr<Rule> >::const_iterator i =
126 rules.begin(); i != rules.end(); ++i) { 129 rules.begin(); i != rules.end(); ++i) {
127 const RuleId& rule_id = *((*i)->id); 130 const RuleId& rule_id = *((*i)->id);
128 RulesDictionaryKey key(extension_id, rule_id); 131 RulesDictionaryKey key(extension_id, rule_id);
129 rules_[key] = *i; 132 rules_[key] = *i;
130 } 133 }
131 134
132 MaybeProcessChangedRules(extension_id); 135 MaybeProcessChangedRules(extension_id);
133 return kSuccess; 136 return kSuccess;
134 } 137 }
135 138
136 std::string RulesRegistryWithCache::RemoveRules( 139 std::string RulesRegistry::RemoveRules(
137 const std::string& extension_id, 140 const std::string& extension_id,
138 const std::vector<std::string>& rule_identifiers) { 141 const std::vector<std::string>& rule_identifiers) {
139 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); 142 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
140 143
141 std::string error = RemoveRulesImpl(extension_id, rule_identifiers); 144 std::string error = RemoveRulesImpl(extension_id, rule_identifiers);
142 145
143 if (!error.empty()) 146 if (!error.empty())
144 return error; 147 return error;
145 148
146 // Commit removal of rules from |rules_| on success. 149 // Commit removal of rules from |rules_| on success.
147 for (std::vector<std::string>::const_iterator i = 150 for (std::vector<std::string>::const_iterator i =
148 rule_identifiers.begin(); i != rule_identifiers.end(); ++i) { 151 rule_identifiers.begin(); i != rule_identifiers.end(); ++i) {
149 RulesDictionaryKey lookup_key(extension_id, *i); 152 RulesDictionaryKey lookup_key(extension_id, *i);
150 rules_.erase(lookup_key); 153 rules_.erase(lookup_key);
151 } 154 }
152 155
153 MaybeProcessChangedRules(extension_id); 156 MaybeProcessChangedRules(extension_id);
157 RemoveUsedRuleIdentifiers(extension_id, rule_identifiers);
154 return kSuccess; 158 return kSuccess;
155 } 159 }
156 160
157 std::string RulesRegistryWithCache::RemoveAllRules( 161 std::string RulesRegistry::RemoveAllRules(const std::string& extension_id) {
158 const std::string& extension_id) {
159 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); 162 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
160 163
161 std::string error = RemoveAllRulesImpl(extension_id); 164 std::string error = RemoveAllRulesImpl(extension_id);
162 165
163 if (!error.empty()) 166 if (!error.empty())
164 return error; 167 return error;
165 168
166 // Commit removal of rules from |rules_| on success. 169 // Commit removal of rules from |rules_| on success.
167 for (RulesDictionary::const_iterator i = rules_.begin(); 170 for (RulesDictionary::const_iterator i = rules_.begin();
168 i != rules_.end();) { 171 i != rules_.end();) {
169 const RulesDictionaryKey& key = i->first; 172 const RulesDictionaryKey& key = i->first;
170 ++i; 173 ++i;
171 if (key.first == extension_id) 174 if (key.first == extension_id)
172 rules_.erase(key); 175 rules_.erase(key);
173 } 176 }
174 177
175 MaybeProcessChangedRules(extension_id); 178 MaybeProcessChangedRules(extension_id);
179 RemoveAllUsedRuleIdentifiers(extension_id);
176 return kSuccess; 180 return kSuccess;
177 } 181 }
178 182
179 std::string RulesRegistryWithCache::GetRules( 183 std::string RulesRegistry::GetRules(
180 const std::string& extension_id, 184 const std::string& extension_id,
181 const std::vector<std::string>& rule_identifiers, 185 const std::vector<std::string>& rule_identifiers,
182 std::vector<linked_ptr<RulesRegistry::Rule> >* out) { 186 std::vector<linked_ptr<RulesRegistry::Rule> >* out) {
183 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); 187 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
184 188
185 for (std::vector<std::string>::const_iterator i = rule_identifiers.begin(); 189 for (std::vector<std::string>::const_iterator i = rule_identifiers.begin();
186 i != rule_identifiers.end(); ++i) { 190 i != rule_identifiers.end(); ++i) {
187 RulesDictionaryKey lookup_key(extension_id, *i); 191 RulesDictionaryKey lookup_key(extension_id, *i);
188 RulesDictionary::iterator entry = rules_.find(lookup_key); 192 RulesDictionary::iterator entry = rules_.find(lookup_key);
189 if (entry != rules_.end()) 193 if (entry != rules_.end())
190 out->push_back(entry->second); 194 out->push_back(entry->second);
191 } 195 }
192 return kSuccess; 196 return kSuccess;
193 } 197 }
194 198
195 std::string RulesRegistryWithCache::GetAllRules( 199 std::string RulesRegistry::GetAllRules(
196 const std::string& extension_id, 200 const std::string& extension_id,
197 std::vector<linked_ptr<RulesRegistry::Rule> >* out) { 201 std::vector<linked_ptr<RulesRegistry::Rule> >* out) {
198 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); 202 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
199 203
200 for (RulesDictionary::const_iterator i = rules_.begin(); 204 for (RulesDictionary::const_iterator i = rules_.begin();
201 i != rules_.end(); ++i) { 205 i != rules_.end(); ++i) {
202 const RulesDictionaryKey& key = i->first; 206 const RulesDictionaryKey& key = i->first;
203 if (key.first == extension_id) 207 if (key.first == extension_id)
204 out->push_back(i->second); 208 out->push_back(i->second);
205 } 209 }
206 return kSuccess; 210 return kSuccess;
207 } 211 }
208 212
209 void RulesRegistryWithCache::OnExtensionUnloaded( 213 void RulesRegistry::OnExtensionUnloaded(const std::string& extension_id) {
210 const std::string& extension_id) {
211 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); 214 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
212 std::string error = RemoveAllRules(extension_id); 215 std::string error = RemoveAllRules(extension_id);
213 if (!error.empty()) 216 if (!error.empty())
214 LOG(ERROR) << error; 217 LOG(ERROR) << error;
218 used_rule_identifiers_.erase(extension_id);
215 } 219 }
216 220
217 RulesRegistryWithCache::~RulesRegistryWithCache() { 221 size_t RulesRegistry::GetNumberOfUsedRuleIdentifiersForTesting() const {
222 size_t entry_count = 0u;
223 for (RuleIdentifiersMap::const_iterator extension =
224 used_rule_identifiers_.begin();
225 extension != used_rule_identifiers_.end();
226 ++extension) {
227 // Each extension is counted as 1 just for being there. Otherwise we miss
228 // keys with empty values.
229 entry_count += 1u + extension->second.size();
230 }
231 return entry_count;
218 } 232 }
219 233
220 void RulesRegistryWithCache::MarkReady(base::Time storage_init_time) { 234 RulesRegistry::~RulesRegistry() {
235 }
236
237 void RulesRegistry::MarkReady(base::Time storage_init_time) {
221 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); 238 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
222 239
223 if (!storage_init_time.is_null()) { 240 if (!storage_init_time.is_null()) {
224 UMA_HISTOGRAM_TIMES("Extensions.DeclarativeRulesStorageInitialization", 241 UMA_HISTOGRAM_TIMES("Extensions.DeclarativeRulesStorageInitialization",
225 base::Time::Now() - storage_init_time); 242 base::Time::Now() - storage_init_time);
226 } 243 }
227 244
228 ready_.Signal(); 245 ready_.Signal();
229 } 246 }
230 247
231 void RulesRegistryWithCache::DeserializeAndAddRules( 248 void RulesRegistry::DeserializeAndAddRules(
232 const std::string& extension_id, 249 const std::string& extension_id,
233 scoped_ptr<base::Value> rules) { 250 scoped_ptr<base::Value> rules) {
234 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); 251 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
235 252
236 AddRules(extension_id, RulesFromValue(rules.get())); 253 AddRules(extension_id, RulesFromValue(rules.get()));
237 } 254 }
238 255
239 void RulesRegistryWithCache::ProcessChangedRules( 256 void RulesRegistry::ProcessChangedRules(const std::string& extension_id) {
240 const std::string& extension_id) {
241 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); 257 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
242 258
243 process_changed_rules_requested_ = NOT_SCHEDULED_FOR_PROCESSING; 259 process_changed_rules_requested_ = NOT_SCHEDULED_FOR_PROCESSING;
244 260
245 std::vector<linked_ptr<RulesRegistry::Rule> > new_rules; 261 std::vector<linked_ptr<RulesRegistry::Rule> > new_rules;
246 std::string error = GetAllRules(extension_id, &new_rules); 262 std::string error = GetAllRules(extension_id, &new_rules);
247 DCHECK_EQ(std::string(), error); 263 DCHECK_EQ(std::string(), error);
248 content::BrowserThread::PostTask( 264 content::BrowserThread::PostTask(
249 content::BrowserThread::UI, 265 content::BrowserThread::UI,
250 FROM_HERE, 266 FROM_HERE,
251 base::Bind(&RuleStorageOnUI::WriteToStorage, 267 base::Bind(&RulesCacheDelegate::WriteToStorage,
252 storage_on_ui_, 268 cache_delegate_,
253 extension_id, 269 extension_id,
254 base::Passed(RulesToValue(new_rules)))); 270 base::Passed(RulesToValue(new_rules))));
255 } 271 }
256 272
257 void RulesRegistryWithCache::MaybeProcessChangedRules( 273 void RulesRegistry::MaybeProcessChangedRules(const std::string& extension_id) {
258 const std::string& extension_id) {
259 if (process_changed_rules_requested_ != NOT_SCHEDULED_FOR_PROCESSING) 274 if (process_changed_rules_requested_ != NOT_SCHEDULED_FOR_PROCESSING)
260 return; 275 return;
261 276
262 process_changed_rules_requested_ = SCHEDULED_FOR_PROCESSING; 277 process_changed_rules_requested_ = SCHEDULED_FOR_PROCESSING;
263 ready_.Post(FROM_HERE, 278 ready_.Post(FROM_HERE,
264 base::Bind(&RulesRegistryWithCache::ProcessChangedRules, 279 base::Bind(&RulesRegistry::ProcessChangedRules,
265 weak_ptr_factory_.GetWeakPtr(), 280 weak_ptr_factory_.GetWeakPtr(),
266 extension_id)); 281 extension_id));
267 } 282 }
268 283
269 // RulesRegistryWithCache::RuleStorageOnUI 284 bool RulesRegistry::IsUniqueId(const std::string& extension_id,
270 285 const std::string& rule_id) const {
271 const char RulesRegistryWithCache::RuleStorageOnUI::kRulesStoredKey[] = 286 RuleIdentifiersMap::const_iterator identifiers =
272 "has_declarative_rules"; 287 used_rule_identifiers_.find(extension_id);
273 288 if (identifiers == used_rule_identifiers_.end())
274 RulesRegistryWithCache::RuleStorageOnUI::RuleStorageOnUI( 289 return true;
275 Profile* profile, 290 return identifiers->second.find(rule_id) == identifiers->second.end();
276 const std::string& event_name,
277 content::BrowserThread::ID rules_registry_thread,
278 base::WeakPtr<RulesRegistryWithCache> registry,
279 bool log_storage_init_delay)
280 : profile_(profile),
281 storage_key_(GetDeclarativeRuleStorageKey(event_name,
282 profile->IsOffTheRecord())),
283 rules_stored_key_(GetRulesStoredKey(event_name,
284 profile->IsOffTheRecord())),
285 log_storage_init_delay_(log_storage_init_delay),
286 registry_(registry),
287 rules_registry_thread_(rules_registry_thread),
288 notified_registry_(false),
289 weak_ptr_factory_(this) {}
290
291 RulesRegistryWithCache::RuleStorageOnUI::~RuleStorageOnUI() {}
292
293 // Returns the key to use for storing whether the rules have been stored.
294 // static
295 std::string RulesRegistryWithCache::RuleStorageOnUI::GetRulesStoredKey(
296 const std::string& event_name,
297 bool incognito) {
298 std::string result(kRulesStoredKey);
299 result += incognito ? ".incognito." : ".";
300 return result + event_name;
301 } 291 }
302 292
303 // This is called from the constructor of RulesRegistryWithCache, so it is 293 std::string RulesRegistry::GenerateUniqueId(const std::string& extension_id) {
304 // important that it both 294 while (!IsUniqueId(extension_id, ToId(last_generated_rule_identifier_id_)))
305 // 1. calls no (in particular virtual) methods of the rules registry, and 295 ++last_generated_rule_identifier_id_;
306 // 2. does not create scoped_refptr holding the registry. (A short-lived 296 return ToId(last_generated_rule_identifier_id_);
307 // scoped_refptr might delete the rules registry before it is constructed.)
308 void RulesRegistryWithCache::RuleStorageOnUI::Init() {
309 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
310
311 ExtensionSystem& system = *ExtensionSystem::Get(profile_);
312 extensions::StateStore* store = system.rules_store();
313 if (store)
314 store->RegisterKey(storage_key_);
315
316 registrar_.Add(this,
317 chrome::NOTIFICATION_EXTENSION_LOADED,
318 content::Source<Profile>(profile_->GetOriginalProfile()));
319
320 if (profile_->IsOffTheRecord())
321 log_storage_init_delay_ = false;
322
323 system.ready().Post(
324 FROM_HERE,
325 base::Bind(&RuleStorageOnUI::ReadRulesForInstalledExtensions,
326 GetWeakPtr()));
327 system.ready().Post(FROM_HERE,
328 base::Bind(&RuleStorageOnUI::CheckIfReady, GetWeakPtr()));
329 } 297 }
330 298
331 void RulesRegistryWithCache::RuleStorageOnUI::WriteToStorage( 299 std::string RulesRegistry::CheckAndFillInOptionalRules(
332 const std::string& extension_id, 300 const std::string& extension_id,
333 scoped_ptr<base::Value> value) { 301 const std::vector<linked_ptr<RulesRegistry::Rule> >& rules) {
334 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 302 // IDs we have inserted, in case we need to rollback this operation.
335 if (!profile_) 303 std::vector<std::string> rollback_log;
336 return;
337 304
338 const base::ListValue* rules = NULL; 305 // First we insert all rules with existing identifier, so that generated
339 CHECK(value->GetAsList(&rules)); 306 // identifiers cannot collide with identifiers passed by the caller.
340 bool rules_stored_previously = GetDeclarativeRulesStored(extension_id); 307 for (std::vector<linked_ptr<RulesRegistry::Rule> >::const_iterator i =
341 bool store_rules = !rules->empty(); 308 rules.begin(); i != rules.end(); ++i) {
342 SetDeclarativeRulesStored(extension_id, store_rules); 309 RulesRegistry::Rule* rule = i->get();
343 if (!rules_stored_previously && !store_rules) 310 if (rule->id.get()) {
344 return; 311 std::string id = *(rule->id);
345 312 if (!IsUniqueId(extension_id, id)) {
346 StateStore* store = ExtensionSystem::Get(profile_)->rules_store(); 313 RemoveUsedRuleIdentifiers(extension_id, rollback_log);
347 if (store) 314 return "Id " + id + " was used multiple times.";
348 store->SetExtensionValue(extension_id, storage_key_, value.Pass()); 315 }
316 used_rule_identifiers_[extension_id].insert(id);
317 }
318 }
319 // Now we generate IDs in case they were not specificed in the rules. This
Jeffrey Yasskin 2013/10/30 22:30:48 sp: specificed
Fady Samuel 2013/10/31 14:02:24 Done.
320 // cannot fail so we do not need to keep track of a rollback log.
321 for (std::vector<linked_ptr<RulesRegistry::Rule> >::const_iterator i =
322 rules.begin(); i != rules.end(); ++i) {
323 RulesRegistry::Rule* rule = i->get();
324 if (!rule->id.get()) {
325 rule->id.reset(new std::string(GenerateUniqueId(extension_id)));
326 used_rule_identifiers_[extension_id].insert(*(rule->id));
327 }
328 }
329 return std::string();
349 } 330 }
350 331
351 void RulesRegistryWithCache::RuleStorageOnUI::Observe( 332 void RulesRegistry::FillInOptionalPriorities(
352 int type, 333 const std::vector<linked_ptr<RulesRegistry::Rule> >& rules) {
353 const content::NotificationSource& source, 334 std::vector<linked_ptr<RulesRegistry::Rule> >::const_iterator i;
354 const content::NotificationDetails& details) { 335 for (i = rules.begin(); i != rules.end(); ++i) {
355 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 336 if (!(*i)->priority.get())
356 DCHECK(type == chrome::NOTIFICATION_EXTENSION_LOADED); 337 (*i)->priority.reset(new int(DEFAULT_PRIORITY));
357
358 const extensions::Extension* extension =
359 content::Details<const extensions::Extension>(details).ptr();
360 // TODO(mpcomplete): This API check should generalize to any use of
361 // declarative rules, not just webRequest.
362 if (extension->HasAPIPermission(APIPermission::kDeclarativeContent) ||
363 extension->HasAPIPermission(APIPermission::kDeclarativeWebRequest)) {
364 ExtensionInfoMap* extension_info_map =
365 ExtensionSystem::Get(profile_)->info_map();
366 if (profile_->IsOffTheRecord() &&
367 !extension_info_map->IsIncognitoEnabled(extension->id())) {
368 // Ignore this extension.
369 } else {
370 ReadFromStorage(extension->id());
371 }
372 } 338 }
373 } 339 }
374 340
375 void RulesRegistryWithCache::RuleStorageOnUI::CheckIfReady() { 341 void RulesRegistry::RemoveUsedRuleIdentifiers(
376 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 342 const std::string& extension_id,
377 if (notified_registry_ || !waiting_for_extensions_.empty()) 343 const std::vector<std::string>& identifiers) {
378 return; 344 std::vector<std::string>::const_iterator i;
379 345 for (i = identifiers.begin(); i != identifiers.end(); ++i)
380 content::BrowserThread::PostTask( 346 used_rule_identifiers_[extension_id].erase(*i);
381 rules_registry_thread_,
382 FROM_HERE,
383 base::Bind(
384 &RulesRegistryWithCache::MarkReady, registry_, storage_init_time_));
385 notified_registry_ = true;
386 } 347 }
387 348
388 void 349 void RulesRegistry::RemoveAllUsedRuleIdentifiers(
389 RulesRegistryWithCache::RuleStorageOnUI::ReadRulesForInstalledExtensions() {
390 ExtensionSystem& system = *ExtensionSystem::Get(profile_);
391 ExtensionService* extension_service = system.extension_service();
392 DCHECK(extension_service);
393 // In an OTR profile, we start on top of a normal profile already, so the
394 // extension service should be ready.
395 DCHECK(!profile_->IsOffTheRecord() || extension_service->is_ready());
396 if (extension_service->is_ready()) {
397 const ExtensionSet* extensions = extension_service->extensions();
398 for (ExtensionSet::const_iterator i = extensions->begin();
399 i != extensions->end();
400 ++i) {
401 bool needs_apis_storing_rules =
402 (*i)->HasAPIPermission(APIPermission::kDeclarativeContent) ||
403 (*i)->HasAPIPermission(APIPermission::kDeclarativeWebRequest);
404 bool respects_off_the_record =
405 !(profile_->IsOffTheRecord()) ||
406 extension_util::IsIncognitoEnabled((*i)->id(), extension_service);
407 if (needs_apis_storing_rules && respects_off_the_record)
408 ReadFromStorage((*i)->id());
409 }
410 }
411 }
412
413 void RulesRegistryWithCache::RuleStorageOnUI::ReadFromStorage(
414 const std::string& extension_id) { 350 const std::string& extension_id) {
415 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 351 used_rule_identifiers_.erase(extension_id);
416 if (!profile_)
417 return;
418
419 if (log_storage_init_delay_ && storage_init_time_.is_null())
420 storage_init_time_ = base::Time::Now();
421
422 if (!GetDeclarativeRulesStored(extension_id)) {
423 ExtensionSystem::Get(profile_)->ready().Post(
424 FROM_HERE, base::Bind(&RuleStorageOnUI::CheckIfReady, GetWeakPtr()));
425 return;
426 }
427
428 extensions::StateStore* store = ExtensionSystem::Get(profile_)->rules_store();
429 if (!store)
430 return;
431 waiting_for_extensions_.insert(extension_id);
432 store->GetExtensionValue(extension_id,
433 storage_key_,
434 base::Bind(&RuleStorageOnUI::ReadFromStorageCallback,
435 weak_ptr_factory_.GetWeakPtr(),
436 extension_id));
437 }
438
439 void RulesRegistryWithCache::RuleStorageOnUI::ReadFromStorageCallback(
440 const std::string& extension_id,
441 scoped_ptr<base::Value> value) {
442 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
443 content::BrowserThread::PostTask(
444 rules_registry_thread_,
445 FROM_HERE,
446 base::Bind(&RulesRegistryWithCache::DeserializeAndAddRules,
447 registry_,
448 extension_id,
449 base::Passed(&value)));
450
451 waiting_for_extensions_.erase(extension_id);
452
453 if (waiting_for_extensions_.empty())
454 ExtensionSystem::Get(profile_)->ready().Post(
455 FROM_HERE, base::Bind(&RuleStorageOnUI::CheckIfReady, GetWeakPtr()));
456 }
457
458 bool RulesRegistryWithCache::RuleStorageOnUI::GetDeclarativeRulesStored(
459 const std::string& extension_id) const {
460 CHECK(profile_);
461 const ExtensionScopedPrefs* extension_prefs = ExtensionPrefs::Get(profile_);
462
463 bool rules_stored = true;
464 if (extension_prefs->ReadPrefAsBoolean(
465 extension_id, rules_stored_key_, &rules_stored))
466 return rules_stored;
467
468 // Safe default -- if we don't know that the rules are not stored, we force
469 // a read by returning true.
470 return true;
471 }
472
473 void RulesRegistryWithCache::RuleStorageOnUI::SetDeclarativeRulesStored(
474 const std::string& extension_id,
475 bool rules_stored) {
476 CHECK(profile_);
477 ExtensionScopedPrefs* extension_prefs = ExtensionPrefs::Get(profile_);
478 extension_prefs->UpdateExtensionPref(
479 extension_id,
480 rules_stored_key_,
481 new base::FundamentalValue(rules_stored));
482 } 352 }
483 353
484 } // namespace extensions 354 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698