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

Unified Diff: extensions/browser/api/declarative/rules_registry.cc

Issue 1158693006: Create a mechanism define declarative rules via the extension manifest. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: addressing comments Created 5 years, 6 months 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 side-by-side diff with in-line comments
Download patch
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..5ae4c776de443723851c42f43418f9e257771b2a 100644
--- a/extensions/browser/api/declarative/rules_registry.cc
+++ b/extensions/browser/api/declarative/rules_registry.cc
@@ -22,23 +22,28 @@
#include "extensions/browser/extension_system.h"
#include "extensions/browser/state_store.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,15 +54,95 @@ 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);
}
return rules;
}
+// Converts a rule defined in the manifest into a JSON internal format. The
+// difference is that actions and conditions use a "type" key to define the
+// type of rule/condition, while the internal format uses a "instanceType" key
+// for this. This function walks through all the conditions and rules to swap
+// the manifest key for the internal key.
+bool ConvertManifestRule(const linked_ptr<RulesRegistry::Rule>& rule) {
+ auto convert_list = [](std::vector<linked_ptr<base::Value>>& list) {
+ for (const linked_ptr<base::Value>& value : list) {
+ base::DictionaryValue* dictionary = nullptr;
+ if (!value->GetAsDictionary(&dictionary))
+ return false;
+ std::string type;
+ if (!dictionary->GetString("type", &type))
+ return false;
+ dictionary->Remove("type", nullptr);
+ dictionary->SetString("instanceType", type);
+ }
+ return true;
+ };
+ return convert_list(rule->actions) && convert_list(rule->conditions);
+}
+
+std::vector<linked_ptr<RulesRegistry::Rule>> RulesFromManifest(
+ const base::Value* value,
+ const std::string& event_name) {
+ std::vector<linked_ptr<RulesRegistry::Rule>> rules;
+
+ // The following is an example of how an event programmatic rule definition
Mike Wittman 2015/06/05 23:15:58 You'll need to add something like this to the mani
+ // translates to a manifest definition.
+ //
+ // From javascript:
+ //
+ // chrome.declarativeContent.onPageChanged.addRules([{
+ // actions: [
+ // new chrome.declarativeContent.ShowPageAction()
+ // ],
+ // conditions: [
+ // new chrome.declarativeContent.PageStateMatcher({css: ["video"]})
+ // ]
+ // }]);
+ //
+ // In manifest:
+ //
+ // "event_rules": [{
+ // "event" : "declarativeContent.onPageChanged",
+ // "actions" : [{
+ // "type": "declarativeContent.ShowPageAction"
+ // }],
+ // "conditions" : [{
+ // "css": ["video"],
+ // "type" : "declarativeContent.PageStateMatcher"
+ // }]
+ // }]
+ //
+ // The javascript objects get translated into JSON objects with a "type"
+ // field to indicate the instance type. Instead of adding rules to a
+ // specific event list, each rule has an "event" field to indicate which
+ // event it applies to.
+ //
+ const base::ListValue* list = nullptr;
+ if (!value->GetAsList(&list))
+ return rules;
+
+ for (size_t i = 0; i < list->GetSize(); ++i) {
+ const base::DictionaryValue* dict = nullptr;
+ if (!list->GetDictionary(i, &dict))
+ continue;
+ std::string event;
+ if (!dict->GetString("event", &event) || event_name != event) {
+ continue;
+ }
+ linked_ptr<RulesRegistry::Rule> rule(new RulesRegistry::Rule());
+ if (RulesRegistry::Rule::Populate(*dict, rule.get()) &&
+ ConvertManifestRule(rule)) {
+ rules.push_back(rule);
+ }
+ }
+
+ return rules;
+}
+
std::string ToId(int identifier) {
return base::StringPrintf("_%d_", identifier);
}
@@ -65,8 +150,6 @@ std::string ToId(int identifier) {
} // namespace
-namespace extensions {
-
// RulesRegistry
RulesRegistry::RulesRegistry(content::BrowserContext* browser_context,
@@ -90,7 +173,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 +184,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 +199,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 +208,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 +223,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 +231,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 +257,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 uninstall) {
DCHECK_CURRENTLY_ON(owner_thread());
std::string error = RemoveAllRulesImpl(extension_id);
@@ -171,13 +273,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 (uninstall)
+ remove_rules(manifest_rules_);
RemoveAllUsedRuleIdentifiers(extension_id);
return kSuccess;
@@ -188,45 +294,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);
+ const base::ListValue* value = NULL;
+ if (extension->manifest()->GetList(manifest_keys::kEventRules, &value)) {
+ std::string error =
+ AddRulesInternal(extension->id(), RulesFromManifest(value, event_name_),
+ manifest_rules_);
+ if (!error.empty())
+ LOG(ERROR) << error;
+ }
+ std::string error = AddRulesImpl(extension->id(), rules);
if (!error.empty())
LOG(ERROR) << error;
}
@@ -249,7 +371,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 +395,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) {
« no previous file with comments | « extensions/browser/api/declarative/rules_registry.h ('k') | extensions/browser/api/declarative/rules_registry_service.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698