Index: chrome/browser/extensions/api/declarative_content/content_condition.cc |
diff --git a/chrome/browser/extensions/api/declarative_content/content_condition.cc b/chrome/browser/extensions/api/declarative_content/content_condition.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8ae49e5d41df84e83801fb058b95542d672a7b02 |
--- /dev/null |
+++ b/chrome/browser/extensions/api/declarative_content/content_condition.cc |
@@ -0,0 +1,140 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/extensions/api/declarative_content/content_condition.h" |
+ |
+#include "base/stringprintf.h" |
+#include "base/values.h" |
+#include "chrome/browser/extensions/api/declarative_content/content_constants.h" |
+#include "chrome/common/extensions/matcher/url_matcher.h" |
+#include "chrome/common/extensions/matcher/url_matcher_factory.h" |
+ |
+namespace keys = extensions::declarative_content_constants; |
+ |
+namespace { |
+static extensions::URLMatcherConditionSet::ID g_next_id = 0; |
+ |
+// TODO(jyasskin): improve error messaging to give more meaningful messages |
+// to the extension developer. |
+// Error messages: |
+const char kExpectedDictionary[] = "A condition has to be a dictionary."; |
+const char kConditionWithoutInstanceType[] = "A condition had no instanceType"; |
+const char kExpectedOtherConditionType[] = "Expected a condition of type " |
+ "declarativeContent.PageStateMatcher"; |
+const char kUnknownConditionAttribute[] = "Unknown condition attribute '%s'"; |
+const char kInvalidTypeOfParamter[] = "Attribute '%s' has an invalid type"; |
+} // namespace |
+ |
+namespace extensions { |
+ |
+namespace keys = declarative_content_constants; |
+ |
+RendererContentMatchData::RendererContentMatchData() {} |
+RendererContentMatchData::~RendererContentMatchData() {} |
+ |
+// |
+// ContentCondition |
+// |
+ |
+ContentCondition::ContentCondition( |
+ scoped_refptr<URLMatcherConditionSet> url_matcher_conditions, |
+ const std::vector<std::string>& css_selectors) |
+ : url_matcher_conditions_(url_matcher_conditions), |
+ css_selectors_(css_selectors) { |
+ CHECK(url_matcher_conditions.get()); |
+} |
+ |
+ContentCondition::~ContentCondition() {} |
+ |
+bool ContentCondition::IsFulfilled( |
+ const RendererContentMatchData& renderer_data) const { |
+ if (!ContainsKey(renderer_data.page_url_matches, |
+ url_matcher_conditions_->id())) |
+ return false; |
+ |
+ // All attributes must be fulfilled for a fulfilled condition. |
+ for (std::vector<std::string>::const_iterator i = |
+ css_selectors_.begin(); i != css_selectors_.end(); ++i) { |
+ if (!ContainsKey(renderer_data.css_selectors, *i)) |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+// static |
+scoped_ptr<ContentCondition> ContentCondition::Create( |
+ URLMatcherConditionFactory* url_matcher_condition_factory, |
+ const base::Value& condition, |
+ std::string* error) { |
+ const base::DictionaryValue* condition_dict = NULL; |
+ if (!condition.GetAsDictionary(&condition_dict)) { |
+ *error = kExpectedDictionary; |
+ return scoped_ptr<ContentCondition>(NULL); |
+ } |
+ |
+ // Verify that we are dealing with a Condition whose type we understand. |
+ std::string instance_type; |
+ if (!condition_dict->GetString(keys::kInstanceType, &instance_type)) { |
+ *error = kConditionWithoutInstanceType; |
+ return scoped_ptr<ContentCondition>(NULL); |
+ } |
+ if (instance_type != keys::kPageStateMatcherType) { |
+ *error = kExpectedOtherConditionType; |
+ return scoped_ptr<ContentCondition>(NULL); |
+ } |
+ |
+ scoped_refptr<URLMatcherConditionSet> url_matcher_condition_set; |
+ std::vector<std::string> css_rules; |
+ |
+ for (base::DictionaryValue::Iterator iter(*condition_dict); |
+ iter.HasNext(); iter.Advance()) { |
+ const std::string& condition_attribute_name = iter.key(); |
+ const Value& condition_attribute_value = iter.value(); |
+ if (condition_attribute_name == keys::kInstanceType) { |
+ // Skip this. |
+ } else if (condition_attribute_name == keys::kPageUrl) { |
+ const base::DictionaryValue* dict = NULL; |
+ if (!condition_attribute_value.GetAsDictionary(&dict)) { |
+ *error = base::StringPrintf(kInvalidTypeOfParamter, |
+ condition_attribute_name.c_str()); |
+ } else { |
+ url_matcher_condition_set = |
+ URLMatcherFactory::CreateFromURLFilterDictionary( |
+ url_matcher_condition_factory, dict, ++g_next_id, error); |
+ } |
+ } else if (condition_attribute_name == keys::kCss) { |
+ const base::ListValue* css_rules_value = NULL; |
+ if (!condition_attribute_value.GetAsList(&css_rules_value)) { |
+ *error = base::StringPrintf(kInvalidTypeOfParamter, |
+ condition_attribute_name.c_str()); |
+ } |
+ for (size_t i = 0; i < css_rules_value->GetSize(); ++i) { |
+ std::string css_rule; |
+ if (!css_rules_value->GetString(i, &css_rule)) { |
+ *error = base::StringPrintf(kInvalidTypeOfParamter, |
+ condition_attribute_name.c_str()); |
+ break; |
+ } |
+ css_rules.push_back(css_rule); |
+ } |
+ } else { |
+ *error = base::StringPrintf(kUnknownConditionAttribute, |
+ condition_attribute_name.c_str()); |
+ } |
+ if (!error->empty()) |
+ return scoped_ptr<ContentCondition>(NULL); |
+ } |
+ |
+ if (!url_matcher_condition_set) { |
+ URLMatcherConditionSet::Conditions url_matcher_conditions; |
+ url_matcher_conditions.insert( |
+ url_matcher_condition_factory->CreateHostPrefixCondition("")); |
+ url_matcher_condition_set = |
+ new URLMatcherConditionSet(++g_next_id, url_matcher_conditions); |
+ } |
+ return scoped_ptr<ContentCondition>( |
+ new ContentCondition(url_matcher_condition_set, css_rules)); |
+} |
+ |
+} // namespace extensions |