| Index: extensions/browser/api/declarative/rules_registry.cc
|
| diff --git a/extensions/browser/api/declarative/rules_registry.cc b/extensions/browser/api/declarative/rules_registry.cc
|
| index dfd9c35260ace0ea706aa383d78d355c8177e57b..15d4154737ae0331506325f04282eb6c98b28673 100644
|
| --- a/extensions/browser/api/declarative/rules_registry.cc
|
| +++ b/extensions/browser/api/declarative/rules_registry.cc
|
| @@ -21,24 +21,30 @@
|
| #include "extensions/browser/extension_prefs.h"
|
| #include "extensions/browser/extension_system.h"
|
| #include "extensions/browser/state_store.h"
|
| +#include "extensions/common/api/declarative/declarative_manifest_data.h"
|
| #include "extensions/common/extension.h"
|
| +#include "extensions/common/manifest_constants.h"
|
| +
|
| +namespace extensions {
|
|
|
| namespace {
|
|
|
| const char kSuccess[] = "";
|
| const char kDuplicateRuleId[] = "Duplicate rule ID: %s";
|
| +const char kErrorCannotRemoveManifestRules[] =
|
| + "Rules declared in the 'event_rules' manifest field cannot be removed";
|
|
|
| scoped_ptr<base::Value> RulesToValue(
|
| - const std::vector<linked_ptr<extensions::RulesRegistry::Rule> >& rules) {
|
| + const std::vector<linked_ptr<RulesRegistry::Rule>>& rules) {
|
| scoped_ptr<base::ListValue> list(new base::ListValue());
|
| for (size_t i = 0; i < rules.size(); ++i)
|
| list->Append(rules[i]->ToValue().release());
|
| return list.Pass();
|
| }
|
|
|
| -std::vector<linked_ptr<extensions::RulesRegistry::Rule> > RulesFromValue(
|
| +std::vector<linked_ptr<RulesRegistry::Rule>> RulesFromValue(
|
| const base::Value* value) {
|
| - std::vector<linked_ptr<extensions::RulesRegistry::Rule> > rules;
|
| + std::vector<linked_ptr<RulesRegistry::Rule>> rules;
|
|
|
| const base::ListValue* list = NULL;
|
| if (!value || !value->GetAsList(&list))
|
| @@ -49,9 +55,8 @@ std::vector<linked_ptr<extensions::RulesRegistry::Rule> > RulesFromValue(
|
| const base::DictionaryValue* dict = NULL;
|
| if (!list->GetDictionary(i, &dict))
|
| continue;
|
| - linked_ptr<extensions::RulesRegistry::Rule> rule(
|
| - new extensions::RulesRegistry::Rule());
|
| - if (extensions::RulesRegistry::Rule::Populate(*dict, rule.get()))
|
| + linked_ptr<RulesRegistry::Rule> rule(new RulesRegistry::Rule());
|
| + if (RulesRegistry::Rule::Populate(*dict, rule.get()))
|
| rules.push_back(rule);
|
| }
|
|
|
| @@ -65,8 +70,6 @@ std::string ToId(int identifier) {
|
| } // namespace
|
|
|
|
|
| -namespace extensions {
|
| -
|
| // RulesRegistry
|
|
|
| RulesRegistry::RulesRegistry(content::BrowserContext* browser_context,
|
| @@ -90,7 +93,8 @@ RulesRegistry::RulesRegistry(content::BrowserContext* browser_context,
|
|
|
| std::string RulesRegistry::AddRulesNoFill(
|
| const std::string& extension_id,
|
| - const std::vector<linked_ptr<Rule> >& rules) {
|
| + const std::vector<linked_ptr<Rule>>& rules,
|
| + RulesDictionary* out) {
|
| DCHECK_CURRENTLY_ON(owner_thread());
|
|
|
| // Verify that all rule IDs are new.
|
| @@ -100,7 +104,8 @@ std::string RulesRegistry::AddRulesNoFill(
|
| // Every rule should have a priority assigned.
|
| DCHECK((*i)->priority);
|
| RulesDictionaryKey key(extension_id, rule_id);
|
| - if (rules_.find(key) != rules_.end())
|
| + if (rules_.find(key) != rules_.end() ||
|
| + manifest_rules_.find(key) != manifest_rules_.end())
|
| return base::StringPrintf(kDuplicateRuleId, rule_id.c_str());
|
| }
|
|
|
| @@ -114,7 +119,7 @@ std::string RulesRegistry::AddRulesNoFill(
|
| rules.begin(); i != rules.end(); ++i) {
|
| const RuleId& rule_id = *((*i)->id);
|
| RulesDictionaryKey key(extension_id, rule_id);
|
| - rules_[key] = *i;
|
| + (*out)[key] = *i;
|
| }
|
|
|
| MaybeProcessChangedRules(extension_id);
|
| @@ -123,7 +128,14 @@ std::string RulesRegistry::AddRulesNoFill(
|
|
|
| std::string RulesRegistry::AddRules(
|
| const std::string& extension_id,
|
| - const std::vector<linked_ptr<Rule> >& rules) {
|
| + const std::vector<linked_ptr<Rule>>& rules) {
|
| + return AddRulesInternal(extension_id, rules, &rules_);
|
| +}
|
| +
|
| +std::string RulesRegistry::AddRulesInternal(
|
| + const std::string& extension_id,
|
| + const std::vector<linked_ptr<Rule>>& rules,
|
| + RulesDictionary* out) {
|
| DCHECK_CURRENTLY_ON(owner_thread());
|
|
|
| std::string error = CheckAndFillInOptionalRules(extension_id, rules);
|
| @@ -131,7 +143,7 @@ std::string RulesRegistry::AddRules(
|
| return error;
|
| FillInOptionalPriorities(rules);
|
|
|
| - return AddRulesNoFill(extension_id, rules);
|
| + return AddRulesNoFill(extension_id, rules, out);
|
| }
|
|
|
| std::string RulesRegistry::RemoveRules(
|
| @@ -139,6 +151,14 @@ std::string RulesRegistry::RemoveRules(
|
| const std::vector<std::string>& rule_identifiers) {
|
| DCHECK_CURRENTLY_ON(owner_thread());
|
|
|
| + // Check if any of the rules are non-removable.
|
| + for (RuleId rule_id : rule_identifiers) {
|
| + RulesDictionaryKey lookup_key(extension_id, rule_id);
|
| + RulesDictionary::iterator itr = manifest_rules_.find(lookup_key);
|
| + if (itr != manifest_rules_.end())
|
| + return kErrorCannotRemoveManifestRules;
|
| + }
|
| +
|
| std::string error = RemoveRulesImpl(extension_id, rule_identifiers);
|
|
|
| if (!error.empty())
|
| @@ -157,13 +177,15 @@ std::string RulesRegistry::RemoveRules(
|
| }
|
|
|
| std::string RulesRegistry::RemoveAllRules(const std::string& extension_id) {
|
| - std::string result = RulesRegistry::RemoveAllRulesNoStoreUpdate(extension_id);
|
| + std::string result =
|
| + RulesRegistry::RemoveAllRulesNoStoreUpdate(extension_id, false);
|
| MaybeProcessChangedRules(extension_id); // Now update the prefs and store.
|
| return result;
|
| }
|
|
|
| std::string RulesRegistry::RemoveAllRulesNoStoreUpdate(
|
| - const std::string& extension_id) {
|
| + const std::string& extension_id,
|
| + bool remove_manifest_rules) {
|
| DCHECK_CURRENTLY_ON(owner_thread());
|
|
|
| std::string error = RemoveAllRulesImpl(extension_id);
|
| @@ -171,13 +193,17 @@ std::string RulesRegistry::RemoveAllRulesNoStoreUpdate(
|
| if (!error.empty())
|
| return error;
|
|
|
| - for (RulesDictionary::const_iterator i = rules_.begin();
|
| - i != rules_.end();) {
|
| - const RulesDictionaryKey& key = i->first;
|
| - ++i;
|
| - if (key.first == extension_id)
|
| - rules_.erase(key);
|
| - }
|
| + auto remove_rules = [&extension_id](RulesDictionary& dictionary) {
|
| + for (auto it = dictionary.begin(); it != dictionary.end();) {
|
| + if (it->first.first == extension_id)
|
| + dictionary.erase(it++);
|
| + else
|
| + ++it;
|
| + }
|
| + };
|
| + remove_rules(rules_);
|
| + if (remove_manifest_rules)
|
| + remove_rules(manifest_rules_);
|
|
|
| RemoveAllUsedRuleIdentifiers(extension_id);
|
| return kSuccess;
|
| @@ -188,45 +214,61 @@ void RulesRegistry::GetRules(const std::string& extension_id,
|
| std::vector<linked_ptr<Rule> >* out) {
|
| DCHECK_CURRENTLY_ON(owner_thread());
|
|
|
| - for (std::vector<std::string>::const_iterator i = rule_identifiers.begin();
|
| - i != rule_identifiers.end(); ++i) {
|
| - RulesDictionaryKey lookup_key(extension_id, *i);
|
| + for (const auto& i : rule_identifiers) {
|
| + RulesDictionaryKey lookup_key(extension_id, i);
|
| RulesDictionary::iterator entry = rules_.find(lookup_key);
|
| + if (entry == rules_.end())
|
| + entry = manifest_rules_.find(lookup_key);
|
| if (entry != rules_.end())
|
| out->push_back(entry->second);
|
| }
|
| }
|
|
|
| +void RulesRegistry::GetRules(
|
| + const std::string& extension_id,
|
| + RulesDictionary& rules,
|
| + std::vector<linked_ptr<RulesRegistry::Rule>>* out) {
|
| + for (const auto& i : rules) {
|
| + const RulesDictionaryKey& key = i.first;
|
| + if (key.first == extension_id)
|
| + out->push_back(i.second);
|
| + }
|
| +}
|
| +
|
| void RulesRegistry::GetAllRules(const std::string& extension_id,
|
| std::vector<linked_ptr<Rule> >* out) {
|
| DCHECK_CURRENTLY_ON(owner_thread());
|
| - for (RulesDictionary::const_iterator i = rules_.begin();
|
| - i != rules_.end(); ++i) {
|
| - const RulesDictionaryKey& key = i->first;
|
| - if (key.first == extension_id)
|
| - out->push_back(i->second);
|
| - }
|
| + GetRules(extension_id, manifest_rules_, out);
|
| + GetRules(extension_id, rules_, out);
|
| }
|
|
|
| -void RulesRegistry::OnExtensionUnloaded(const std::string& extension_id) {
|
| +void RulesRegistry::OnExtensionUnloaded(const Extension* extension) {
|
| DCHECK_CURRENTLY_ON(owner_thread());
|
| - std::string error = RemoveAllRulesImpl(extension_id);
|
| + std::string error = RemoveAllRulesImpl(extension->id());
|
| if (!error.empty())
|
| LOG(ERROR) << error;
|
| }
|
|
|
| -void RulesRegistry::OnExtensionUninstalled(const std::string& extension_id) {
|
| +void RulesRegistry::OnExtensionUninstalled(const Extension* extension) {
|
| DCHECK_CURRENTLY_ON(owner_thread());
|
| - std::string error = RemoveAllRulesNoStoreUpdate(extension_id);
|
| + std::string error = RemoveAllRulesNoStoreUpdate(extension->id(), true);
|
| if (!error.empty())
|
| LOG(ERROR) << error;
|
| }
|
|
|
| -void RulesRegistry::OnExtensionLoaded(const std::string& extension_id) {
|
| +void RulesRegistry::OnExtensionLoaded(const Extension* extension) {
|
| DCHECK_CURRENTLY_ON(owner_thread());
|
| - std::vector<linked_ptr<Rule> > rules;
|
| - GetAllRules(extension_id, &rules);
|
| - std::string error = AddRulesImpl(extension_id, rules);
|
| + std::vector<linked_ptr<Rule>> rules;
|
| + GetAllRules(extension->id(), &rules);
|
| + std::vector<linked_ptr<Rule>>& manifest_rules =
|
| + DeclarativeManifestData::Get(extension)->RulesForEvent(event_name_);
|
| + if (manifest_rules.size()) {
|
| + std::string error =
|
| + AddRulesInternal(extension->id(), manifest_rules, &manifest_rules_);
|
| + if (!error.empty())
|
| + LOG(ERROR) << error;
|
| + }
|
| + std::string error = AddRulesImpl(extension->id(), rules);
|
| if (!error.empty())
|
| LOG(ERROR) << error;
|
| }
|
| @@ -249,7 +291,7 @@ void RulesRegistry::DeserializeAndAddRules(
|
| scoped_ptr<base::Value> rules) {
|
| DCHECK_CURRENTLY_ON(owner_thread());
|
|
|
| - AddRulesNoFill(extension_id, RulesFromValue(rules.get()));
|
| + AddRulesNoFill(extension_id, RulesFromValue(rules.get()), &rules_);
|
| }
|
|
|
| RulesRegistry::~RulesRegistry() {
|
| @@ -273,14 +315,11 @@ void RulesRegistry::ProcessChangedRules(const std::string& extension_id) {
|
| process_changed_rules_requested_[extension_id] = NOT_SCHEDULED_FOR_PROCESSING;
|
|
|
| std::vector<linked_ptr<Rule> > new_rules;
|
| - GetAllRules(extension_id, &new_rules);
|
| + GetRules(extension_id, rules_, &new_rules);
|
| content::BrowserThread::PostTask(
|
| - content::BrowserThread::UI,
|
| - FROM_HERE,
|
| - base::Bind(&RulesCacheDelegate::WriteToStorage,
|
| - cache_delegate_,
|
| - extension_id,
|
| - base::Passed(RulesToValue(new_rules))));
|
| + content::BrowserThread::UI, FROM_HERE,
|
| + base::Bind(&RulesCacheDelegate::WriteToStorage, cache_delegate_,
|
| + extension_id, base::Passed(RulesToValue(new_rules))));
|
| }
|
|
|
| void RulesRegistry::MaybeProcessChangedRules(const std::string& extension_id) {
|
|
|