Chromium Code Reviews| 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 "extensions/browser/api/declarative/rules_registry.h" | 5 #include "extensions/browser/api/declarative/rules_registry.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
| 12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 13 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
| 14 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
| 15 #include "base/time/time.h" | 15 #include "base/time/time.h" |
| 16 #include "base/values.h" | 16 #include "base/values.h" |
| 17 #include "content/public/browser/browser_thread.h" | 17 #include "content/public/browser/browser_thread.h" |
| 18 #include "content/public/browser/notification_details.h" | 18 #include "content/public/browser/notification_details.h" |
| 19 #include "content/public/browser/notification_source.h" | 19 #include "content/public/browser/notification_source.h" |
| 20 #include "extensions/browser/api/declarative/rules_cache_delegate.h" | 20 #include "extensions/browser/api/declarative/rules_cache_delegate.h" |
| 21 #include "extensions/browser/extension_prefs.h" | 21 #include "extensions/browser/extension_prefs.h" |
| 22 #include "extensions/browser/extension_registry.h" | |
| 22 #include "extensions/browser/extension_system.h" | 23 #include "extensions/browser/extension_system.h" |
| 23 #include "extensions/browser/state_store.h" | 24 #include "extensions/browser/state_store.h" |
| 24 #include "extensions/common/extension.h" | 25 #include "extensions/common/extension.h" |
| 26 #include "extensions/common/manifest_constants.h" | |
| 25 | 27 |
| 26 namespace { | 28 namespace { |
| 27 | 29 |
| 28 const char kSuccess[] = ""; | 30 const char kSuccess[] = ""; |
| 29 const char kDuplicateRuleId[] = "Duplicate rule ID: %s"; | 31 const char kDuplicateRuleId[] = "Duplicate rule ID: %s"; |
| 30 | 32 |
| 31 scoped_ptr<base::Value> RulesToValue( | 33 scoped_ptr<base::Value> RulesToValue( |
| 32 const std::vector<linked_ptr<extensions::RulesRegistry::Rule> >& rules) { | 34 const std::vector<linked_ptr<extensions::RulesRegistry::Rule> >& rules) { |
| 33 scoped_ptr<base::ListValue> list(new base::ListValue()); | 35 scoped_ptr<base::ListValue> list(new base::ListValue()); |
| 34 for (size_t i = 0; i < rules.size(); ++i) | 36 for (size_t i = 0; i < rules.size(); ++i) |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 51 continue; | 53 continue; |
| 52 linked_ptr<extensions::RulesRegistry::Rule> rule( | 54 linked_ptr<extensions::RulesRegistry::Rule> rule( |
| 53 new extensions::RulesRegistry::Rule()); | 55 new extensions::RulesRegistry::Rule()); |
| 54 if (extensions::RulesRegistry::Rule::Populate(*dict, rule.get())) | 56 if (extensions::RulesRegistry::Rule::Populate(*dict, rule.get())) |
| 55 rules.push_back(rule); | 57 rules.push_back(rule); |
| 56 } | 58 } |
| 57 | 59 |
| 58 return rules; | 60 return rules; |
| 59 } | 61 } |
| 60 | 62 |
| 63 scoped_ptr<base::ListValue> ConvertListFromManifest( | |
| 64 const base::ListValue* list) { | |
| 65 scoped_ptr<base::ListValue> result(new base::ListValue); | |
| 66 for (base::ListValue::const_iterator it = list->begin(); it != list->end(); | |
| 67 ++it) { | |
| 68 base::DictionaryValue* dictionary = nullptr; | |
| 69 if (!(*it)->GetAsDictionary(&dictionary)) | |
| 70 continue; | |
| 71 std::string type; | |
| 72 if (!dictionary->GetString("type", &type)) | |
| 73 continue; | |
| 74 scoped_ptr<base::DictionaryValue> copy = dictionary->CreateDeepCopy(); | |
| 75 copy->Remove("type", NULL); | |
| 76 copy->SetString("instanceType", type); | |
| 77 result->Append(copy.Pass()); | |
| 78 } | |
| 79 return result.Pass(); | |
| 80 } | |
| 81 | |
| 82 std::vector<linked_ptr<extensions::RulesRegistry::Rule>> RulesFromManifest( | |
|
not at google - send to devlin
2015/06/04 17:58:49
- This file is already in the extensions namespace
danduong
2015/06/04 19:10:59
- All these helper functions are in anonymous name
not at google - send to devlin
2015/06/04 19:23:52
I see. Move the "namespace extensions {" declarati
danduong
2015/06/04 21:39:40
Done.
| |
| 83 const base::Value* value, | |
| 84 const std::string& event_name) { | |
| 85 std::vector<linked_ptr<extensions::RulesRegistry::Rule>> rules; | |
| 86 | |
| 87 const base::ListValue* list = nullptr; | |
| 88 if (!value || !value->GetAsList(&list)) | |
| 89 return rules; | |
| 90 | |
| 91 for (size_t i = 0; i < list->GetSize(); ++i) { | |
|
not at google - send to devlin
2015/06/04 17:58:49
You should look at defining this structure in exte
danduong
2015/06/05 06:41:57
I looked into it and I ran into some problems with
| |
| 92 const base::DictionaryValue* dict = nullptr; | |
| 93 if (!list->GetDictionary(i, &dict)) | |
| 94 continue; | |
| 95 std::string event; | |
| 96 if (!dict->GetString("event", &event)) | |
| 97 continue; | |
| 98 if (event_name != event) | |
| 99 continue; | |
| 100 const base::ListValue* list; | |
| 101 if (!dict->GetList("conditions", &list) || !list->GetSize()) | |
| 102 continue; | |
| 103 scoped_ptr<base::ListValue> conditions = ConvertListFromManifest(list); | |
| 104 if (!conditions->GetSize()) | |
| 105 continue; | |
| 106 if (!dict->GetList("actions", &list) || !list->GetSize()) | |
| 107 continue; | |
| 108 scoped_ptr<base::ListValue> actions = ConvertListFromManifest(list); | |
| 109 if (!actions->GetSize()) | |
| 110 continue; | |
| 111 scoped_ptr<base::DictionaryValue> rule_dict(new base::DictionaryValue); | |
| 112 rule_dict->Set("conditions", conditions.Pass()); | |
| 113 rule_dict->Set("actions", actions.Pass()); | |
| 114 rule_dict->SetBoolean("removable", false); | |
| 115 linked_ptr<extensions::RulesRegistry::Rule> rule( | |
| 116 new extensions::RulesRegistry::Rule()); | |
| 117 if (extensions::RulesRegistry::Rule::Populate(*rule_dict, rule.get())) | |
| 118 rules.push_back(rule); | |
| 119 } | |
| 120 | |
| 121 return rules; | |
| 122 } | |
| 123 | |
| 61 std::string ToId(int identifier) { | 124 std::string ToId(int identifier) { |
| 62 return base::StringPrintf("_%d_", identifier); | 125 return base::StringPrintf("_%d_", identifier); |
| 63 } | 126 } |
| 64 | 127 |
| 65 } // namespace | 128 } // namespace |
| 66 | 129 |
| 67 | 130 |
| 68 namespace extensions { | 131 namespace extensions { |
| 69 | 132 |
| 70 // RulesRegistry | 133 // RulesRegistry |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 132 FillInOptionalPriorities(rules); | 195 FillInOptionalPriorities(rules); |
| 133 | 196 |
| 134 return AddRulesNoFill(extension_id, rules); | 197 return AddRulesNoFill(extension_id, rules); |
| 135 } | 198 } |
| 136 | 199 |
| 137 std::string RulesRegistry::RemoveRules( | 200 std::string RulesRegistry::RemoveRules( |
| 138 const std::string& extension_id, | 201 const std::string& extension_id, |
| 139 const std::vector<std::string>& rule_identifiers) { | 202 const std::vector<std::string>& rule_identifiers) { |
| 140 DCHECK_CURRENTLY_ON(owner_thread()); | 203 DCHECK_CURRENTLY_ON(owner_thread()); |
| 141 | 204 |
| 205 // Check if any of the rules are non-removable. | |
| 206 for (RuleId rule_id : rule_identifiers) { | |
| 207 RulesDictionaryKey lookup_key(extension_id, rule_id); | |
| 208 RulesDictionary::iterator entry = rules_.find(lookup_key); | |
| 209 if (entry != rules_.end()) { | |
| 210 Rule* rule = entry->second.get(); | |
| 211 if (rule->removable.get() && !*(rule->removable)) | |
| 212 return "List contains non-removable rules"; | |
|
not at google - send to devlin
2015/06/04 17:58:48
I'd prefer to define this as a constant.
danduong
2015/06/04 19:10:58
Done.
| |
| 213 } | |
| 214 } | |
| 215 | |
| 142 std::string error = RemoveRulesImpl(extension_id, rule_identifiers); | 216 std::string error = RemoveRulesImpl(extension_id, rule_identifiers); |
| 143 | 217 |
| 144 if (!error.empty()) | 218 if (!error.empty()) |
| 145 return error; | 219 return error; |
| 146 | 220 |
| 147 for (std::vector<std::string>::const_iterator i = rule_identifiers.begin(); | 221 for (std::vector<std::string>::const_iterator i = rule_identifiers.begin(); |
| 148 i != rule_identifiers.end(); | 222 i != rule_identifiers.end(); |
| 149 ++i) { | 223 ++i) { |
| 150 RulesDictionaryKey lookup_key(extension_id, *i); | 224 RulesDictionaryKey lookup_key(extension_id, *i); |
| 151 rules_.erase(lookup_key); | 225 rules_.erase(lookup_key); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 215 LOG(ERROR) << error; | 289 LOG(ERROR) << error; |
| 216 } | 290 } |
| 217 | 291 |
| 218 void RulesRegistry::OnExtensionUninstalled(const std::string& extension_id) { | 292 void RulesRegistry::OnExtensionUninstalled(const std::string& extension_id) { |
| 219 DCHECK_CURRENTLY_ON(owner_thread()); | 293 DCHECK_CURRENTLY_ON(owner_thread()); |
| 220 std::string error = RemoveAllRulesNoStoreUpdate(extension_id); | 294 std::string error = RemoveAllRulesNoStoreUpdate(extension_id); |
| 221 if (!error.empty()) | 295 if (!error.empty()) |
| 222 LOG(ERROR) << error; | 296 LOG(ERROR) << error; |
| 223 } | 297 } |
| 224 | 298 |
| 225 void RulesRegistry::OnExtensionLoaded(const std::string& extension_id) { | 299 void RulesRegistry::OnExtensionLoaded(const std::string& extension_id) { |
|
not at google - send to devlin
2015/06/04 17:58:49
Repeat previous comment:
Could you update OnExten
| |
| 226 DCHECK_CURRENTLY_ON(owner_thread()); | 300 DCHECK_CURRENTLY_ON(owner_thread()); |
| 227 std::vector<linked_ptr<Rule> > rules; | 301 std::vector<linked_ptr<Rule> > rules; |
| 228 GetAllRules(extension_id, &rules); | 302 GetAllRules(extension_id, &rules); |
| 229 std::string error = AddRulesImpl(extension_id, rules); | 303 if (rules.empty()) { |
|
not at google - send to devlin
2015/06/04 17:58:48
Repeat previous comment:
Why only if there are no
danduong
2015/06/04 19:10:59
Isn't that use case still met, since the complete
not at google - send to devlin
2015/06/04 19:23:53
I think this won't work for update, though. There
danduong
2015/06/04 19:56:07
Update would work still right? Uninstall will remo
not at google - send to devlin
2015/06/04 20:02:21
Maybe. Either way this code looks wrong. I would h
danduong
2015/06/04 21:39:40
Done.
| |
| 230 if (!error.empty()) | 304 // If no rules have been registered yet, check if there are any rules |
| 231 LOG(ERROR) << error; | 305 // defined in the extension manifest to add. |
| 306 const Extension* extension = | |
| 307 ExtensionRegistry::Get(browser_context()) | |
| 308 ->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING); | |
|
not at google - send to devlin
2015/06/04 17:58:49
Btw once https://codereview.chromium.org/113035301
danduong
2015/06/04 19:10:59
Acknowledged.
| |
| 309 const base::ListValue* value = NULL; | |
| 310 if (extension->manifest()->GetList(manifest_keys::kEventRules, &value)) { | |
| 311 AddRules(extension_id, RulesFromManifest(value, event_name_)); | |
|
Mike Wittman
2015/06/04 18:40:13
this needs to handle the error which may be return
danduong
2015/06/04 19:10:59
Done.
| |
| 312 } | |
| 313 } else { | |
| 314 std::string error = AddRulesImpl(extension_id, rules); | |
| 315 if (!error.empty()) | |
| 316 LOG(ERROR) << error; | |
| 317 } | |
| 232 } | 318 } |
| 233 | 319 |
| 234 size_t RulesRegistry::GetNumberOfUsedRuleIdentifiersForTesting() const { | 320 size_t RulesRegistry::GetNumberOfUsedRuleIdentifiersForTesting() const { |
| 235 size_t entry_count = 0u; | 321 size_t entry_count = 0u; |
| 236 for (RuleIdentifiersMap::const_iterator extension = | 322 for (RuleIdentifiersMap::const_iterator extension = |
| 237 used_rule_identifiers_.begin(); | 323 used_rule_identifiers_.begin(); |
| 238 extension != used_rule_identifiers_.end(); | 324 extension != used_rule_identifiers_.end(); |
| 239 ++extension) { | 325 ++extension) { |
| 240 // Each extension is counted as 1 just for being there. Otherwise we miss | 326 // Each extension is counted as 1 just for being there. Otherwise we miss |
| 241 // keys with empty values. | 327 // keys with empty values. |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 367 for (i = identifiers.begin(); i != identifiers.end(); ++i) | 453 for (i = identifiers.begin(); i != identifiers.end(); ++i) |
| 368 used_rule_identifiers_[extension_id].erase(*i); | 454 used_rule_identifiers_[extension_id].erase(*i); |
| 369 } | 455 } |
| 370 | 456 |
| 371 void RulesRegistry::RemoveAllUsedRuleIdentifiers( | 457 void RulesRegistry::RemoveAllUsedRuleIdentifiers( |
| 372 const std::string& extension_id) { | 458 const std::string& extension_id) { |
| 373 used_rule_identifiers_.erase(extension_id); | 459 used_rule_identifiers_.erase(extension_id); |
| 374 } | 460 } |
| 375 | 461 |
| 376 } // namespace extensions | 462 } // namespace extensions |
| OLD | NEW |