OLD | NEW |
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_with_cache.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.h" | 9 #include "base/message_loop.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 24 matching lines...) Expand all Loading... |
35 } | 35 } |
36 | 36 |
37 std::vector<linked_ptr<extensions::RulesRegistry::Rule> > RulesFromValue( | 37 std::vector<linked_ptr<extensions::RulesRegistry::Rule> > RulesFromValue( |
38 const base::Value* value) { | 38 const base::Value* value) { |
39 std::vector<linked_ptr<extensions::RulesRegistry::Rule> > rules; | 39 std::vector<linked_ptr<extensions::RulesRegistry::Rule> > rules; |
40 | 40 |
41 const base::ListValue* list = NULL; | 41 const base::ListValue* list = NULL; |
42 if (!value || !value->GetAsList(&list)) | 42 if (!value || !value->GetAsList(&list)) |
43 return rules; | 43 return rules; |
44 | 44 |
| 45 rules.reserve(list->GetSize()); |
45 for (size_t i = 0; i < list->GetSize(); ++i) { | 46 for (size_t i = 0; i < list->GetSize(); ++i) { |
46 const base::DictionaryValue* dict = NULL; | 47 const base::DictionaryValue* dict = NULL; |
47 if (!list->GetDictionary(i, &dict)) | 48 if (!list->GetDictionary(i, &dict)) |
48 continue; | 49 continue; |
49 linked_ptr<extensions::RulesRegistry::Rule> rule( | 50 linked_ptr<extensions::RulesRegistry::Rule> rule( |
50 new extensions::RulesRegistry::Rule()); | 51 new extensions::RulesRegistry::Rule()); |
51 if (extensions::RulesRegistry::Rule::Populate(*dict, rule.get())) | 52 if (extensions::RulesRegistry::Rule::Populate(*dict, rule.get())) |
52 rules.push_back(rule); | 53 rules.push_back(rule); |
53 } | 54 } |
54 | 55 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 } | 105 } |
105 | 106 |
106 void RulesRegistryWithCache::AddReadyCallback(const base::Closure& callback) { | 107 void RulesRegistryWithCache::AddReadyCallback(const base::Closure& callback) { |
107 ready_callbacks_.push_back(callback); | 108 ready_callbacks_.push_back(callback); |
108 } | 109 } |
109 | 110 |
110 std::string RulesRegistryWithCache::AddRules( | 111 std::string RulesRegistryWithCache::AddRules( |
111 const std::string& extension_id, | 112 const std::string& extension_id, |
112 const std::vector<linked_ptr<Rule> >& rules) { | 113 const std::vector<linked_ptr<Rule> >& rules) { |
113 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); | 114 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); |
| 115 RulesDictionary& current_rules = rules_[extension_id]; |
114 | 116 |
115 // Verify that all rule IDs are new. | 117 // Verify that all rule IDs are new. |
116 for (std::vector<linked_ptr<Rule> >::const_iterator i = | 118 for (std::vector<linked_ptr<Rule> >::const_iterator i = |
117 rules.begin(); i != rules.end(); ++i) { | 119 rules.begin(); i != rules.end(); ++i) { |
118 const RuleId& rule_id = *((*i)->id); | 120 const RuleId& rule_id = *((*i)->id); |
119 RulesDictionaryKey key(extension_id, rule_id); | 121 if (current_rules.find(rule_id) != current_rules.end()) |
120 if (rules_.find(key) != rules_.end()) | |
121 return base::StringPrintf(kDuplicateRuleId, rule_id.c_str()); | 122 return base::StringPrintf(kDuplicateRuleId, rule_id.c_str()); |
122 } | 123 } |
123 | 124 |
124 std::string error = AddRulesImpl(extension_id, rules); | 125 std::string error = AddRulesImpl(extension_id, rules); |
125 | 126 |
126 if (!error.empty()) | 127 if (!error.empty()) |
127 return error; | 128 return error; |
128 | 129 |
129 // Commit all rules into |rules_| on success. | 130 // Commit all rules into |rules_| on success. |
130 for (std::vector<linked_ptr<Rule> >::const_iterator i = | 131 for (std::vector<linked_ptr<Rule> >::const_iterator i = |
131 rules.begin(); i != rules.end(); ++i) { | 132 rules.begin(); i != rules.end(); ++i) { |
132 const RuleId& rule_id = *((*i)->id); | 133 const RuleId& rule_id = *((*i)->id); |
133 RulesDictionaryKey key(extension_id, rule_id); | 134 current_rules[rule_id] = *i; |
134 rules_[key] = *i; | |
135 } | 135 } |
136 | 136 |
137 ProcessChangedRules(extension_id); | 137 ProcessChangedRules(extension_id); |
138 return kSuccess; | 138 return kSuccess; |
139 } | 139 } |
140 | 140 |
141 std::string RulesRegistryWithCache::RemoveRules( | 141 std::string RulesRegistryWithCache::RemoveRules( |
142 const std::string& extension_id, | 142 const std::string& extension_id, |
143 const std::vector<std::string>& rule_identifiers) { | 143 const std::vector<std::string>& rule_identifiers) { |
144 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); | 144 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); |
145 | 145 |
146 std::string error = RemoveRulesImpl(extension_id, rule_identifiers); | 146 std::string error = RemoveRulesImpl(extension_id, rule_identifiers); |
147 | 147 |
148 if (!error.empty()) | 148 if (!error.empty()) |
149 return error; | 149 return error; |
150 | 150 |
151 // Commit removal of rules from |rules_| on success. | 151 // Commit removal of rules from |rules_| on success. |
| 152 RulesDictionary& current_rules = rules_[extension_id]; |
152 for (std::vector<std::string>::const_iterator i = | 153 for (std::vector<std::string>::const_iterator i = |
153 rule_identifiers.begin(); i != rule_identifiers.end(); ++i) { | 154 rule_identifiers.begin(); i != rule_identifiers.end(); ++i) { |
154 RulesDictionaryKey lookup_key(extension_id, *i); | 155 current_rules.erase(*i); |
155 rules_.erase(lookup_key); | |
156 } | 156 } |
| 157 if (current_rules.empty()) |
| 158 rules_.erase(extension_id); |
157 | 159 |
158 ProcessChangedRules(extension_id); | 160 ProcessChangedRules(extension_id); |
159 return kSuccess; | 161 return kSuccess; |
160 } | 162 } |
161 | 163 |
162 std::string RulesRegistryWithCache::RemoveAllRules( | 164 std::string RulesRegistryWithCache::RemoveAllRules( |
163 const std::string& extension_id) { | 165 const std::string& extension_id) { |
164 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); | 166 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); |
165 | 167 |
166 std::string error = RemoveAllRulesImpl(extension_id); | 168 std::string error = RemoveAllRulesImpl(extension_id); |
167 | 169 |
168 if (!error.empty()) | 170 if (!error.empty()) |
169 return error; | 171 return error; |
170 | 172 |
171 // Commit removal of rules from |rules_| on success. | 173 // Commit removal of rules from |rules_| on success. |
172 for (RulesDictionary::const_iterator i = rules_.begin(); | 174 rules_.erase(extension_id); |
173 i != rules_.end();) { | |
174 const RulesDictionaryKey& key = i->first; | |
175 ++i; | |
176 if (key.first == extension_id) | |
177 rules_.erase(key); | |
178 } | |
179 | 175 |
180 ProcessChangedRules(extension_id); | 176 ProcessChangedRules(extension_id); |
181 return kSuccess; | 177 return kSuccess; |
182 } | 178 } |
183 | 179 |
184 std::string RulesRegistryWithCache::GetRules( | 180 std::string RulesRegistryWithCache::GetRules( |
185 const std::string& extension_id, | 181 const std::string& extension_id, |
186 const std::vector<std::string>& rule_identifiers, | 182 const std::vector<std::string>& rule_identifiers, |
187 std::vector<linked_ptr<RulesRegistry::Rule> >* out) { | 183 std::vector<linked_ptr<RulesRegistry::Rule> >* out) { |
188 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); | 184 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); |
189 | 185 |
| 186 RulesDictionary& current_rules = rules_[extension_id]; |
190 for (std::vector<std::string>::const_iterator i = rule_identifiers.begin(); | 187 for (std::vector<std::string>::const_iterator i = rule_identifiers.begin(); |
191 i != rule_identifiers.end(); ++i) { | 188 i != rule_identifiers.end(); ++i) { |
192 RulesDictionaryKey lookup_key(extension_id, *i); | 189 RulesDictionary::iterator entry = current_rules.find(*i); |
193 RulesDictionary::iterator entry = rules_.find(lookup_key); | 190 if (entry != current_rules.end()) |
194 if (entry != rules_.end()) | |
195 out->push_back(entry->second); | 191 out->push_back(entry->second); |
196 } | 192 } |
197 return kSuccess; | 193 return kSuccess; |
198 } | 194 } |
199 | 195 |
200 std::string RulesRegistryWithCache::GetAllRules( | 196 std::string RulesRegistryWithCache::GetAllRules( |
201 const std::string& extension_id, | 197 const std::string& extension_id, |
202 std::vector<linked_ptr<RulesRegistry::Rule> >* out) { | 198 std::vector<linked_ptr<RulesRegistry::Rule> >* out) { |
203 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); | 199 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); |
204 | 200 |
205 for (RulesDictionary::const_iterator i = rules_.begin(); | 201 RulesDictionary& current_rules = rules_[extension_id]; |
206 i != rules_.end(); ++i) { | 202 out->reserve(out->size() + current_rules.size()); |
207 const RulesDictionaryKey& key = i->first; | 203 for (RulesDictionary::const_iterator i = current_rules.begin(); |
208 if (key.first == extension_id) | 204 i != current_rules.end(); ++i) { |
209 out->push_back(i->second); | 205 out->push_back(i->second); |
210 } | 206 } |
211 return kSuccess; | 207 return kSuccess; |
212 } | 208 } |
213 | 209 |
214 void RulesRegistryWithCache::OnExtensionUnloaded( | 210 void RulesRegistryWithCache::OnExtensionUnloaded( |
215 const std::string& extension_id) { | 211 const std::string& extension_id) { |
216 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); | 212 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); |
217 std::string error = RemoveAllRules(extension_id); | 213 std::string error = RemoveAllRules(extension_id); |
218 if (!error.empty()) | 214 if (!error.empty()) |
219 LOG(ERROR) << error; | 215 LOG(ERROR) << error; |
(...skipping 23 matching lines...) Expand all Loading... |
243 scoped_ptr<base::Value> rules) { | 239 scoped_ptr<base::Value> rules) { |
244 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); | 240 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); |
245 | 241 |
246 AddRules(extension_id, RulesFromValue(rules.get())); | 242 AddRules(extension_id, RulesFromValue(rules.get())); |
247 } | 243 } |
248 | 244 |
249 void RulesRegistryWithCache::ProcessChangedRules( | 245 void RulesRegistryWithCache::ProcessChangedRules( |
250 const std::string& extension_id) { | 246 const std::string& extension_id) { |
251 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); | 247 DCHECK(content::BrowserThread::CurrentlyOn(owner_thread())); |
252 | 248 |
253 std::vector<linked_ptr<RulesRegistry::Rule> > new_rules; | 249 scoped_ptr<RulesVector> new_rules(new RulesVector()); |
254 std::string error = GetAllRules(extension_id, &new_rules); | 250 std::string error = GetAllRules(extension_id, new_rules.get()); |
255 DCHECK_EQ(std::string(), error); | 251 DCHECK_EQ(std::string(), error); |
256 content::BrowserThread::PostTask( | 252 content::BrowserThread::PostTask( |
257 content::BrowserThread::UI, | 253 content::BrowserThread::UI, |
258 FROM_HERE, | 254 FROM_HERE, |
259 base::Bind(&RuleStorageOnUI::WriteToStorage, | 255 base::Bind(&RuleStorageOnUI::WriteToStorage, |
260 storage_on_ui_, | 256 storage_on_ui_, |
261 extension_id, | 257 extension_id, |
262 base::Passed(RulesToValue(new_rules)))); | 258 base::Passed(&new_rules))); |
263 } | 259 } |
264 | 260 |
265 // RulesRegistryWithCache::RuleStorageOnUI | 261 // RulesRegistryWithCache::RuleStorageOnUI |
266 | 262 |
267 RulesRegistryWithCache::RuleStorageOnUI::RuleStorageOnUI( | 263 RulesRegistryWithCache::RuleStorageOnUI::RuleStorageOnUI( |
268 Profile* profile, | 264 Profile* profile, |
269 const std::string& storage_key, | 265 const std::string& storage_key, |
270 content::BrowserThread::ID rules_registry_thread, | 266 content::BrowserThread::ID rules_registry_thread, |
271 base::WeakPtr<RulesRegistryWithCache> registry, | 267 base::WeakPtr<RulesRegistryWithCache> registry, |
272 bool log_storage_init_delay) | 268 bool log_storage_init_delay) |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 // can post tasks for the not-yet-initialized registry to run, we need to | 315 // can post tasks for the not-yet-initialized registry to run, we need to |
320 // postpone checking for being ready (=all rules loaded), on the registry's | 316 // postpone checking for being ready (=all rules loaded), on the registry's |
321 // thread. | 317 // thread. |
322 base::MessageLoop::current()->PostTask( | 318 base::MessageLoop::current()->PostTask( |
323 FROM_HERE, base::Bind(&RuleStorageOnUI::CheckIfReady, GetWeakPtr())); | 319 FROM_HERE, base::Bind(&RuleStorageOnUI::CheckIfReady, GetWeakPtr())); |
324 } | 320 } |
325 } | 321 } |
326 | 322 |
327 void RulesRegistryWithCache::RuleStorageOnUI::WriteToStorage( | 323 void RulesRegistryWithCache::RuleStorageOnUI::WriteToStorage( |
328 const std::string& extension_id, | 324 const std::string& extension_id, |
329 scoped_ptr<base::Value> value) { | 325 scoped_ptr<RulesVector> new_rules) { |
330 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 326 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
331 if (!profile_) | 327 if (!profile_) |
332 return; | 328 return; |
333 | 329 |
334 StateStore* store = ExtensionSystem::Get(profile_)->rules_store(); | 330 StateStore* store = ExtensionSystem::Get(profile_)->rules_store(); |
335 if (store) | 331 if (store) { |
336 store->SetExtensionValue(extension_id, storage_key_, value.Pass()); | 332 store->SetExtensionValue( |
| 333 extension_id, storage_key_, RulesToValue(*new_rules)); |
| 334 } |
337 } | 335 } |
338 | 336 |
339 void RulesRegistryWithCache::RuleStorageOnUI::Observe( | 337 void RulesRegistryWithCache::RuleStorageOnUI::Observe( |
340 int type, | 338 int type, |
341 const content::NotificationSource& source, | 339 const content::NotificationSource& source, |
342 const content::NotificationDetails& details) { | 340 const content::NotificationDetails& details) { |
343 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 341 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
344 if (type == chrome::NOTIFICATION_EXTENSION_LOADED) { | 342 if (type == chrome::NOTIFICATION_EXTENSION_LOADED) { |
345 const extensions::Extension* extension = | 343 const extensions::Extension* extension = |
346 content::Details<const extensions::Extension>(details).ptr(); | 344 content::Details<const extensions::Extension>(details).ptr(); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 registry_, | 405 registry_, |
408 extension_id, | 406 extension_id, |
409 base::Passed(&value))); | 407 base::Passed(&value))); |
410 | 408 |
411 waiting_for_extensions_.erase(extension_id); | 409 waiting_for_extensions_.erase(extension_id); |
412 | 410 |
413 CheckIfReady(); | 411 CheckIfReady(); |
414 } | 412 } |
415 | 413 |
416 } // namespace extensions | 414 } // namespace extensions |
OLD | NEW |