1 // Copyright 2013 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 "extensions/browser/api/declarative/rules_registry.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/values.h"
11 #include "content/public/test/test_browser_thread.h"
12 #include "extensions/browser/api/declarative/rules_registry_service.h"
13 #include "extensions/browser/api/declarative/test_rules_registry.h"
14 #include "extensions/browser/api_test_utils.h"
15 #include "extensions/common/extension.h"
16 #include "extensions/common/extension_builder.h"
17 #include "testing/gtest/include/gtest/gtest.h"
20 const char kExtensionId
[] = "foobar";
21 const char kRuleId
[] = "foo";
22 const int key
= extensions::RulesRegistryService::kDefaultRulesRegistryID
;
25 namespace extensions
{
27 using api_test_utils::ParseDictionary
;
29 TEST(RulesRegistryTest
, FillOptionalIdentifiers
) {
30 base::MessageLoopForUI message_loop
;
31 content::TestBrowserThread
thread(content::BrowserThread::UI
, &message_loop
);
34 scoped_refptr
<RulesRegistry
> registry
=
35 new TestRulesRegistry(content::BrowserThread::UI
, "" /*event_name*/, key
);
37 // Add rules and check that their identifiers are filled and unique.
39 std::vector
<linked_ptr
<api::events::Rule
>> add_rules
;
40 add_rules
.push_back(make_linked_ptr(new api::events::Rule
));
41 add_rules
.push_back(make_linked_ptr(new api::events::Rule
));
42 error
= registry
->AddRules(kExtensionId
, add_rules
);
43 EXPECT_TRUE(error
.empty()) << error
;
45 std::vector
<linked_ptr
<api::events::Rule
>> get_rules
;
46 registry
->GetAllRules(kExtensionId
, &get_rules
);
48 ASSERT_EQ(2u, get_rules
.size());
50 ASSERT_TRUE(get_rules
[0]->id
.get());
51 EXPECT_NE("", *get_rules
[0]->id
);
53 ASSERT_TRUE(get_rules
[1]->id
.get());
54 EXPECT_NE("", *get_rules
[1]->id
);
56 EXPECT_NE(*get_rules
[0]->id
, *get_rules
[1]->id
);
58 EXPECT_EQ(1u /*extensions*/ + 2u /*rules*/,
59 registry
->GetNumberOfUsedRuleIdentifiersForTesting());
61 // Check that we cannot add a new rule with the same ID.
63 std::vector
<linked_ptr
<api::events::Rule
>> add_rules_2
;
64 add_rules_2
.push_back(make_linked_ptr(new api::events::Rule
));
65 add_rules_2
[0]->id
.reset(new std::string(*get_rules
[0]->id
));
66 error
= registry
->AddRules(kExtensionId
, add_rules_2
);
67 EXPECT_FALSE(error
.empty());
69 std::vector
<linked_ptr
<api::events::Rule
>> get_rules_2
;
70 registry
->GetAllRules(kExtensionId
, &get_rules_2
);
71 ASSERT_EQ(2u, get_rules_2
.size());
72 EXPECT_EQ(1u /*extensions*/ + 2u /*rules*/,
73 registry
->GetNumberOfUsedRuleIdentifiersForTesting());
75 // Check that we can register the old rule IDs once they were unregistered.
77 std::vector
<std::string
> remove_rules_3
;
78 remove_rules_3
.push_back(*get_rules
[0]->id
);
79 error
= registry
->RemoveRules(kExtensionId
, remove_rules_3
);
80 EXPECT_TRUE(error
.empty()) << error
;
82 EXPECT_EQ(1u /*extensions*/ + 1u /*rules*/,
83 registry
->GetNumberOfUsedRuleIdentifiersForTesting());
85 std::vector
<linked_ptr
<api::events::Rule
>> get_rules_3a
;
86 registry
->GetAllRules(kExtensionId
, &get_rules_3a
);
87 ASSERT_EQ(1u, get_rules_3a
.size());
89 std::vector
<linked_ptr
<api::events::Rule
>> add_rules_3
;
90 add_rules_3
.push_back(make_linked_ptr(new api::events::Rule
));
91 add_rules_3
[0]->id
.reset(new std::string(*get_rules
[0]->id
));
92 error
= registry
->AddRules(kExtensionId
, add_rules_3
);
93 EXPECT_TRUE(error
.empty()) << error
;
94 EXPECT_EQ(1u /*extensions*/ + 2u /*rules*/,
95 registry
->GetNumberOfUsedRuleIdentifiersForTesting());
97 std::vector
<linked_ptr
<api::events::Rule
>> get_rules_3b
;
98 registry
->GetAllRules(kExtensionId
, &get_rules_3b
);
99 ASSERT_EQ(2u, get_rules_3b
.size());
101 // Check that we can register a rule with an ID that is not modified.
103 error
= registry
->RemoveAllRules(kExtensionId
);
104 EXPECT_TRUE(error
.empty()) << error
;
105 EXPECT_EQ(0u /*extensions*/ + 0u /*rules*/,
106 registry
->GetNumberOfUsedRuleIdentifiersForTesting());
108 std::vector
<linked_ptr
<api::events::Rule
>> get_rules_4a
;
109 registry
->GetAllRules(kExtensionId
, &get_rules_4a
);
110 ASSERT_TRUE(get_rules_4a
.empty());
112 std::vector
<linked_ptr
<api::events::Rule
>> add_rules_4
;
113 add_rules_4
.push_back(make_linked_ptr(new api::events::Rule
));
114 add_rules_4
[0]->id
.reset(new std::string(kRuleId
));
115 error
= registry
->AddRules(kExtensionId
, add_rules_4
);
116 EXPECT_TRUE(error
.empty()) << error
;
118 EXPECT_EQ(1u /*extensions*/ + 1u /*rules*/,
119 registry
->GetNumberOfUsedRuleIdentifiersForTesting());
121 std::vector
<linked_ptr
<api::events::Rule
>> get_rules_4b
;
122 registry
->GetAllRules(kExtensionId
, &get_rules_4b
);
124 ASSERT_EQ(1u, get_rules_4b
.size());
126 ASSERT_TRUE(get_rules_4b
[0]->id
.get());
127 EXPECT_EQ(kRuleId
, *get_rules_4b
[0]->id
);
130 scoped_ptr
<base::DictionaryValue
> manifest
= ParseDictionary(
132 " \"name\": \"Test\","
133 " \"version\": \"1\""
135 scoped_refptr
<Extension
> extension
= ExtensionBuilder()
136 .SetManifest(manifest
.Pass())
139 registry
->OnExtensionUninstalled(extension
.get());
140 EXPECT_EQ(0u /*extensions*/ + 0u /*rules*/,
141 registry
->GetNumberOfUsedRuleIdentifiersForTesting());
143 // Make sure that deletion traits of registry are executed.
145 message_loop
.RunUntilIdle();
148 TEST(RulesRegistryTest
, FillOptionalPriority
) {
149 base::MessageLoopForUI message_loop
;
150 content::TestBrowserThread
thread(content::BrowserThread::UI
, &message_loop
);
153 scoped_refptr
<RulesRegistry
> registry
=
154 new TestRulesRegistry(content::BrowserThread::UI
, "" /*event_name*/, key
);
156 // Add rules and check that their priorities are filled if they are empty.
158 std::vector
<linked_ptr
<api::events::Rule
>> add_rules
;
159 add_rules
.push_back(make_linked_ptr(new api::events::Rule
));
160 add_rules
[0]->priority
.reset(new int(2));
161 add_rules
.push_back(make_linked_ptr(new api::events::Rule
));
162 error
= registry
->AddRules(kExtensionId
, add_rules
);
163 EXPECT_TRUE(error
.empty()) << error
;
165 std::vector
<linked_ptr
<api::events::Rule
>> get_rules
;
166 registry
->GetAllRules(kExtensionId
, &get_rules
);
168 ASSERT_EQ(2u, get_rules
.size());
170 ASSERT_TRUE(get_rules
[0]->priority
.get());
171 ASSERT_TRUE(get_rules
[1]->priority
.get());
173 // Verify the precondition so that the following EXPECT_EQ statements work.
174 EXPECT_GT(RulesRegistry::DEFAULT_PRIORITY
, 2);
175 EXPECT_EQ(2, std::min(*get_rules
[0]->priority
, *get_rules
[1]->priority
));
176 EXPECT_EQ(RulesRegistry::DEFAULT_PRIORITY
,
177 std::max(*get_rules
[0]->priority
, *get_rules
[1]->priority
));
179 // Make sure that deletion traits of registry are executed.
181 message_loop
.RunUntilIdle();
184 // Test verifies 2 rules defined in the manifest appear in the registry.
185 TEST(RulesRegistryTest
, TwoRulesInManifest
) {
186 base::MessageLoopForUI message_loop
;
187 content::TestBrowserThread
thread(content::BrowserThread::UI
, &message_loop
);
190 scoped_ptr
<base::DictionaryValue
> manifest
= ParseDictionary(
192 " \"name\": \"Test\","
193 " \"version\": \"1\","
194 " \"event_rules\": ["
197 " \"priority\": 200,"
198 " \"tags\": [\"tagged\"],"
199 " \"event\": \"declarativeContent.onPageChanged\","
201 " \"type\": \"declarativeContent.ShowPageAction\""
203 " \"conditions\" : [{"
204 " \"css\": [\"video\"],"
205 " \"type\" : \"declarativeContent.PageStateMatcher\""
209 " \"event\": \"declarativeContent.onPageChanged\","
211 " \"type\": \"declarativeContent.ShowPageAction\""
213 " \"conditions\" : [{"
214 " \"css\": [\"input[type='password']\"],"
215 " \"type\" : \"declarativeContent.PageStateMatcher\""
220 scoped_refptr
<Extension
> extension
= ExtensionBuilder()
221 .SetManifest(manifest
.Pass())
225 scoped_refptr
<RulesRegistry
> registry
= new TestRulesRegistry(
226 content::BrowserThread::UI
, "declarativeContent.onPageChanged", key
);
227 // Simulate what RulesRegistryService would do on extension load.
228 registry
->OnExtensionLoaded(extension
.get());
230 std::vector
<linked_ptr
<api::events::Rule
>> get_rules
;
231 registry
->GetAllRules(kExtensionId
, &get_rules
);
233 ASSERT_EQ(2u, get_rules
.size());
234 scoped_ptr
<base::DictionaryValue
> expected_rule_0
= ParseDictionary(
237 " \"priority\": 200,"
238 " \"tags\": [\"tagged\"],"
240 " \"instanceType\": \"declarativeContent.ShowPageAction\""
242 " \"conditions\" : [{"
243 " \"css\": [\"video\"],"
244 " \"instanceType\" : \"declarativeContent.PageStateMatcher\""
247 EXPECT_TRUE(expected_rule_0
->Equals(get_rules
[0]->ToValue().get()));
249 scoped_ptr
<base::DictionaryValue
> expected_rule_1
= ParseDictionary(
252 " \"priority\": 100,"
254 " \"instanceType\": \"declarativeContent.ShowPageAction\""
256 " \"conditions\" : [{"
257 " \"css\": [\"input[type='password']\"],"
258 " \"instanceType\" : \"declarativeContent.PageStateMatcher\""
261 EXPECT_TRUE(expected_rule_1
->Equals(get_rules
[1]->ToValue().get()));
264 // Tests verifies that rules defined in the manifest cannot be deleted but
265 // programmatically added rules still can be deleted.
266 TEST(RulesRegistryTest
, DeleteRuleInManifest
) {
267 base::MessageLoopForUI message_loop
;
268 content::TestBrowserThread
thread(content::BrowserThread::UI
, &message_loop
);
271 scoped_ptr
<base::DictionaryValue
> manifest
= ParseDictionary(
273 " \"name\": \"Test\","
274 " \"version\": \"1\","
275 " \"event_rules\": [{"
276 " \"id\": \"manifest_rule_0\","
277 " \"event\": \"declarativeContent.onPageChanged\","
279 " \"type\": \"declarativeContent.ShowPageAction\""
281 " \"conditions\" : [{"
282 " \"css\": [\"video\"],"
283 " \"type\" : \"declarativeContent.PageStateMatcher\""
287 scoped_refptr
<Extension
> extension
= ExtensionBuilder()
288 .SetManifest(manifest
.Pass())
292 scoped_refptr
<RulesRegistry
> registry
= new TestRulesRegistry(
293 content::BrowserThread::UI
, "declarativeContent.onPageChanged", key
);
294 // Simulate what RulesRegistryService would do on extension load.
295 registry
->OnExtensionLoaded(extension
.get());
296 // Add some extra rules outside of the manifest.
297 std::vector
<linked_ptr
<api::events::Rule
>> add_rules
;
298 linked_ptr
<api::events::Rule
> rule_1
= make_linked_ptr(new api::events::Rule
);
299 rule_1
->id
.reset(new std::string("rule_1"));
300 linked_ptr
<api::events::Rule
> rule_2
= make_linked_ptr(new api::events::Rule
);
301 rule_2
->id
.reset(new std::string("rule_2"));
302 add_rules
.push_back(rule_1
);
303 add_rules
.push_back(rule_2
);
304 registry
->AddRules(kExtensionId
, add_rules
);
306 std::vector
<linked_ptr
<api::events::Rule
>> get_rules
;
307 registry
->GetAllRules(kExtensionId
, &get_rules
);
308 ASSERT_EQ(3u, get_rules
.size());
309 EXPECT_EQ("manifest_rule_0", *(get_rules
[0]->id
));
310 EXPECT_EQ("rule_1", *(get_rules
[1]->id
));
311 EXPECT_EQ("rule_2", *(get_rules
[2]->id
));
313 // Remove a rule from outside the manifest.
314 std::vector
<std::string
> remove_ids
;
315 remove_ids
.push_back("rule_1");
316 EXPECT_TRUE(registry
->RemoveRules(kExtensionId
, remove_ids
).empty());
318 registry
->GetAllRules(kExtensionId
, &get_rules
);
319 EXPECT_EQ(2u, get_rules
.size());
320 EXPECT_EQ("manifest_rule_0", *(get_rules
[0]->id
));
321 EXPECT_EQ("rule_2", *(get_rules
[1]->id
));
323 // Attempt to remove rule in manifest.
325 remove_ids
.push_back("manifest_rule_0");
326 EXPECT_FALSE(registry
->RemoveRules(kExtensionId
, remove_ids
).empty());
328 registry
->GetAllRules(kExtensionId
, &get_rules
);
329 ASSERT_EQ(2u, get_rules
.size());
330 EXPECT_EQ("manifest_rule_0", *(get_rules
[0]->id
));
331 EXPECT_EQ("rule_2", *(get_rules
[1]->id
));
334 registry
->RemoveAllRules(kExtensionId
);
336 registry
->GetAllRules(kExtensionId
, &get_rules
);
337 ASSERT_EQ(1u, get_rules
.size());
338 EXPECT_EQ("manifest_rule_0", *(get_rules
[0]->id
));
341 } // namespace extensions