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 "content/public/test/test_browser_thread_bundle.h"
20 #include "extensions/browser/api/declarative/rules_cache_delegate.h"
21 #include "extensions/browser/api/declarative/rules_registry_service.h"
22 #include "extensions/browser/api/declarative/test_rules_registry.h"
23 #include "extensions/browser/extension_prefs.h"
24 #include "extensions/browser/extension_registry.h"
25 #include "extensions/browser/value_store/testing_value_store.h"
26 #include "extensions/common/extension.h"
27 #include "extensions/common/manifest_constants.h"
28 #include "extensions/common/permissions/permissions_data.h"
29 #include "testing/gtest/include/gtest/gtest.h"
31 using extension_test_util::LoadManifestUnchecked
;
34 const char kRuleId
[] = "rule";
35 const char kRule2Id
[] = "rule2";
38 namespace extensions
{
39 const int kRulesRegistryID
= RulesRegistryService::kDefaultRulesRegistryID
;
41 class RulesRegistryWithCacheTest
: public testing::Test
{
43 RulesRegistryWithCacheTest()
44 : cache_delegate_(/*log_storage_init_delay=*/false),
45 registry_(new TestRulesRegistry(profile(),
47 content::BrowserThread::UI
,
51 void SetUp() override
{
52 env_
.GetExtensionPrefs(); // Force creation before adding extensions.
53 // Note that env_.MakeExtension below also forces the creation of
56 base::DictionaryValue manifest_extra
;
58 CHECK(Extension::ProducePEM("test extension 1", &key
));
59 manifest_extra
.SetString(manifest_keys::kPublicKey
, key
);
60 extension1_
= env_
.MakeExtension(manifest_extra
);
61 CHECK(extension1_
.get());
63 // Different "key" values for the two extensions ensure a different ID.
64 CHECK(Extension::ProducePEM("test extension 2", &key
));
65 manifest_extra
.SetString(manifest_keys::kPublicKey
, key
);
66 extension2_
= env_
.MakeExtension(manifest_extra
);
67 CHECK(extension2_
.get());
68 CHECK_NE(extension2_
->id(), extension1_
->id());
71 ~RulesRegistryWithCacheTest() override
{}
73 std::string
AddRule(const std::string
& extension_id
,
74 const std::string
& rule_id
,
75 TestRulesRegistry
* registry
) {
76 std::vector
<linked_ptr
<RulesRegistry::Rule
> > add_rules
;
77 add_rules
.push_back(make_linked_ptr(new RulesRegistry::Rule
));
78 add_rules
[0]->id
.reset(new std::string(rule_id
));
79 return registry
->AddRules(extension_id
, add_rules
);
82 std::string
AddRule(const std::string
& extension_id
,
83 const std::string
& rule_id
) {
84 return AddRule(extension_id
, rule_id
, registry_
.get());
87 std::string
RemoveRule(const std::string
& extension_id
,
88 const std::string
& rule_id
) {
89 std::vector
<std::string
> remove_rules
;
90 remove_rules
.push_back(rule_id
);
91 return registry_
->RemoveRules(extension_id
, remove_rules
);
94 int GetNumberOfRules(const std::string
& extension_id
,
95 TestRulesRegistry
* registry
) {
96 std::vector
<linked_ptr
<RulesRegistry::Rule
> > get_rules
;
97 registry
->GetAllRules(extension_id
, &get_rules
);
98 return get_rules
.size();
101 int GetNumberOfRules(const std::string
& extension_id
) {
102 return GetNumberOfRules(extension_id
, registry_
.get());
105 TestingProfile
* profile() const { return env_
.profile(); }
108 TestExtensionEnvironment env_
;
109 RulesCacheDelegate cache_delegate_
;
110 scoped_refptr
<TestRulesRegistry
> registry_
;
111 scoped_refptr
<const Extension
> extension1_
;
112 scoped_refptr
<const Extension
> extension2_
;
115 TEST_F(RulesRegistryWithCacheTest
, AddRules
) {
116 // Check that nothing happens if the concrete RulesRegistry refuses to insert
118 registry_
->SetResult("Error");
119 EXPECT_EQ("Error", AddRule(extension1_
->id(), kRuleId
));
120 EXPECT_EQ(0, GetNumberOfRules(extension1_
->id()));
121 registry_
->SetResult(std::string());
123 // Check that rules can be inserted.
124 EXPECT_EQ("", AddRule(extension1_
->id(), kRule2Id
));
125 EXPECT_EQ(1, GetNumberOfRules(extension1_
->id()));
127 // Check that rules cannot be inserted twice with the same kRuleId.
128 EXPECT_NE("", AddRule(extension1_
->id(), kRuleId
));
129 EXPECT_EQ(1, GetNumberOfRules(extension1_
->id()));
131 // Check that different extensions may use the same kRuleId.
132 EXPECT_EQ("", AddRule(extension2_
->id(), kRuleId
));
133 EXPECT_EQ(1, GetNumberOfRules(extension1_
->id()));
134 EXPECT_EQ(1, GetNumberOfRules(extension2_
->id()));
137 TEST_F(RulesRegistryWithCacheTest
, RemoveRules
) {
139 EXPECT_EQ("", AddRule(extension1_
->id(), kRuleId
));
140 EXPECT_EQ("", AddRule(extension2_
->id(), kRuleId
));
141 EXPECT_EQ(1, GetNumberOfRules(extension1_
->id()));
142 EXPECT_EQ(1, GetNumberOfRules(extension2_
->id()));
144 // Check that nothing happens if the concrete RuleRegistry refuses to remove
146 registry_
->SetResult("Error");
147 EXPECT_EQ("Error", RemoveRule(extension1_
->id(), kRuleId
));
148 EXPECT_EQ(1, GetNumberOfRules(extension1_
->id()));
149 registry_
->SetResult(std::string());
151 // Check that nothing happens if a rule does not exist.
152 EXPECT_EQ("", RemoveRule(extension1_
->id(), "unknown_rule"));
153 EXPECT_EQ(1, GetNumberOfRules(extension1_
->id()));
155 // Check that rules may be removed and only for the correct extension.
156 EXPECT_EQ("", RemoveRule(extension1_
->id(), kRuleId
));
157 EXPECT_EQ(0, GetNumberOfRules(extension1_
->id()));
158 EXPECT_EQ(1, GetNumberOfRules(extension2_
->id()));
161 TEST_F(RulesRegistryWithCacheTest
, RemoveAllRules
) {
163 EXPECT_EQ("", AddRule(extension1_
->id(), kRuleId
));
164 EXPECT_EQ("", AddRule(extension1_
->id(), kRule2Id
));
165 EXPECT_EQ("", AddRule(extension2_
->id(), kRuleId
));
166 EXPECT_EQ(2, GetNumberOfRules(extension1_
->id()));
167 EXPECT_EQ(1, GetNumberOfRules(extension2_
->id()));
169 // Check that nothing happens if the concrete RuleRegistry refuses to remove
171 registry_
->SetResult("Error");
172 EXPECT_EQ("Error", registry_
->RemoveAllRules(extension1_
->id()));
173 EXPECT_EQ(2, GetNumberOfRules(extension1_
->id()));
174 registry_
->SetResult(std::string());
176 // Check that rules may be removed and only for the correct extension.
177 EXPECT_EQ("", registry_
->RemoveAllRules(extension1_
->id()));
178 EXPECT_EQ(0, GetNumberOfRules(extension1_
->id()));
179 EXPECT_EQ(1, GetNumberOfRules(extension2_
->id()));
182 TEST_F(RulesRegistryWithCacheTest
, GetRules
) {
184 EXPECT_EQ("", AddRule(extension1_
->id(), kRuleId
));
185 EXPECT_EQ("", AddRule(extension1_
->id(), kRule2Id
));
186 EXPECT_EQ("", AddRule(extension2_
->id(), kRuleId
));
188 // Check that we get the correct rule and unknown rules are ignored.
189 std::vector
<std::string
> rules_to_get
;
190 rules_to_get
.push_back(kRuleId
);
191 rules_to_get
.push_back("unknown_rule");
192 std::vector
<linked_ptr
<RulesRegistry::Rule
> > gotten_rules
;
193 registry_
->GetRules(extension1_
->id(), rules_to_get
, &gotten_rules
);
194 ASSERT_EQ(1u, gotten_rules
.size());
195 ASSERT_TRUE(gotten_rules
[0]->id
.get());
196 EXPECT_EQ(kRuleId
, *(gotten_rules
[0]->id
));
199 TEST_F(RulesRegistryWithCacheTest
, GetAllRules
) {
201 EXPECT_EQ("", AddRule(extension1_
->id(), kRuleId
));
202 EXPECT_EQ("", AddRule(extension1_
->id(), kRule2Id
));
203 EXPECT_EQ("", AddRule(extension2_
->id(), kRuleId
));
205 // Check that we get the correct rules.
206 std::vector
<linked_ptr
<RulesRegistry::Rule
> > gotten_rules
;
207 registry_
->GetAllRules(extension1_
->id(), &gotten_rules
);
208 EXPECT_EQ(2u, gotten_rules
.size());
209 ASSERT_TRUE(gotten_rules
[0]->id
.get());
210 ASSERT_TRUE(gotten_rules
[1]->id
.get());
211 EXPECT_TRUE( (kRuleId
== *(gotten_rules
[0]->id
) &&
212 kRule2Id
== *(gotten_rules
[1]->id
)) ||
213 (kRuleId
== *(gotten_rules
[1]->id
) &&
214 kRule2Id
== *(gotten_rules
[0]->id
)) );
217 TEST_F(RulesRegistryWithCacheTest
, OnExtensionUninstalled
) {
219 EXPECT_EQ("", AddRule(extension1_
->id(), kRuleId
));
220 EXPECT_EQ("", AddRule(extension2_
->id(), kRuleId
));
222 // Check that the correct rules are removed.
223 registry_
->OnExtensionUninstalled(extension1_
->id());
224 EXPECT_EQ(0, GetNumberOfRules(extension1_
->id()));
225 EXPECT_EQ(1, GetNumberOfRules(extension2_
->id()));
228 TEST_F(RulesRegistryWithCacheTest
, DeclarativeRulesStored
) {
229 ExtensionPrefs
* extension_prefs
= env_
.GetExtensionPrefs();
230 // The value store is first created during GetExtensionService.
231 TestingValueStore
* store
= env_
.GetExtensionSystem()->value_store();
233 const std::string
event_name("testEvent");
234 const std::string
rules_stored_key(
235 RulesCacheDelegate::GetRulesStoredKey(
236 event_name
, profile()->IsOffTheRecord()));
237 scoped_ptr
<RulesCacheDelegate
> cache_delegate(new RulesCacheDelegate(false));
238 scoped_refptr
<RulesRegistry
> registry(
239 new TestRulesRegistry(profile(), event_name
, content::BrowserThread::UI
,
240 cache_delegate
.get(), kRulesRegistryID
));
242 // 1. Test the handling of preferences.
243 // Default value is always true.
244 EXPECT_TRUE(cache_delegate
->GetDeclarativeRulesStored(extension1_
->id()));
246 extension_prefs
->UpdateExtensionPref(
247 extension1_
->id(), rules_stored_key
, new base::FundamentalValue(false));
248 EXPECT_FALSE(cache_delegate
->GetDeclarativeRulesStored(extension1_
->id()));
250 extension_prefs
->UpdateExtensionPref(
251 extension1_
->id(), rules_stored_key
, new base::FundamentalValue(true));
252 EXPECT_TRUE(cache_delegate
->GetDeclarativeRulesStored(extension1_
->id()));
254 // 2. Test writing behavior.
255 int write_count
= store
->write_count();
257 scoped_ptr
<base::ListValue
> value(new base::ListValue
);
258 value
->AppendBoolean(true);
259 cache_delegate
->WriteToStorage(extension1_
->id(), value
.Pass());
260 EXPECT_TRUE(cache_delegate
->GetDeclarativeRulesStored(extension1_
->id()));
261 base::RunLoop().RunUntilIdle();
262 EXPECT_EQ(write_count
+ 1, store
->write_count());
263 write_count
= store
->write_count();
265 value
.reset(new base::ListValue
);
266 cache_delegate
->WriteToStorage(extension1_
->id(), value
.Pass());
267 EXPECT_FALSE(cache_delegate
->GetDeclarativeRulesStored(extension1_
->id()));
268 base::RunLoop().RunUntilIdle();
269 // No rules currently, but previously there were, so we expect a write.
270 EXPECT_EQ(write_count
+ 1, store
->write_count());
271 write_count
= store
->write_count();
273 value
.reset(new base::ListValue
);
274 cache_delegate
->WriteToStorage(extension1_
->id(), value
.Pass());
275 EXPECT_FALSE(cache_delegate
->GetDeclarativeRulesStored(extension1_
->id()));
276 base::RunLoop().RunUntilIdle();
277 EXPECT_EQ(write_count
, store
->write_count());
279 // 3. Test reading behavior.
280 int read_count
= store
->read_count();
282 cache_delegate
->SetDeclarativeRulesStored(extension1_
->id(), false);
283 cache_delegate
->ReadFromStorage(extension1_
->id());
284 base::RunLoop().RunUntilIdle();
285 EXPECT_EQ(read_count
, store
->read_count());
286 read_count
= store
->read_count();
288 cache_delegate
->SetDeclarativeRulesStored(extension1_
->id(), true);
289 cache_delegate
->ReadFromStorage(extension1_
->id());
290 base::RunLoop().RunUntilIdle();
291 EXPECT_EQ(read_count
+ 1, store
->read_count());
294 // Test that each registry has its own "are some rules stored" flag.
295 TEST_F(RulesRegistryWithCacheTest
, RulesStoredFlagMultipleRegistries
) {
296 ExtensionPrefs
* extension_prefs
= env_
.GetExtensionPrefs();
298 const std::string
event_name1("testEvent1");
299 const std::string
event_name2("testEvent2");
300 const std::string
rules_stored_key1(
301 RulesCacheDelegate::GetRulesStoredKey(
302 event_name1
, profile()->IsOffTheRecord()));
303 const std::string
rules_stored_key2(
304 RulesCacheDelegate::GetRulesStoredKey(
305 event_name2
, profile()->IsOffTheRecord()));
306 scoped_ptr
<RulesCacheDelegate
> cache_delegate1(new RulesCacheDelegate(false));
307 scoped_refptr
<RulesRegistry
> registry1(
308 new TestRulesRegistry(profile(), event_name1
, content::BrowserThread::UI
,
309 cache_delegate1
.get(), kRulesRegistryID
));
311 scoped_ptr
<RulesCacheDelegate
> cache_delegate2(new RulesCacheDelegate(false));
312 scoped_refptr
<RulesRegistry
> registry2(
313 new TestRulesRegistry(profile(), event_name2
, content::BrowserThread::UI
,
314 cache_delegate2
.get(), kRulesRegistryID
));
316 // Checkt the correct default values.
317 EXPECT_TRUE(cache_delegate1
->GetDeclarativeRulesStored(extension1_
->id()));
318 EXPECT_TRUE(cache_delegate2
->GetDeclarativeRulesStored(extension1_
->id()));
320 // Update the flag for the first registry.
321 extension_prefs
->UpdateExtensionPref(
322 extension1_
->id(), rules_stored_key1
, new base::FundamentalValue(false));
323 EXPECT_FALSE(cache_delegate1
->GetDeclarativeRulesStored(extension1_
->id()));
324 EXPECT_TRUE(cache_delegate2
->GetDeclarativeRulesStored(extension1_
->id()));
327 TEST_F(RulesRegistryWithCacheTest
, RulesPreservedAcrossRestart
) {
328 // This test makes sure that rules are restored from the rule store
329 // on registry (in particular, browser) restart.
331 // TODO(vabr): Once some API using declarative rules enters the stable
332 // channel, make sure to use that API here, and remove |channel|.
333 ScopedCurrentChannel
channel(chrome::VersionInfo::CHANNEL_UNKNOWN
);
335 ExtensionService
* extension_service
= env_
.GetExtensionService();
337 // 1. Add an extension, before rules registry gets created.
339 scoped_refptr
<Extension
> extension(
340 LoadManifestUnchecked("permissions",
341 "web_request_all_host_permissions.json",
342 Manifest::INVALID_LOCATION
,
346 ASSERT_TRUE(error
.empty());
347 extension_service
->AddExtension(extension
.get());
348 EXPECT_TRUE(extensions::ExtensionRegistry::Get(env_
.profile())
349 ->enabled_extensions()
350 .Contains(extension
->id()));
351 EXPECT_TRUE(extension
->permissions_data()->HasAPIPermission(
352 APIPermission::kDeclarativeWebRequest
));
353 env_
.GetExtensionSystem()->SetReady();
355 // 2. First run, adding a rule for the extension.
356 scoped_ptr
<RulesCacheDelegate
> cache_delegate(new RulesCacheDelegate(false));
357 scoped_refptr
<TestRulesRegistry
> registry(
358 new TestRulesRegistry(profile(), "testEvent", content::BrowserThread::UI
,
359 cache_delegate
.get(), kRulesRegistryID
));
361 AddRule(extension1_
->id(), kRuleId
, registry
.get());
362 base::RunLoop().RunUntilIdle(); // Posted tasks store the added rule.
363 EXPECT_EQ(1, GetNumberOfRules(extension1_
->id(), registry
.get()));
365 // 3. Restart the TestRulesRegistry and see the rule still there.
366 cache_delegate
.reset(new RulesCacheDelegate(false));
368 new TestRulesRegistry(profile(), "testEvent", content::BrowserThread::UI
,
369 cache_delegate
.get(), kRulesRegistryID
);
371 base::RunLoop().RunUntilIdle(); // Posted tasks retrieve the stored rule.
372 EXPECT_EQ(1, GetNumberOfRules(extension1_
->id(), registry
.get()));
375 TEST_F(RulesRegistryWithCacheTest
, ConcurrentStoringOfRules
) {
376 // When an extension updates its rules, the new set of rules is stored to disk
377 // with some delay. While it is acceptable for a quick series of updates for a
378 // single extension to only write the last one, we should never forget to
379 // write a rules update for extension A, just because it is immediately
380 // followed by a rules update for extension B.
381 extensions::TestExtensionSystem
* system
= env_
.GetExtensionSystem();
382 TestingValueStore
* store
= system
->value_store();
384 int write_count
= store
->write_count();
385 EXPECT_EQ("", AddRule(extension1_
->id(), kRuleId
));
386 EXPECT_EQ("", AddRule(extension2_
->id(), kRule2Id
));
387 env_
.GetExtensionSystem()->SetReady();
388 base::RunLoop().RunUntilIdle();
389 EXPECT_EQ(write_count
+ 2, store
->write_count());
392 } // namespace extensions