summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos/settings
diff options
context:
space:
mode:
authordmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-31 19:45:58 +0000
committerdmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-31 19:45:58 +0000
commit1efe63c885b492499347012308392abfc2a3ad09 (patch)
tree721062dc820f601e5cd665230ebd232f0a9a79bd /chrome/browser/chromeos/settings
parent9a9e90b57da5f150551373e9c777da72fd414c57 (diff)
downloadchromium_src-1efe63c885b492499347012308392abfc2a3ad09.zip
chromium_src-1efe63c885b492499347012308392abfc2a3ad09.tar.gz
chromium_src-1efe63c885b492499347012308392abfc2a3ad09.tar.bz2
Revert 154457 - Switch from SignedSettings to DeviceSettingsService.
This broke GoogleUpdateTest.StatsConsent on Linux ChromiumOS bots. Check the try jobs from the original code review - the same test failed on the Linux ChromeOS Valgrind bot. DevicePolicyCache and DeviceSettingsProvider now go through DeviceSettingsService, which provides a unified and simpler API to Chrome OS device settings. BUG=chromium:139126 TEST=Unit tests, everything related to enterprise enrollment and device settings still works. TBR=ben@chromium.org Review URL: https://chromiumcodereview.appspot.com/10832035 TBR=mnissler@chromium.org Review URL: https://chromiumcodereview.appspot.com/10918027 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@154483 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/chromeos/settings')
-rw-r--r--chrome/browser/chromeos/settings/cros_settings.cc173
-rw-r--r--chrome/browser/chromeos/settings/cros_settings.h18
-rw-r--r--chrome/browser/chromeos/settings/cros_settings_provider.h3
-rw-r--r--chrome/browser/chromeos/settings/cros_settings_unittest.cc81
-rw-r--r--chrome/browser/chromeos/settings/device_settings_cache.cc59
-rw-r--r--chrome/browser/chromeos/settings/device_settings_provider.cc415
-rw-r--r--chrome/browser/chromeos/settings/device_settings_provider.h121
-rw-r--r--chrome/browser/chromeos/settings/device_settings_provider_unittest.cc242
-rw-r--r--chrome/browser/chromeos/settings/owner_manager.cc2
-rw-r--r--chrome/browser/chromeos/settings/session_manager_observer.cc4
-rw-r--r--chrome/browser/chromeos/settings/signed_settings_cache.cc133
-rw-r--r--chrome/browser/chromeos/settings/signed_settings_cache.h (renamed from chrome/browser/chromeos/settings/device_settings_cache.h)22
-rw-r--r--chrome/browser/chromeos/settings/signed_settings_cache_unittest.cc (renamed from chrome/browser/chromeos/settings/device_settings_cache_unittest.cc)20
-rw-r--r--chrome/browser/chromeos/settings/signed_settings_migration_helper.cc66
-rw-r--r--chrome/browser/chromeos/settings/signed_settings_migration_helper.h59
-rw-r--r--chrome/browser/chromeos/settings/stub_cros_settings_provider.cc3
-rw-r--r--chrome/browser/chromeos/settings/stub_cros_settings_provider.h1
-rw-r--r--chrome/browser/chromeos/settings/system_settings_provider.cc5
-rw-r--r--chrome/browser/chromeos/settings/system_settings_provider.h1
19 files changed, 862 insertions, 566 deletions
diff --git a/chrome/browser/chromeos/settings/cros_settings.cc b/chrome/browser/chromeos/settings/cros_settings.cc
index f0592f3..a0622b4 100644
--- a/chrome/browser/chromeos/settings/cros_settings.cc
+++ b/chrome/browser/chromeos/settings/cros_settings.cc
@@ -11,7 +11,7 @@
#include "base/string_util.h"
#include "base/values.h"
#include "chrome/browser/chromeos/settings/device_settings_provider.h"
-#include "chrome/browser/chromeos/settings/device_settings_service.h"
+#include "chrome/browser/chromeos/settings/signed_settings_helper.h"
#include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
#include "chrome/browser/chromeos/settings/system_settings_provider.h"
#include "chrome/common/chrome_notification_types.h"
@@ -35,6 +35,22 @@ bool CrosSettings::IsCrosSettings(const std::string& path) {
return StartsWithASCII(path, kCrosSettingsPrefix, true);
}
+void CrosSettings::FireObservers(const std::string& path) {
+ DCHECK(CalledOnValidThread());
+ SettingsObserverMap::iterator observer_iterator =
+ settings_observers_.find(path);
+ if (observer_iterator == settings_observers_.end())
+ return;
+
+ NotificationObserverList::Iterator it(*(observer_iterator->second));
+ content::NotificationObserver* observer;
+ while ((observer = it.GetNext()) != NULL) {
+ observer->Observe(chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED,
+ content::Source<CrosSettings>(this),
+ content::Details<const std::string>(&path));
+ }
+}
+
void CrosSettings::Set(const std::string& path, const base::Value& in_value) {
DCHECK(CalledOnValidThread());
CrosSettingsProvider* provider;
@@ -43,27 +59,6 @@ void CrosSettings::Set(const std::string& path, const base::Value& in_value) {
provider->Set(path, in_value);
}
-const base::Value* CrosSettings::GetPref(const std::string& path) const {
- DCHECK(CalledOnValidThread());
- CrosSettingsProvider* provider = GetProvider(path);
- if (provider)
- return provider->Get(path);
- NOTREACHED() << path << " preference was not found in the signed settings.";
- return NULL;
-}
-
-CrosSettingsProvider::TrustedStatus CrosSettings::PrepareTrustedValues(
- const base::Closure& callback) const {
- DCHECK(CalledOnValidThread());
- for (size_t i = 0; i < providers_.size(); ++i) {
- CrosSettingsProvider::TrustedStatus status =
- providers_[i]->PrepareTrustedValues(callback);
- if (status != CrosSettingsProvider::TRUSTED)
- return status;
- }
- return CrosSettingsProvider::TRUSTED;
-}
-
void CrosSettings::SetBoolean(const std::string& path, bool in_value) {
DCHECK(CalledOnValidThread());
base::FundamentalValue value(in_value);
@@ -109,51 +104,6 @@ void CrosSettings::RemoveFromList(const std::string& path,
Set(path, *new_value);
}
-bool CrosSettings::GetBoolean(const std::string& path,
- bool* bool_value) const {
- DCHECK(CalledOnValidThread());
- const base::Value* value = GetPref(path);
- if (value)
- return value->GetAsBoolean(bool_value);
- return false;
-}
-
-bool CrosSettings::GetInteger(const std::string& path,
- int* out_value) const {
- DCHECK(CalledOnValidThread());
- const base::Value* value = GetPref(path);
- if (value)
- return value->GetAsInteger(out_value);
- return false;
-}
-
-bool CrosSettings::GetDouble(const std::string& path,
- double* out_value) const {
- DCHECK(CalledOnValidThread());
- const base::Value* value = GetPref(path);
- if (value)
- return value->GetAsDouble(out_value);
- return false;
-}
-
-bool CrosSettings::GetString(const std::string& path,
- std::string* out_value) const {
- DCHECK(CalledOnValidThread());
- const base::Value* value = GetPref(path);
- if (value)
- return value->GetAsString(out_value);
- return false;
-}
-
-bool CrosSettings::GetList(const std::string& path,
- const base::ListValue** out_value) const {
- DCHECK(CalledOnValidThread());
- const base::Value* value = GetPref(path);
- if (value)
- return value->GetAsList(out_value);
- return false;
-}
-
bool CrosSettings::FindEmailInList(const std::string& path,
const std::string& email) const {
DCHECK(CalledOnValidThread());
@@ -270,6 +220,77 @@ CrosSettingsProvider* CrosSettings::GetProvider(
return NULL;
}
+void CrosSettings::ReloadProviders() {
+ for (size_t i = 0; i < providers_.size(); ++i)
+ providers_[i]->Reload();
+}
+
+const base::Value* CrosSettings::GetPref(const std::string& path) const {
+ DCHECK(CalledOnValidThread());
+ CrosSettingsProvider* provider = GetProvider(path);
+ if (provider)
+ return provider->Get(path);
+ NOTREACHED() << path << " preference was not found in the signed settings.";
+ return NULL;
+}
+
+CrosSettingsProvider::TrustedStatus CrosSettings::PrepareTrustedValues(
+ const base::Closure& callback) const {
+ DCHECK(CalledOnValidThread());
+ for (size_t i = 0; i < providers_.size(); ++i) {
+ CrosSettingsProvider::TrustedStatus status =
+ providers_[i]->PrepareTrustedValues(callback);
+ if (status != CrosSettingsProvider::TRUSTED)
+ return status;
+ }
+ return CrosSettingsProvider::TRUSTED;
+}
+
+bool CrosSettings::GetBoolean(const std::string& path,
+ bool* bool_value) const {
+ DCHECK(CalledOnValidThread());
+ const base::Value* value = GetPref(path);
+ if (value)
+ return value->GetAsBoolean(bool_value);
+ return false;
+}
+
+bool CrosSettings::GetInteger(const std::string& path,
+ int* out_value) const {
+ DCHECK(CalledOnValidThread());
+ const base::Value* value = GetPref(path);
+ if (value)
+ return value->GetAsInteger(out_value);
+ return false;
+}
+
+bool CrosSettings::GetDouble(const std::string& path,
+ double* out_value) const {
+ DCHECK(CalledOnValidThread());
+ const base::Value* value = GetPref(path);
+ if (value)
+ return value->GetAsDouble(out_value);
+ return false;
+}
+
+bool CrosSettings::GetString(const std::string& path,
+ std::string* out_value) const {
+ DCHECK(CalledOnValidThread());
+ const base::Value* value = GetPref(path);
+ if (value)
+ return value->GetAsString(out_value);
+ return false;
+}
+
+bool CrosSettings::GetList(const std::string& path,
+ const base::ListValue** out_value) const {
+ DCHECK(CalledOnValidThread());
+ const base::Value* value = GetPref(path);
+ if (value)
+ return value->GetAsList(out_value);
+ return false;
+}
+
CrosSettings::CrosSettings() {
CrosSettingsProvider::NotifyObserversCallback notify_cb(
base::Bind(&CrosSettings::FireObservers,
@@ -280,7 +301,7 @@ CrosSettings::CrosSettings() {
AddSettingsProvider(new StubCrosSettingsProvider(notify_cb));
} else {
AddSettingsProvider(
- new DeviceSettingsProvider(notify_cb, DeviceSettingsService::Get()));
+ new DeviceSettingsProvider(notify_cb, SignedSettingsHelper::Get()));
}
// System settings are not mocked currently.
AddSettingsProvider(new SystemSettingsProvider(notify_cb));
@@ -291,20 +312,4 @@ CrosSettings::~CrosSettings() {
STLDeleteValues(&settings_observers_);
}
-void CrosSettings::FireObservers(const std::string& path) {
- DCHECK(CalledOnValidThread());
- SettingsObserverMap::iterator observer_iterator =
- settings_observers_.find(path);
- if (observer_iterator == settings_observers_.end())
- return;
-
- NotificationObserverList::Iterator it(*(observer_iterator->second));
- content::NotificationObserver* observer;
- while ((observer = it.GetNext()) != NULL) {
- observer->Observe(chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED,
- content::Source<CrosSettings>(this),
- content::Details<const std::string>(&path));
- }
-}
-
} // namespace chromeos
diff --git a/chrome/browser/chromeos/settings/cros_settings.h b/chrome/browser/chromeos/settings/cros_settings.h
index 4148ee6..128184c 100644
--- a/chrome/browser/chromeos/settings/cros_settings.h
+++ b/chrome/browser/chromeos/settings/cros_settings.h
@@ -91,16 +91,12 @@ class CrosSettings : public base::NonThreadSafe {
// Returns the provider that handles settings with the |path| or prefix.
CrosSettingsProvider* GetProvider(const std::string& path) const;
+ // Forces all providers to reload their caches from the respective backing
+ // stores if they have any.
+ void ReloadProviders();
+
private:
friend struct base::DefaultLazyInstanceTraits<CrosSettings>;
- friend class CrosSettingsTest;
-
- // Public for testing.
- CrosSettings();
- ~CrosSettings();
-
- // Fires system setting change notification.
- void FireObservers(const std::string& path);
// List of ChromeOS system settings providers.
std::vector<CrosSettingsProvider*> providers_;
@@ -113,6 +109,12 @@ class CrosSettings : public base::NonThreadSafe {
SettingsObserverMap;
SettingsObserverMap settings_observers_;
+ CrosSettings();
+ ~CrosSettings();
+
+ // Fires system setting change notification.
+ void FireObservers(const std::string& path);
+
DISALLOW_COPY_AND_ASSIGN(CrosSettings);
};
diff --git a/chrome/browser/chromeos/settings/cros_settings_provider.h b/chrome/browser/chromeos/settings/cros_settings_provider.h
index 6196555..2477f34 100644
--- a/chrome/browser/chromeos/settings/cros_settings_provider.h
+++ b/chrome/browser/chromeos/settings/cros_settings_provider.h
@@ -58,6 +58,9 @@ class CrosSettingsProvider {
// Gets the namespace prefix provided by this provider.
virtual bool HandlesSetting(const std::string& path) const = 0;
+ // Reloads the caches if the provider has any.
+ virtual void Reload() = 0;
+
void SetNotifyObserversCallback(const NotifyObserversCallback& notify_cb);
protected:
diff --git a/chrome/browser/chromeos/settings/cros_settings_unittest.cc b/chrome/browser/chromeos/settings/cros_settings_unittest.cc
index e3fc928..f5fb133 100644
--- a/chrome/browser/chromeos/settings/cros_settings_unittest.cc
+++ b/chrome/browser/chromeos/settings/cros_settings_unittest.cc
@@ -2,19 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "chrome/browser/chromeos/settings/signed_settings.h"
+
#include <map>
#include <string>
#include "base/bind.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop.h"
#include "base/stl_util.h"
#include "base/values.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/login/mock_user_manager.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/cros_settings_names.h"
-#include "chrome/browser/chromeos/settings/device_settings_test_helper.h"
-#include "chrome/browser/policy/cloud_policy_constants.h"
+#include "chrome/browser/chromeos/settings/signed_settings_cache.h"
#include "chrome/browser/policy/proto/chrome_device_policy.pb.h"
#include "chrome/browser/policy/proto/device_management_backend.pb.h"
#include "chrome/test/base/testing_browser_process.h"
@@ -22,8 +24,10 @@
#include "content/public/test/test_browser_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
-namespace em = enterprise_management;
+using ::testing::AnyNumber;
+using ::testing::Return;
+namespace em = enterprise_management;
namespace chromeos {
class CrosSettingsTest : public testing::Test {
@@ -31,15 +35,28 @@ class CrosSettingsTest : public testing::Test {
CrosSettingsTest()
: message_loop_(MessageLoop::TYPE_UI),
ui_thread_(content::BrowserThread::UI, &message_loop_),
- local_state_(static_cast<TestingBrowserProcess*>(g_browser_process)),
- weak_factory_(this) {}
+ file_thread_(content::BrowserThread::FILE, &message_loop_),
+ pointer_factory_(this),
+ local_state_(static_cast<TestingBrowserProcess*>(g_browser_process)) {
+ }
- virtual ~CrosSettingsTest() {}
+ virtual ~CrosSettingsTest() {
+ }
+
+ virtual void SetUp() {
+ EXPECT_CALL(*mock_user_manager_.user_manager(), IsCurrentUserOwner())
+ .Times(AnyNumber())
+ .WillRepeatedly(Return(true));
+ // Reset the cache between tests.
+ ApplyEmptyPolicy();
+ }
- virtual void TearDown() OVERRIDE {
+ virtual void TearDown() {
+ message_loop_.RunAllPending();
ASSERT_TRUE(expected_props_.empty());
+ // Reset the cache between tests.
+ ApplyEmptyPolicy();
STLDeleteValues(&expected_props_);
- expected_props_.clear();
}
void FetchPref(const std::string& pref) {
@@ -48,12 +65,12 @@ class CrosSettingsTest : public testing::Test {
return;
if (CrosSettingsProvider::TRUSTED ==
- settings_.PrepareTrustedValues(
- base::Bind(&CrosSettingsTest::FetchPref,
- weak_factory_.GetWeakPtr(), pref))) {
+ CrosSettings::Get()->PrepareTrustedValues(
+ base::Bind(&CrosSettingsTest::FetchPref,
+ pointer_factory_.GetWeakPtr(), pref))) {
scoped_ptr<base::Value> expected_value(
expected_props_.find(pref)->second);
- const base::Value* pref_value = settings_.GetPref(pref);
+ const base::Value* pref_value = CrosSettings::Get()->GetPref(pref);
if (expected_value.get()) {
ASSERT_TRUE(pref_value);
ASSERT_TRUE(expected_value->Equals(pref_value));
@@ -66,7 +83,7 @@ class CrosSettingsTest : public testing::Test {
void SetPref(const std::string& pref_name, const base::Value* value) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- settings_.Set(pref_name, *value);
+ CrosSettings::Get()->Set(pref_name, *value);
}
void AddExpectation(const std::string& pref_name, base::Value* value) {
@@ -79,7 +96,7 @@ class CrosSettingsTest : public testing::Test {
// Prepare some policy blob.
em::PolicyFetchResponse response;
em::ChromeDeviceSettingsProto pol;
- policy->set_policy_type(policy::dm_protocol::kChromeDevicePolicyType);
+ policy->set_policy_type(chromeos::kDevicePolicyType);
policy->set_username("me@owner");
policy->set_policy_value(pol.SerializeAsString());
// Wipe the signed settings store.
@@ -87,16 +104,25 @@ class CrosSettingsTest : public testing::Test {
response.set_policy_data_signature("false");
}
+ void ApplyEmptyPolicy() {
+ em::PolicyData fake_pol;
+ PrepareEmptyPolicy(&fake_pol);
+ signed_settings_cache::Store(fake_pol, local_state_.Get());
+ CrosSettings::Get()->ReloadProviders();
+ }
+
+ std::map<std::string, base::Value*> expected_props_;
+
MessageLoop message_loop_;
content::TestBrowserThread ui_thread_;
+ content::TestBrowserThread file_thread_;
- ScopedTestingLocalState local_state_;
- ScopedDeviceSettingsTestHelper device_settings_test_helper_;
- CrosSettings settings_;
+ base::WeakPtrFactory<CrosSettingsTest> pointer_factory_;
- base::WeakPtrFactory<CrosSettingsTest> weak_factory_;
+ ScopedTestingLocalState local_state_;
- std::map<std::string, base::Value*> expected_props_;
+ ScopedMockUserManagerEnabler mock_user_manager_;
+ ScopedStubCrosEnabler stub_cros_enabler_;
};
TEST_F(CrosSettingsTest, SetPref) {
@@ -105,6 +131,7 @@ TEST_F(CrosSettingsTest, SetPref) {
base::Value::CreateBooleanValue(false));
SetPref(kAccountsPrefAllowGuest, expected_props_[kAccountsPrefAllowGuest]);
FetchPref(kAccountsPrefAllowGuest);
+ message_loop_.RunAllPending();
ASSERT_TRUE(expected_props_.empty());
}
@@ -136,7 +163,7 @@ TEST_F(CrosSettingsTest, SetWhitelistWithListOps) {
base::Value::CreateBooleanValue(false));
AddExpectation(kAccountsPrefUsers, whitelist);
// Add some user to the whitelist.
- settings_.AppendToList(kAccountsPrefUsers, &hacky_user);
+ CrosSettings::Get()->AppendToList(kAccountsPrefUsers, &hacky_user);
FetchPref(kAccountsPrefAllowNewUser);
FetchPref(kAccountsPrefUsers);
}
@@ -154,10 +181,11 @@ TEST_F(CrosSettingsTest, SetWhitelistWithListOps2) {
SetPref(kAccountsPrefUsers, &whitelist);
FetchPref(kAccountsPrefAllowNewUser);
FetchPref(kAccountsPrefUsers);
+ message_loop_.RunAllPending();
ASSERT_TRUE(expected_props_.empty());
// Now try to remove one element from that list.
AddExpectation(kAccountsPrefUsers, expected_list);
- settings_.RemoveFromList(kAccountsPrefUsers, &lamy_user);
+ CrosSettings::Get()->RemoveFromList(kAccountsPrefUsers, &lamy_user);
FetchPref(kAccountsPrefAllowNewUser);
FetchPref(kAccountsPrefUsers);
}
@@ -199,6 +227,13 @@ TEST_F(CrosSettingsTest, SetAllowNewUsers) {
FetchPref(kAccountsPrefAllowNewUser);
}
+TEST_F(CrosSettingsTest, SetOwner) {
+ base::StringValue hacky_owner("h@xxor");
+ AddExpectation(kDeviceOwner, base::Value::CreateStringValue("h@xxor"));
+ SetPref(kDeviceOwner, &hacky_owner);
+ FetchPref(kDeviceOwner);
+}
+
TEST_F(CrosSettingsTest, SetEphemeralUsersEnabled) {
base::FundamentalValue ephemeral_users_enabled(true);
AddExpectation(kAccountsPrefEphemeralUsersEnabled,
@@ -214,7 +249,7 @@ TEST_F(CrosSettingsTest, FindEmailInList) {
list.Append(base::Value::CreateStringValue("with.dots@gmail.com"));
list.Append(base::Value::CreateStringValue("Upper@example.com"));
- CrosSettings* cs = &settings_;
+ CrosSettings* cs = CrosSettings::Get();
cs->Set(kAccountsPrefUsers, list);
EXPECT_TRUE(cs->FindEmailInList(kAccountsPrefUsers, "user@example.com"));
diff --git a/chrome/browser/chromeos/settings/device_settings_cache.cc b/chrome/browser/chromeos/settings/device_settings_cache.cc
deleted file mode 100644
index 178cbfb..0000000
--- a/chrome/browser/chromeos/settings/device_settings_cache.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/settings/device_settings_cache.h"
-
-#include <string>
-
-#include "base/base64.h"
-#include "base/bind.h"
-#include "chrome/browser/chromeos/settings/cros_settings.h"
-#include "chrome/browser/policy/proto/device_management_backend.pb.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/common/pref_names.h"
-
-namespace em = enterprise_management;
-
-namespace chromeos {
-
-namespace device_settings_cache {
-
-void RegisterPrefs(PrefService* local_state) {
- local_state->RegisterStringPref(prefs::kDeviceSettingsCache,
- "invalid",
- PrefService::UNSYNCABLE_PREF);
-}
-
-bool Store(const em::PolicyData& policy, PrefService* local_state) {
- if (local_state) {
- std::string policy_string = policy.SerializeAsString();
- std::string encoded;
- if (!base::Base64Encode(policy_string, &encoded)) {
- LOG(ERROR) << "Can't encode policy in base64.";
- return false;
- }
- local_state->SetString(prefs::kDeviceSettingsCache, encoded);
- return true;
- }
- return false;
-}
-
-bool Retrieve(em::PolicyData *policy, PrefService* local_state) {
- if (local_state) {
- std::string encoded =
- local_state->GetString(prefs::kDeviceSettingsCache);
- std::string policy_string;
- if (!base::Base64Decode(encoded, &policy_string)) {
- // This is normal and happens on first boot.
- VLOG(1) << "Can't decode policy from base64.";
- return false;
- }
- return policy->ParseFromString(policy_string);
- }
- return false;
-}
-
-} // namespace device_settings_cache
-
-} // namespace chromeos
diff --git a/chrome/browser/chromeos/settings/device_settings_provider.cc b/chrome/browser/chromeos/settings/device_settings_provider.cc
index 1a6b56b..ed03b55 100644
--- a/chrome/browser/chromeos/settings/device_settings_provider.cc
+++ b/chrome/browser/chromeos/settings/device_settings_provider.cc
@@ -15,15 +15,19 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/network_library.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/cros_settings_names.h"
-#include "chrome/browser/chromeos/settings/device_settings_cache.h"
+#include "chrome/browser/chromeos/settings/signed_settings_cache.h"
+#include "chrome/browser/chromeos/settings/signed_settings_helper.h"
#include "chrome/browser/policy/app_pack_updater.h"
#include "chrome/browser/policy/browser_policy_connector.h"
#include "chrome/browser/policy/cloud_policy_constants.h"
-#include "chrome/browser/policy/proto/device_management_backend.pb.h"
+#include "chrome/browser/policy/proto/chrome_device_policy.pb.h"
#include "chrome/browser/ui/options/options_util.h"
+#include "chrome/common/chrome_notification_types.h"
#include "chrome/installer/util/google_update_settings.h"
+#include "content/public/browser/notification_service.h"
using google::protobuf::RepeatedPtrField;
@@ -60,6 +64,9 @@ const char* kKnownSettings[] = {
kSystemTimezonePolicy,
};
+// Upper bound for number of retries to fetch a signed setting.
+static const int kNumRetriesLimit = 9;
+
// Legacy policy file location. Used to detect migration from pre v12 ChromeOS.
const char kLegacyPolicyFile[] = "/var/lib/whitelist/preferences";
@@ -81,30 +88,43 @@ bool HasOldMetricsFile() {
DeviceSettingsProvider::DeviceSettingsProvider(
const NotifyObserversCallback& notify_cb,
- DeviceSettingsService* device_settings_service)
+ SignedSettingsHelper* signed_settings_helper)
: CrosSettingsProvider(notify_cb),
- device_settings_service_(device_settings_service),
- trusted_status_(TEMPORARILY_UNTRUSTED),
- ownership_status_(device_settings_service_->GetOwnershipStatus()),
- ALLOW_THIS_IN_INITIALIZER_LIST(store_callback_factory_(this)) {
- device_settings_service_->AddObserver(this);
-
- if (!UpdateFromService()) {
- // Make sure we have at least the cache data immediately.
- RetrieveCachedData();
- }
+ signed_settings_helper_(signed_settings_helper),
+ ownership_status_(OwnershipService::GetSharedInstance()->GetStatus(true)),
+ migration_helper_(new SignedSettingsMigrationHelper()),
+ retries_left_(kNumRetriesLimit),
+ trusted_status_(TEMPORARILY_UNTRUSTED) {
+ // Register for notification when ownership is taken so that we can update
+ // the |ownership_status_| and reload if needed.
+ registrar_.Add(this, chrome::NOTIFICATION_OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED,
+ content::NotificationService::AllSources());
+ // Make sure we have at least the cache data immediately.
+ RetrieveCachedData();
+ // Start prefetching preferences.
+ Reload();
}
DeviceSettingsProvider::~DeviceSettingsProvider() {
- device_settings_service_->RemoveObserver(this);
+}
+
+void DeviceSettingsProvider::Reload() {
+ // While fetching we can't trust the cache anymore.
+ trusted_status_ = TEMPORARILY_UNTRUSTED;
+ if (ownership_status_ == OwnershipService::OWNERSHIP_NONE) {
+ RetrieveCachedData();
+ } else {
+ // Retrieve the real data.
+ signed_settings_helper_->StartRetrievePolicyOp(
+ base::Bind(&DeviceSettingsProvider::OnRetrievePolicyCompleted,
+ base::Unretained(this)));
+ }
}
void DeviceSettingsProvider::DoSet(const std::string& path,
const base::Value& in_value) {
- // Make sure that either the current user is the device owner or the
- // device doesn't have an owner yet.
- if (!(device_settings_service_->HasPrivateOwnerKey() ||
- ownership_status_ == DeviceSettingsService::OWNERSHIP_NONE)) {
+ if (!UserManager::Get()->IsCurrentUserOwner() &&
+ ownership_status_ != OwnershipService::OWNERSHIP_NONE) {
LOG(WARNING) << "Changing settings from non-owner, setting=" << path;
// Revert UI change.
@@ -114,60 +134,43 @@ void DeviceSettingsProvider::DoSet(const std::string& path,
if (IsControlledSetting(path)) {
pending_changes_.push_back(PendingQueueElement(path, in_value.DeepCopy()));
- if (!store_callback_factory_.HasWeakPtrs())
+ if (pending_changes_.size() == 1)
SetInPolicy();
} else {
NOTREACHED() << "Try to set unhandled cros setting " << path;
}
}
-void DeviceSettingsProvider::OwnershipStatusChanged() {
- DeviceSettingsService::OwnershipStatus new_ownership_status =
- device_settings_service_->GetOwnershipStatus();
-
- // If the device just became owned, write the settings accumulated in the
- // cache to device settings proper. It is important that writing only happens
- // in this case, as during normal operation, the contents of the cache should
- // never overwrite actual device settings.
- if (new_ownership_status == DeviceSettingsService::OWNERSHIP_TAKEN &&
- ownership_status_ == DeviceSettingsService::OWNERSHIP_NONE &&
- device_settings_service_->HasPrivateOwnerKey()) {
-
- // There shouldn't be any pending writes, since the cache writes are all
- // immediate.
- DCHECK(!store_callback_factory_.HasWeakPtrs());
-
- // Apply the locally-accumulated device settings on top of the initial
- // settings from the service and write back the result.
- if (device_settings_service_->device_settings()) {
- em::ChromeDeviceSettingsProto new_settings(
- *device_settings_service_->device_settings());
- new_settings.MergeFrom(device_settings_);
- device_settings_.Swap(&new_settings);
- }
- StoreDeviceSettings();
+void DeviceSettingsProvider::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ if (type == chrome::NOTIFICATION_OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED) {
+ // Reload the policy blob once the owner key has been loaded or updated.
+ ownership_status_ = OwnershipService::OWNERSHIP_TAKEN;
+ Reload();
}
-
- // The owner key might have become available, allowing migration to happen.
- AttemptMigration();
-
- ownership_status_ = new_ownership_status;
}
-void DeviceSettingsProvider::DeviceSettingsUpdated() {
- if (!store_callback_factory_.HasWeakPtrs())
- UpdateAndProceedStoring();
+const em::PolicyData DeviceSettingsProvider::policy() const {
+ return policy_;
}
void DeviceSettingsProvider::RetrieveCachedData() {
- em::PolicyData policy_data;
- if (!device_settings_cache::Retrieve(&policy_data,
- g_browser_process->local_state()) ||
- !device_settings_.ParseFromString(policy_data.policy_value())) {
- VLOG(1) << "Can't retrieve temp store, possibly not created yet.";
+ // If there is no owner yet, this function will pull the policy cache from the
+ // temp storage and use that instead.
+ em::PolicyData policy;
+ if (!signed_settings_cache::Retrieve(&policy,
+ g_browser_process->local_state())) {
+ VLOG(1) << "Can't retrieve temp store possibly not created yet.";
+ // Prepare empty data for the case we don't have temp cache yet.
+ policy.set_policy_type(kDevicePolicyType);
+ em::ChromeDeviceSettingsProto pol;
+ policy.set_policy_value(pol.SerializeAsString());
}
- UpdateValuesCache(policy_data, device_settings_);
+ policy_ = policy;
+ UpdateValuesCache();
}
void DeviceSettingsProvider::SetInPolicy() {
@@ -176,44 +179,62 @@ void DeviceSettingsProvider::SetInPolicy() {
return;
}
- if (RequestTrustedEntity() != TRUSTED) {
- // Re-sync device settings before proceeding.
- device_settings_service_->Load();
+ const std::string& prop = pending_changes_[0].first;
+ base::Value* value = pending_changes_[0].second;
+ if (prop == kDeviceOwner) {
+ // Just store it in the memory cache without trusted checks or persisting.
+ std::string owner;
+ if (value->GetAsString(&owner)) {
+ policy_.set_username(owner);
+ // In this case the |value_cache_| takes the ownership of |value|.
+ values_cache_.SetValue(prop, value);
+ NotifyObservers(prop);
+ // We can't trust this value anymore until we reload the real username.
+ trusted_status_ = TEMPORARILY_UNTRUSTED;
+ pending_changes_.erase(pending_changes_.begin());
+ if (!pending_changes_.empty())
+ SetInPolicy();
+ } else {
+ NOTREACHED();
+ }
return;
}
- std::string prop(pending_changes_.front().first);
- scoped_ptr<base::Value> value(pending_changes_.front().second);
- pending_changes_.pop_front();
+ if (RequestTrustedEntity() != TRUSTED) {
+ // Otherwise we should first reload and apply on top of that.
+ signed_settings_helper_->StartRetrievePolicyOp(
+ base::Bind(&DeviceSettingsProvider::FinishSetInPolicy,
+ base::Unretained(this)));
+ return;
+ }
trusted_status_ = TEMPORARILY_UNTRUSTED;
+ em::PolicyData data = policy();
+ em::ChromeDeviceSettingsProto pol;
+ pol.ParseFromString(data.policy_value());
if (prop == kAccountsPrefAllowNewUser) {
- em::AllowNewUsersProto* allow =
- device_settings_.mutable_allow_new_users();
+ em::AllowNewUsersProto* allow = pol.mutable_allow_new_users();
bool allow_value;
if (value->GetAsBoolean(&allow_value))
allow->set_allow_new_users(allow_value);
else
NOTREACHED();
} else if (prop == kAccountsPrefAllowGuest) {
- em::GuestModeEnabledProto* guest =
- device_settings_.mutable_guest_mode_enabled();
+ em::GuestModeEnabledProto* guest = pol.mutable_guest_mode_enabled();
bool guest_value;
if (value->GetAsBoolean(&guest_value))
guest->set_guest_mode_enabled(guest_value);
else
NOTREACHED();
} else if (prop == kAccountsPrefShowUserNamesOnSignIn) {
- em::ShowUserNamesOnSigninProto* show =
- device_settings_.mutable_show_user_names();
+ em::ShowUserNamesOnSigninProto* show = pol.mutable_show_user_names();
bool show_value;
if (value->GetAsBoolean(&show_value))
show->set_show_user_names(show_value);
else
NOTREACHED();
} else if (prop == kSignedDataRoamingEnabled) {
- em::DataRoamingEnabledProto* roam =
- device_settings_.mutable_data_roaming_enabled();
+ em::DataRoamingEnabledProto* roam = pol.mutable_data_roaming_enabled();
bool roaming_value = false;
if (value->GetAsBoolean(&roaming_value))
roam->set_data_roaming_enabled(roaming_value);
@@ -225,23 +246,20 @@ void DeviceSettingsProvider::SetInPolicy() {
std::string proxy_value;
if (value->GetAsString(&proxy_value)) {
bool success =
- device_settings_.mutable_device_proxy_settings()->ParseFromString(
- proxy_value);
+ pol.mutable_device_proxy_settings()->ParseFromString(proxy_value);
DCHECK(success);
} else {
NOTREACHED();
}
} else if (prop == kReleaseChannel) {
- em::ReleaseChannelProto* release_channel =
- device_settings_.mutable_release_channel();
+ em::ReleaseChannelProto* release_channel = pol.mutable_release_channel();
std::string channel_value;
if (value->GetAsString(&channel_value))
release_channel->set_release_channel(channel_value);
else
NOTREACHED();
} else if (prop == kStatsReportingPref) {
- em::MetricsEnabledProto* metrics =
- device_settings_.mutable_metrics_enabled();
+ em::MetricsEnabledProto* metrics = pol.mutable_metrics_enabled();
bool metrics_value = false;
if (value->GetAsBoolean(&metrics_value))
metrics->set_metrics_enabled(metrics_value);
@@ -249,8 +267,7 @@ void DeviceSettingsProvider::SetInPolicy() {
NOTREACHED();
ApplyMetricsSetting(false, metrics_value);
} else if (prop == kAccountsPrefUsers) {
- em::UserWhitelistProto* whitelist_proto =
- device_settings_.mutable_user_whitelist();
+ em::UserWhitelistProto* whitelist_proto = pol.mutable_user_whitelist();
whitelist_proto->clear_user_whitelist();
base::ListValue& users = static_cast<base::ListValue&>(*value);
for (base::ListValue::const_iterator i = users.begin();
@@ -261,19 +278,17 @@ void DeviceSettingsProvider::SetInPolicy() {
}
} else if (prop == kAccountsPrefEphemeralUsersEnabled) {
em::EphemeralUsersEnabledProto* ephemeral_users_enabled =
- device_settings_.mutable_ephemeral_users_enabled();
+ pol.mutable_ephemeral_users_enabled();
bool ephemeral_users_enabled_value = false;
- if (value->GetAsBoolean(&ephemeral_users_enabled_value)) {
+ if (value->GetAsBoolean(&ephemeral_users_enabled_value))
ephemeral_users_enabled->set_ephemeral_users_enabled(
ephemeral_users_enabled_value);
- } else {
+ else
NOTREACHED();
- }
} else {
// The remaining settings don't support Set(), since they are not
// intended to be customizable by the user:
// kAppPack
- // kDeviceOwner
// kIdleLogoutTimeout
// kIdleLogoutWarningDuration
// kReleaseChannelDelegated
@@ -286,29 +301,48 @@ void DeviceSettingsProvider::SetInPolicy() {
// kStartUpUrls
// kSystemTimezonePolicy
- LOG(FATAL) << "Device setting " << prop << " is read-only.";
+ NOTREACHED();
}
-
- em::PolicyData data;
- data.set_username(device_settings_service_->GetUsername());
- CHECK(device_settings_.SerializeToString(data.mutable_policy_value()));
-
+ data.set_policy_value(pol.SerializeAsString());
// Set the cache to the updated value.
- UpdateValuesCache(data, device_settings_);
+ policy_ = data;
+ UpdateValuesCache();
- if (!device_settings_cache::Store(data, g_browser_process->local_state()))
+ if (!signed_settings_cache::Store(data, g_browser_process->local_state()))
LOG(ERROR) << "Couldn't store to the temp storage.";
- if (ownership_status_ == DeviceSettingsService::OWNERSHIP_TAKEN) {
- StoreDeviceSettings();
+ if (ownership_status_ == OwnershipService::OWNERSHIP_TAKEN) {
+ em::PolicyFetchResponse policy_envelope;
+ policy_envelope.set_policy_data(policy_.SerializeAsString());
+ signed_settings_helper_->StartStorePolicyOp(
+ policy_envelope,
+ base::Bind(&DeviceSettingsProvider::OnStorePolicyCompleted,
+ base::Unretained(this)));
} else {
// OnStorePolicyCompleted won't get called in this case so proceed with any
// pending operations immediately.
+ delete pending_changes_[0].second;
+ pending_changes_.erase(pending_changes_.begin());
if (!pending_changes_.empty())
SetInPolicy();
}
}
+void DeviceSettingsProvider::FinishSetInPolicy(
+ SignedSettings::ReturnCode code,
+ const em::PolicyFetchResponse& policy) {
+ if (code != SignedSettings::SUCCESS) {
+ LOG(ERROR) << "Can't serialize to policy error code: " << code;
+ Reload();
+ return;
+ }
+ // Update the internal caches and set the trusted flag to true so that we
+ // can pass the trustedness check in the second call to SetInPolicy.
+ OnRetrievePolicyCompleted(code, policy);
+
+ SetInPolicy();
+}
+
void DeviceSettingsProvider::DecodeLoginPolicies(
const em::ChromeDeviceSettingsProto& policy,
PrefValueMap* new_values_cache) const {
@@ -504,19 +538,21 @@ void DeviceSettingsProvider::DecodeGenericPolicies(
}
}
-void DeviceSettingsProvider::UpdateValuesCache(
- const em::PolicyData& policy_data,
- const em::ChromeDeviceSettingsProto& settings) {
+void DeviceSettingsProvider::UpdateValuesCache() {
+ const em::PolicyData data = policy();
PrefValueMap new_values_cache;
- if (policy_data.has_username() && !policy_data.has_request_token())
- new_values_cache.SetString(kDeviceOwner, policy_data.username());
+ if (data.has_username() && !data.has_request_token())
+ new_values_cache.SetString(kDeviceOwner, data.username());
- DecodeLoginPolicies(settings, &new_values_cache);
- DecodeKioskPolicies(settings, &new_values_cache);
- DecodeNetworkPolicies(settings, &new_values_cache);
- DecodeReportingPolicies(settings, &new_values_cache);
- DecodeGenericPolicies(settings, &new_values_cache);
+ em::ChromeDeviceSettingsProto pol;
+ pol.ParseFromString(data.policy_value());
+
+ DecodeLoginPolicies(pol, &new_values_cache);
+ DecodeKioskPolicies(pol, &new_values_cache);
+ DecodeNetworkPolicies(pol, &new_values_cache);
+ DecodeReportingPolicies(pol, &new_values_cache);
+ DecodeGenericPolicies(pol, &new_values_cache);
// Collect all notifications but send them only after we have swapped the
// cache so that if somebody actually reads the cache will be already valid.
@@ -543,18 +579,18 @@ void DeviceSettingsProvider::UpdateValuesCache(
}
void DeviceSettingsProvider::ApplyMetricsSetting(bool use_file,
- bool new_value) {
+ bool new_value) const {
// TODO(pastarmovj): Remove this once migration is not needed anymore.
// If the value is not set we should try to migrate legacy consent file.
if (use_file) {
new_value = HasOldMetricsFile();
// Make sure the values will get eventually written to the policy file.
- migration_values_.SetValue(kStatsReportingPref,
- base::Value::CreateBooleanValue(new_value));
- AttemptMigration();
+ migration_helper_->AddMigrationValue(
+ kStatsReportingPref, base::Value::CreateBooleanValue(new_value));
+ migration_helper_->MigrateValues();
LOG(INFO) << "No metrics policy set will revert to checking "
- << "consent file which is "
- << (new_value ? "on." : "off.");
+ << "consent file which is "
+ << (new_value ? "on." : "off.");
}
VLOG(1) << "Metrics policy is being set to : " << new_value
<< "(use file : " << use_file << ")";
@@ -563,7 +599,7 @@ void DeviceSettingsProvider::ApplyMetricsSetting(bool use_file,
OptionsUtil::ResolveMetricsReportingEnabled(new_value);
}
-void DeviceSettingsProvider::ApplyRoamingSetting(bool new_value) {
+void DeviceSettingsProvider::ApplyRoamingSetting(bool new_value) const {
NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
const NetworkDevice* cellular = cros->FindCellularDevice();
if (cellular) {
@@ -578,26 +614,25 @@ void DeviceSettingsProvider::ApplyRoamingSetting(bool new_value) {
}
}
-void DeviceSettingsProvider::ApplySideEffects(
- const em::ChromeDeviceSettingsProto& settings) {
+void DeviceSettingsProvider::ApplySideEffects() const {
+ const em::PolicyData data = policy();
+ em::ChromeDeviceSettingsProto pol;
+ pol.ParseFromString(data.policy_value());
// First migrate metrics settings as needed.
- if (settings.has_metrics_enabled())
- ApplyMetricsSetting(false, settings.metrics_enabled().metrics_enabled());
+ if (pol.has_metrics_enabled())
+ ApplyMetricsSetting(false, pol.metrics_enabled().metrics_enabled());
else
ApplyMetricsSetting(true, false);
-
// Next set the roaming setting as needed.
- ApplyRoamingSetting(
- settings.has_data_roaming_enabled() ?
- settings.data_roaming_enabled().data_roaming_enabled() :
- false);
+ ApplyRoamingSetting(pol.has_data_roaming_enabled() ?
+ pol.data_roaming_enabled().data_roaming_enabled() : false);
}
bool DeviceSettingsProvider::MitigateMissingPolicy() {
// First check if the device has been owned already and if not exit
// immediately.
if (g_browser_process->browser_policy_connector()->GetDeviceMode() !=
- policy::DEVICE_MODE_CONSUMER) {
+ policy::DEVICE_MODE_CONSUMER) {
return false;
}
@@ -610,15 +645,17 @@ bool DeviceSettingsProvider::MitigateMissingPolicy() {
LOG(ERROR) << "Corruption of the policy data has been detected."
<< "Switching to \"safe-mode\" policies until the owner logs in "
<< "to regenerate the policy data.";
-
- device_settings_.Clear();
- device_settings_.mutable_allow_new_users()->set_allow_new_users(true);
- device_settings_.mutable_guest_mode_enabled()->set_guest_mode_enabled(true);
- em::PolicyData empty_policy_data;
- UpdateValuesCache(empty_policy_data, device_settings_);
+ values_cache_.SetBoolean(kAccountsPrefAllowNewUser, true);
+ values_cache_.SetBoolean(kAccountsPrefAllowGuest, true);
values_cache_.SetBoolean(kPolicyMissingMitigationMode, true);
trusted_status_ = TRUSTED;
-
+ // Make sure we will recreate the policy once the owner logs in.
+ // Any value not in this list will be left to the default which is fine as
+ // we repopulate the whitelist with the owner and all other existing users
+ // every time the owner enables whitelist filtering on the UI.
+ migration_helper_->AddMigrationValue(
+ kAccountsPrefAllowNewUser, base::Value::CreateBooleanValue(true));
+ migration_helper_->MigrateValues();
return true;
}
@@ -648,93 +685,83 @@ bool DeviceSettingsProvider::HandlesSetting(const std::string& path) const {
DeviceSettingsProvider::TrustedStatus
DeviceSettingsProvider::RequestTrustedEntity() {
- if (ownership_status_ == DeviceSettingsService::OWNERSHIP_NONE)
+ if (ownership_status_ == OwnershipService::OWNERSHIP_NONE)
return TRUSTED;
return trusted_status_;
}
-void DeviceSettingsProvider::UpdateAndProceedStoring() {
- // Re-sync the cache from the service.
- UpdateFromService();
+void DeviceSettingsProvider::OnStorePolicyCompleted(
+ SignedSettings::ReturnCode code) {
+ // In any case reload the policy cache to now.
+ if (code != SignedSettings::SUCCESS) {
+ Reload();
+ } else {
+ trusted_status_ = TRUSTED;
+ // TODO(pastarmovj): Make those side effects responsibility of the
+ // respective subsystems.
+ ApplySideEffects();
+ // Notify the observers we are done.
+ std::vector<base::Closure> callbacks;
+ callbacks.swap(callbacks_);
+ for (size_t i = 0; i < callbacks.size(); ++i)
+ callbacks[i].Run();
+ }
- // Trigger the next change if necessary.
- if (trusted_status_ == TRUSTED &&
- !store_callback_factory_.HasWeakPtrs() &&
- !pending_changes_.empty()) {
+ // Clear the finished task and proceed with any other stores that could be
+ // pending by now.
+ delete pending_changes_[0].second;
+ pending_changes_.erase(pending_changes_.begin());
+ if (!pending_changes_.empty())
SetInPolicy();
- }
}
-bool DeviceSettingsProvider::UpdateFromService() {
- bool settings_loaded = false;
- switch (device_settings_service_->status()) {
- case DeviceSettingsService::STORE_SUCCESS: {
- const em::PolicyData* policy_data =
- device_settings_service_->policy_data();
- const em::ChromeDeviceSettingsProto* device_settings =
- device_settings_service_->device_settings();
- if (policy_data && device_settings) {
- UpdateValuesCache(*policy_data, *device_settings);
- device_settings_ = *device_settings;
- trusted_status_ = TRUSTED;
-
- // TODO(pastarmovj): Make those side effects responsibility of the
- // respective subsystems.
- ApplySideEffects(*device_settings);
-
- settings_loaded = true;
- } else {
- // Initial policy load is still pending.
- trusted_status_ = TEMPORARILY_UNTRUSTED;
- }
+void DeviceSettingsProvider::OnRetrievePolicyCompleted(
+ SignedSettings::ReturnCode code,
+ const em::PolicyFetchResponse& policy_data) {
+ VLOG(1) << "OnRetrievePolicyCompleted. Error code: " << code
+ << ", trusted status : " << trusted_status_
+ << ", ownership status : " << ownership_status_;
+ switch (code) {
+ case SignedSettings::SUCCESS: {
+ DCHECK(policy_data.has_policy_data());
+ policy_.ParseFromString(policy_data.policy_data());
+ signed_settings_cache::Store(policy(),
+ g_browser_process->local_state());
+ UpdateValuesCache();
+ trusted_status_ = TRUSTED;
+ // TODO(pastarmovj): Make those side effects responsibility of the
+ // respective subsystems.
+ ApplySideEffects();
break;
}
- case DeviceSettingsService::STORE_NO_POLICY:
+ case SignedSettings::NOT_FOUND:
if (MitigateMissingPolicy())
break;
- // fall through.
- case DeviceSettingsService::STORE_KEY_UNAVAILABLE:
- VLOG(1) << "No policies present yet, will use the temp storage.";
+ case SignedSettings::KEY_UNAVAILABLE: {
+ if (ownership_status_ != OwnershipService::OWNERSHIP_TAKEN)
+ NOTREACHED() << "No policies present yet, will use the temp storage.";
trusted_status_ = PERMANENTLY_UNTRUSTED;
break;
- case DeviceSettingsService::STORE_POLICY_ERROR:
- case DeviceSettingsService::STORE_VALIDATION_ERROR:
- case DeviceSettingsService::STORE_INVALID_POLICY:
- case DeviceSettingsService::STORE_OPERATION_FAILED:
- LOG(ERROR) << "Failed to retrieve cros policies. Reason: "
- << device_settings_service_->status();
+ }
+ case SignedSettings::BAD_SIGNATURE:
+ case SignedSettings::OPERATION_FAILED: {
+ LOG(ERROR) << "Failed to retrieve cros policies. Reason:" << code;
+ if (retries_left_ > 0) {
+ trusted_status_ = TEMPORARILY_UNTRUSTED;
+ retries_left_ -= 1;
+ Reload();
+ return;
+ }
+ LOG(ERROR) << "No retries left";
trusted_status_ = PERMANENTLY_UNTRUSTED;
break;
+ }
}
-
// Notify the observers we are done.
std::vector<base::Closure> callbacks;
callbacks.swap(callbacks_);
for (size_t i = 0; i < callbacks.size(); ++i)
callbacks[i].Run();
-
- return settings_loaded;
-}
-
-void DeviceSettingsProvider::StoreDeviceSettings() {
- // Mute all previous callbacks to guarantee the |pending_changes_| queue is
- // processed serially.
- store_callback_factory_.InvalidateWeakPtrs();
-
- device_settings_service_->SignAndStore(
- scoped_ptr<em::ChromeDeviceSettingsProto>(
- new em::ChromeDeviceSettingsProto(device_settings_)),
- base::Bind(&DeviceSettingsProvider::UpdateAndProceedStoring,
- store_callback_factory_.GetWeakPtr()));
-}
-
-void DeviceSettingsProvider::AttemptMigration() {
- if (device_settings_service_->HasPrivateOwnerKey()) {
- PrefValueMap::const_iterator i;
- for (i = migration_values_.begin(); i != migration_values_.end(); ++i)
- DoSet(i->first, *i->second);
- migration_values_.Clear();
- }
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/settings/device_settings_provider.h b/chrome/browser/chromeos/settings/device_settings_provider.h
index cf625df..03735b5 100644
--- a/chrome/browser/chromeos/settings/device_settings_provider.h
+++ b/chrome/browser/chromeos/settings/device_settings_provider.h
@@ -5,20 +5,18 @@
#ifndef CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_SETTINGS_PROVIDER_H_
#define CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_SETTINGS_PROVIDER_H_
-#include <deque>
#include <string>
#include <utility>
#include <vector>
#include "base/basictypes.h"
#include "base/callback_forward.h"
-#include "base/gtest_prod_util.h"
-#include "base/memory/weak_ptr.h"
#include "chrome/browser/chromeos/settings/cros_settings_provider.h"
-#include "chrome/browser/chromeos/settings/device_settings_service.h"
-#include "chrome/browser/policy/proto/chrome_device_policy.pb.h"
-#include "chrome/browser/prefs/pref_value_map.h"
+#include "chrome/browser/chromeos/settings/ownership_service.h"
+#include "chrome/browser/chromeos/settings/signed_settings_migration_helper.h"
+#include "chrome/browser/policy/proto/device_management_backend.pb.h"
#include "chrome/browser/prefs/pref_value_map.h"
+#include "content/public/browser/notification_registrar.h"
namespace base {
class Value;
@@ -30,12 +28,12 @@ class ChromeDeviceSettingsProto;
namespace chromeos {
-// CrosSettingsProvider implementation that works with device settings.
+// CrosSettingsProvider implementation that works with SignedSettings.
class DeviceSettingsProvider : public CrosSettingsProvider,
- public DeviceSettingsService::Observer {
+ public content::NotificationObserver {
public:
DeviceSettingsProvider(const NotifyObserversCallback& notify_cb,
- DeviceSettingsService* device_settings_service);
+ SignedSettingsHelper* signed_settings_helper);
virtual ~DeviceSettingsProvider();
// CrosSettingsProvider implementation.
@@ -43,26 +41,35 @@ class DeviceSettingsProvider : public CrosSettingsProvider,
virtual TrustedStatus PrepareTrustedValues(
const base::Closure& callback) OVERRIDE;
virtual bool HandlesSetting(const std::string& path) const OVERRIDE;
+ virtual void Reload() OVERRIDE;
private:
// CrosSettingsProvider implementation:
virtual void DoSet(const std::string& path,
const base::Value& value) OVERRIDE;
- // DeviceSettingsService::Observer implementation:
- virtual void OwnershipStatusChanged() OVERRIDE;
- virtual void DeviceSettingsUpdated() OVERRIDE;
+ // content::NotificationObserver implementation:
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ const enterprise_management::PolicyData policy() const;
// Populates in-memory cache from the local_state cache that is used to store
- // device settings before the device is owned and to speed up policy
+ // signed settings before the device is owned and to speed up policy
// availability before the policy blob is fetched on boot.
void RetrieveCachedData();
- // Stores a value from the |pending_changes_| queue in the device settings.
+ // Stores a value from the |pending_changes_| queue in the signed settings.
// If the device is not owned yet the data ends up only in the local_state
// cache and is serialized once ownership is acquired.
void SetInPolicy();
+ // Finalizes stores to the policy file if the cache is dirty.
+ void FinishSetInPolicy(
+ SignedSettings::ReturnCode code,
+ const enterprise_management::PolicyFetchResponse& policy);
+
// Decode the various groups of policies.
void DecodeLoginPolicies(
const enterprise_management::ChromeDeviceSettingsProto& policy,
@@ -80,21 +87,18 @@ class DeviceSettingsProvider : public CrosSettingsProvider,
const enterprise_management::ChromeDeviceSettingsProto& policy,
PrefValueMap* new_values_cache) const;
- // Parses the policy data and fills in |values_cache_|.
- void UpdateValuesCache(
- const enterprise_management::PolicyData& policy_data,
- const enterprise_management::ChromeDeviceSettingsProto& settings);
+ // Parses the policy cache and fills the cache of base::Value objects.
+ void UpdateValuesCache();
// Applies the metrics policy and if not set migrates the legacy file.
- void ApplyMetricsSetting(bool use_file, bool new_value);
+ void ApplyMetricsSetting(bool use_file, bool new_value) const;
// Applies the data roaming policy.
- void ApplyRoamingSetting(bool new_value);
+ void ApplyRoamingSetting(bool new_value) const;
// Applies any changes of the policies that are not handled by the respective
// subsystems.
- void ApplySideEffects(
- const enterprise_management::ChromeDeviceSettingsProto& settings);
+ void ApplySideEffects() const;
// In case of missing policy blob we should verify if this is upgrade of
// machine owned from pre version 12 OS and the user never touched the device
@@ -102,55 +106,58 @@ class DeviceSettingsProvider : public CrosSettingsProvider,
// comes and changes that.
bool MitigateMissingPolicy();
+ // Called right before boolean property is changed.
+ void OnBooleanPropertyChange(const std::string& path, bool new_value);
+
// Checks if the current cache value can be trusted for being representative
// for the disk cache.
TrustedStatus RequestTrustedEntity();
- // Invokes UpdateFromService() to synchronize with |device_settings_service_|,
- // then triggers the next store operation if applicable.
- void UpdateAndProceedStoring();
-
- // Re-reads state from |device_settings_service_|, adjusts
- // |trusted_status_| and calls UpdateValuesCache() if applicable. Returns true
- // if new settings have been loaded.
- bool UpdateFromService();
-
- // Sends |device_settings_| to |device_settings_service_| for signing and
- // storage in session_manager.
- void StoreDeviceSettings();
-
- // Checks the current ownership status to see whether the device owner is
- // logged in and writes the data accumulated in |migration_values_| to proper
- // device settings.
- void AttemptMigration();
+ // Called right after signed value was checked.
+ void OnPropertyRetrieve(const std::string& path,
+ const base::Value* value,
+ bool use_default_value);
+
+ // Callback of StorePolicyOp for ordinary policy stores.
+ void OnStorePolicyCompleted(SignedSettings::ReturnCode code);
+
+ // Callback of RetrievePolicyOp for ordinary policy [re]loads.
+ void OnRetrievePolicyCompleted(
+ SignedSettings::ReturnCode code,
+ const enterprise_management::PolicyFetchResponse& policy);
+
+ // These setters are for test use only.
+ void set_ownership_status(OwnershipService::Status status) {
+ ownership_status_ = status;
+ }
+ void set_trusted_status(TrustedStatus status) {
+ trusted_status_ = status;
+ }
+ void set_retries_left(int retries) {
+ retries_left_ = retries;
+ }
// Pending callbacks that need to be invoked after settings verification.
std::vector<base::Closure> callbacks_;
- DeviceSettingsService* device_settings_service_;
- mutable PrefValueMap migration_values_;
+ SignedSettingsHelper* signed_settings_helper_;
+ OwnershipService::Status ownership_status_;
+ mutable scoped_ptr<SignedSettingsMigrationHelper> migration_helper_;
+
+ content::NotificationRegistrar registrar_;
+
+ // In order to guard against occasional failure to fetch a property
+ // we allow for some number of retries.
+ int retries_left_;
+ enterprise_management::PolicyData policy_;
TrustedStatus trusted_status_;
- DeviceSettingsService::OwnershipStatus ownership_status_;
-
- // The device settings as currently reported through the CrosSettingsProvider
- // interface. This may be different from the actual current device settings
- // (which can be obtained from |device_settings_service_|) in case the device
- // does not have an owner yet or there are pending changes that have not yet
- // been written to session_manager.
- enterprise_management::ChromeDeviceSettingsProto device_settings_;
-
- // A cache of values, indexed by the settings keys served through the
- // CrosSettingsProvider interface. This is always kept in sync with the raw
- // data found in |device_settings_|.
+
PrefValueMap values_cache_;
// This is a queue for set requests, because those need to be sequential.
typedef std::pair<std::string, base::Value*> PendingQueueElement;
- std::deque<PendingQueueElement> pending_changes_;
-
- // Weak pointer factory for creating store operation callbacks.
- base::WeakPtrFactory<DeviceSettingsProvider> store_callback_factory_;
+ std::vector<PendingQueueElement> pending_changes_;
friend class DeviceSettingsProviderTest;
FRIEND_TEST_ALL_PREFIXES(DeviceSettingsProviderTest,
diff --git a/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc b/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
index 8943eee3e..e05c24c 100644
--- a/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
+++ b/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
@@ -7,14 +7,13 @@
#include <string>
#include "base/bind.h"
-#include "base/callback.h"
#include "base/message_loop.h"
#include "base/values.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/login/mock_user_manager.h"
#include "chrome/browser/chromeos/settings/cros_settings_names.h"
-#include "chrome/browser/chromeos/settings/device_settings_test_helper.h"
-#include "chrome/browser/chromeos/settings/mock_owner_key_util.h"
-#include "chrome/browser/policy/policy_builder.h"
+#include "chrome/browser/chromeos/settings/mock_signed_settings_helper.h"
+#include "chrome/browser/chromeos/settings/ownership_service.h"
#include "chrome/browser/policy/proto/chrome_device_policy.pb.h"
#include "chrome/browser/policy/proto/device_management_backend.pb.h"
#include "chrome/test/base/testing_browser_process.h"
@@ -24,82 +23,96 @@
#include "testing/gtest/include/gtest/gtest.h"
namespace em = enterprise_management;
-
namespace chromeos {
using ::testing::AnyNumber;
using ::testing::Mock;
+using ::testing::Return;
+using ::testing::SaveArg;
using ::testing::_;
class DeviceSettingsProviderTest: public testing::Test {
- public:
+public:
MOCK_METHOD1(SettingChanged, void(const std::string&));
MOCK_METHOD0(GetTrustedCallback, void(void));
- protected:
+protected:
DeviceSettingsProviderTest()
: message_loop_(MessageLoop::TYPE_UI),
ui_thread_(content::BrowserThread::UI, &message_loop_),
file_thread_(content::BrowserThread::FILE, &message_loop_),
- local_state_(static_cast<TestingBrowserProcess*>(g_browser_process)),
- owner_key_util_(new MockOwnerKeyUtil()) {}
+ local_state_(static_cast<TestingBrowserProcess*>(g_browser_process)) {
+ }
+
+ virtual ~DeviceSettingsProviderTest() {
+ }
virtual void SetUp() OVERRIDE {
- policy_.payload().mutable_metrics_enabled()->set_metrics_enabled(false);
- policy_.Build();
+ PrepareEmptyPolicy();
- device_settings_test_helper_.set_policy_blob(policy_.GetBlob());
+ EXPECT_CALL(signed_settings_helper_, StartRetrievePolicyOp(_))
+ .WillRepeatedly(
+ MockSignedSettingsHelperRetrievePolicy(SignedSettings::SUCCESS,
+ policy_blob_));
+ EXPECT_CALL(signed_settings_helper_, StartStorePolicyOp(_,_))
+ .WillRepeatedly(DoAll(
+ SaveArg<0>(&policy_blob_),
+ MockSignedSettingsHelperStorePolicy(SignedSettings::SUCCESS)));
- device_settings_service_.Initialize(&device_settings_test_helper_,
- owner_key_util_);
+ EXPECT_CALL(*mock_user_manager_.user_manager(), IsCurrentUserOwner())
+ .WillRepeatedly(Return(true));
EXPECT_CALL(*this, SettingChanged(_)).Times(AnyNumber());
provider_.reset(
new DeviceSettingsProvider(
base::Bind(&DeviceSettingsProviderTest::SettingChanged,
base::Unretained(this)),
- &device_settings_service_));
+ &signed_settings_helper_));
+ provider_->set_ownership_status(OwnershipService::OWNERSHIP_TAKEN);
+
+ // To prevent flooding the logs.
+ provider_->set_retries_left(1);
+ provider_->Reload();
Mock::VerifyAndClearExpectations(this);
}
- virtual void TearDown() OVERRIDE {
- device_settings_service_.Shutdown();
+ void PrepareEmptyPolicy() {
+ em::PolicyData policy;
+ em::ChromeDeviceSettingsProto pol;
+ // Set metrics to disabled to prevent us from running into code that is not
+ // mocked.
+ pol.mutable_metrics_enabled()->set_metrics_enabled(false);
+ policy.set_policy_type(chromeos::kDevicePolicyType);
+ policy.set_username("me@owner");
+ policy.set_policy_value(pol.SerializeAsString());
+ // Wipe the signed settings store.
+ policy_blob_.set_policy_data(policy.SerializeAsString());
+ policy_blob_.set_policy_data_signature("false");
}
+ em::PolicyFetchResponse policy_blob_;
+
+ scoped_ptr<DeviceSettingsProvider> provider_;
+
MessageLoop message_loop_;
content::TestBrowserThread ui_thread_;
content::TestBrowserThread file_thread_;
- ScopedStubCrosEnabler stub_cros_enabler_;
-
ScopedTestingLocalState local_state_;
- DeviceSettingsTestHelper device_settings_test_helper_;
- scoped_refptr<MockOwnerKeyUtil> owner_key_util_;
-
- DeviceSettingsService device_settings_service_;
-
- policy::DevicePolicyBuilder policy_;
-
- scoped_ptr<DeviceSettingsProvider> provider_;
+ MockSignedSettingsHelper signed_settings_helper_;
- private:
- DISALLOW_COPY_AND_ASSIGN(DeviceSettingsProviderTest);
+ ScopedStubCrosEnabler stub_cros_enabler_;
+ ScopedMockUserManagerEnabler mock_user_manager_;
};
TEST_F(DeviceSettingsProviderTest, InitializationTest) {
- owner_key_util_->SetPublicKeyFromPrivateKey(policy_.signing_key());
-
- // Have the service load a settings blob.
- EXPECT_CALL(*this, SettingChanged(_)).Times(AnyNumber());
- device_settings_service_.Load();
- device_settings_test_helper_.Flush();
- Mock::VerifyAndClearExpectations(this);
-
// Verify that the policy blob has been correctly parsed and trusted.
// The trusted flag should be set before the call to PrepareTrustedValues.
EXPECT_EQ(CrosSettingsProvider::TRUSTED,
- provider_->PrepareTrustedValues(base::Closure()));
+ provider_->PrepareTrustedValues(
+ base::Bind(&DeviceSettingsProviderTest::GetTrustedCallback,
+ base::Unretained(this))));
const base::Value* value = provider_->Get(kStatsReportingPref);
ASSERT_TRUE(value);
bool bool_value;
@@ -108,13 +121,16 @@ TEST_F(DeviceSettingsProviderTest, InitializationTest) {
}
TEST_F(DeviceSettingsProviderTest, InitializationTestUnowned) {
- // Have the service check the key.
- device_settings_service_.Load();
- device_settings_test_helper_.Flush();
+ // No calls to the SignedSettingsHelper should occur in this case!
+ Mock::VerifyAndClear(&signed_settings_helper_);
+ provider_->set_ownership_status(OwnershipService::OWNERSHIP_NONE);
+ provider_->Reload();
// The trusted flag should be set before the call to PrepareTrustedValues.
EXPECT_EQ(CrosSettingsProvider::TRUSTED,
- provider_->PrepareTrustedValues(base::Closure()));
+ provider_->PrepareTrustedValues(
+ base::Bind(&DeviceSettingsProviderTest::GetTrustedCallback,
+ base::Unretained(this))));
const base::Value* value = provider_->Get(kReleaseChannel);
ASSERT_TRUE(value);
std::string string_value;
@@ -122,38 +138,26 @@ TEST_F(DeviceSettingsProviderTest, InitializationTestUnowned) {
EXPECT_TRUE(string_value.empty());
// Sets should succeed though and be readable from the cache.
- EXPECT_CALL(*this, SettingChanged(_)).Times(AnyNumber());
EXPECT_CALL(*this, SettingChanged(kReleaseChannel)).Times(1);
base::StringValue new_value("stable-channel");
provider_->Set(kReleaseChannel, new_value);
- Mock::VerifyAndClearExpectations(this);
-
- // This shouldn't trigger a write.
- device_settings_test_helper_.set_policy_blob(std::string());
- device_settings_test_helper_.Flush();
- EXPECT_EQ(std::string(), device_settings_test_helper_.policy_blob());
-
- // Verify the change has been applied.
+ // Do one more reload here to make sure we don't flip randomly between stores.
+ provider_->Reload();
+ // Verify the change has not been applied.
const base::Value* saved_value = provider_->Get(kReleaseChannel);
ASSERT_TRUE(saved_value);
EXPECT_TRUE(saved_value->GetAsString(&string_value));
ASSERT_EQ("stable-channel", string_value);
+ Mock::VerifyAndClearExpectations(this);
}
TEST_F(DeviceSettingsProviderTest, SetPrefFailed) {
+ EXPECT_CALL(*this, SettingChanged(kStatsReportingPref)).Times(1);
// If we are not the owner no sets should work.
- owner_key_util_->SetPublicKeyFromPrivateKey(policy_.signing_key());
-
+ EXPECT_CALL(*mock_user_manager_.user_manager(), IsCurrentUserOwner())
+ .WillOnce(Return(false));
base::FundamentalValue value(true);
- EXPECT_CALL(*this, SettingChanged(kStatsReportingPref)).Times(1);
provider_->Set(kStatsReportingPref, value);
- Mock::VerifyAndClearExpectations(this);
-
- // This shouldn't trigger a write.
- device_settings_test_helper_.set_policy_blob(std::string());
- device_settings_test_helper_.Flush();
- EXPECT_EQ(std::string(), device_settings_test_helper_.policy_blob());
-
// Verify the change has not been applied.
const base::Value* saved_value = provider_->Get(kStatsReportingPref);
ASSERT_TRUE(saved_value);
@@ -163,26 +167,10 @@ TEST_F(DeviceSettingsProviderTest, SetPrefFailed) {
}
TEST_F(DeviceSettingsProviderTest, SetPrefSucceed) {
- owner_key_util_->SetPrivateKey(policy_.signing_key());
- device_settings_service_.SetUsername(policy_.policy_data().username());
- device_settings_test_helper_.Flush();
-
- base::FundamentalValue value(true);
- EXPECT_CALL(*this, SettingChanged(_)).Times(AnyNumber());
EXPECT_CALL(*this, SettingChanged(kStatsReportingPref)).Times(1);
+ base::FundamentalValue value(true);
provider_->Set(kStatsReportingPref, value);
- Mock::VerifyAndClearExpectations(this);
-
- // Process the store.
- device_settings_test_helper_.set_policy_blob(std::string());
- device_settings_test_helper_.Flush();
-
- // Verify that the device policy has been adjusted.
- ASSERT_TRUE(device_settings_service_.device_settings());
- EXPECT_TRUE(device_settings_service_.device_settings()->
- metrics_enabled().metrics_enabled());
-
- // Verify the change has been applied.
+ // Verify the change has not been applied.
const base::Value* saved_value = provider_->Get(kStatsReportingPref);
ASSERT_TRUE(saved_value);
bool bool_value;
@@ -190,64 +178,84 @@ TEST_F(DeviceSettingsProviderTest, SetPrefSucceed) {
EXPECT_TRUE(bool_value);
}
-TEST_F(DeviceSettingsProviderTest, PolicyRetrievalFailedBadSignature) {
- owner_key_util_->SetPublicKeyFromPrivateKey(policy_.signing_key());
- policy_.policy().set_policy_data_signature("bad signature");
- device_settings_test_helper_.set_policy_blob(policy_.GetBlob());
-
- device_settings_service_.Load();
- device_settings_test_helper_.Flush();
-
- // Verify that the cached settings blob is not "trusted".
- EXPECT_EQ(DeviceSettingsService::STORE_VALIDATION_ERROR,
- device_settings_service_.status());
+TEST_F(DeviceSettingsProviderTest, PolicyRetrievalFailedBadSingature) {
+ // No calls to the SignedSettingsHelper should occur in this case!
+ Mock::VerifyAndClear(&signed_settings_helper_);
+ EXPECT_CALL(signed_settings_helper_, StartRetrievePolicyOp(_))
+ .WillRepeatedly(
+ MockSignedSettingsHelperRetrievePolicy(
+ SignedSettings::BAD_SIGNATURE,
+ policy_blob_));
+ provider_->Reload();
+ // Verify that the cache policy blob is not "trusted".
EXPECT_EQ(CrosSettingsProvider::PERMANENTLY_UNTRUSTED,
- provider_->PrepareTrustedValues(base::Closure()));
+ provider_->PrepareTrustedValues(
+ base::Bind(&DeviceSettingsProviderTest::GetTrustedCallback,
+ base::Unretained(this))));
}
-TEST_F(DeviceSettingsProviderTest, PolicyRetrievalNoPolicy) {
- owner_key_util_->SetPublicKeyFromPrivateKey(policy_.signing_key());
- device_settings_test_helper_.set_policy_blob(std::string());
-
- device_settings_service_.Load();
- device_settings_test_helper_.Flush();
-
- // Verify that the cached settings blob is not "trusted".
- EXPECT_EQ(DeviceSettingsService::STORE_NO_POLICY,
- device_settings_service_.status());
+TEST_F(DeviceSettingsProviderTest, PolicyRetrievalOperationFailedPermanently) {
+ // No calls to the SignedSettingsHelper should occur in this case!
+ Mock::VerifyAndClear(&signed_settings_helper_);
+ EXPECT_CALL(signed_settings_helper_, StartRetrievePolicyOp(_))
+ .WillRepeatedly(
+ MockSignedSettingsHelperRetrievePolicy(
+ SignedSettings::OPERATION_FAILED,
+ policy_blob_));
+ provider_->Reload();
+ // Verify that the cache policy blob is not "trusted".
EXPECT_EQ(CrosSettingsProvider::PERMANENTLY_UNTRUSTED,
- provider_->PrepareTrustedValues(base::Closure()));
+ provider_->PrepareTrustedValues(
+ base::Bind(&DeviceSettingsProviderTest::GetTrustedCallback,
+ base::Unretained(this))));
}
-TEST_F(DeviceSettingsProviderTest, PolicyFailedPermanentlyNotification) {
- owner_key_util_->SetPublicKeyFromPrivateKey(policy_.signing_key());
- device_settings_test_helper_.set_policy_blob(std::string());
+TEST_F(DeviceSettingsProviderTest, PolicyRetrievalOperationFailedOnce) {
+ // No calls to the SignedSettingsHelper should occur in this case!
+ Mock::VerifyAndClear(&signed_settings_helper_);
+ EXPECT_CALL(signed_settings_helper_, StartRetrievePolicyOp(_))
+ .WillOnce(
+ MockSignedSettingsHelperRetrievePolicy(
+ SignedSettings::OPERATION_FAILED,
+ policy_blob_))
+ .WillRepeatedly(
+ MockSignedSettingsHelperRetrievePolicy(
+ SignedSettings::SUCCESS,
+ policy_blob_));
+ // Should be trusted after an automatic reload.
+ provider_->Reload();
+ // Verify that the cache policy blob is not "trusted".
+ EXPECT_EQ(CrosSettingsProvider::TRUSTED,
+ provider_->PrepareTrustedValues(
+ base::Bind(&DeviceSettingsProviderTest::GetTrustedCallback,
+ base::Unretained(this))));
+}
+TEST_F(DeviceSettingsProviderTest, PolicyFailedPermanentlyNotification) {
+ Mock::VerifyAndClear(&signed_settings_helper_);
+ EXPECT_CALL(signed_settings_helper_, StartRetrievePolicyOp(_))
+ .WillRepeatedly(
+ MockSignedSettingsHelperRetrievePolicy(
+ SignedSettings::OPERATION_FAILED,
+ policy_blob_));
+
+ provider_->set_trusted_status(CrosSettingsProvider::TEMPORARILY_UNTRUSTED);
EXPECT_CALL(*this, GetTrustedCallback());
EXPECT_EQ(CrosSettingsProvider::TEMPORARILY_UNTRUSTED,
provider_->PrepareTrustedValues(
base::Bind(&DeviceSettingsProviderTest::GetTrustedCallback,
base::Unretained(this))));
-
- device_settings_service_.Load();
- device_settings_test_helper_.Flush();
- Mock::VerifyAndClearExpectations(this);
-
- EXPECT_EQ(CrosSettingsProvider::PERMANENTLY_UNTRUSTED,
- provider_->PrepareTrustedValues(base::Closure()));
+ provider_->Reload();
}
TEST_F(DeviceSettingsProviderTest, PolicyLoadNotification) {
+ provider_->set_trusted_status(CrosSettingsProvider::TEMPORARILY_UNTRUSTED);
EXPECT_CALL(*this, GetTrustedCallback());
-
EXPECT_EQ(CrosSettingsProvider::TEMPORARILY_UNTRUSTED,
provider_->PrepareTrustedValues(
base::Bind(&DeviceSettingsProviderTest::GetTrustedCallback,
base::Unretained(this))));
-
- device_settings_service_.Load();
- device_settings_test_helper_.Flush();
- Mock::VerifyAndClearExpectations(this);
+ provider_->Reload();
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/settings/owner_manager.cc b/chrome/browser/chromeos/settings/owner_manager.cc
index 60e69a3..385af76 100644
--- a/chrome/browser/chromeos/settings/owner_manager.cc
+++ b/chrome/browser/chromeos/settings/owner_manager.cc
@@ -12,7 +12,7 @@
#include "base/file_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/boot_times_loader.h"
-#include "chrome/browser/chromeos/settings/device_settings_cache.h"
+#include "chrome/browser/chromeos/settings/signed_settings_cache.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
diff --git a/chrome/browser/chromeos/settings/session_manager_observer.cc b/chrome/browser/chromeos/settings/session_manager_observer.cc
index fba6894..6bb828c 100644
--- a/chrome/browser/chromeos/settings/session_manager_observer.cc
+++ b/chrome/browser/chromeos/settings/session_manager_observer.cc
@@ -5,8 +5,8 @@
#include "chrome/browser/chromeos/settings/session_manager_observer.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chromeos/settings/device_settings_cache.h"
#include "chrome/browser/chromeos/settings/signed_settings.h"
+#include "chrome/browser/chromeos/settings/signed_settings_cache.h"
#include "chrome/common/chrome_notification_types.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "content/public/browser/browser_thread.h"
@@ -60,7 +60,7 @@ void SessionManagerObserver::OwnerKeySet(bool success) {
// Now owner is assigned and key is generated and we should persist
// those settings into signed storage.
if (success && g_browser_process && g_browser_process->local_state())
- device_settings_cache::Finalize(g_browser_process->local_state());
+ signed_settings_cache::Finalize(g_browser_process->local_state());
// Whether we exported the public key or not, send a notification
// indicating that we're done with this attempt.
diff --git a/chrome/browser/chromeos/settings/signed_settings_cache.cc b/chrome/browser/chromeos/settings/signed_settings_cache.cc
new file mode 100644
index 0000000..811f428
--- /dev/null
+++ b/chrome/browser/chromeos/settings/signed_settings_cache.cc
@@ -0,0 +1,133 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/settings/signed_settings_cache.h"
+
+#include <string>
+
+#include "base/base64.h"
+#include "base/bind.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
+#include "chrome/browser/chromeos/settings/ownership_service.h"
+#include "chrome/browser/chromeos/settings/signed_settings_helper.h"
+#include "chrome/browser/policy/proto/device_management_backend.pb.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/common/pref_names.h"
+
+using content::BrowserThread;
+
+namespace em = enterprise_management;
+
+namespace chromeos {
+
+namespace {
+
+void OnStorePolicyCompleted(SignedSettings::ReturnCode code) {
+ if (code != SignedSettings::SUCCESS)
+ LOG(ERROR) << "Couldn't save temp store to the policy blob. code: " << code;
+ else
+ CrosSettings::Get()->ReloadProviders();
+}
+
+void FinishFinalize(PrefService* local_state,
+ SignedSettings::ReturnCode code,
+ const em::PolicyFetchResponse& policy) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (code != SignedSettings::SUCCESS) {
+ LOG(ERROR) << "Can't finalize temp store error code:" << code;
+ return;
+ }
+
+ if (local_state) {
+ std::string encoded =
+ local_state->GetString(prefs::kSignedSettingsCache);
+ std::string policy_string;
+ if (!base::Base64Decode(encoded, &policy_string)) {
+ LOG(ERROR) << "Can't decode policy from base64 on finalizing.";
+ return;
+ }
+
+ em::PolicyData merging_policy_data;
+ if (!merging_policy_data.ParseFromString(policy_string)) {
+ LOG(ERROR) << "Can't decode policy from string on finalizing.";
+ return;
+ }
+
+ em::PolicyFetchResponse policy_envelope = policy;
+ DCHECK(policy_envelope.has_policy_data());
+ em::PolicyData base_policy_data;
+ base_policy_data.ParseFromString(policy_envelope.policy_data());
+ // Merge only the policy value as we should never ever rewrite the other
+ // fields of the PolicyData protobuf.
+ base_policy_data.set_policy_value(merging_policy_data.policy_value());
+ policy_envelope.set_policy_data(base_policy_data.SerializeAsString());
+ DCHECK(base_policy_data.has_username());
+ policy_envelope.clear_policy_data_signature();
+ SignedSettingsHelper::Get()->StartStorePolicyOp(
+ policy_envelope, base::Bind(&OnStorePolicyCompleted));
+ }
+}
+
+// Reload the initial policy blob, and if successful apply the settings from
+// temp storage, and write them back the blob in FinishFinalize.
+void ReloadSignedSettingsAndFinalize(
+ PrefService* local_state,
+ OwnershipService::Status status,
+ bool current_user_is_owner) {
+ if (current_user_is_owner) {
+ SignedSettingsHelper::Get()->StartRetrievePolicyOp(
+ base::Bind(FinishFinalize, local_state));
+ }
+}
+
+} // namespace
+
+namespace signed_settings_cache {
+
+void RegisterPrefs(PrefService* local_state) {
+ local_state->RegisterStringPref(prefs::kSignedSettingsCache,
+ "invalid",
+ PrefService::UNSYNCABLE_PREF);
+}
+
+bool Store(const em::PolicyData& policy, PrefService* local_state) {
+ if (local_state) {
+ std::string policy_string = policy.SerializeAsString();
+ std::string encoded;
+ if (!base::Base64Encode(policy_string, &encoded)) {
+ LOG(ERROR) << "Can't encode policy in base64.";
+ return false;
+ }
+ local_state->SetString(prefs::kSignedSettingsCache, encoded);
+ return true;
+ }
+ return false;
+}
+
+bool Retrieve(em::PolicyData *policy, PrefService* local_state) {
+ if (local_state) {
+ std::string encoded =
+ local_state->GetString(prefs::kSignedSettingsCache);
+ std::string policy_string;
+ if (!base::Base64Decode(encoded, &policy_string)) {
+ // This is normal and happens on first boot.
+ VLOG(1) << "Can't decode policy from base64.";
+ return false;
+ }
+ return policy->ParseFromString(policy_string);
+ }
+ return false;
+}
+
+void Finalize(PrefService* local_state) {
+ // First we have to make sure the owner is really logged in because the key
+ // notification is generated on every cloud policy key rotation too.
+ OwnershipService::GetSharedInstance()->GetStatusAsync(
+ base::Bind(&ReloadSignedSettingsAndFinalize, local_state));
+}
+
+} // namespace signed_settings_cache
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/settings/device_settings_cache.h b/chrome/browser/chromeos/settings/signed_settings_cache.h
index 8f6f7cf..ab9da59 100644
--- a/chrome/browser/chromeos/settings/device_settings_cache.h
+++ b/chrome/browser/chromeos/settings/signed_settings_cache.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_SETTINGS_CACHE_H_
-#define CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_SETTINGS_CACHE_H_
+#ifndef CHROME_BROWSER_CHROMEOS_SETTINGS_SIGNED_SETTINGS_CACHE_H_
+#define CHROME_BROWSER_CHROMEOS_SETTINGS_SIGNED_SETTINGS_CACHE_H_
namespace enterprise_management {
class PolicyData;
@@ -13,11 +13,11 @@ class PrefService;
namespace chromeos {
-// There is need (metrics at OOBE stage) to store settings (that normally would
-// go into DeviceSettings storage) before owner has been assigned (hence no key
-// is available). This set of functions serves as a transient storage in that
-// case.
-namespace device_settings_cache {
+// There is need (metrics at OOBE stage) to store settings
+// (that normally would go into SignedSettings storage)
+// before owner has been assigned (hence no key is available).
+// This set of functions serves as a transient storage in that case.
+namespace signed_settings_cache {
// Registers required pref section.
void RegisterPrefs(PrefService* local_state);
@@ -29,11 +29,11 @@ bool Store(const enterprise_management::PolicyData &policy,
bool Retrieve(enterprise_management::PolicyData *policy,
PrefService* local_state);
-// Call this after owner has been assigned to persist settings into
-// DeviceSettings storage.
+// Call this after owner has been assigned to persist settings
+// into SignedSettings storage.
void Finalize(PrefService* local_state);
-} // namespace device_settings_cache
+} // namespace signed_settings_cache
} // namespace chromeos
-#endif // CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_SETTINGS_CACHE_H_
+#endif // CHROME_BROWSER_CHROMEOS_SETTINGS_SIGNED_SETTINGS_CACHE_H_
diff --git a/chrome/browser/chromeos/settings/device_settings_cache_unittest.cc b/chrome/browser/chromeos/settings/signed_settings_cache_unittest.cc
index d47021b5..de8bbc5 100644
--- a/chrome/browser/chromeos/settings/device_settings_cache_unittest.cc
+++ b/chrome/browser/chromeos/settings/signed_settings_cache_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/browser/chromeos/settings/device_settings_cache.h"
+#include "chrome/browser/chromeos/settings/signed_settings_cache.h"
#include "chrome/browser/policy/proto/chrome_device_policy.pb.h"
#include "chrome/browser/policy/proto/device_management_backend.pb.h"
@@ -14,7 +14,7 @@ namespace em = enterprise_management;
namespace chromeos {
-class DeviceSettingsCacheTest : public testing::Test {
+class SignedSettingsCacheTest : public testing::Test {
protected:
virtual void SetUp() {
// prepare some data.
@@ -23,18 +23,18 @@ class DeviceSettingsCacheTest : public testing::Test {
pol.mutable_allow_new_users()->set_allow_new_users(false);
policy_.set_policy_value(pol.SerializeAsString());
- device_settings_cache::RegisterPrefs(&local_state_);
+ signed_settings_cache::RegisterPrefs(&local_state_);
}
TestingPrefService local_state_;
em::PolicyData policy_;
};
-TEST_F(DeviceSettingsCacheTest, Basic) {
- EXPECT_TRUE(device_settings_cache::Store(policy_, &local_state_));
+TEST_F(SignedSettingsCacheTest, Basic) {
+ EXPECT_TRUE(signed_settings_cache::Store(policy_, &local_state_));
em::PolicyData policy_out;
- EXPECT_TRUE(device_settings_cache::Retrieve(&policy_out, &local_state_));
+ EXPECT_TRUE(signed_settings_cache::Retrieve(&policy_out, &local_state_));
EXPECT_TRUE(policy_out.has_policy_type());
EXPECT_TRUE(policy_out.has_policy_value());
@@ -45,13 +45,13 @@ TEST_F(DeviceSettingsCacheTest, Basic) {
EXPECT_FALSE(pol.allow_new_users().allow_new_users());
}
-TEST_F(DeviceSettingsCacheTest, CorruptData) {
- EXPECT_TRUE(device_settings_cache::Store(policy_, &local_state_));
+TEST_F(SignedSettingsCacheTest, CorruptData) {
+ EXPECT_TRUE(signed_settings_cache::Store(policy_, &local_state_));
- local_state_.SetString(prefs::kDeviceSettingsCache, "blaaa");
+ local_state_.SetString(prefs::kSignedSettingsCache, "blaaa");
em::PolicyData policy_out;
- EXPECT_FALSE(device_settings_cache::Retrieve(&policy_out, &local_state_));
+ EXPECT_FALSE(signed_settings_cache::Retrieve(&policy_out, &local_state_));
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/settings/signed_settings_migration_helper.cc b/chrome/browser/chromeos/settings/signed_settings_migration_helper.cc
new file mode 100644
index 0000000..566f2b3
--- /dev/null
+++ b/chrome/browser/chromeos/settings/signed_settings_migration_helper.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/settings/signed_settings_migration_helper.h"
+
+#include "base/bind.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "content/public/browser/notification_service.h"
+
+namespace chromeos {
+
+SignedSettingsMigrationHelper::SignedSettingsMigrationHelper()
+ : ALLOW_THIS_IN_INITIALIZER_LIST(ptr_factory_(this)) {
+ registrar_.Add(this, chrome::NOTIFICATION_OWNERSHIP_CHECKED,
+ content::NotificationService::AllSources());
+}
+
+SignedSettingsMigrationHelper::~SignedSettingsMigrationHelper() {
+ registrar_.RemoveAll();
+ migration_values_.Clear();
+}
+
+void SignedSettingsMigrationHelper::AddMigrationValue(const std::string& path,
+ base::Value* value) {
+ migration_values_.SetValue(path, value);
+}
+
+void SignedSettingsMigrationHelper::MigrateValues(void) {
+ ptr_factory_.InvalidateWeakPtrs();
+ OwnershipService::GetSharedInstance()->GetStatusAsync(
+ base::Bind(&SignedSettingsMigrationHelper::DoMigrateValues,
+ ptr_factory_.GetWeakPtr()));
+}
+
+// NotificationObserver overrides:
+void SignedSettingsMigrationHelper::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ if (type == chrome::NOTIFICATION_OWNERSHIP_CHECKED)
+ MigrateValues();
+}
+
+void SignedSettingsMigrationHelper::DoMigrateValues(
+ OwnershipService::Status status,
+ bool current_user_is_owner) {
+ // We can call StartStorePropertyOp in two cases - either if the owner is
+ // currently logged in and the policy can be updated immediately or if there
+ // is no owner yet in which case the value will be temporarily stored in the
+ // SignedSettingsCache until the device is owned. If none of these
+ // cases is met then we will wait for user change notification and retry.
+ if (current_user_is_owner || status != OwnershipService::OWNERSHIP_TAKEN) {
+ std::map<std::string, base::Value*>::const_iterator i;
+ for (i = migration_values_.begin(); i != migration_values_.end(); ++i) {
+ // Queue all values for storing.
+ CrosSettings::Get()->Set(i->first, *i->second);
+ }
+ migration_values_.Clear();
+ }
+}
+
+} // namespace chromeos
+
diff --git a/chrome/browser/chromeos/settings/signed_settings_migration_helper.h b/chrome/browser/chromeos/settings/signed_settings_migration_helper.h
new file mode 100644
index 0000000..13d5bfb
--- /dev/null
+++ b/chrome/browser/chromeos/settings/signed_settings_migration_helper.h
@@ -0,0 +1,59 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_SETTINGS_SIGNED_SETTINGS_MIGRATION_HELPER_H_
+#define CHROME_BROWSER_CHROMEOS_SETTINGS_SIGNED_SETTINGS_MIGRATION_HELPER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/chromeos/settings/ownership_service.h"
+#include "chrome/browser/chromeos/settings/signed_settings_helper.h"
+#include "chrome/browser/prefs/pref_value_map.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+namespace base {
+class Value;
+}
+
+namespace chromeos {
+
+// This class provides the means to migrate settings to the signed settings
+// store. It does one of three things - store the settings in the policy blob
+// immediately if the current user is the owner. Uses the
+// SignedSettingsCache if there is no owner yet, or waits for an
+// OWNERSHIP_CHECKED notification to delay the storing until the owner has
+// logged in.
+class SignedSettingsMigrationHelper : public content::NotificationObserver {
+ public:
+ SignedSettingsMigrationHelper();
+ virtual ~SignedSettingsMigrationHelper();
+
+ // Adds a value to be migrated. The class takes ownership of the |value|.
+ void AddMigrationValue(const std::string& path, base::Value* value);
+
+ // Initiates values migration. If the device is already owned this will
+ // happen immediately if not it will wait for ownership login and finish the
+ // migration then.
+ void MigrateValues(void);
+
+ // NotificationObserver overrides:
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ private:
+ // Does the actual migration when ownership has been confirmed.
+ void DoMigrateValues(OwnershipService::Status status,
+ bool current_user_is_owner);
+
+ content::NotificationRegistrar registrar_;
+ base::WeakPtrFactory<SignedSettingsMigrationHelper> ptr_factory_;
+ PrefValueMap migration_values_;
+
+ DISALLOW_COPY_AND_ASSIGN(SignedSettingsMigrationHelper);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_SETTINGS_SIGNED_SETTINGS_MIGRATION_HELPER_H_
diff --git a/chrome/browser/chromeos/settings/stub_cros_settings_provider.cc b/chrome/browser/chromeos/settings/stub_cros_settings_provider.cc
index 83c9d75..facadc3 100644
--- a/chrome/browser/chromeos/settings/stub_cros_settings_provider.cc
+++ b/chrome/browser/chromeos/settings/stub_cros_settings_provider.cc
@@ -73,6 +73,9 @@ bool StubCrosSettingsProvider::HandlesSetting(const std::string& path) const {
return std::find(kHandledSettings, end, path) != end;
}
+void StubCrosSettingsProvider::Reload() {
+}
+
void StubCrosSettingsProvider::DoSet(const std::string& path,
const base::Value& value) {
values_.SetValue(path, value.DeepCopy());
diff --git a/chrome/browser/chromeos/settings/stub_cros_settings_provider.h b/chrome/browser/chromeos/settings/stub_cros_settings_provider.h
index 9d88bf7..13a10cc 100644
--- a/chrome/browser/chromeos/settings/stub_cros_settings_provider.h
+++ b/chrome/browser/chromeos/settings/stub_cros_settings_provider.h
@@ -26,6 +26,7 @@ class StubCrosSettingsProvider : public CrosSettingsProvider {
virtual TrustedStatus PrepareTrustedValues(
const base::Closure& callback) OVERRIDE;
virtual bool HandlesSetting(const std::string& path) const OVERRIDE;
+ virtual void Reload() OVERRIDE;
private:
// CrosSettingsProvider implementation:
diff --git a/chrome/browser/chromeos/settings/system_settings_provider.cc b/chrome/browser/chromeos/settings/system_settings_provider.cc
index 75a8656..5148c74 100644
--- a/chrome/browser/chromeos/settings/system_settings_provider.cc
+++ b/chrome/browser/chromeos/settings/system_settings_provider.cc
@@ -60,6 +60,11 @@ bool SystemSettingsProvider::HandlesSetting(const std::string& path) const {
return path == kSystemTimezone;
}
+void SystemSettingsProvider::Reload() {
+ // TODO(pastarmovj): We can actually cache the timezone here to make returning
+ // it faster.
+}
+
void SystemSettingsProvider::TimezoneChanged(const icu::TimeZone& timezone) {
// Fires system setting change notification.
timezone_value_.reset(base::Value::CreateStringValue(
diff --git a/chrome/browser/chromeos/settings/system_settings_provider.h b/chrome/browser/chromeos/settings/system_settings_provider.h
index 578a1c5..49ef2aa 100644
--- a/chrome/browser/chromeos/settings/system_settings_provider.h
+++ b/chrome/browser/chromeos/settings/system_settings_provider.h
@@ -30,6 +30,7 @@ class SystemSettingsProvider : public CrosSettingsProvider,
virtual TrustedStatus PrepareTrustedValues(
const base::Closure& callback) OVERRIDE;
virtual bool HandlesSetting(const std::string& path) const OVERRIDE;
+ virtual void Reload() OVERRIDE;
// TimezoneSettings::Observer implementation.
virtual void TimezoneChanged(const icu::TimeZone& timezone) OVERRIDE;