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