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 "extensions/browser/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/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" 28 29using extension_test_util::LoadManifestUnchecked; 30 31namespace { 32const char kRuleId[] = "rule"; 33const char kRule2Id[] = "rule2"; 34} 35 36namespace extensions { 37 38class RulesRegistryWithCacheTest : public testing::Test { 39 public: 40 RulesRegistryWithCacheTest() 41 : cache_delegate_(/*log_storage_init_delay=*/false), 42 registry_(new TestRulesRegistry(profile(), 43 /*event_name=*/"", 44 content::BrowserThread::UI, 45 &cache_delegate_, 46 RulesRegistry::WebViewKey(0, 0))) {} 47 48 virtual void SetUp() { 49 env_.GetExtensionPrefs(); // Force creation before adding extensions. 50 // Note that env_.MakeExtension below also forces the creation of 51 // ExtensionService. 52 53 base::DictionaryValue manifest_extra; 54 std::string key; 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()); 59 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()); 66 } 67 68 virtual ~RulesRegistryWithCacheTest() {} 69 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); 77 } 78 79 std::string AddRule(const std::string& extension_id, 80 const std::string& rule_id) { 81 return AddRule(extension_id, rule_id, registry_.get()); 82 } 83 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); 89 } 90 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(); 96 } 97 98 int GetNumberOfRules(const std::string& extension_id) { 99 return GetNumberOfRules(extension_id, registry_.get()); 100 } 101 102 TestingProfile* profile() const { return env_.profile(); } 103 104 protected: 105 TestExtensionEnvironment env_; 106 RulesCacheDelegate cache_delegate_; 107 scoped_refptr<TestRulesRegistry> registry_; 108 scoped_refptr<const Extension> extension1_; 109 scoped_refptr<const Extension> extension2_; 110}; 111 112TEST_F(RulesRegistryWithCacheTest, AddRules) { 113 // Check that nothing happens if the concrete RulesRegistry refuses to insert 114 // the rules. 115 registry_->SetResult("Error"); 116 EXPECT_EQ("Error", AddRule(extension1_->id(), kRuleId)); 117 EXPECT_EQ(0, GetNumberOfRules(extension1_->id())); 118 registry_->SetResult(std::string()); 119 120 // Check that rules can be inserted. 121 EXPECT_EQ("", AddRule(extension1_->id(), kRule2Id)); 122 EXPECT_EQ(1, GetNumberOfRules(extension1_->id())); 123 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())); 127 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())); 132} 133 134TEST_F(RulesRegistryWithCacheTest, RemoveRules) { 135 // Prime registry. 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())); 140 141 // Check that nothing happens if the concrete RuleRegistry refuses to remove 142 // the rules. 143 registry_->SetResult("Error"); 144 EXPECT_EQ("Error", RemoveRule(extension1_->id(), kRuleId)); 145 EXPECT_EQ(1, GetNumberOfRules(extension1_->id())); 146 registry_->SetResult(std::string()); 147 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())); 151 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())); 156} 157 158TEST_F(RulesRegistryWithCacheTest, RemoveAllRules) { 159 // Prime registry. 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())); 165 166 // Check that nothing happens if the concrete RuleRegistry refuses to remove 167 // the rules. 168 registry_->SetResult("Error"); 169 EXPECT_EQ("Error", registry_->RemoveAllRules(extension1_->id())); 170 EXPECT_EQ(2, GetNumberOfRules(extension1_->id())); 171 registry_->SetResult(std::string()); 172 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())); 177} 178 179TEST_F(RulesRegistryWithCacheTest, GetRules) { 180 // Prime registry. 181 EXPECT_EQ("", AddRule(extension1_->id(), kRuleId)); 182 EXPECT_EQ("", AddRule(extension1_->id(), kRule2Id)); 183 EXPECT_EQ("", AddRule(extension2_->id(), kRuleId)); 184 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)); 194} 195 196TEST_F(RulesRegistryWithCacheTest, GetAllRules) { 197 // Prime registry. 198 EXPECT_EQ("", AddRule(extension1_->id(), kRuleId)); 199 EXPECT_EQ("", AddRule(extension1_->id(), kRule2Id)); 200 EXPECT_EQ("", AddRule(extension2_->id(), kRuleId)); 201 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)) ); 212} 213 214TEST_F(RulesRegistryWithCacheTest, OnExtensionUninstalled) { 215 // Prime registry. 216 EXPECT_EQ("", AddRule(extension1_->id(), kRuleId)); 217 EXPECT_EQ("", AddRule(extension2_->id(), kRuleId)); 218 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())); 223} 224 225TEST_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(); 229 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))); 239 240 // 1. Test the handling of preferences. 241 // Default value is always true. 242 EXPECT_TRUE(cache_delegate->GetDeclarativeRulesStored(extension1_->id())); 243 244 extension_prefs->UpdateExtensionPref( 245 extension1_->id(), rules_stored_key, new base::FundamentalValue(false)); 246 EXPECT_FALSE(cache_delegate->GetDeclarativeRulesStored(extension1_->id())); 247 248 extension_prefs->UpdateExtensionPref( 249 extension1_->id(), rules_stored_key, new base::FundamentalValue(true)); 250 EXPECT_TRUE(cache_delegate->GetDeclarativeRulesStored(extension1_->id())); 251 252 // 2. Test writing behavior. 253 int write_count = store->write_count(); 254 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(); 263 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(); 272 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()); 279 280 // 3. Test reading behavior. 281 int read_count = store->read_count(); 282 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(); 288 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()); 293} 294 295// Test that each registry has its own "are some rules stored" flag. 296TEST_F(RulesRegistryWithCacheTest, RulesStoredFlagMultipleRegistries) { 297 ExtensionPrefs* extension_prefs = env_.GetExtensionPrefs(); 298 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))); 312 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))); 318 319 // Checkt the correct default values. 320 EXPECT_TRUE(cache_delegate1->GetDeclarativeRulesStored(extension1_->id())); 321 EXPECT_TRUE(cache_delegate2->GetDeclarativeRulesStored(extension1_->id())); 322 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())); 328} 329 330TEST_F(RulesRegistryWithCacheTest, RulesPreservedAcrossRestart) { 331 // This test makes sure that rules are restored from the rule store 332 // on registry (in particular, browser) restart. 333 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); 337 338 ExtensionService* extension_service = env_.GetExtensionService(); 339 340 // 1. Add an extension, before rules registry gets created. 341 std::string error; 342 scoped_refptr<Extension> extension( 343 LoadManifestUnchecked("permissions", 344 "web_request_all_host_permissions.json", 345 Manifest::INVALID_LOCATION, 346 Extension::NO_FLAGS, 347 extension1_->id(), 348 &error)); 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(); 355 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( 359 profile(), 360 "testEvent", 361 content::BrowserThread::UI, 362 cache_delegate.get(), 363 RulesRegistry::WebViewKey(0, 0))); 364 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())); 368 369 // 3. Restart the TestRulesRegistry and see the rule still there. 370 cache_delegate.reset(new RulesCacheDelegate(false)); 371 registry = new TestRulesRegistry( 372 profile(), 373 "testEvent", 374 content::BrowserThread::UI, 375 cache_delegate.get(), 376 RulesRegistry::WebViewKey(0, 0)); 377 378 base::RunLoop().RunUntilIdle(); // Posted tasks retrieve the stored rule. 379 EXPECT_EQ(1, GetNumberOfRules(extension1_->id(), registry.get())); 380} 381 382TEST_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(); 390 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()); 397} 398 399} // namespace extensions 400