| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "extensions/browser/api/declarative/declarative_rule.h" | 5 #include "extensions/browser/api/declarative/declarative_rule.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
| 9 #include "base/test/values_test_util.h" | 9 #include "base/test/values_test_util.h" |
| 10 #include "base/values.h" | 10 #include "base/values.h" |
| 11 #include "components/url_matcher/url_matcher_constants.h" | 11 #include "components/url_matcher/url_matcher_constants.h" |
| 12 #include "extensions/common/extension_builder.h" | 12 #include "extensions/common/extension_builder.h" |
| 13 #include "testing/gmock/include/gmock/gmock.h" | 13 #include "testing/gmock/include/gmock/gmock.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
| 15 | 15 |
| 16 using base::test::ParseJson; | 16 using base::test::ParseJson; |
| 17 using url_matcher::URLMatcher; | 17 using url_matcher::URLMatcher; |
| 18 using url_matcher::URLMatcherConditionFactory; | 18 using url_matcher::URLMatcherConditionFactory; |
| 19 using url_matcher::URLMatcherConditionSet; | 19 using url_matcher::URLMatcherConditionSet; |
| 20 | 20 |
| 21 namespace extensions { | 21 namespace extensions { |
| 22 | 22 |
| 23 namespace { | 23 namespace { |
| 24 | 24 |
| 25 scoped_ptr<base::DictionaryValue> SimpleManifest() { | 25 std::unique_ptr<base::DictionaryValue> SimpleManifest() { |
| 26 return DictionaryBuilder() | 26 return DictionaryBuilder() |
| 27 .Set("name", "extension") | 27 .Set("name", "extension") |
| 28 .Set("manifest_version", 2) | 28 .Set("manifest_version", 2) |
| 29 .Set("version", "1.0") | 29 .Set("version", "1.0") |
| 30 .Build(); | 30 .Build(); |
| 31 } | 31 } |
| 32 | 32 |
| 33 } // namespace | 33 } // namespace |
| 34 | 34 |
| 35 struct RecordingCondition { | 35 struct RecordingCondition { |
| 36 typedef int MatchData; | 36 typedef int MatchData; |
| 37 | 37 |
| 38 URLMatcherConditionFactory* factory; | 38 URLMatcherConditionFactory* factory; |
| 39 scoped_ptr<base::Value> value; | 39 std::unique_ptr<base::Value> value; |
| 40 | 40 |
| 41 void GetURLMatcherConditionSets( | 41 void GetURLMatcherConditionSets( |
| 42 URLMatcherConditionSet::Vector* condition_sets) const { | 42 URLMatcherConditionSet::Vector* condition_sets) const { |
| 43 // No condition sets. | 43 // No condition sets. |
| 44 } | 44 } |
| 45 | 45 |
| 46 static scoped_ptr<RecordingCondition> Create( | 46 static std::unique_ptr<RecordingCondition> Create( |
| 47 const Extension* extension, | 47 const Extension* extension, |
| 48 URLMatcherConditionFactory* url_matcher_condition_factory, | 48 URLMatcherConditionFactory* url_matcher_condition_factory, |
| 49 const base::Value& condition, | 49 const base::Value& condition, |
| 50 std::string* error) { | 50 std::string* error) { |
| 51 const base::DictionaryValue* dict = NULL; | 51 const base::DictionaryValue* dict = NULL; |
| 52 if (condition.GetAsDictionary(&dict) && dict->HasKey("bad_key")) { | 52 if (condition.GetAsDictionary(&dict) && dict->HasKey("bad_key")) { |
| 53 *error = "Found error key"; | 53 *error = "Found error key"; |
| 54 return scoped_ptr<RecordingCondition>(); | 54 return std::unique_ptr<RecordingCondition>(); |
| 55 } | 55 } |
| 56 | 56 |
| 57 scoped_ptr<RecordingCondition> result(new RecordingCondition()); | 57 std::unique_ptr<RecordingCondition> result(new RecordingCondition()); |
| 58 result->factory = url_matcher_condition_factory; | 58 result->factory = url_matcher_condition_factory; |
| 59 result->value.reset(condition.DeepCopy()); | 59 result->value.reset(condition.DeepCopy()); |
| 60 return result; | 60 return result; |
| 61 } | 61 } |
| 62 }; | 62 }; |
| 63 typedef DeclarativeConditionSet<RecordingCondition> RecordingConditionSet; | 63 typedef DeclarativeConditionSet<RecordingCondition> RecordingConditionSet; |
| 64 | 64 |
| 65 TEST(DeclarativeConditionTest, ErrorConditionSet) { | 65 TEST(DeclarativeConditionTest, ErrorConditionSet) { |
| 66 URLMatcher matcher; | 66 URLMatcher matcher; |
| 67 RecordingConditionSet::Values conditions; | 67 RecordingConditionSet::Values conditions; |
| 68 conditions.push_back(ParseJson("{\"key\": 1}")); | 68 conditions.push_back(ParseJson("{\"key\": 1}")); |
| 69 conditions.push_back(ParseJson("{\"bad_key\": 2}")); | 69 conditions.push_back(ParseJson("{\"bad_key\": 2}")); |
| 70 | 70 |
| 71 std::string error; | 71 std::string error; |
| 72 scoped_ptr<RecordingConditionSet> result = RecordingConditionSet::Create( | 72 std::unique_ptr<RecordingConditionSet> result = RecordingConditionSet::Create( |
| 73 NULL, matcher.condition_factory(), conditions, &error); | 73 NULL, matcher.condition_factory(), conditions, &error); |
| 74 EXPECT_EQ("Found error key", error); | 74 EXPECT_EQ("Found error key", error); |
| 75 ASSERT_FALSE(result); | 75 ASSERT_FALSE(result); |
| 76 } | 76 } |
| 77 | 77 |
| 78 TEST(DeclarativeConditionTest, CreateConditionSet) { | 78 TEST(DeclarativeConditionTest, CreateConditionSet) { |
| 79 URLMatcher matcher; | 79 URLMatcher matcher; |
| 80 RecordingConditionSet::Values conditions; | 80 RecordingConditionSet::Values conditions; |
| 81 conditions.push_back(ParseJson("{\"key\": 1}")); | 81 conditions.push_back(ParseJson("{\"key\": 1}")); |
| 82 conditions.push_back(ParseJson("[\"val1\", 2]")); | 82 conditions.push_back(ParseJson("[\"val1\", 2]")); |
| 83 | 83 |
| 84 // Test insertion | 84 // Test insertion |
| 85 std::string error; | 85 std::string error; |
| 86 scoped_ptr<RecordingConditionSet> result = RecordingConditionSet::Create( | 86 std::unique_ptr<RecordingConditionSet> result = RecordingConditionSet::Create( |
| 87 NULL, matcher.condition_factory(), conditions, &error); | 87 NULL, matcher.condition_factory(), conditions, &error); |
| 88 EXPECT_EQ("", error); | 88 EXPECT_EQ("", error); |
| 89 ASSERT_TRUE(result); | 89 ASSERT_TRUE(result); |
| 90 EXPECT_EQ(2u, result->conditions().size()); | 90 EXPECT_EQ(2u, result->conditions().size()); |
| 91 | 91 |
| 92 EXPECT_EQ(matcher.condition_factory(), result->conditions()[0]->factory); | 92 EXPECT_EQ(matcher.condition_factory(), result->conditions()[0]->factory); |
| 93 EXPECT_TRUE(ParseJson("{\"key\": 1}")->Equals( | 93 EXPECT_TRUE(ParseJson("{\"key\": 1}")->Equals( |
| 94 result->conditions()[0]->value.get())); | 94 result->conditions()[0]->value.get())); |
| 95 } | 95 } |
| 96 | 96 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 118 condition_sets->push_back(condition_set); | 118 condition_sets->push_back(condition_set); |
| 119 } | 119 } |
| 120 | 120 |
| 121 bool IsFulfilled(const MatchData& match_data) const { | 121 bool IsFulfilled(const MatchData& match_data) const { |
| 122 if (condition_set_id != -1 && | 122 if (condition_set_id != -1 && |
| 123 !ContainsKey(match_data.url_matches, condition_set_id)) | 123 !ContainsKey(match_data.url_matches, condition_set_id)) |
| 124 return false; | 124 return false; |
| 125 return match_data.value <= max_value; | 125 return match_data.value <= max_value; |
| 126 } | 126 } |
| 127 | 127 |
| 128 static scoped_ptr<FulfillableCondition> Create( | 128 static std::unique_ptr<FulfillableCondition> Create( |
| 129 const Extension* extension, | 129 const Extension* extension, |
| 130 URLMatcherConditionFactory* url_matcher_condition_factory, | 130 URLMatcherConditionFactory* url_matcher_condition_factory, |
| 131 const base::Value& condition, | 131 const base::Value& condition, |
| 132 std::string* error) { | 132 std::string* error) { |
| 133 scoped_ptr<FulfillableCondition> result(new FulfillableCondition()); | 133 std::unique_ptr<FulfillableCondition> result(new FulfillableCondition()); |
| 134 const base::DictionaryValue* dict; | 134 const base::DictionaryValue* dict; |
| 135 if (!condition.GetAsDictionary(&dict)) { | 135 if (!condition.GetAsDictionary(&dict)) { |
| 136 *error = "Expected dict"; | 136 *error = "Expected dict"; |
| 137 return result; | 137 return result; |
| 138 } | 138 } |
| 139 if (!dict->GetInteger("url_id", &result->condition_set_id)) | 139 if (!dict->GetInteger("url_id", &result->condition_set_id)) |
| 140 result->condition_set_id = -1; | 140 result->condition_set_id = -1; |
| 141 if (!dict->GetInteger("max", &result->max_value)) | 141 if (!dict->GetInteger("max", &result->max_value)) |
| 142 *error = "Expected integer at ['max']"; | 142 *error = "Expected integer at ['max']"; |
| 143 if (result->condition_set_id != -1) { | 143 if (result->condition_set_id != -1) { |
| 144 result->condition_set = new URLMatcherConditionSet( | 144 result->condition_set = new URLMatcherConditionSet( |
| 145 result->condition_set_id, | 145 result->condition_set_id, |
| 146 URLMatcherConditionSet::Conditions()); | 146 URLMatcherConditionSet::Conditions()); |
| 147 } | 147 } |
| 148 return result; | 148 return result; |
| 149 } | 149 } |
| 150 }; | 150 }; |
| 151 | 151 |
| 152 TEST(DeclarativeConditionTest, FulfillConditionSet) { | 152 TEST(DeclarativeConditionTest, FulfillConditionSet) { |
| 153 typedef DeclarativeConditionSet<FulfillableCondition> FulfillableConditionSet; | 153 typedef DeclarativeConditionSet<FulfillableCondition> FulfillableConditionSet; |
| 154 FulfillableConditionSet::Values conditions; | 154 FulfillableConditionSet::Values conditions; |
| 155 conditions.push_back(ParseJson("{\"url_id\": 1, \"max\": 3}")); | 155 conditions.push_back(ParseJson("{\"url_id\": 1, \"max\": 3}")); |
| 156 conditions.push_back(ParseJson("{\"url_id\": 2, \"max\": 5}")); | 156 conditions.push_back(ParseJson("{\"url_id\": 2, \"max\": 5}")); |
| 157 conditions.push_back(ParseJson("{\"url_id\": 3, \"max\": 1}")); | 157 conditions.push_back(ParseJson("{\"url_id\": 3, \"max\": 1}")); |
| 158 conditions.push_back(ParseJson("{\"max\": -5}")); // No url. | 158 conditions.push_back(ParseJson("{\"max\": -5}")); // No url. |
| 159 | 159 |
| 160 // Test insertion | 160 // Test insertion |
| 161 std::string error; | 161 std::string error; |
| 162 scoped_ptr<FulfillableConditionSet> result = | 162 std::unique_ptr<FulfillableConditionSet> result = |
| 163 FulfillableConditionSet::Create(NULL, NULL, conditions, &error); | 163 FulfillableConditionSet::Create(NULL, NULL, conditions, &error); |
| 164 ASSERT_EQ("", error); | 164 ASSERT_EQ("", error); |
| 165 ASSERT_TRUE(result); | 165 ASSERT_TRUE(result); |
| 166 EXPECT_EQ(4u, result->conditions().size()); | 166 EXPECT_EQ(4u, result->conditions().size()); |
| 167 | 167 |
| 168 std::set<URLMatcherConditionSet::ID> url_matches; | 168 std::set<URLMatcherConditionSet::ID> url_matches; |
| 169 FulfillableCondition::MatchData match_data = { 0, url_matches }; | 169 FulfillableCondition::MatchData match_data = { 0, url_matches }; |
| 170 EXPECT_FALSE(result->IsFulfilled(1, match_data)) | 170 EXPECT_FALSE(result->IsFulfilled(1, match_data)) |
| 171 << "Testing an ID that's not in url_matches forwards to the Condition, " | 171 << "Testing an ID that's not in url_matches forwards to the Condition, " |
| 172 << "which doesn't match."; | 172 << "which doesn't match."; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 }; | 253 }; |
| 254 typedef DeclarativeActionSet<SummingAction> SummingActionSet; | 254 typedef DeclarativeActionSet<SummingAction> SummingActionSet; |
| 255 | 255 |
| 256 TEST(DeclarativeActionTest, ErrorActionSet) { | 256 TEST(DeclarativeActionTest, ErrorActionSet) { |
| 257 SummingActionSet::Values actions; | 257 SummingActionSet::Values actions; |
| 258 actions.push_back(ParseJson("{\"value\": 1}")); | 258 actions.push_back(ParseJson("{\"value\": 1}")); |
| 259 actions.push_back(ParseJson("{\"error\": \"the error\"}")); | 259 actions.push_back(ParseJson("{\"error\": \"the error\"}")); |
| 260 | 260 |
| 261 std::string error; | 261 std::string error; |
| 262 bool bad = false; | 262 bool bad = false; |
| 263 scoped_ptr<SummingActionSet> result = | 263 std::unique_ptr<SummingActionSet> result = |
| 264 SummingActionSet::Create(NULL, NULL, actions, &error, &bad); | 264 SummingActionSet::Create(NULL, NULL, actions, &error, &bad); |
| 265 EXPECT_EQ("the error", error); | 265 EXPECT_EQ("the error", error); |
| 266 EXPECT_FALSE(bad); | 266 EXPECT_FALSE(bad); |
| 267 EXPECT_FALSE(result); | 267 EXPECT_FALSE(result); |
| 268 | 268 |
| 269 actions.clear(); | 269 actions.clear(); |
| 270 actions.push_back(ParseJson("{\"value\": 1}")); | 270 actions.push_back(ParseJson("{\"value\": 1}")); |
| 271 actions.push_back(ParseJson("{\"bad\": 3}")); | 271 actions.push_back(ParseJson("{\"bad\": 3}")); |
| 272 result = SummingActionSet::Create(NULL, NULL, actions, &error, &bad); | 272 result = SummingActionSet::Create(NULL, NULL, actions, &error, &bad); |
| 273 EXPECT_EQ("", error); | 273 EXPECT_EQ("", error); |
| 274 EXPECT_TRUE(bad); | 274 EXPECT_TRUE(bad); |
| 275 EXPECT_FALSE(result); | 275 EXPECT_FALSE(result); |
| 276 } | 276 } |
| 277 | 277 |
| 278 TEST(DeclarativeActionTest, ApplyActionSet) { | 278 TEST(DeclarativeActionTest, ApplyActionSet) { |
| 279 SummingActionSet::Values actions; | 279 SummingActionSet::Values actions; |
| 280 actions.push_back( | 280 actions.push_back( |
| 281 ParseJson("{\"value\": 1," | 281 ParseJson("{\"value\": 1," |
| 282 " \"priority\": 5}")); | 282 " \"priority\": 5}")); |
| 283 actions.push_back(ParseJson("{\"value\": 2}")); | 283 actions.push_back(ParseJson("{\"value\": 2}")); |
| 284 | 284 |
| 285 // Test insertion | 285 // Test insertion |
| 286 std::string error; | 286 std::string error; |
| 287 bool bad = false; | 287 bool bad = false; |
| 288 scoped_ptr<SummingActionSet> result = | 288 std::unique_ptr<SummingActionSet> result = |
| 289 SummingActionSet::Create(NULL, NULL, actions, &error, &bad); | 289 SummingActionSet::Create(NULL, NULL, actions, &error, &bad); |
| 290 EXPECT_EQ("", error); | 290 EXPECT_EQ("", error); |
| 291 EXPECT_FALSE(bad); | 291 EXPECT_FALSE(bad); |
| 292 ASSERT_TRUE(result); | 292 ASSERT_TRUE(result); |
| 293 EXPECT_EQ(2u, result->actions().size()); | 293 EXPECT_EQ(2u, result->actions().size()); |
| 294 | 294 |
| 295 int sum = 0; | 295 int sum = 0; |
| 296 result->Apply("ext_id", base::Time(), &sum); | 296 result->Apply("ext_id", base::Time(), &sum); |
| 297 EXPECT_EQ(3, sum); | 297 EXPECT_EQ(3, sum); |
| 298 EXPECT_EQ(5, result->GetMinimumPriority()); | 298 EXPECT_EQ(5, result->GetMinimumPriority()); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 320 const char kExtensionId[] = "ext1"; | 320 const char kExtensionId[] = "ext1"; |
| 321 scoped_refptr<Extension> extension = ExtensionBuilder() | 321 scoped_refptr<Extension> extension = ExtensionBuilder() |
| 322 .SetManifest(SimpleManifest()) | 322 .SetManifest(SimpleManifest()) |
| 323 .SetID(kExtensionId) | 323 .SetID(kExtensionId) |
| 324 .Build(); | 324 .Build(); |
| 325 | 325 |
| 326 base::Time install_time = base::Time::Now(); | 326 base::Time install_time = base::Time::Now(); |
| 327 | 327 |
| 328 URLMatcher matcher; | 328 URLMatcher matcher; |
| 329 std::string error; | 329 std::string error; |
| 330 scoped_ptr<Rule> rule(Rule::Create(matcher.condition_factory(), | 330 std::unique_ptr<Rule> rule(Rule::Create( |
| 331 NULL, | 331 matcher.condition_factory(), NULL, extension.get(), install_time, |
| 332 extension.get(), | 332 json_rule, Rule::ConsistencyChecker(), &error)); |
| 333 install_time, | |
| 334 json_rule, | |
| 335 Rule::ConsistencyChecker(), | |
| 336 &error)); | |
| 337 EXPECT_EQ("", error); | 333 EXPECT_EQ("", error); |
| 338 ASSERT_TRUE(rule.get()); | 334 ASSERT_TRUE(rule.get()); |
| 339 | 335 |
| 340 EXPECT_EQ(kExtensionId, rule->id().first); | 336 EXPECT_EQ(kExtensionId, rule->id().first); |
| 341 EXPECT_EQ("rule1", rule->id().second); | 337 EXPECT_EQ("rule1", rule->id().second); |
| 342 | 338 |
| 343 EXPECT_EQ(200, rule->priority()); | 339 EXPECT_EQ(200, rule->priority()); |
| 344 | 340 |
| 345 const Rule::ConditionSet& condition_set = rule->conditions(); | 341 const Rule::ConditionSet& condition_set = rule->conditions(); |
| 346 const Rule::ConditionSet::Conditions& conditions = | 342 const Rule::ConditionSet::Conditions& conditions = |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 " {\"url_id\": 2, \"max\": 5}, \n" | 385 " {\"url_id\": 2, \"max\": 5}, \n" |
| 390 " ], \n" | 386 " ], \n" |
| 391 " \"actions\": [ \n" | 387 " \"actions\": [ \n" |
| 392 " { \n" | 388 " { \n" |
| 393 " \"value\": 2 \n" | 389 " \"value\": 2 \n" |
| 394 " } \n" | 390 " } \n" |
| 395 " ], \n" | 391 " ], \n" |
| 396 " \"priority\": 200 \n" | 392 " \"priority\": 200 \n" |
| 397 "}"), | 393 "}"), |
| 398 json_rule.get())); | 394 json_rule.get())); |
| 399 scoped_ptr<Rule> rule(Rule::Create(matcher.condition_factory(), | 395 std::unique_ptr<Rule> rule(Rule::Create( |
| 400 NULL, | 396 matcher.condition_factory(), NULL, extension.get(), base::Time(), |
| 401 extension.get(), | 397 json_rule, base::Bind(AtLeastOneCondition), &error)); |
| 402 base::Time(), | |
| 403 json_rule, | |
| 404 base::Bind(AtLeastOneCondition), | |
| 405 &error)); | |
| 406 EXPECT_TRUE(rule); | 398 EXPECT_TRUE(rule); |
| 407 EXPECT_EQ("", error); | 399 EXPECT_EQ("", error); |
| 408 | 400 |
| 409 ASSERT_TRUE(Rule::JsonRule::Populate( | 401 ASSERT_TRUE(Rule::JsonRule::Populate( |
| 410 *ParseJson("{ \n" | 402 *ParseJson("{ \n" |
| 411 " \"id\": \"rule1\", \n" | 403 " \"id\": \"rule1\", \n" |
| 412 " \"conditions\": [ \n" | 404 " \"conditions\": [ \n" |
| 413 " ], \n" | 405 " ], \n" |
| 414 " \"actions\": [ \n" | 406 " \"actions\": [ \n" |
| 415 " { \n" | 407 " { \n" |
| 416 " \"value\": 2 \n" | 408 " \"value\": 2 \n" |
| 417 " } \n" | 409 " } \n" |
| 418 " ], \n" | 410 " ], \n" |
| 419 " \"priority\": 200 \n" | 411 " \"priority\": 200 \n" |
| 420 "}"), | 412 "}"), |
| 421 json_rule.get())); | 413 json_rule.get())); |
| 422 rule = Rule::Create(matcher.condition_factory(), | 414 rule = Rule::Create(matcher.condition_factory(), |
| 423 NULL, | 415 NULL, |
| 424 extension.get(), | 416 extension.get(), |
| 425 base::Time(), | 417 base::Time(), |
| 426 json_rule, | 418 json_rule, |
| 427 base::Bind(AtLeastOneCondition), | 419 base::Bind(AtLeastOneCondition), |
| 428 &error); | 420 &error); |
| 429 EXPECT_FALSE(rule); | 421 EXPECT_FALSE(rule); |
| 430 EXPECT_EQ("No conditions", error); | 422 EXPECT_EQ("No conditions", error); |
| 431 } | 423 } |
| 432 | 424 |
| 433 } // namespace extensions | 425 } // namespace extensions |
| OLD | NEW |