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 "components/url_matcher/url_matcher_factory.h"
12 using url_matcher::URLMatcherConditionFactory
;
13 using url_matcher::URLMatcherConditionSet
;
14 using url_matcher::URLMatcherFactory
;
16 namespace keys
= extensions::declarative_content_constants
;
19 static URLMatcherConditionSet::ID g_next_id
= 0;
21 // TODO(jyasskin): improve error messaging to give more meaningful messages
22 // to the extension developer.
24 const char kExpectedDictionary
[] = "A condition has to be a dictionary.";
25 const char kConditionWithoutInstanceType
[] = "A condition had no instanceType";
26 const char kExpectedOtherConditionType
[] = "Expected a condition of type "
27 "declarativeContent.PageStateMatcher";
28 const char kUnknownConditionAttribute
[] = "Unknown condition attribute '%s'";
29 const char kInvalidTypeOfParamter
[] = "Attribute '%s' has an invalid type";
32 namespace extensions
{
34 namespace keys
= declarative_content_constants
;
36 RendererContentMatchData::RendererContentMatchData() {}
37 RendererContentMatchData::~RendererContentMatchData() {}
43 ContentCondition::ContentCondition(
44 scoped_refptr
<URLMatcherConditionSet
> url_matcher_conditions
,
45 const std::vector
<std::string
>& css_selectors
)
46 : url_matcher_conditions_(url_matcher_conditions
),
47 css_selectors_(css_selectors
) {
48 CHECK(url_matcher_conditions
.get());
51 ContentCondition::~ContentCondition() {}
53 bool ContentCondition::IsFulfilled(
54 const RendererContentMatchData
& renderer_data
) const {
55 if (!ContainsKey(renderer_data
.page_url_matches
,
56 url_matcher_conditions_
->id()))
59 // All attributes must be fulfilled for a fulfilled condition.
60 for (std::vector
<std::string
>::const_iterator i
=
61 css_selectors_
.begin(); i
!= css_selectors_
.end(); ++i
) {
62 if (!ContainsKey(renderer_data
.css_selectors
, *i
))
69 scoped_ptr
<ContentCondition
> ContentCondition::Create(
70 const Extension
* extension
,
71 URLMatcherConditionFactory
* url_matcher_condition_factory
,
72 const base::Value
& condition
,
74 const base::DictionaryValue
* condition_dict
= NULL
;
75 if (!condition
.GetAsDictionary(&condition_dict
)) {
76 *error
= kExpectedDictionary
;
77 return scoped_ptr
<ContentCondition
>();
80 // Verify that we are dealing with a Condition whose type we understand.
81 std::string instance_type
;
82 if (!condition_dict
->GetString(keys::kInstanceType
, &instance_type
)) {
83 *error
= kConditionWithoutInstanceType
;
84 return scoped_ptr
<ContentCondition
>();
86 if (instance_type
!= keys::kPageStateMatcherType
) {
87 *error
= kExpectedOtherConditionType
;
88 return scoped_ptr
<ContentCondition
>();
91 scoped_refptr
<URLMatcherConditionSet
> url_matcher_condition_set
;
92 std::vector
<std::string
> css_rules
;
94 for (base::DictionaryValue::Iterator
iter(*condition_dict
);
95 !iter
.IsAtEnd(); iter
.Advance()) {
96 const std::string
& condition_attribute_name
= iter
.key();
97 const base::Value
& condition_attribute_value
= iter
.value();
98 if (condition_attribute_name
== keys::kInstanceType
) {
100 } else if (condition_attribute_name
== keys::kPageUrl
) {
101 const base::DictionaryValue
* dict
= NULL
;
102 if (!condition_attribute_value
.GetAsDictionary(&dict
)) {
103 *error
= base::StringPrintf(kInvalidTypeOfParamter
,
104 condition_attribute_name
.c_str());
106 url_matcher_condition_set
=
107 URLMatcherFactory::CreateFromURLFilterDictionary(
108 url_matcher_condition_factory
, dict
, ++g_next_id
, error
);
110 } else if (condition_attribute_name
== keys::kCss
) {
111 const base::ListValue
* css_rules_value
= NULL
;
112 if (condition_attribute_value
.GetAsList(&css_rules_value
)) {
113 for (size_t i
= 0; i
< css_rules_value
->GetSize(); ++i
) {
114 std::string css_rule
;
115 if (!css_rules_value
->GetString(i
, &css_rule
)) {
116 *error
= base::StringPrintf(kInvalidTypeOfParamter
,
117 condition_attribute_name
.c_str());
120 css_rules
.push_back(css_rule
);
123 *error
= base::StringPrintf(kInvalidTypeOfParamter
,
124 condition_attribute_name
.c_str());
127 *error
= base::StringPrintf(kUnknownConditionAttribute
,
128 condition_attribute_name
.c_str());
131 return scoped_ptr
<ContentCondition
>();
134 if (!url_matcher_condition_set
.get()) {
135 URLMatcherConditionSet::Conditions url_matcher_conditions
;
136 url_matcher_conditions
.insert(
137 url_matcher_condition_factory
->CreateHostPrefixCondition(
139 url_matcher_condition_set
=
140 new URLMatcherConditionSet(++g_next_id
, url_matcher_conditions
);
142 return scoped_ptr
<ContentCondition
>(
143 new ContentCondition(url_matcher_condition_set
, css_rules
));
146 } // namespace extensions