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.
5 #include "extensions/browser/api/declarative/rules_registry.h"
7 // Here we test the TestRulesRegistry which is the simplest possible
8 // implementation of RulesRegistryWithCache as a proxy for
9 // RulesRegistryWithCache.
11 #include "base/command_line.h"
12 #include "base/run_loop.h"
13 #include "chrome/browser/extensions/extension_service.h"
14 #include "chrome/browser/extensions/test_extension_environment.h"
15 #include "chrome/browser/extensions/test_extension_system.h"
16 #include "chrome/common/extensions/extension_test_util.h"
17 #include "chrome/common/extensions/features/feature_channel.h"
18 #include "chrome/test/base/testing_profile.h"
19 #include "components/version_info/version_info.h"
20 #include "content/public/test/test_browser_thread_bundle.h"
21 #include "extensions/browser/api/declarative/rules_cache_delegate.h"
22 #include "extensions/browser/api/declarative/rules_registry_service.h"
23 #include "extensions/browser/api/declarative/test_rules_registry.h"
24 #include "extensions/browser/extension_prefs.h"
25 #include "extensions/browser/extension_registry.h"
26 #include "extensions/browser/value_store/testing_value_store.h"
27 #include "extensions/common/extension.h"
28 #include "extensions/common/manifest_constants.h"
29 #include "extensions/common/permissions/permissions_data.h"
30 #include "testing/gtest/include/gtest/gtest.h"
32 using extension_test_util::LoadManifestUnchecked
;
35 const char kRuleId
[] = "rule";
36 const char kRule2Id
[] = "rule2";
39 namespace extensions
{
40 const int kRulesRegistryID
= RulesRegistryService::kDefaultRulesRegistryID
;
42 class RulesRegistryWithCacheTest
: public testing::Test
{
44 RulesRegistryWithCacheTest()
45 : cache_delegate_(/*log_storage_init_delay=*/false),
46 registry_(new TestRulesRegistry(profile(),
48 content::BrowserThread::UI
,
52 void SetUp() override
{
53 // Note that env_.MakeExtension below also forces the creation of
55 base::DictionaryValue manifest_extra
;
57 CHECK(Extension::ProducePEM("test extension 1", &key
));
58 manifest_extra
.SetString(manifest_keys::kPublicKey
, key
);
59 extension1_
= env_
.MakeExtension(manifest_extra
);
60 CHECK(extension1_
.get());
62 // Different "key" values for the two extensions ensure a different ID.
63 CHECK(Extension::ProducePEM("test extension 2", &key
));
64 manifest_extra
.SetString(manifest_keys::kPublicKey
, key
);
65 extension2_
= env_
.MakeExtension(manifest_extra
);
66 CHECK(extension2_
.get());
67 CHECK_NE(extension2_
->id(), extension1_
->id());
70 ~RulesRegistryWithCacheTest() override
{}
72 std::string
AddRule(const std::string
& extension_id
,
73 const std::string
& rule_id
,
74 TestRulesRegistry
* registry
) {
75 std::vector
<linked_ptr
<api::events::Rule
>> add_rules
;
76 add_rules
.push_back(make_linked_ptr(new api::events::Rule
));
77 add_rules
[0]->id
.reset(new std::string(rule_id
));
78 return registry
->AddRules(extension_id
, add_rules
);
81 std::string
AddRule(const std::string
& extension_id
,
82 const std::string
& rule_id
) {
83 return AddRule(extension_id
, rule_id
, registry_
.get());
86 std::string
RemoveRule(const std::string
& extension_id
,
87 const std::string
& rule_id
) {
88 std::vector
<std::string
> remove_rules
;
89 remove_rules
.push_back(rule_id
);
90 return registry_
->RemoveRules(extension_id
, remove_rules
);
93 int GetNumberOfRules(const std::string
& extension_id
,
94 TestRulesRegistry
* registry
) {
95 std::vector
<linked_ptr
<api::events::Rule
>> get_rules
;
96 registry
->GetAllRules(extension_id
, &get_rules
);
97 return get_rules
.size();
100 int GetNumberOfRules(const std::string
& extension_id
) {
101 return GetNumberOfRules(extension_id
, registry_
.get());
104 TestingProfile
* profile() const { return env_
.profile(); }
107 TestExtensionEnvironment env_
;
108 RulesCacheDelegate cache_delegate_
;
109 scoped_refptr
<TestRulesRegistry
> registry_
;
110 scoped_refptr
<const Extension
> extension1_
;
111 scoped_refptr
<const Extension
> extension2_
;
114 TEST_F(RulesRegistryWithCacheTest
, AddRules
) {
115 // Check that nothing happens if the concrete RulesRegistry refuses to insert
117 registry_
->SetResult("Error");
118 EXPECT_EQ("Error", AddRule(extension1_
->id(), kRuleId
));
119 EXPECT_EQ(0, GetNumberOfRules(extension1_
->id()));
120 registry_
->SetResult(std::string());
122 // Check that rules can be inserted.
123 EXPECT_EQ("", AddRule(extension1_
->id(), kRule2Id
));
124 EXPECT_EQ(1, GetNumberOfRules(extension1_
->id()));
126 // Check that rules cannot be inserted twice with the same kRuleId.
127 EXPECT_NE("", AddRule(extension1_
->id(), kRuleId
));
128 EXPECT_EQ(1, GetNumberOfRules(extension1_
->id()));
130 // Check that different extensions may use the same kRuleId.
131 EXPECT_EQ("", AddRule(extension2_
->id(), kRuleId
));
132 EXPECT_EQ(1, GetNumberOfRules(extension1_
->id()));
133 EXPECT_EQ(1, GetNumberOfRules(extension2_
->id()));
136 TEST_F(RulesRegistryWithCacheTest
, RemoveRules
) {
138 EXPECT_EQ("", AddRule(extension1_
->id(), kRuleId
));
139 EXPECT_EQ("", AddRule(extension2_
->id(), kRuleId
));
140 EXPECT_EQ(1, GetNumberOfRules(extension1_
->id()));
141 EXPECT_EQ(1, GetNumberOfRules(extension2_
->id()));
143 // Check that nothing happens if the concrete RuleRegistry refuses to remove
145 registry_
->SetResult("Error");
146 EXPECT_EQ("Error", RemoveRule(extension1_
->id(), kRuleId
));
147 EXPECT_EQ(1, GetNumberOfRules(extension1_
->id()));
148 registry_
->SetResult(std::string());
150 // Check that nothing happens if a rule does not exist.
151 EXPECT_EQ("", RemoveRule(extension1_
->id(), "unknown_rule"));
152 EXPECT_EQ(1, GetNumberOfRules(extension1_
->id()));
154 // Check that rules may be removed and only for the correct extension.
155 EXPECT_EQ("", RemoveRule(extension1_
->id(), kRuleId
));
156 EXPECT_EQ(0, GetNumberOfRules(extension1_
->id()));
157 EXPECT_EQ(1, GetNumberOfRules(extension2_
->id()));
160 TEST_F(RulesRegistryWithCacheTest
, RemoveAllRules
) {
162 EXPECT_EQ("", AddRule(extension1_
->id(), kRuleId
));
163 EXPECT_EQ("", AddRule(extension1_
->id(), kRule2Id
));
164 EXPECT_EQ("", AddRule(extension2_
->id(), kRuleId
));
165 EXPECT_EQ(2, GetNumberOfRules(extension1_
->id()));
166 EXPECT_EQ(1, GetNumberOfRules(extension2_
->id()));
168 // Check that nothing happens if the concrete RuleRegistry refuses to remove
170 registry_
->SetResult("Error");
171 EXPECT_EQ("Error", registry_
->RemoveAllRules(extension1_
->id()));
172 EXPECT_EQ(2, GetNumberOfRules(extension1_
->id()));
173 registry_
->SetResult(std::string());
175 // Check that rules may be removed and only for the correct extension.
176 EXPECT_EQ("", registry_
->RemoveAllRules(extension1_
->id()));
177 EXPECT_EQ(0, GetNumberOfRules(extension1_
->id()));
178 EXPECT_EQ(1, GetNumberOfRules(extension2_
->id()));
181 TEST_F(RulesRegistryWithCacheTest
, GetRules
) {
183 EXPECT_EQ("", AddRule(extension1_
->id(), kRuleId
));
184 EXPECT_EQ("", AddRule(extension1_
->id(), kRule2Id
));
185 EXPECT_EQ("", AddRule(extension2_
->id(), kRuleId
));
187 // Check that we get the correct rule and unknown rules are ignored.
188 std::vector
<std::string
> rules_to_get
;
189 rules_to_get
.push_back(kRuleId
);
190 rules_to_get
.push_back("unknown_rule");
191 std::vector
<linked_ptr
<api::events::Rule
>> gotten_rules
;
192 registry_
->GetRules(extension1_
->id(), rules_to_get
, &gotten_rules
);
193 ASSERT_EQ(1u, gotten_rules
.size());
194 ASSERT_TRUE(gotten_rules
[0]->id
.get());
195 EXPECT_EQ(kRuleId
, *(gotten_rules
[0]->id
));
198 TEST_F(RulesRegistryWithCacheTest
, GetAllRules
) {
200 EXPECT_EQ("", AddRule(extension1_
->id(), kRuleId
));
201 EXPECT_EQ("", AddRule(extension1_
->id(), kRule2Id
));
202 EXPECT_EQ("", AddRule(extension2_
->id(), kRuleId
));
204 // Check that we get the correct rules.
205 std::vector
<linked_ptr
<api::events::Rule
>> gotten_rules
;
206 registry_
->GetAllRules(extension1_
->id(), &gotten_rules
);
207 EXPECT_EQ(2u, gotten_rules
.size());
208 ASSERT_TRUE(gotten_rules
[0]->id
.get());
209 ASSERT_TRUE(gotten_rules
[1]->id
.get());
210 EXPECT_TRUE((kRuleId
== *(gotten_rules
[0]->id
) &&
211 kRule2Id
== *(gotten_rules
[1]->id
)) ||
212 (kRuleId
== *(gotten_rules
[1]->id
) &&
213 kRule2Id
== *(gotten_rules
[0]->id
)) );
216 TEST_F(RulesRegistryWithCacheTest
, OnExtensionUninstalled
) {
218 EXPECT_EQ("", AddRule(extension1_
->id(), kRuleId
));
219 EXPECT_EQ("", AddRule(extension2_
->id(), kRuleId
));
221 // Check that the correct rules are removed.
222 registry_
->OnExtensionUninstalled(extension1_
.get());
223 EXPECT_EQ(0, GetNumberOfRules(extension1_
->id()));
224 EXPECT_EQ(1, GetNumberOfRules(extension2_
->id()));
227 TEST_F(RulesRegistryWithCacheTest
, DeclarativeRulesStored
) {
228 ExtensionPrefs
* extension_prefs
= env_
.GetExtensionPrefs();
229 // The value store is first created during GetExtensionService.
230 TestingValueStore
* store
= env_
.GetExtensionSystem()->value_store();
232 const std::string
event_name("testEvent");
233 const std::string
rules_stored_key(
234 RulesCacheDelegate::GetRulesStoredKey(
235 event_name
, profile()->IsOffTheRecord()));
236 scoped_ptr
<RulesCacheDelegate
> cache_delegate(new RulesCacheDelegate(false));
237 scoped_refptr
<RulesRegistry
> registry(
238 new TestRulesRegistry(profile(), event_name
, content::BrowserThread::UI
,
239 cache_delegate
.get(), kRulesRegistryID
));
241 // 1. Test the handling of preferences.
242 // Default value is always true.
243 EXPECT_TRUE(cache_delegate
->GetDeclarativeRulesStored(extension1_
->id()));
245 extension_prefs
->UpdateExtensionPref(
246 extension1_
->id(), rules_stored_key
, new base::FundamentalValue(false));
247 EXPECT_FALSE(cache_delegate
->GetDeclarativeRulesStored(extension1_
->id()));
249 extension_prefs
->UpdateExtensionPref(
250 extension1_
->id(), rules_stored_key
, new base::FundamentalValue(true));
251 EXPECT_TRUE(cache_delegate
->GetDeclarativeRulesStored(extension1_
->id()));
253 // 2. Test writing behavior.
254 int write_count
= store
->write_count();
256 scoped_ptr
<base::ListValue
> value(new base::ListValue
);
257 value
->AppendBoolean(true);
258 cache_delegate
->WriteToStorage(extension1_
->id(), value
.Pass());
259 EXPECT_TRUE(cache_delegate
->GetDeclarativeRulesStored(extension1_
->id()));
260 base::RunLoop().RunUntilIdle();
261 EXPECT_EQ(write_count
+ 1, store
->write_count());
262 write_count
= store
->write_count();
264 value
.reset(new base::ListValue
);
265 cache_delegate
->WriteToStorage(extension1_
->id(), value
.Pass());
266 EXPECT_FALSE(cache_delegate
->GetDeclarativeRulesStored(extension1_
->id()));
267 base::RunLoop().RunUntilIdle();
268 // No rules currently, but previously there were, so we expect a write.
269 EXPECT_EQ(write_count
+ 1, store
->write_count());
270 write_count
= store
->write_count();
272 value
.reset(new base::ListValue
);
273 cache_delegate
->WriteToStorage(extension1_
->id(), value
.Pass());
274 EXPECT_FALSE(cache_delegate
->GetDeclarativeRulesStored(extension1_
->id()));
275 base::RunLoop().RunUntilIdle();
276 EXPECT_EQ(write_count
, store
->write_count());
278 // 3. Test reading behavior.
279 int read_count
= store
->read_count();
281 cache_delegate
->SetDeclarativeRulesStored(extension1_
->id(), false);
282 cache_delegate
->ReadFromStorage(extension1_
->id());
283 base::RunLoop().RunUntilIdle();
284 EXPECT_EQ(read_count
, store
->read_count());
285 read_count
= store
->read_count();
287 cache_delegate
->SetDeclarativeRulesStored(extension1_
->id(), true);
288 cache_delegate
->ReadFromStorage(extension1_
->id());
289 base::RunLoop().RunUntilIdle();
290 EXPECT_EQ(read_count
+ 1, store
->read_count());
293 // Test that each registry has its own "are some rules stored" flag.
294 TEST_F(RulesRegistryWithCacheTest
, RulesStoredFlagMultipleRegistries
) {
295 ExtensionPrefs
* extension_prefs
= env_
.GetExtensionPrefs();
297 const std::string
event_name1("testEvent1");
298 const std::string
event_name2("testEvent2");
299 const std::string
rules_stored_key1(
300 RulesCacheDelegate::GetRulesStoredKey(
301 event_name1
, profile()->IsOffTheRecord()));
302 const std::string
rules_stored_key2(
303 RulesCacheDelegate::GetRulesStoredKey(
304 event_name2
, profile()->IsOffTheRecord()));
305 scoped_ptr
<RulesCacheDelegate
> cache_delegate1(new RulesCacheDelegate(false));
306 scoped_refptr
<RulesRegistry
> registry1(
307 new TestRulesRegistry(profile(), event_name1
, content::BrowserThread::UI
,
308 cache_delegate1
.get(), kRulesRegistryID
));
310 scoped_ptr
<RulesCacheDelegate
> cache_delegate2(new RulesCacheDelegate(false));
311 scoped_refptr
<RulesRegistry
> registry2(
312 new TestRulesRegistry(profile(), event_name2
, content::BrowserThread::UI
,
313 cache_delegate2
.get(), kRulesRegistryID
));
315 // Checkt the correct default values.
316 EXPECT_TRUE(cache_delegate1
->GetDeclarativeRulesStored(extension1_
->id()));
317 EXPECT_TRUE(cache_delegate2
->GetDeclarativeRulesStored(extension1_
->id()));
319 // Update the flag for the first registry.
320 extension_prefs
->UpdateExtensionPref(
321 extension1_
->id(), rules_stored_key1
, new base::FundamentalValue(false));
322 EXPECT_FALSE(cache_delegate1
->GetDeclarativeRulesStored(extension1_
->id()));
323 EXPECT_TRUE(cache_delegate2
->GetDeclarativeRulesStored(extension1_
->id()));
326 TEST_F(RulesRegistryWithCacheTest
, RulesPreservedAcrossRestart
) {
327 // This test makes sure that rules are restored from the rule store
328 // on registry (in particular, browser) restart.
330 // TODO(vabr): Once some API using declarative rules enters the stable
331 // channel, make sure to use that API here, and remove |channel|.
332 ScopedCurrentChannel
channel(version_info::Channel::UNKNOWN
);
334 ExtensionService
* extension_service
= env_
.GetExtensionService();
336 // 1. Add an extension, before rules registry gets created.
338 scoped_refptr
<Extension
> extension(
339 LoadManifestUnchecked("permissions",
340 "web_request_all_host_permissions.json",
341 Manifest::INVALID_LOCATION
,
345 ASSERT_TRUE(error
.empty());
346 extension_service
->AddExtension(extension
.get());
347 EXPECT_TRUE(extensions::ExtensionRegistry::Get(env_
.profile())
348 ->enabled_extensions()
349 .Contains(extension
->id()));
350 EXPECT_TRUE(extension
->permissions_data()->HasAPIPermission(
351 APIPermission::kDeclarativeWebRequest
));
352 env_
.GetExtensionSystem()->SetReady();
354 // 2. First run, adding a rule for the extension.
355 scoped_ptr
<RulesCacheDelegate
> cache_delegate(new RulesCacheDelegate(false));
356 scoped_refptr
<TestRulesRegistry
> registry(
357 new TestRulesRegistry(profile(), "testEvent", content::BrowserThread::UI
,
358 cache_delegate
.get(), kRulesRegistryID
));
360 AddRule(extension1_
->id(), kRuleId
, registry
.get());
361 base::RunLoop().RunUntilIdle(); // Posted tasks store the added rule.
362 EXPECT_EQ(1, GetNumberOfRules(extension1_
->id(), registry
.get()));
364 // 3. Restart the TestRulesRegistry and see the rule still there.
365 cache_delegate
.reset(new RulesCacheDelegate(false));
367 new TestRulesRegistry(profile(), "testEvent", content::BrowserThread::UI
,
368 cache_delegate
.get(), kRulesRegistryID
);
370 base::RunLoop().RunUntilIdle(); // Posted tasks retrieve the stored rule.
371 EXPECT_EQ(1, GetNumberOfRules(extension1_
->id(), registry
.get()));
374 TEST_F(RulesRegistryWithCacheTest
, ConcurrentStoringOfRules
) {
375 // When an extension updates its rules, the new set of rules is stored to disk
376 // with some delay. While it is acceptable for a quick series of updates for a
377 // single extension to only write the last one, we should never forget to
378 // write a rules update for extension A, just because it is immediately
379 // followed by a rules update for extension B.
380 extensions::TestExtensionSystem
* system
= env_
.GetExtensionSystem();
381 TestingValueStore
* store
= system
->value_store();
383 int write_count
= store
->write_count();
384 EXPECT_EQ("", AddRule(extension1_
->id(), kRuleId
));
385 EXPECT_EQ("", AddRule(extension2_
->id(), kRule2Id
));
386 env_
.GetExtensionSystem()->SetReady();
387 base::RunLoop().RunUntilIdle();
388 EXPECT_EQ(write_count
+ 2, store
->write_count());
391 } // namespace extensions