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
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/declarative_content/content_condition.h"
7 #include "base/strings/stringprintf.h"
8 #include "base/values.h"
9 #include "chrome/browser/extensions/api/declarative_content/content_constants.h"
10 #include "extensions/common/matcher/url_matcher_factory.h"
12 namespace keys = extensions::declarative_content_constants;
15 static extensions::URLMatcherConditionSet::ID g_next_id = 0;
17 // TODO(jyasskin): improve error messaging to give more meaningful messages
18 // to the extension developer.
20 const char kExpectedDictionary[] = "A condition has to be a dictionary.";
21 const char kConditionWithoutInstanceType[] = "A condition had no instanceType";
22 const char kExpectedOtherConditionType[] = "Expected a condition of type "
23 "declarativeContent.PageStateMatcher";
24 const char kUnknownConditionAttribute[] = "Unknown condition attribute '%s'";
25 const char kInvalidTypeOfParamter[] = "Attribute '%s' has an invalid type";
28 namespace extensions {
30 namespace keys = declarative_content_constants;
32 RendererContentMatchData::RendererContentMatchData() {}
33 RendererContentMatchData::~RendererContentMatchData() {}
39 ContentCondition::ContentCondition(
40 scoped_refptr<URLMatcherConditionSet> url_matcher_conditions,
41 const std::vector<std::string>& css_selectors)
42 : url_matcher_conditions_(url_matcher_conditions),
43 css_selectors_(css_selectors) {
44 CHECK(url_matcher_conditions.get());
47 ContentCondition::~ContentCondition() {}
49 bool ContentCondition::IsFulfilled(
50 const RendererContentMatchData& renderer_data) const {
51 if (!ContainsKey(renderer_data.page_url_matches,
52 url_matcher_conditions_->id()))
55 // All attributes must be fulfilled for a fulfilled condition.
56 for (std::vector<std::string>::const_iterator i =
57 css_selectors_.begin(); i != css_selectors_.end(); ++i) {
58 if (!ContainsKey(renderer_data.css_selectors, *i))
65 scoped_ptr<ContentCondition> ContentCondition::Create(
66 const Extension* extension,
67 URLMatcherConditionFactory* url_matcher_condition_factory,
68 const base::Value& condition,
70 const base::DictionaryValue* condition_dict = NULL;
71 if (!condition.GetAsDictionary(&condition_dict)) {
72 *error = kExpectedDictionary;
73 return scoped_ptr<ContentCondition>();
76 // Verify that we are dealing with a Condition whose type we understand.
77 std::string instance_type;
78 if (!condition_dict->GetString(keys::kInstanceType, &instance_type)) {
79 *error = kConditionWithoutInstanceType;
80 return scoped_ptr<ContentCondition>();
82 if (instance_type != keys::kPageStateMatcherType) {
83 *error = kExpectedOtherConditionType;
84 return scoped_ptr<ContentCondition>();
87 scoped_refptr<URLMatcherConditionSet> url_matcher_condition_set;
88 std::vector<std::string> css_rules;
90 for (base::DictionaryValue::Iterator iter(*condition_dict);
91 !iter.IsAtEnd(); iter.Advance()) {
92 const std::string& condition_attribute_name = iter.key();
93 const Value& condition_attribute_value = iter.value();
94 if (condition_attribute_name == keys::kInstanceType) {
96 } else if (condition_attribute_name == keys::kPageUrl) {
97 const base::DictionaryValue* dict = NULL;
98 if (!condition_attribute_value.GetAsDictionary(&dict)) {
99 *error = base::StringPrintf(kInvalidTypeOfParamter,
100 condition_attribute_name.c_str());
102 url_matcher_condition_set =
103 URLMatcherFactory::CreateFromURLFilterDictionary(
104 url_matcher_condition_factory, dict, ++g_next_id, error);
106 } else if (condition_attribute_name == keys::kCss) {
107 const base::ListValue* css_rules_value = NULL;
108 if (condition_attribute_value.GetAsList(&css_rules_value)) {
109 for (size_t i = 0; i < css_rules_value->GetSize(); ++i) {
110 std::string css_rule;
111 if (!css_rules_value->GetString(i, &css_rule)) {
112 *error = base::StringPrintf(kInvalidTypeOfParamter,
113 condition_attribute_name.c_str());
116 css_rules.push_back(css_rule);
119 *error = base::StringPrintf(kInvalidTypeOfParamter,
120 condition_attribute_name.c_str());
123 *error = base::StringPrintf(kUnknownConditionAttribute,
124 condition_attribute_name.c_str());
127 return scoped_ptr<ContentCondition>();
130 if (!url_matcher_condition_set.get()) {
131 URLMatcherConditionSet::Conditions url_matcher_conditions;
132 url_matcher_conditions.insert(
133 url_matcher_condition_factory->CreateHostPrefixCondition(
135 url_matcher_condition_set =
136 new URLMatcherConditionSet(++g_next_id, url_matcher_conditions);
138 return scoped_ptr<ContentCondition>(
139 new ContentCondition(url_matcher_condition_set, css_rules));
142 } // namespace extensions