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/test_rules_registry.h"
22 #include "extensions/browser/extension_prefs.h"
23 #include "extensions/browser/value_store/testing_value_store.h"
24 #include "extensions/common/extension.h"
25 #include "extensions/common/manifest_constants.h"
26 #include "extensions/common/permissions/permissions_data.h"
27 #include "testing/gtest/include/gtest/gtest.h"
29 using extension_test_util::LoadManifestUnchecked;
32 const char kRuleId[] = "rule";
33 const char kRule2Id[] = "rule2";
36 namespace extensions {
38 class RulesRegistryWithCacheTest : public testing::Test {
40 RulesRegistryWithCacheTest()
41 : cache_delegate_(/*log_storage_init_delay=*/false),
42 registry_(new TestRulesRegistry(profile(),
44 content::BrowserThread::UI,
46 RulesRegistry::WebViewKey(0, 0))) {}
48 virtual void SetUp() {
49 env_.GetExtensionPrefs(); // Force creation before adding extensions.
50 // Note that env_.MakeExtension below also forces the creation of
53 base::DictionaryValue manifest_extra;
55 CHECK(Extension::ProducePEM("test extension 1", &key));
56 manifest_extra.SetString(manifest_keys::kPublicKey, key);
57 extension1_ = env_.MakeExtension(manifest_extra);
58 CHECK(extension1_.get());
60 // Different "key" values for the two extensions ensure a different ID.
61 CHECK(Extension::ProducePEM("test extension 2", &key));
62 manifest_extra.SetString(manifest_keys::kPublicKey, key);
63 extension2_ = env_.MakeExtension(manifest_extra);
64 CHECK(extension2_.get());
65 CHECK_NE(extension2_->id(), extension1_->id());
68 virtual ~RulesRegistryWithCacheTest() {}
70 std::string AddRule(const std::string& extension_id,
71 const std::string& rule_id,
72 TestRulesRegistry* registry) {
73 std::vector<linked_ptr<RulesRegistry::Rule> > add_rules;
74 add_rules.push_back(make_linked_ptr(new RulesRegistry::Rule));
75 add_rules[0]->id.reset(new std::string(rule_id));
76 return registry->AddRules(extension_id, add_rules);
79 std::string AddRule(const std::string& extension_id,
80 const std::string& rule_id) {
81 return AddRule(extension_id, rule_id, registry_.get());
84 std::string RemoveRule(const std::string& extension_id,
85 const std::string& rule_id) {
86 std::vector<std::string> remove_rules;
87 remove_rules.push_back(rule_id);
88 return registry_->RemoveRules(extension_id, remove_rules);
91 int GetNumberOfRules(const std::string& extension_id,
92 TestRulesRegistry* registry) {
93 std::vector<linked_ptr<RulesRegistry::Rule> > get_rules;
94 registry->GetAllRules(extension_id, &get_rules);
95 return get_rules.size();
98 int GetNumberOfRules(const std::string& extension_id) {
99 return GetNumberOfRules(extension_id, registry_.get());
102 TestingProfile* profile() const { return env_.profile(); }
105 TestExtensionEnvironment env_;
106 RulesCacheDelegate cache_delegate_;
107 scoped_refptr<TestRulesRegistry> registry_;
108 scoped_refptr<const Extension> extension1_;
109 scoped_refptr<const Extension> extension2_;
112 TEST_F(RulesRegistryWithCacheTest, AddRules) {
113 // Check that nothing happens if the concrete RulesRegistry refuses to insert
115 registry_->SetResult("Error");
116 EXPECT_EQ("Error", AddRule(extension1_->id(), kRuleId));
117 EXPECT_EQ(0, GetNumberOfRules(extension1_->id()));
118 registry_->SetResult(std::string());
120 // Check that rules can be inserted.
121 EXPECT_EQ("", AddRule(extension1_->id(), kRule2Id));
122 EXPECT_EQ(1, GetNumberOfRules(extension1_->id()));
124 // Check that rules cannot be inserted twice with the same kRuleId.
125 EXPECT_NE("", AddRule(extension1_->id(), kRuleId));
126 EXPECT_EQ(1, GetNumberOfRules(extension1_->id()));
128 // Check that different extensions may use the same kRuleId.
129 EXPECT_EQ("", AddRule(extension2_->id(), kRuleId));
130 EXPECT_EQ(1, GetNumberOfRules(extension1_->id()));
131 EXPECT_EQ(1, GetNumberOfRules(extension2_->id()));
134 TEST_F(RulesRegistryWithCacheTest, RemoveRules) {
136 EXPECT_EQ("", AddRule(extension1_->id(), kRuleId));
137 EXPECT_EQ("", AddRule(extension2_->id(), kRuleId));
138 EXPECT_EQ(1, GetNumberOfRules(extension1_->id()));
139 EXPECT_EQ(1, GetNumberOfRules(extension2_->id()));
141 // Check that nothing happens if the concrete RuleRegistry refuses to remove
143 registry_->SetResult("Error");
144 EXPECT_EQ("Error", RemoveRule(extension1_->id(), kRuleId));
145 EXPECT_EQ(1, GetNumberOfRules(extension1_->id()));
146 registry_->SetResult(std::string());
148 // Check that nothing happens if a rule does not exist.
149 EXPECT_EQ("", RemoveRule(extension1_->id(), "unknown_rule"));
150 EXPECT_EQ(1, GetNumberOfRules(extension1_->id()));
152 // Check that rules may be removed and only for the correct extension.
153 EXPECT_EQ("", RemoveRule(extension1_->id(), kRuleId));
154 EXPECT_EQ(0, GetNumberOfRules(extension1_->id()));
155 EXPECT_EQ(1, GetNumberOfRules(extension2_->id()));
158 TEST_F(RulesRegistryWithCacheTest, RemoveAllRules) {
160 EXPECT_EQ("", AddRule(extension1_->id(), kRuleId));
161 EXPECT_EQ("", AddRule(extension1_->id(), kRule2Id));
162 EXPECT_EQ("", AddRule(extension2_->id(), kRuleId));
163 EXPECT_EQ(2, GetNumberOfRules(extension1_->id()));
164 EXPECT_EQ(1, GetNumberOfRules(extension2_->id()));
166 // Check that nothing happens if the concrete RuleRegistry refuses to remove
168 registry_->SetResult("Error");
169 EXPECT_EQ("Error", registry_->RemoveAllRules(extension1_->id()));
170 EXPECT_EQ(2, GetNumberOfRules(extension1_->id()));
171 registry_->SetResult(std::string());
173 // Check that rules may be removed and only for the correct extension.
174 EXPECT_EQ("", registry_->RemoveAllRules(extension1_->id()));
175 EXPECT_EQ(0, GetNumberOfRules(extension1_->id()));
176 EXPECT_EQ(1, GetNumberOfRules(extension2_->id()));
179 TEST_F(RulesRegistryWithCacheTest, GetRules) {
181 EXPECT_EQ("", AddRule(extension1_->id(), kRuleId));
182 EXPECT_EQ("", AddRule(extension1_->id(), kRule2Id));
183 EXPECT_EQ("", AddRule(extension2_->id(), kRuleId));
185 // Check that we get the correct rule and unknown rules are ignored.
186 std::vector<std::string> rules_to_get;
187 rules_to_get.push_back(kRuleId);
188 rules_to_get.push_back("unknown_rule");
189 std::vector<linked_ptr<RulesRegistry::Rule> > gotten_rules;
190 registry_->GetRules(extension1_->id(), rules_to_get, &gotten_rules);
191 ASSERT_EQ(1u, gotten_rules.size());
192 ASSERT_TRUE(gotten_rules[0]->id.get());
193 EXPECT_EQ(kRuleId, *(gotten_rules[0]->id));
196 TEST_F(RulesRegistryWithCacheTest, GetAllRules) {
198 EXPECT_EQ("", AddRule(extension1_->id(), kRuleId));
199 EXPECT_EQ("", AddRule(extension1_->id(), kRule2Id));
200 EXPECT_EQ("", AddRule(extension2_->id(), kRuleId));
202 // Check that we get the correct rules.
203 std::vector<linked_ptr<RulesRegistry::Rule> > gotten_rules;
204 registry_->GetAllRules(extension1_->id(), &gotten_rules);
205 EXPECT_EQ(2u, gotten_rules.size());
206 ASSERT_TRUE(gotten_rules[0]->id.get());
207 ASSERT_TRUE(gotten_rules[1]->id.get());
208 EXPECT_TRUE( (kRuleId == *(gotten_rules[0]->id) &&
209 kRule2Id == *(gotten_rules[1]->id)) ||
210 (kRuleId == *(gotten_rules[1]->id) &&
211 kRule2Id == *(gotten_rules[0]->id)) );
214 TEST_F(RulesRegistryWithCacheTest, OnExtensionUninstalled) {
216 EXPECT_EQ("", AddRule(extension1_->id(), kRuleId));
217 EXPECT_EQ("", AddRule(extension2_->id(), kRuleId));
219 // Check that the correct rules are removed.
220 registry_->OnExtensionUninstalled(extension1_->id());
221 EXPECT_EQ(0, GetNumberOfRules(extension1_->id()));
222 EXPECT_EQ(1, GetNumberOfRules(extension2_->id()));
225 TEST_F(RulesRegistryWithCacheTest, DeclarativeRulesStored) {
226 ExtensionPrefs* extension_prefs = env_.GetExtensionPrefs();
227 // The value store is first created during GetExtensionService.
228 TestingValueStore* store = env_.GetExtensionSystem()->value_store();
230 const std::string event_name("testEvent");
231 const std::string rules_stored_key(
232 RulesCacheDelegate::GetRulesStoredKey(
233 event_name, profile()->IsOffTheRecord()));
234 scoped_ptr<RulesCacheDelegate> cache_delegate(new RulesCacheDelegate(false));
235 scoped_refptr<RulesRegistry> registry(new TestRulesRegistry(
236 profile(), event_name, content::BrowserThread::UI,
237 cache_delegate.get(),
238 RulesRegistry::WebViewKey(0, 0)));
240 // 1. Test the handling of preferences.
241 // Default value is always true.
242 EXPECT_TRUE(cache_delegate->GetDeclarativeRulesStored(extension1_->id()));
244 extension_prefs->UpdateExtensionPref(
245 extension1_->id(), rules_stored_key, new base::FundamentalValue(false));
246 EXPECT_FALSE(cache_delegate->GetDeclarativeRulesStored(extension1_->id()));
248 extension_prefs->UpdateExtensionPref(
249 extension1_->id(), rules_stored_key, new base::FundamentalValue(true));
250 EXPECT_TRUE(cache_delegate->GetDeclarativeRulesStored(extension1_->id()));
252 // 2. Test writing behavior.
253 int write_count = store->write_count();
255 scoped_ptr<base::ListValue> value(new base::ListValue);
256 value->AppendBoolean(true);
257 cache_delegate->WriteToStorage(extension1_->id(),
258 value.PassAs<base::Value>());
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(),
266 value.PassAs<base::Value>());
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(),
275 value.PassAs<base::Value>());
276 EXPECT_FALSE(cache_delegate->GetDeclarativeRulesStored(extension1_->id()));
277 base::RunLoop().RunUntilIdle();
278 EXPECT_EQ(write_count, store->write_count());
280 // 3. Test reading behavior.
281 int read_count = store->read_count();
283 cache_delegate->SetDeclarativeRulesStored(extension1_->id(), false);
284 cache_delegate->ReadFromStorage(extension1_->id());
285 base::RunLoop().RunUntilIdle();
286 EXPECT_EQ(read_count, store->read_count());
287 read_count = store->read_count();
289 cache_delegate->SetDeclarativeRulesStored(extension1_->id(), true);
290 cache_delegate->ReadFromStorage(extension1_->id());
291 base::RunLoop().RunUntilIdle();
292 EXPECT_EQ(read_count + 1, store->read_count());
295 // Test that each registry has its own "are some rules stored" flag.
296 TEST_F(RulesRegistryWithCacheTest, RulesStoredFlagMultipleRegistries) {
297 ExtensionPrefs* extension_prefs = env_.GetExtensionPrefs();
299 const std::string event_name1("testEvent1");
300 const std::string event_name2("testEvent2");
301 const std::string rules_stored_key1(
302 RulesCacheDelegate::GetRulesStoredKey(
303 event_name1, profile()->IsOffTheRecord()));
304 const std::string rules_stored_key2(
305 RulesCacheDelegate::GetRulesStoredKey(
306 event_name2, profile()->IsOffTheRecord()));
307 scoped_ptr<RulesCacheDelegate> cache_delegate1(new RulesCacheDelegate(false));
308 scoped_refptr<RulesRegistry> registry1(new TestRulesRegistry(
309 profile(), event_name1, content::BrowserThread::UI,
310 cache_delegate1.get(),
311 RulesRegistry::WebViewKey(0, 0)));
313 scoped_ptr<RulesCacheDelegate> cache_delegate2(new RulesCacheDelegate(false));
314 scoped_refptr<RulesRegistry> registry2(new TestRulesRegistry(
315 profile(), event_name2, content::BrowserThread::UI,
316 cache_delegate2.get(),
317 RulesRegistry::WebViewKey(0, 0)));
319 // Checkt the correct default values.
320 EXPECT_TRUE(cache_delegate1->GetDeclarativeRulesStored(extension1_->id()));
321 EXPECT_TRUE(cache_delegate2->GetDeclarativeRulesStored(extension1_->id()));
323 // Update the flag for the first registry.
324 extension_prefs->UpdateExtensionPref(
325 extension1_->id(), rules_stored_key1, new base::FundamentalValue(false));
326 EXPECT_FALSE(cache_delegate1->GetDeclarativeRulesStored(extension1_->id()));
327 EXPECT_TRUE(cache_delegate2->GetDeclarativeRulesStored(extension1_->id()));
330 TEST_F(RulesRegistryWithCacheTest, RulesPreservedAcrossRestart) {
331 // This test makes sure that rules are restored from the rule store
332 // on registry (in particular, browser) restart.
334 // TODO(vabr): Once some API using declarative rules enters the stable
335 // channel, make sure to use that API here, and remove |channel|.
336 ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_UNKNOWN);
338 ExtensionService* extension_service = env_.GetExtensionService();
340 // 1. Add an extension, before rules registry gets created.
342 scoped_refptr<Extension> extension(
343 LoadManifestUnchecked("permissions",
344 "web_request_all_host_permissions.json",
345 Manifest::INVALID_LOCATION,
349 ASSERT_TRUE(error.empty());
350 extension_service->AddExtension(extension.get());
351 EXPECT_TRUE(extension_service->extensions()->Contains(extension->id()));
352 EXPECT_TRUE(extension->permissions_data()->HasAPIPermission(
353 APIPermission::kDeclarativeWebRequest));
354 env_.GetExtensionSystem()->SetReady();
356 // 2. First run, adding a rule for the extension.
357 scoped_ptr<RulesCacheDelegate> cache_delegate(new RulesCacheDelegate(false));
358 scoped_refptr<TestRulesRegistry> registry(new TestRulesRegistry(
361 content::BrowserThread::UI,
362 cache_delegate.get(),
363 RulesRegistry::WebViewKey(0, 0)));
365 AddRule(extension1_->id(), kRuleId, registry.get());
366 base::RunLoop().RunUntilIdle(); // Posted tasks store the added rule.
367 EXPECT_EQ(1, GetNumberOfRules(extension1_->id(), registry.get()));
369 // 3. Restart the TestRulesRegistry and see the rule still there.
370 cache_delegate.reset(new RulesCacheDelegate(false));
371 registry = new TestRulesRegistry(
374 content::BrowserThread::UI,
375 cache_delegate.get(),
376 RulesRegistry::WebViewKey(0, 0));
378 base::RunLoop().RunUntilIdle(); // Posted tasks retrieve the stored rule.
379 EXPECT_EQ(1, GetNumberOfRules(extension1_->id(), registry.get()));
382 TEST_F(RulesRegistryWithCacheTest, ConcurrentStoringOfRules) {
383 // When an extension updates its rules, the new set of rules is stored to disk
384 // with some delay. While it is acceptable for a quick series of updates for a
385 // single extension to only write the last one, we should never forget to
386 // write a rules update for extension A, just because it is immediately
387 // followed by a rules update for extension B.
388 extensions::TestExtensionSystem* system = env_.GetExtensionSystem();
389 TestingValueStore* store = system->value_store();
391 int write_count = store->write_count();
392 EXPECT_EQ("", AddRule(extension1_->id(), kRuleId));
393 EXPECT_EQ("", AddRule(extension2_->id(), kRule2Id));
394 env_.GetExtensionSystem()->SetReady();
395 base::RunLoop().RunUntilIdle();
396 EXPECT_EQ(write_count + 2, store->write_count());
399 } // namespace extensions