- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / declarative_content / content_condition.cc
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/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"
11
12 namespace keys = extensions::declarative_content_constants;
13
14 namespace {
15 static extensions::URLMatcherConditionSet::ID g_next_id = 0;
16
17 // TODO(jyasskin): improve error messaging to give more meaningful messages
18 // to the extension developer.
19 // Error messages:
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";
26 }  // namespace
27
28 namespace extensions {
29
30 namespace keys = declarative_content_constants;
31
32 RendererContentMatchData::RendererContentMatchData() {}
33 RendererContentMatchData::~RendererContentMatchData() {}
34
35 //
36 // ContentCondition
37 //
38
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());
45 }
46
47 ContentCondition::~ContentCondition() {}
48
49 bool ContentCondition::IsFulfilled(
50     const RendererContentMatchData& renderer_data) const {
51   if (!ContainsKey(renderer_data.page_url_matches,
52                    url_matcher_conditions_->id()))
53     return false;
54
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))
59       return false;
60   }
61   return true;
62 }
63
64 // static
65 scoped_ptr<ContentCondition> ContentCondition::Create(
66     const Extension* extension,
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>();
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>();
81   }
82   if (instance_type != keys::kPageStateMatcherType) {
83     *error = kExpectedOtherConditionType;
84     return scoped_ptr<ContentCondition>();
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.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) {
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         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());
114             break;
115           }
116           css_rules.push_back(css_rule);
117         }
118       } else {
119         *error = base::StringPrintf(kInvalidTypeOfParamter,
120                                     condition_attribute_name.c_str());
121       }
122     } else {
123       *error = base::StringPrintf(kUnknownConditionAttribute,
124                                   condition_attribute_name.c_str());
125     }
126     if (!error->empty())
127       return scoped_ptr<ContentCondition>();
128   }
129
130   if (!url_matcher_condition_set.get()) {
131     URLMatcherConditionSet::Conditions url_matcher_conditions;
132     url_matcher_conditions.insert(
133         url_matcher_condition_factory->CreateHostPrefixCondition(
134             std::string()));
135     url_matcher_condition_set =
136         new URLMatcherConditionSet(++g_next_id, url_matcher_conditions);
137   }
138   return scoped_ptr<ContentCondition>(
139       new ContentCondition(url_matcher_condition_set, css_rules));
140 }
141
142 }  // namespace extensions