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. 4 5 #include "chrome/browser/extensions/api/declarative/rules_registry.h" 6 7 // Here we test the TestRulesRegistry which is the simplest possible 8 // implementation of RulesRegistryWithCache as a proxy for 9 // RulesRegistryWithCache. 10 11 #include "base/command_line.h" 12 #include "base/run_loop.h" 13 #include "chrome/browser/extensions/api/declarative/rules_cache_delegate.h" 14 #include "chrome/browser/extensions/api/declarative/test_rules_registry.h" 15 #include "chrome/browser/extensions/extension_prefs.h" 16 #include "chrome/browser/extensions/extension_service.h" 17 #include "chrome/browser/extensions/test_extension_environment.h" 18 #include "chrome/browser/extensions/test_extension_system.h" 19 #include "chrome/browser/value_store/testing_value_store.h" 20 #include "chrome/common/extensions/extension_test_util.h" 21 #include "chrome/common/extensions/features/feature_channel.h" 22 #include "chrome/test/base/testing_profile.h" 23 #include "extensions/common/extension.h" 24 #include "extensions/common/manifest_constants.h" 25 #include "testing/gtest/include/gtest/gtest.h" 26 27 using extension_test_util::LoadManifestUnchecked; 28 29 namespace { 30 const char kRuleId[] = "rule"; 31 const char kRule2Id[] = "rule2"; 32 } 33 34 namespace extensions { 35 36 class RulesRegistryWithCacheTest : public testing::Test { 37 public: 38 RulesRegistryWithCacheTest() 39 : cache_delegate_(/*log_storage_init_delay=*/false), 40 registry_(new TestRulesRegistry(profile(), 41 /*event_name=*/"", 42 content::BrowserThread::UI, 43 &cache_delegate_, 44 RulesRegistry::WebViewKey(0, 0))) {} 45 46 virtual void SetUp() { 47 env_.GetExtensionPrefs(); // Force creation before adding extensions. 48 // Note that env_.MakeExtension below also forces the creation of 49 // ExtensionService. 50 51 base::DictionaryValue manifest_extra; 52 std::string key; 53 CHECK(Extension::ProducePEM("test extension 1", &key)); 54 manifest_extra.SetString(manifest_keys::kPublicKey, key); 55 extension1_ = env_.MakeExtension(manifest_extra); 56 CHECK(extension1_.get()); 57 58 // Different "key" values for the two extensions ensure a different ID. 59 CHECK(Extension::ProducePEM("test extension 2", &key)); 60 manifest_extra.SetString(manifest_keys::kPublicKey, key); 61 extension2_ = env_.MakeExtension(manifest_extra); 62 CHECK(extension2_.get()); 63 CHECK_NE(extension2_->id(), extension1_->id()); 64 } 65 66 virtual ~RulesRegistryWithCacheTest() {} 67 68 std::string AddRule(const std::string& extension_id, 69 const std::string& rule_id, 70 TestRulesRegistry* registry) { 71 std::vector<linked_ptr<RulesRegistry::Rule> > add_rules; 72 add_rules.push_back(make_linked_ptr(new RulesRegistry::Rule)); 73 add_rules[0]->id.reset(new std::string(rule_id)); 74 return registry->AddRules(extension_id, add_rules); 75 } 76 77 std::string AddRule(const std::string& extension_id, 78 const std::string& rule_id) { 79 return AddRule(extension_id, rule_id, registry_.get()); 80 } 81 82 std::string RemoveRule(const std::string& extension_id, 83 const std::string& rule_id) { 84 std::vector<std::string> remove_rules; 85 remove_rules.push_back(rule_id); 86 return registry_->RemoveRules(extension_id, remove_rules); 87 } 88 89 int GetNumberOfRules(const std::string& extension_id, 90 TestRulesRegistry* registry) { 91 std::vector<linked_ptr<RulesRegistry::Rule> > get_rules; 92 registry->GetAllRules(extension_id, &get_rules); 93 return get_rules.size(); 94 } 95 96 int GetNumberOfRules(const std::string& extension_id) { 97 return GetNumberOfRules(extension_id, registry_.get()); 98 } 99 100 TestingProfile* profile() const { return env_.profile(); } 101 102 protected: 103 TestExtensionEnvironment env_; 104 RulesCacheDelegate cache_delegate_; 105 scoped_refptr<TestRulesRegistry> registry_; 106 scoped_refptr<const Extension> extension1_; 107 scoped_refptr<const Extension> extension2_; 108 }; 109 110 TEST_F(RulesRegistryWithCacheTest, AddRules) { 111 // Check that nothing happens if the concrete RulesRegistry refuses to insert 112 // the rules. 113 registry_->SetResult("Error"); 114 EXPECT_EQ("Error", AddRule(extension1_->id(), kRuleId)); 115 EXPECT_EQ(0, GetNumberOfRules(extension1_->id())); 116 registry_->SetResult(std::string()); 117 118 // Check that rules can be inserted. 119 EXPECT_EQ("", AddRule(extension1_->id(), kRule2Id)); 120 EXPECT_EQ(1, GetNumberOfRules(extension1_->id())); 121 122 // Check that rules cannot be inserted twice with the same kRuleId. 123 EXPECT_NE("", AddRule(extension1_->id(), kRuleId)); 124 EXPECT_EQ(1, GetNumberOfRules(extension1_->id())); 125 126 // Check that different extensions may use the same kRuleId. 127 EXPECT_EQ("", AddRule(extension2_->id(), kRuleId)); 128 EXPECT_EQ(1, GetNumberOfRules(extension1_->id())); 129 EXPECT_EQ(1, GetNumberOfRules(extension2_->id())); 130 } 131 132 TEST_F(RulesRegistryWithCacheTest, RemoveRules) { 133 // Prime registry. 134 EXPECT_EQ("", AddRule(extension1_->id(), kRuleId)); 135 EXPECT_EQ("", AddRule(extension2_->id(), kRuleId)); 136 EXPECT_EQ(1, GetNumberOfRules(extension1_->id())); 137 EXPECT_EQ(1, GetNumberOfRules(extension2_->id())); 138 139 // Check that nothing happens if the concrete RuleRegistry refuses to remove 140 // the rules. 141 registry_->SetResult("Error"); 142 EXPECT_EQ("Error", RemoveRule(extension1_->id(), kRuleId)); 143 EXPECT_EQ(1, GetNumberOfRules(extension1_->id())); 144 registry_->SetResult(std::string()); 145 146 // Check that nothing happens if a rule does not exist. 147 EXPECT_EQ("", RemoveRule(extension1_->id(), "unknown_rule")); 148 EXPECT_EQ(1, GetNumberOfRules(extension1_->id())); 149 150 // Check that rules may be removed and only for the correct extension. 151 EXPECT_EQ("", RemoveRule(extension1_->id(), kRuleId)); 152 EXPECT_EQ(0, GetNumberOfRules(extension1_->id())); 153 EXPECT_EQ(1, GetNumberOfRules(extension2_->id())); 154 } 155 156 TEST_F(RulesRegistryWithCacheTest, RemoveAllRules) { 157 // Prime registry. 158 EXPECT_EQ("", AddRule(extension1_->id(), kRuleId)); 159 EXPECT_EQ("", AddRule(extension1_->id(), kRule2Id)); 160 EXPECT_EQ("", AddRule(extension2_->id(), kRuleId)); 161 EXPECT_EQ(2, GetNumberOfRules(extension1_->id())); 162 EXPECT_EQ(1, GetNumberOfRules(extension2_->id())); 163 164 // Check that nothing happens if the concrete RuleRegistry refuses to remove 165 // the rules. 166 registry_->SetResult("Error"); 167 EXPECT_EQ("Error", registry_->RemoveAllRules(extension1_->id())); 168 EXPECT_EQ(2, GetNumberOfRules(extension1_->id())); 169 registry_->SetResult(std::string()); 170 171 // Check that rules may be removed and only for the correct extension. 172 EXPECT_EQ("", registry_->RemoveAllRules(extension1_->id())); 173 EXPECT_EQ(0, GetNumberOfRules(extension1_->id())); 174 EXPECT_EQ(1, GetNumberOfRules(extension2_->id())); 175 } 176 177 TEST_F(RulesRegistryWithCacheTest, GetRules) { 178 // Prime registry. 179 EXPECT_EQ("", AddRule(extension1_->id(), kRuleId)); 180 EXPECT_EQ("", AddRule(extension1_->id(), kRule2Id)); 181 EXPECT_EQ("", AddRule(extension2_->id(), kRuleId)); 182 183 // Check that we get the correct rule and unknown rules are ignored. 184 std::vector<std::string> rules_to_get; 185 rules_to_get.push_back(kRuleId); 186 rules_to_get.push_back("unknown_rule"); 187 std::vector<linked_ptr<RulesRegistry::Rule> > gotten_rules; 188 registry_->GetRules(extension1_->id(), rules_to_get, &gotten_rules); 189 ASSERT_EQ(1u, gotten_rules.size()); 190 ASSERT_TRUE(gotten_rules[0]->id.get()); 191 EXPECT_EQ(kRuleId, *(gotten_rules[0]->id)); 192 } 193 194 TEST_F(RulesRegistryWithCacheTest, GetAllRules) { 195 // Prime registry. 196 EXPECT_EQ("", AddRule(extension1_->id(), kRuleId)); 197 EXPECT_EQ("", AddRule(extension1_->id(), kRule2Id)); 198 EXPECT_EQ("", AddRule(extension2_->id(), kRuleId)); 199 200 // Check that we get the correct rules. 201 std::vector<linked_ptr<RulesRegistry::Rule> > gotten_rules; 202 registry_->GetAllRules(extension1_->id(), &gotten_rules); 203 EXPECT_EQ(2u, gotten_rules.size()); 204 ASSERT_TRUE(gotten_rules[0]->id.get()); 205 ASSERT_TRUE(gotten_rules[1]->id.get()); 206 EXPECT_TRUE( (kRuleId == *(gotten_rules[0]->id) && 207 kRule2Id == *(gotten_rules[1]->id)) || 208 (kRuleId == *(gotten_rules[1]->id) && 209 kRule2Id == *(gotten_rules[0]->id)) ); 210 } 211 212 TEST_F(RulesRegistryWithCacheTest, OnExtensionUninstalled) { 213 // Prime registry. 214 EXPECT_EQ("", AddRule(extension1_->id(), kRuleId)); 215 EXPECT_EQ("", AddRule(extension2_->id(), kRuleId)); 216 217 // Check that the correct rules are removed. 218 registry_->OnExtensionUninstalled(extension1_->id()); 219 EXPECT_EQ(0, GetNumberOfRules(extension1_->id())); 220 EXPECT_EQ(1, GetNumberOfRules(extension2_->id())); 221 } 222 223 TEST_F(RulesRegistryWithCacheTest, DeclarativeRulesStored) { 224 ExtensionPrefs* extension_prefs = env_.GetExtensionPrefs(); 225 // The value store is first created during GetExtensionService. 226 TestingValueStore* store = env_.GetExtensionSystem()->value_store(); 227 228 const std::string event_name("testEvent"); 229 const std::string rules_stored_key( 230 RulesCacheDelegate::GetRulesStoredKey( 231 event_name, profile()->IsOffTheRecord())); 232 scoped_ptr<RulesCacheDelegate> cache_delegate(new RulesCacheDelegate(false)); 233 scoped_refptr<RulesRegistry> registry(new TestRulesRegistry( 234 profile(), event_name, content::BrowserThread::UI, 235 cache_delegate.get(), 236 RulesRegistry::WebViewKey(0, 0))); 237 238 // 1. Test the handling of preferences. 239 // Default value is always true. 240 EXPECT_TRUE(cache_delegate->GetDeclarativeRulesStored(extension1_->id())); 241 242 extension_prefs->UpdateExtensionPref( 243 extension1_->id(), rules_stored_key, new base::FundamentalValue(false)); 244 EXPECT_FALSE(cache_delegate->GetDeclarativeRulesStored(extension1_->id())); 245 246 extension_prefs->UpdateExtensionPref( 247 extension1_->id(), rules_stored_key, new base::FundamentalValue(true)); 248 EXPECT_TRUE(cache_delegate->GetDeclarativeRulesStored(extension1_->id())); 249 250 // 2. Test writing behavior. 251 int write_count = store->write_count(); 252 253 scoped_ptr<base::ListValue> value(new base::ListValue); 254 value->AppendBoolean(true); 255 cache_delegate->WriteToStorage(extension1_->id(), 256 value.PassAs<base::Value>()); 257 EXPECT_TRUE(cache_delegate->GetDeclarativeRulesStored(extension1_->id())); 258 base::RunLoop().RunUntilIdle(); 259 EXPECT_EQ(write_count + 1, store->write_count()); 260 write_count = store->write_count(); 261 262 value.reset(new base::ListValue); 263 cache_delegate->WriteToStorage(extension1_->id(), 264 value.PassAs<base::Value>()); 265 EXPECT_FALSE(cache_delegate->GetDeclarativeRulesStored(extension1_->id())); 266 base::RunLoop().RunUntilIdle(); 267 // No rules currently, but previously there were, so we expect a write. 268 EXPECT_EQ(write_count + 1, store->write_count()); 269 write_count = store->write_count(); 270 271 value.reset(new base::ListValue); 272 cache_delegate->WriteToStorage(extension1_->id(), 273 value.PassAs<base::Value>()); 274 EXPECT_FALSE(cache_delegate->GetDeclarativeRulesStored(extension1_->id())); 275 base::RunLoop().RunUntilIdle(); 276 EXPECT_EQ(write_count, store->write_count()); 277 278 // 3. Test reading behavior. 279 int read_count = store->read_count(); 280 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(); 286 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()); 291 } 292 293 // Test that each registry has its own "are some rules stored" flag. 294 TEST_F(RulesRegistryWithCacheTest, RulesStoredFlagMultipleRegistries) { 295 ExtensionPrefs* extension_prefs = env_.GetExtensionPrefs(); 296 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(new TestRulesRegistry( 307 profile(), event_name1, content::BrowserThread::UI, 308 cache_delegate1.get(), 309 RulesRegistry::WebViewKey(0, 0))); 310 311 scoped_ptr<RulesCacheDelegate> cache_delegate2(new RulesCacheDelegate(false)); 312 scoped_refptr<RulesRegistry> registry2(new TestRulesRegistry( 313 profile(), event_name2, content::BrowserThread::UI, 314 cache_delegate2.get(), 315 RulesRegistry::WebViewKey(0, 0))); 316 317 // Checkt the correct default values. 318 EXPECT_TRUE(cache_delegate1->GetDeclarativeRulesStored(extension1_->id())); 319 EXPECT_TRUE(cache_delegate2->GetDeclarativeRulesStored(extension1_->id())); 320 321 // Update the flag for the first registry. 322 extension_prefs->UpdateExtensionPref( 323 extension1_->id(), rules_stored_key1, new base::FundamentalValue(false)); 324 EXPECT_FALSE(cache_delegate1->GetDeclarativeRulesStored(extension1_->id())); 325 EXPECT_TRUE(cache_delegate2->GetDeclarativeRulesStored(extension1_->id())); 326 } 327 328 TEST_F(RulesRegistryWithCacheTest, RulesPreservedAcrossRestart) { 329 // This test makes sure that rules are restored from the rule store 330 // on registry (in particular, browser) restart. 331 332 // TODO(vabr): Once some API using declarative rules enters the stable 333 // channel, make sure to use that API here, and remove |channel|. 334 ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_UNKNOWN); 335 336 ExtensionService* extension_service = env_.GetExtensionService(); 337 338 // 1. Add an extension, before rules registry gets created. 339 std::string error; 340 scoped_refptr<Extension> extension( 341 LoadManifestUnchecked("permissions", 342 "web_request_all_host_permissions.json", 343 Manifest::INVALID_LOCATION, 344 Extension::NO_FLAGS, 345 extension1_->id(), 346 &error)); 347 ASSERT_TRUE(error.empty()); 348 extension_service->AddExtension(extension.get()); 349 EXPECT_TRUE(extension_service->extensions()->Contains(extension->id())); 350 EXPECT_TRUE( 351 extension->HasAPIPermission(APIPermission::kDeclarativeWebRequest)); 352 env_.GetExtensionSystem()->SetReady(); 353 354 // 2. First run, adding a rule for the extension. 355 scoped_ptr<RulesCacheDelegate> cache_delegate(new RulesCacheDelegate(false)); 356 scoped_refptr<TestRulesRegistry> registry(new TestRulesRegistry( 357 profile(), 358 "testEvent", 359 content::BrowserThread::UI, 360 cache_delegate.get(), 361 RulesRegistry::WebViewKey(0, 0))); 362 363 AddRule(extension1_->id(), kRuleId, registry.get()); 364 base::RunLoop().RunUntilIdle(); // Posted tasks store the added rule. 365 EXPECT_EQ(1, GetNumberOfRules(extension1_->id(), registry.get())); 366 367 // 3. Restart the TestRulesRegistry and see the rule still there. 368 cache_delegate.reset(new RulesCacheDelegate(false)); 369 registry = new TestRulesRegistry( 370 profile(), 371 "testEvent", 372 content::BrowserThread::UI, 373 cache_delegate.get(), 374 RulesRegistry::WebViewKey(0, 0)); 375 376 base::RunLoop().RunUntilIdle(); // Posted tasks retrieve the stored rule. 377 EXPECT_EQ(1, GetNumberOfRules(extension1_->id(), registry.get())); 378 } 379 380 TEST_F(RulesRegistryWithCacheTest, ConcurrentStoringOfRules) { 381 // When an extension updates its rules, the new set of rules is stored to disk 382 // with some delay. While it is acceptable for a quick series of updates for a 383 // single extension to only write the last one, we should never forget to 384 // write a rules update for extension A, just because it is immediately 385 // followed by a rules update for extension B. 386 extensions::TestExtensionSystem* system = env_.GetExtensionSystem(); 387 TestingValueStore* store = system->value_store(); 388 389 int write_count = store->write_count(); 390 EXPECT_EQ("", AddRule(extension1_->id(), kRuleId)); 391 EXPECT_EQ("", AddRule(extension2_->id(), kRule2Id)); 392 env_.GetExtensionSystem()->SetReady(); 393 base::RunLoop().RunUntilIdle(); 394 EXPECT_EQ(write_count + 2, store->write_count()); 395 } 396 397 } // namespace extensions 398