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