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.
5 #include "chrome/browser/extensions/api/storage/policy_value_store.h"
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 "components/policy/core/common/policy_types.h"
16 #include "content/public/test/test_browser_thread.h"
17 #include "extensions/browser/api/storage/settings_observer.h"
18 #include "extensions/browser/value_store/leveldb_value_store.h"
19 #include "extensions/browser/value_store/value_store_unittest.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
26 namespace extensions
{
30 const char kTestExtensionId
[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
31 const char kDatabaseUMAClientName
[] = "Test";
33 class MockSettingsObserver
: public SettingsObserver
{
35 MOCK_METHOD3(OnSettingsChanged
, void(
36 const std::string
& extension_id
,
37 settings_namespace::Namespace settings_namespace
,
38 const std::string
& changes_json
));
41 // Extends PolicyValueStore by overriding the mutating methods, so that the
42 // Get() base implementation can be tested with the ValueStoreTest parameterized
44 class MutablePolicyValueStore
: public PolicyValueStore
{
46 explicit MutablePolicyValueStore(const base::FilePath
& path
)
49 make_scoped_refptr(new SettingsObserverList()),
51 new LeveldbValueStore(kDatabaseUMAClientName
, path
))) {}
52 ~MutablePolicyValueStore() override
{}
54 WriteResult
Set(WriteOptions options
,
55 const std::string
& key
,
56 const base::Value
& value
) override
{
57 return delegate()->Set(options
, key
, value
);
60 WriteResult
Set(WriteOptions options
,
61 const base::DictionaryValue
& values
) override
{
62 return delegate()->Set(options
, values
);
65 WriteResult
Remove(const std::string
& key
) override
{
66 return delegate()->Remove(key
);
69 WriteResult
Remove(const std::vector
<std::string
>& keys
) override
{
70 return delegate()->Remove(keys
);
73 WriteResult
Clear() override
{ return delegate()->Clear(); }
76 DISALLOW_COPY_AND_ASSIGN(MutablePolicyValueStore
);
79 ValueStore
* Param(const base::FilePath
& file_path
) {
80 return new MutablePolicyValueStore(file_path
);
85 INSTANTIATE_TEST_CASE_P(
88 testing::Values(&Param
));
90 class PolicyValueStoreTest
: public testing::Test
{
92 PolicyValueStoreTest()
93 : file_thread_(content::BrowserThread::FILE, &loop_
) {}
94 ~PolicyValueStoreTest() override
{}
96 void SetUp() override
{
97 ASSERT_TRUE(scoped_temp_dir_
.CreateUniqueTempDir());
98 observers_
= new SettingsObserverList();
99 observers_
->AddObserver(&observer_
);
100 store_
.reset(new PolicyValueStore(
101 kTestExtensionId
, observers_
,
102 make_scoped_ptr(new LeveldbValueStore(kDatabaseUMAClientName
,
103 scoped_temp_dir_
.path()))));
106 void TearDown() override
{
107 observers_
->RemoveObserver(&observer_
);
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_
;
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
, policy::POLICY_SOURCE_CLOUD
,
125 expected
.DeepCopy(), nullptr);
126 policies
.Set("may", policy::POLICY_LEVEL_RECOMMENDED
,
127 policy::POLICY_SCOPE_USER
, policy::POLICY_SOURCE_CLOUD
,
128 new base::FundamentalValue(456), NULL
);
129 store_
->SetCurrentPolicy(policies
);
130 ValueStore::ReadResult result
= store_
->Get();
131 ASSERT_FALSE(result
->HasError());
132 EXPECT_EQ(1u, result
->settings().size());
133 base::Value
* value
= NULL
;
134 EXPECT_FALSE(result
->settings().Get("may", &value
));
135 EXPECT_TRUE(result
->settings().Get("must", &value
));
136 EXPECT_TRUE(base::Value::Equals(&expected
, value
));
139 TEST_F(PolicyValueStoreTest
, ReadOnly
) {
140 ValueStore::WriteOptions options
= ValueStore::DEFAULTS
;
142 base::StringValue
string_value("value");
143 EXPECT_TRUE(store_
->Set(options
, "key", string_value
)->HasError());
145 base::DictionaryValue dict
;
146 dict
.SetString("key", "value");
147 EXPECT_TRUE(store_
->Set(options
, dict
)->HasError());
149 EXPECT_TRUE(store_
->Remove("key")->HasError());
150 std::vector
<std::string
> keys
;
151 keys
.push_back("key");
152 EXPECT_TRUE(store_
->Remove(keys
)->HasError());
153 EXPECT_TRUE(store_
->Clear()->HasError());
156 TEST_F(PolicyValueStoreTest
, NotifyOnChanges
) {
157 // Notify when setting the initial policy.
158 const base::StringValue
value("111");
160 ValueStoreChangeList changes
;
161 changes
.push_back(ValueStoreChange("aaa", NULL
, value
.DeepCopy()));
162 EXPECT_CALL(observer_
,
163 OnSettingsChanged(kTestExtensionId
,
164 settings_namespace::MANAGED
,
165 ValueStoreChange::ToJson(changes
)));
168 policy::PolicyMap policies
;
169 policies
.Set("aaa", policy::POLICY_LEVEL_MANDATORY
, policy::POLICY_SCOPE_USER
,
170 policy::POLICY_SOURCE_CLOUD
, value
.DeepCopy(), nullptr);
171 store_
->SetCurrentPolicy(policies
);
172 loop_
.RunUntilIdle();
173 Mock::VerifyAndClearExpectations(&observer_
);
175 // Notify when new policies are added.
177 ValueStoreChangeList changes
;
178 changes
.push_back(ValueStoreChange("bbb", NULL
, value
.DeepCopy()));
179 EXPECT_CALL(observer_
,
180 OnSettingsChanged(kTestExtensionId
,
181 settings_namespace::MANAGED
,
182 ValueStoreChange::ToJson(changes
)));
185 policies
.Set("bbb", policy::POLICY_LEVEL_MANDATORY
, policy::POLICY_SCOPE_USER
,
186 policy::POLICY_SOURCE_CLOUD
, value
.DeepCopy(), nullptr);
187 store_
->SetCurrentPolicy(policies
);
188 loop_
.RunUntilIdle();
189 Mock::VerifyAndClearExpectations(&observer_
);
191 // Notify when policies change.
192 const base::StringValue
new_value("222");
194 ValueStoreChangeList changes
;
196 ValueStoreChange("bbb", value
.DeepCopy(), new_value
.DeepCopy()));
197 EXPECT_CALL(observer_
,
198 OnSettingsChanged(kTestExtensionId
,
199 settings_namespace::MANAGED
,
200 ValueStoreChange::ToJson(changes
)));
203 policies
.Set("bbb", policy::POLICY_LEVEL_MANDATORY
, policy::POLICY_SCOPE_USER
,
204 policy::POLICY_SOURCE_CLOUD
, new_value
.DeepCopy(), nullptr);
205 store_
->SetCurrentPolicy(policies
);
206 loop_
.RunUntilIdle();
207 Mock::VerifyAndClearExpectations(&observer_
);
209 // Notify when policies are removed.
211 ValueStoreChangeList changes
;
212 changes
.push_back(ValueStoreChange("bbb", new_value
.DeepCopy(), NULL
));
213 EXPECT_CALL(observer_
,
214 OnSettingsChanged(kTestExtensionId
,
215 settings_namespace::MANAGED
,
216 ValueStoreChange::ToJson(changes
)));
219 policies
.Erase("bbb");
220 store_
->SetCurrentPolicy(policies
);
221 loop_
.RunUntilIdle();
222 Mock::VerifyAndClearExpectations(&observer_
);
224 // Don't notify when there aren't any changes.
225 EXPECT_CALL(observer_
, OnSettingsChanged(_
, _
, _
)).Times(0);
226 store_
->SetCurrentPolicy(policies
);
227 loop_
.RunUntilIdle();
228 Mock::VerifyAndClearExpectations(&observer_
);
231 } // namespace extensions