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/chromeos/settings/device_settings_provider.h"
6
7#include <string>
8
9#include "base/bind.h"
10#include "base/callback.h"
11#include "base/files/file_util.h"
12#include "base/path_service.h"
13#include "base/test/scoped_path_override.h"
14#include "base/values.h"
15#include "chrome/browser/chromeos/login/users/fake_user_manager.h"
16#include "chrome/browser/chromeos/policy/device_local_account.h"
17#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
18#include "chrome/browser/chromeos/settings/device_settings_test_helper.h"
19#include "chrome/common/chrome_paths.h"
20#include "chrome/test/base/scoped_testing_local_state.h"
21#include "chrome/test/base/testing_browser_process.h"
22#include "chrome/test/base/testing_profile.h"
23#include "chromeos/settings/cros_settings_names.h"
24#include "components/user_manager/user.h"
25#include "policy/proto/device_management_backend.pb.h"
26#include "testing/gmock/include/gmock/gmock.h"
27#include "testing/gtest/include/gtest/gtest.h"
28
29namespace em = enterprise_management;
30
31namespace chromeos {
32
33using ::testing::AnyNumber;
34using ::testing::Mock;
35using ::testing::_;
36
37class DeviceSettingsProviderTest : public DeviceSettingsTestBase {
38 public:
39  MOCK_METHOD1(SettingChanged, void(const std::string&));
40  MOCK_METHOD0(GetTrustedCallback, void(void));
41
42 protected:
43  DeviceSettingsProviderTest()
44      : local_state_(TestingBrowserProcess::GetGlobal()),
45        user_data_dir_override_(chrome::DIR_USER_DATA) {}
46
47  virtual void SetUp() OVERRIDE {
48    DeviceSettingsTestBase::SetUp();
49
50    EXPECT_CALL(*this, SettingChanged(_)).Times(AnyNumber());
51    provider_.reset(
52        new DeviceSettingsProvider(
53            base::Bind(&DeviceSettingsProviderTest::SettingChanged,
54                       base::Unretained(this)),
55            &device_settings_service_));
56    Mock::VerifyAndClearExpectations(this);
57  }
58
59  virtual void TearDown() OVERRIDE {
60    DeviceSettingsTestBase::TearDown();
61  }
62
63  ScopedTestingLocalState local_state_;
64
65  scoped_ptr<DeviceSettingsProvider> provider_;
66
67  base::ScopedPathOverride user_data_dir_override_;
68
69 private:
70  DISALLOW_COPY_AND_ASSIGN(DeviceSettingsProviderTest);
71};
72
73TEST_F(DeviceSettingsProviderTest, InitializationTest) {
74  // Have the service load a settings blob.
75  EXPECT_CALL(*this, SettingChanged(_)).Times(AnyNumber());
76  ReloadDeviceSettings();
77  Mock::VerifyAndClearExpectations(this);
78
79  // Verify that the policy blob has been correctly parsed and trusted.
80  // The trusted flag should be set before the call to PrepareTrustedValues.
81  EXPECT_EQ(CrosSettingsProvider::TRUSTED,
82            provider_->PrepareTrustedValues(base::Closure()));
83  const base::Value* value = provider_->Get(kStatsReportingPref);
84  ASSERT_TRUE(value);
85  bool bool_value;
86  EXPECT_TRUE(value->GetAsBoolean(&bool_value));
87  EXPECT_FALSE(bool_value);
88}
89
90TEST_F(DeviceSettingsProviderTest, InitializationTestUnowned) {
91  // Have the service check the key.
92  owner_key_util_->Clear();
93  ReloadDeviceSettings();
94
95  // The trusted flag should be set before the call to PrepareTrustedValues.
96  EXPECT_EQ(CrosSettingsProvider::TRUSTED,
97            provider_->PrepareTrustedValues(base::Closure()));
98  const base::Value* value = provider_->Get(kReleaseChannel);
99  ASSERT_TRUE(value);
100  std::string string_value;
101  EXPECT_TRUE(value->GetAsString(&string_value));
102  EXPECT_TRUE(string_value.empty());
103
104  // Sets should succeed though and be readable from the cache.
105  EXPECT_CALL(*this, SettingChanged(_)).Times(AnyNumber());
106  EXPECT_CALL(*this, SettingChanged(kReleaseChannel)).Times(1);
107  base::StringValue new_value("stable-channel");
108  provider_->Set(kReleaseChannel, new_value);
109  Mock::VerifyAndClearExpectations(this);
110
111  // This shouldn't trigger a write.
112  device_settings_test_helper_.set_policy_blob(std::string());
113  FlushDeviceSettings();
114  EXPECT_EQ(std::string(), device_settings_test_helper_.policy_blob());
115
116  // Verify the change has been applied.
117  const base::Value* saved_value = provider_->Get(kReleaseChannel);
118  ASSERT_TRUE(saved_value);
119  EXPECT_TRUE(saved_value->GetAsString(&string_value));
120  ASSERT_EQ("stable-channel", string_value);
121}
122
123TEST_F(DeviceSettingsProviderTest, SetPrefFailed) {
124  // If we are not the owner no sets should work.
125  base::FundamentalValue value(true);
126  EXPECT_CALL(*this, SettingChanged(kStatsReportingPref)).Times(1);
127  provider_->Set(kStatsReportingPref, value);
128  Mock::VerifyAndClearExpectations(this);
129
130  // This shouldn't trigger a write.
131  device_settings_test_helper_.set_policy_blob(std::string());
132  FlushDeviceSettings();
133  EXPECT_EQ(std::string(), device_settings_test_helper_.policy_blob());
134
135  // Verify the change has not been applied.
136  const base::Value* saved_value = provider_->Get(kStatsReportingPref);
137  ASSERT_TRUE(saved_value);
138  bool bool_value;
139  EXPECT_TRUE(saved_value->GetAsBoolean(&bool_value));
140  EXPECT_FALSE(bool_value);
141}
142
143TEST_F(DeviceSettingsProviderTest, SetPrefSucceed) {
144  owner_key_util_->SetPrivateKey(device_policy_.GetSigningKey());
145  InitOwner(device_policy_.policy_data().username(), true);
146  FlushDeviceSettings();
147
148  base::FundamentalValue value(true);
149  EXPECT_CALL(*this, SettingChanged(_)).Times(AnyNumber());
150  EXPECT_CALL(*this, SettingChanged(kStatsReportingPref)).Times(1);
151  provider_->Set(kStatsReportingPref, value);
152  Mock::VerifyAndClearExpectations(this);
153
154  // Process the store.
155  device_settings_test_helper_.set_policy_blob(std::string());
156  FlushDeviceSettings();
157
158  // Verify that the device policy has been adjusted.
159  ASSERT_TRUE(device_settings_service_.device_settings());
160  EXPECT_TRUE(device_settings_service_.device_settings()->
161                  metrics_enabled().metrics_enabled());
162
163  // Verify the change has been applied.
164  const base::Value* saved_value = provider_->Get(kStatsReportingPref);
165  ASSERT_TRUE(saved_value);
166  bool bool_value;
167  EXPECT_TRUE(saved_value->GetAsBoolean(&bool_value));
168  EXPECT_TRUE(bool_value);
169}
170
171TEST_F(DeviceSettingsProviderTest, SetPrefTwice) {
172  owner_key_util_->SetPrivateKey(device_policy_.GetSigningKey());
173  InitOwner(device_policy_.policy_data().username(), true);
174  FlushDeviceSettings();
175
176  EXPECT_CALL(*this, SettingChanged(_)).Times(AnyNumber());
177
178  base::StringValue value1("beta");
179  provider_->Set(kReleaseChannel, value1);
180  base::StringValue value2("dev");
181  provider_->Set(kReleaseChannel, value2);
182
183  // Let the changes propagate through the system.
184  device_settings_test_helper_.set_policy_blob(std::string());
185  FlushDeviceSettings();
186
187  // Verify the second change has been applied.
188  const base::Value* saved_value = provider_->Get(kReleaseChannel);
189  EXPECT_TRUE(value2.Equals(saved_value));
190
191  Mock::VerifyAndClearExpectations(this);
192}
193
194TEST_F(DeviceSettingsProviderTest, PolicyRetrievalFailedBadSignature) {
195  owner_key_util_->SetPublicKeyFromPrivateKey(*device_policy_.GetSigningKey());
196  device_policy_.policy().set_policy_data_signature("bad signature");
197  device_settings_test_helper_.set_policy_blob(device_policy_.GetBlob());
198  ReloadDeviceSettings();
199
200  // Verify that the cached settings blob is not "trusted".
201  EXPECT_EQ(DeviceSettingsService::STORE_VALIDATION_ERROR,
202            device_settings_service_.status());
203  EXPECT_EQ(CrosSettingsProvider::PERMANENTLY_UNTRUSTED,
204            provider_->PrepareTrustedValues(base::Closure()));
205}
206
207TEST_F(DeviceSettingsProviderTest, PolicyRetrievalNoPolicy) {
208  owner_key_util_->SetPublicKeyFromPrivateKey(*device_policy_.GetSigningKey());
209  device_settings_test_helper_.set_policy_blob(std::string());
210  ReloadDeviceSettings();
211
212  // Verify that the cached settings blob is not "trusted".
213  EXPECT_EQ(DeviceSettingsService::STORE_NO_POLICY,
214            device_settings_service_.status());
215  EXPECT_EQ(CrosSettingsProvider::PERMANENTLY_UNTRUSTED,
216            provider_->PrepareTrustedValues(base::Closure()));
217}
218
219TEST_F(DeviceSettingsProviderTest, PolicyFailedPermanentlyNotification) {
220  device_settings_test_helper_.set_policy_blob(std::string());
221
222  EXPECT_CALL(*this, GetTrustedCallback());
223  EXPECT_EQ(CrosSettingsProvider::TEMPORARILY_UNTRUSTED,
224            provider_->PrepareTrustedValues(
225                base::Bind(&DeviceSettingsProviderTest::GetTrustedCallback,
226                           base::Unretained(this))));
227
228  ReloadDeviceSettings();
229  Mock::VerifyAndClearExpectations(this);
230
231  EXPECT_EQ(CrosSettingsProvider::PERMANENTLY_UNTRUSTED,
232            provider_->PrepareTrustedValues(base::Closure()));
233}
234
235TEST_F(DeviceSettingsProviderTest, PolicyLoadNotification) {
236  EXPECT_CALL(*this, GetTrustedCallback());
237
238  EXPECT_EQ(CrosSettingsProvider::TEMPORARILY_UNTRUSTED,
239            provider_->PrepareTrustedValues(
240                base::Bind(&DeviceSettingsProviderTest::GetTrustedCallback,
241                           base::Unretained(this))));
242
243  ReloadDeviceSettings();
244  Mock::VerifyAndClearExpectations(this);
245}
246
247TEST_F(DeviceSettingsProviderTest, StatsReportingMigration) {
248  // Create the legacy consent file.
249  base::FilePath consent_file;
250  ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &consent_file));
251  consent_file = consent_file.AppendASCII("Consent To Send Stats");
252  ASSERT_EQ(1, base::WriteFile(consent_file, "0", 1));
253
254  // This should trigger migration because the metrics policy isn't in the blob.
255  device_settings_test_helper_.set_policy_blob(std::string());
256  FlushDeviceSettings();
257  EXPECT_EQ(std::string(), device_settings_test_helper_.policy_blob());
258
259  // Verify that migration has kicked in.
260  const base::Value* saved_value = provider_->Get(kStatsReportingPref);
261  ASSERT_TRUE(saved_value);
262  bool bool_value;
263  EXPECT_TRUE(saved_value->GetAsBoolean(&bool_value));
264  EXPECT_FALSE(bool_value);
265}
266
267TEST_F(DeviceSettingsProviderTest, LegacyDeviceLocalAccounts) {
268  EXPECT_CALL(*this, SettingChanged(_)).Times(AnyNumber());
269  em::DeviceLocalAccountInfoProto* account =
270      device_policy_.payload().mutable_device_local_accounts()->add_account();
271  account->set_deprecated_public_session_id(
272      policy::PolicyBuilder::kFakeUsername);
273  device_policy_.Build();
274  device_settings_test_helper_.set_policy_blob(device_policy_.GetBlob());
275  ReloadDeviceSettings();
276  Mock::VerifyAndClearExpectations(this);
277
278  // On load, the deprecated spec should have been converted to the new format.
279  base::ListValue expected_accounts;
280  scoped_ptr<base::DictionaryValue> entry_dict(new base::DictionaryValue());
281  entry_dict->SetString(kAccountsPrefDeviceLocalAccountsKeyId,
282                        policy::PolicyBuilder::kFakeUsername);
283  entry_dict->SetInteger(kAccountsPrefDeviceLocalAccountsKeyType,
284                         policy::DeviceLocalAccount::TYPE_PUBLIC_SESSION);
285  expected_accounts.Append(entry_dict.release());
286  const base::Value* actual_accounts =
287      provider_->Get(kAccountsPrefDeviceLocalAccounts);
288  EXPECT_TRUE(base::Value::Equals(&expected_accounts, actual_accounts));
289}
290
291} // namespace chromeos
292