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" |
| 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 std::set<URLMatcherConditionSet::ID>& url_matches, |
| 54 const RendererContentMatchData& renderer_data) const { |
| 55 if (!ContainsKey(url_matches, url_matcher_conditions_->id())) |
| 56 return false; |
| 57 |
| 58 // All attributes must be fulfilled for a fulfilled condition. |
| 59 for (std::vector<std::string>::const_iterator i = |
| 60 css_rules_.begin(); i != css_rules_.end(); ++i) { |
| 61 if (!ContainsKey(renderer_data.css_rules, *i)) |
| 62 return false; |
| 63 } |
| 64 return true; |
| 65 } |
| 66 |
| 67 // static |
| 68 scoped_ptr<ContentCondition> ContentCondition::Create( |
| 69 URLMatcherConditionFactory* url_matcher_condition_factory, |
| 70 const base::Value& condition, |
| 71 std::string* error) { |
| 72 const base::DictionaryValue* condition_dict = NULL; |
| 73 if (!condition.GetAsDictionary(&condition_dict)) { |
| 74 *error = kExpectedDictionary; |
| 75 return scoped_ptr<ContentCondition>(NULL); |
| 76 } |
| 77 |
| 78 // Verify that we are dealing with a Condition whose type we understand. |
| 79 std::string instance_type; |
| 80 if (!condition_dict->GetString(keys::kInstanceType, &instance_type)) { |
| 81 *error = kConditionWithoutInstanceType; |
| 82 return scoped_ptr<ContentCondition>(NULL); |
| 83 } |
| 84 if (instance_type != keys::kPageStateMatcherType) { |
| 85 *error = kExpectedOtherConditionType; |
| 86 return scoped_ptr<ContentCondition>(NULL); |
| 87 } |
| 88 |
| 89 scoped_refptr<URLMatcherConditionSet> url_matcher_condition_set; |
| 90 std::vector<std::string> css_rules; |
| 91 |
| 92 for (base::DictionaryValue::Iterator iter(*condition_dict); |
| 93 iter.HasNext(); iter.Advance()) { |
| 94 const std::string& condition_attribute_name = iter.key(); |
| 95 const Value& condition_attribute_value = iter.value(); |
| 96 if (condition_attribute_name == keys::kInstanceType) { |
| 97 // Skip this. |
| 98 } else if (condition_attribute_name == keys::kPageUrl) { |
| 99 const base::DictionaryValue* dict = NULL; |
| 100 if (!condition_attribute_value.GetAsDictionary(&dict)) { |
| 101 *error = base::StringPrintf(kInvalidTypeOfParamter, |
| 102 condition_attribute_name.c_str()); |
| 103 } else { |
| 104 url_matcher_condition_set = |
| 105 URLMatcherFactory::CreateFromURLFilterDictionary( |
| 106 url_matcher_condition_factory, dict, ++g_next_id, error); |
| 107 } |
| 108 } else if (condition_attribute_name == keys::kCss) { |
| 109 const base::ListValue* css_rules_value = NULL; |
| 110 if (!condition_attribute_value.GetAsList(&css_rules_value)) { |
| 111 *error = base::StringPrintf(kInvalidTypeOfParamter, |
| 112 condition_attribute_name.c_str()); |
| 113 } |
| 114 for (size_t i = 0; i < css_rules_value->GetSize(); ++i) { |
| 115 std::string css_rule; |
| 116 if (!css_rules_value->GetString(i, &css_rule)) { |
| 117 *error = base::StringPrintf(kInvalidTypeOfParamter, |
| 118 condition_attribute_name.c_str()); |
| 119 break; |
| 120 } |
| 121 css_rules.push_back(css_rule); |
| 122 } |
| 123 } else { |
| 124 *error = base::StringPrintf(kUnknownConditionAttribute, |
| 125 condition_attribute_name.c_str()); |
| 126 } |
| 127 if (!error->empty()) |
| 128 return scoped_ptr<ContentCondition>(NULL); |
| 129 } |
| 130 |
| 131 if (!url_matcher_condition_set) { |
| 132 URLMatcherConditionSet::Conditions url_matcher_conditions; |
| 133 url_matcher_conditions.insert( |
| 134 url_matcher_condition_factory->CreateHostPrefixCondition("")); |
| 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 |
OLD | NEW |