Home | History | Annotate | Download | only in storage
      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/storage/policy_value_store.h"
      6 
      7 #include "base/callback.h"
      8 #include "base/files/file_path.h"
      9 #include "base/files/scoped_temp_dir.h"
     10 #include "base/memory/ref_counted.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/message_loop/message_loop.h"
     13 #include "components/policy/core/common/external_data_fetcher.h"
     14 #include "components/policy/core/common/policy_map.h"
     15 #include "content/public/test/test_browser_thread.h"
     16 #include "extensions/browser/api/storage/settings_observer.h"
     17 #include "extensions/browser/value_store/leveldb_value_store.h"
     18 #include "extensions/browser/value_store/value_store_unittest.h"
     19 #include "testing/gmock/include/gmock/gmock.h"
     20 #include "testing/gtest/include/gtest/gtest.h"
     21 
     22 using testing::_;
     23 using testing::Mock;
     24 
     25 namespace extensions {
     26 
     27 namespace {
     28 
     29 const char kTestExtensionId[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
     30 
     31 class MockSettingsObserver : public SettingsObserver {
     32  public:
     33   MOCK_METHOD3(OnSettingsChanged, void(
     34       const std::string& extension_id,
     35       settings_namespace::Namespace settings_namespace,
     36       const std::string& changes_json));
     37 };
     38 
     39 // Extends PolicyValueStore by overriding the mutating methods, so that the
     40 // Get() base implementation can be tested with the ValueStoreTest parameterized
     41 // tests.
     42 class MutablePolicyValueStore : public PolicyValueStore {
     43  public:
     44   explicit MutablePolicyValueStore(const base::FilePath& path)
     45       : PolicyValueStore(kTestExtensionId,
     46                          make_scoped_refptr(new SettingsObserverList()),
     47                          scoped_ptr<ValueStore>(new LeveldbValueStore(path))) {}
     48   virtual ~MutablePolicyValueStore() {}
     49 
     50   virtual WriteResult Set(
     51       WriteOptions options,
     52       const std::string& key,
     53       const base::Value& value) OVERRIDE {
     54     return delegate()->Set(options, key, value);
     55   }
     56 
     57   virtual WriteResult Set(
     58       WriteOptions options, const base::DictionaryValue& values) OVERRIDE {
     59     return delegate()->Set(options, values);
     60   }
     61 
     62   virtual WriteResult Remove(const std::string& key) OVERRIDE {
     63     return delegate()->Remove(key);
     64   }
     65 
     66   virtual WriteResult Remove(const std::vector<std::string>& keys) OVERRIDE {
     67     return delegate()->Remove(keys);
     68   }
     69 
     70   virtual WriteResult Clear() OVERRIDE {
     71     return delegate()->Clear();
     72   }
     73 
     74  private:
     75   DISALLOW_COPY_AND_ASSIGN(MutablePolicyValueStore);
     76 };
     77 
     78 ValueStore* Param(const base::FilePath& file_path) {
     79   return new MutablePolicyValueStore(file_path);
     80 }
     81 
     82 }  // namespace
     83 
     84 INSTANTIATE_TEST_CASE_P(
     85     PolicyValueStoreTest,
     86     ValueStoreTest,
     87     testing::Values(&Param));
     88 
     89 class PolicyValueStoreTest : public testing::Test {
     90  public:
     91   PolicyValueStoreTest()
     92       : file_thread_(content::BrowserThread::FILE, &loop_) {}
     93   virtual ~PolicyValueStoreTest() {}
     94 
     95   virtual void SetUp() OVERRIDE {
     96     ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
     97     observers_ = new SettingsObserverList();
     98     observers_->AddObserver(&observer_);
     99     store_.reset(new PolicyValueStore(
    100         kTestExtensionId,
    101         observers_,
    102         scoped_ptr<ValueStore>(
    103             new LeveldbValueStore(scoped_temp_dir_.path()))));
    104   }
    105 
    106   virtual void TearDown() OVERRIDE {
    107     observers_->RemoveObserver(&observer_);
    108     store_.reset();
    109   }
    110 
    111  protected:
    112   base::ScopedTempDir scoped_temp_dir_;
    113   base::MessageLoop loop_;
    114   content::TestBrowserThread file_thread_;
    115   scoped_ptr<PolicyValueStore> store_;
    116   MockSettingsObserver observer_;
    117   scoped_refptr<SettingsObserverList> observers_;
    118 };
    119 
    120 TEST_F(PolicyValueStoreTest, DontProvideRecommendedPolicies) {
    121   policy::PolicyMap policies;
    122   base::FundamentalValue expected(123);
    123   policies.Set("must", policy::POLICY_LEVEL_MANDATORY,
    124                policy::POLICY_SCOPE_USER, expected.DeepCopy(), NULL);
    125   policies.Set("may", policy::POLICY_LEVEL_RECOMMENDED,
    126                policy::POLICY_SCOPE_USER,
    127                new base::FundamentalValue(456), NULL);
    128   store_->SetCurrentPolicy(policies);
    129   ValueStore::ReadResult result = store_->Get();
    130   ASSERT_FALSE(result->HasError());
    131   EXPECT_EQ(1u, result->settings().size());
    132   base::Value* value = NULL;
    133   EXPECT_FALSE(result->settings().Get("may", &value));
    134   EXPECT_TRUE(result->settings().Get("must", &value));
    135   EXPECT_TRUE(base::Value::Equals(&expected, value));
    136 }
    137 
    138 TEST_F(PolicyValueStoreTest, ReadOnly) {
    139   ValueStore::WriteOptions options = ValueStore::DEFAULTS;
    140 
    141   base::StringValue string_value("value");
    142   EXPECT_TRUE(store_->Set(options, "key", string_value)->HasError());
    143 
    144   base::DictionaryValue dict;
    145   dict.SetString("key", "value");
    146   EXPECT_TRUE(store_->Set(options, dict)->HasError());
    147 
    148   EXPECT_TRUE(store_->Remove("key")->HasError());
    149   std::vector<std::string> keys;
    150   keys.push_back("key");
    151   EXPECT_TRUE(store_->Remove(keys)->HasError());
    152   EXPECT_TRUE(store_->Clear()->HasError());
    153 }
    154 
    155 TEST_F(PolicyValueStoreTest, NotifyOnChanges) {
    156   // Notify when setting the initial policy.
    157   const base::StringValue value("111");
    158   {
    159     ValueStoreChangeList changes;
    160     changes.push_back(ValueStoreChange("aaa", NULL, value.DeepCopy()));
    161     EXPECT_CALL(observer_,
    162                 OnSettingsChanged(kTestExtensionId,
    163                                   settings_namespace::MANAGED,
    164                                   ValueStoreChange::ToJson(changes)));
    165   }
    166 
    167   policy::PolicyMap policies;
    168   policies.Set("aaa", policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
    169                value.DeepCopy(), NULL);
    170   store_->SetCurrentPolicy(policies);
    171   loop_.RunUntilIdle();
    172   Mock::VerifyAndClearExpectations(&observer_);
    173 
    174   // Notify when new policies are added.
    175   {
    176     ValueStoreChangeList changes;
    177     changes.push_back(ValueStoreChange("bbb", NULL, value.DeepCopy()));
    178     EXPECT_CALL(observer_,
    179                 OnSettingsChanged(kTestExtensionId,
    180                                   settings_namespace::MANAGED,
    181                                   ValueStoreChange::ToJson(changes)));
    182   }
    183 
    184   policies.Set("bbb", policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
    185                value.DeepCopy(), NULL);
    186   store_->SetCurrentPolicy(policies);
    187   loop_.RunUntilIdle();
    188   Mock::VerifyAndClearExpectations(&observer_);
    189 
    190   // Notify when policies change.
    191   const base::StringValue new_value("222");
    192   {
    193     ValueStoreChangeList changes;
    194     changes.push_back(
    195         ValueStoreChange("bbb", value.DeepCopy(), new_value.DeepCopy()));
    196     EXPECT_CALL(observer_,
    197                 OnSettingsChanged(kTestExtensionId,
    198                                   settings_namespace::MANAGED,
    199                                   ValueStoreChange::ToJson(changes)));
    200   }
    201 
    202   policies.Set("bbb", policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
    203                new_value.DeepCopy(), NULL);
    204   store_->SetCurrentPolicy(policies);
    205   loop_.RunUntilIdle();
    206   Mock::VerifyAndClearExpectations(&observer_);
    207 
    208   // Notify when policies are removed.
    209   {
    210     ValueStoreChangeList changes;
    211     changes.push_back(ValueStoreChange("bbb", new_value.DeepCopy(), NULL));
    212     EXPECT_CALL(observer_,
    213                 OnSettingsChanged(kTestExtensionId,
    214                                   settings_namespace::MANAGED,
    215                                   ValueStoreChange::ToJson(changes)));
    216   }
    217 
    218   policies.Erase("bbb");
    219   store_->SetCurrentPolicy(policies);
    220   loop_.RunUntilIdle();
    221   Mock::VerifyAndClearExpectations(&observer_);
    222 
    223   // Don't notify when there aren't any changes.
    224   EXPECT_CALL(observer_, OnSettingsChanged(_, _, _)).Times(0);
    225   store_->SetCurrentPolicy(policies);
    226   loop_.RunUntilIdle();
    227   Mock::VerifyAndClearExpectations(&observer_);
    228 }
    229 
    230 }  // namespace extensions
    231