Home | History | Annotate | Download | only in declarative
      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