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 "chrome/browser/extensions/api/storage/settings_observer.h"
     14 #include "chrome/browser/policy/external_data_fetcher.h"
     15 #include "chrome/browser/policy/policy_map.h"
     16 #include "chrome/browser/value_store/leveldb_value_store.h"
     17 #include "chrome/browser/value_store/value_store_unittest.h"
     18 #include "content/public/test/test_browser_thread.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                base::Value::CreateIntegerValue(456), NULL);
    128   store_->SetCurrentPolicy(policies, false);
    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   policy::PolicyMap policies;
    157   policies.Set("aaa", policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
    158                base::Value::CreateStringValue("111"), NULL);
    159   EXPECT_CALL(observer_, OnSettingsChanged(_, _, _)).Times(0);
    160   // No notification when setting the initial policy.
    161   store_->SetCurrentPolicy(policies, false);
    162   loop_.RunUntilIdle();
    163   Mock::VerifyAndClearExpectations(&observer_);
    164 
    165   // And no notifications on changes when not asked for.
    166   policies.Set("aaa", policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
    167                base::Value::CreateStringValue("222"), NULL);
    168   policies.Set("bbb", policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
    169                base::Value::CreateStringValue("223"), NULL);
    170   EXPECT_CALL(observer_, OnSettingsChanged(_, _, _)).Times(0);
    171   store_->SetCurrentPolicy(policies, false);
    172   loop_.RunUntilIdle();
    173   Mock::VerifyAndClearExpectations(&observer_);
    174 
    175   // Notify when new policies are added.
    176   ValueStoreChangeList changes;
    177   base::StringValue value("333");
    178   changes.push_back(ValueStoreChange("ccc", NULL, value.DeepCopy()));
    179   policies.Set("ccc", policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
    180                value.DeepCopy(), NULL);
    181   EXPECT_CALL(observer_, OnSettingsChanged(kTestExtensionId,
    182                                            settings_namespace::MANAGED,
    183                                            ValueStoreChange::ToJson(changes)));
    184   store_->SetCurrentPolicy(policies, true);
    185   loop_.RunUntilIdle();
    186   Mock::VerifyAndClearExpectations(&observer_);
    187 
    188   // Notify when policies change.
    189   changes.clear();
    190   base::StringValue new_value("444");
    191   changes.push_back(
    192       ValueStoreChange("ccc", value.DeepCopy(), new_value.DeepCopy()));
    193   policies.Set("ccc", policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
    194                new_value.DeepCopy(), NULL);
    195   EXPECT_CALL(observer_, OnSettingsChanged(kTestExtensionId,
    196                                            settings_namespace::MANAGED,
    197                                            ValueStoreChange::ToJson(changes)));
    198   store_->SetCurrentPolicy(policies, true);
    199   loop_.RunUntilIdle();
    200   Mock::VerifyAndClearExpectations(&observer_);
    201 
    202   // Notify when policies are removed.
    203   changes.clear();
    204   changes.push_back(ValueStoreChange("ccc", new_value.DeepCopy(), NULL));
    205   policies.Erase("ccc");
    206   EXPECT_CALL(observer_, OnSettingsChanged(kTestExtensionId,
    207                                            settings_namespace::MANAGED,
    208                                            ValueStoreChange::ToJson(changes)));
    209   store_->SetCurrentPolicy(policies, true);
    210   loop_.RunUntilIdle();
    211   Mock::VerifyAndClearExpectations(&observer_);
    212 
    213   // Don't notify when there aren't changes.
    214   EXPECT_CALL(observer_, OnSettingsChanged(_, _, _)).Times(0);
    215   store_->SetCurrentPolicy(policies, true);
    216   loop_.RunUntilIdle();
    217   Mock::VerifyAndClearExpectations(&observer_);
    218 }
    219 
    220 }  // namespace extensions
    221