OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "chrome/browser/extensions/api/declarative_content/content_condition.h" | |
6 | |
7 #include "base/bind.h" | |
battre
2012/12/15 11:54:10
nit: can you check whether all of these are needed
Jeffrey Yasskin
2013/01/17 09:22:56
Done.
| |
8 #include "base/logging.h" | |
9 #include "base/stringprintf.h" | |
10 #include "base/values.h" | |
11 #include "chrome/browser/extensions/api/declarative_content/content_constants.h" | |
12 #include "chrome/common/extensions/matcher/url_matcher.h" | |
13 #include "chrome/common/extensions/matcher/url_matcher_factory.h" | |
14 | |
15 namespace keys = extensions::declarative_content_constants; | |
16 | |
17 namespace { | |
18 static extensions::URLMatcherConditionSet::ID g_next_id = 0; | |
19 | |
20 // TODO(jyasskin): improve error messaging to give more meaningful messages | |
21 // to the extension developer. | |
22 // Error messages: | |
23 const char kExpectedDictionary[] = "A condition has to be a dictionary."; | |
24 const char kConditionWithoutInstanceType[] = "A condition had no instanceType"; | |
25 const char kExpectedOtherConditionType[] = "Expected a condition of type " | |
26 "declarativeContent.PageStateMatcher"; | |
27 const char kUnknownConditionAttribute[] = "Unknown condition attribute '%s'"; | |
28 const char kInvalidTypeOfParamter[] = "Attribute '%s' has an invalid type"; | |
29 } // namespace | |
30 | |
31 namespace extensions { | |
32 | |
33 namespace keys = declarative_content_constants; | |
34 | |
35 RendererContentMatchData::RendererContentMatchData() {} | |
36 RendererContentMatchData::~RendererContentMatchData() {} | |
37 | |
38 // | |
39 // ContentCondition | |
40 // | |
41 | |
42 ContentCondition::ContentCondition( | |
43 scoped_refptr<URLMatcherConditionSet> url_matcher_conditions, | |
44 const std::vector<std::string>& css_rules) | |
45 : url_matcher_conditions_(url_matcher_conditions), | |
46 css_rules_(css_rules) { | |
47 CHECK(url_matcher_conditions.get()); | |
48 } | |
49 | |
50 ContentCondition::~ContentCondition() {} | |
51 | |
52 bool ContentCondition::IsFulfilled( | |
53 const RendererContentMatchData& renderer_data) const { | |
54 // Assume the URL matches or this condition wouldn't get checked. | |
55 | |
56 // All attributes must be fulfilled for a fulfilled condition. | |
57 for (std::vector<std::string>::const_iterator i = | |
58 css_rules_.begin(); i != css_rules_.end(); ++i) { | |
59 if (!ContainsKey(renderer_data.css_rules, *i)) | |
60 return false; | |
61 } | |
62 return true; | |
63 } | |
64 | |
65 // static | |
66 scoped_ptr<ContentCondition> ContentCondition::Create( | |
67 URLMatcherConditionFactory* url_matcher_condition_factory, | |
68 const base::Value& condition, | |
69 std::string* error) { | |
70 const base::DictionaryValue* condition_dict = NULL; | |
71 if (!condition.GetAsDictionary(&condition_dict)) { | |
72 *error = kExpectedDictionary; | |
73 return scoped_ptr<ContentCondition>(NULL); | |
74 } | |
75 | |
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>(NULL); | |
81 } | |
82 if (instance_type != keys::kPageStateMatcherType) { | |
83 *error = kExpectedOtherConditionType; | |
84 return scoped_ptr<ContentCondition>(NULL); | |
85 } | |
86 | |
87 scoped_refptr<URLMatcherConditionSet> url_matcher_condition_set; | |
88 std::vector<std::string> css_rules; | |
89 | |
90 for (base::DictionaryValue::Iterator iter(*condition_dict); | |
91 iter.HasNext(); 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) { | |
95 // Skip this. | |
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()); | |
101 } else { | |
102 url_matcher_condition_set = | |
103 URLMatcherFactory::CreateFromURLFilterDictionary( | |
104 url_matcher_condition_factory, dict, ++g_next_id, error); | |
105 } | |
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 *error = base::StringPrintf(kInvalidTypeOfParamter, | |
110 condition_attribute_name.c_str()); | |
111 } | |
112 for (size_t i = 0; i < css_rules_value->GetSize(); ++i) { | |
113 std::string css_rule; | |
114 if (!css_rules_value->GetString(i, &css_rule)) { | |
115 *error = base::StringPrintf(kInvalidTypeOfParamter, | |
116 condition_attribute_name.c_str()); | |
117 break; | |
118 } | |
119 css_rules.push_back(css_rule); | |
120 } | |
121 } else { | |
122 *error = base::StringPrintf(kUnknownConditionAttribute, | |
123 condition_attribute_name.c_str()); | |
124 } | |
125 if (!error->empty()) | |
126 return scoped_ptr<ContentCondition>(NULL); | |
127 } | |
128 | |
129 if (!url_matcher_condition_set) { | |
130 URLMatcherConditionSet::Conditions url_matcher_conditions; | |
131 url_matcher_conditions.insert( | |
132 url_matcher_condition_factory->CreateHostPrefixCondition("")); | |
133 url_matcher_condition_set = | |
134 new URLMatcherConditionSet(++g_next_id, url_matcher_conditions); | |
135 } | |
136 return scoped_ptr<ContentCondition>( | |
137 new ContentCondition(url_matcher_condition_set, css_rules)); | |
138 } | |
139 | |
140 } // namespace extensions | |
OLD | NEW |