cros_settings.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/settings/cros_settings.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
115e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/settings/device_settings_provider.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/settings/device_settings_service.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/settings/system_settings_provider.h"
17b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chromeos/chromeos_switches.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_auth_util.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static CrosSettings*  g_cros_settings = NULL;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CrosSettings::Initialize() {
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(!g_cros_settings);
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  g_cros_settings = new CrosSettings(DeviceSettingsService::Get());
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool CrosSettings::IsInitialized() {
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return g_cros_settings;
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CrosSettings::Shutdown() {
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(g_cros_settings);
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  delete g_cros_settings;
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  g_cros_settings = NULL;
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CrosSettings* CrosSettings::Get() {
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(g_cros_settings);
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return g_cros_settings;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)CrosSettings::CrosSettings(DeviceSettingsService* device_settings_service) {
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CrosSettingsProvider::NotifyObserversCallback notify_cb(
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&CrosSettings::FireObservers,
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 // This is safe since |this| is never deleted.
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 base::Unretained(this)));
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (CommandLine::ForCurrentProcess()->HasSwitch(
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          switches::kStubCrosSettings)) {
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    AddSettingsProvider(new StubCrosSettingsProvider(notify_cb));
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    AddSettingsProvider(
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        new DeviceSettingsProvider(notify_cb, device_settings_service));
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // System settings are not mocked currently.
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  AddSettingsProvider(new SystemSettingsProvider(notify_cb));
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)CrosSettings::~CrosSettings() {
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  STLDeleteElements(&providers_);
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  STLDeleteValues(&settings_observers_);
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CrosSettings::IsCrosSettings(const std::string& path) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return StartsWithASCII(path, kCrosSettingsPrefix, true);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrosSettings::Set(const std::string& path, const base::Value& in_value) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CrosSettingsProvider* provider;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  provider = GetProvider(path);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (provider)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    provider->Set(path, in_value);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const base::Value* CrosSettings::GetPref(const std::string& path) const {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CrosSettingsProvider* provider = GetProvider(path);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (provider)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return provider->Get(path);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << path << " preference was not found in the signed settings.";
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CrosSettingsProvider::TrustedStatus CrosSettings::PrepareTrustedValues(
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& callback) const {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < providers_.size(); ++i) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrosSettingsProvider::TrustedStatus status =
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        providers_[i]->PrepareTrustedValues(callback);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (status != CrosSettingsProvider::TRUSTED)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return status;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CrosSettingsProvider::TRUSTED;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrosSettings::SetBoolean(const std::string& path, bool in_value) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::FundamentalValue value(in_value);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Set(path, value);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrosSettings::SetInteger(const std::string& path, int in_value) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::FundamentalValue value(in_value);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Set(path, value);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrosSettings::SetDouble(const std::string& path, double in_value) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::FundamentalValue value(in_value);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Set(path, value);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrosSettings::SetString(const std::string& path,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const std::string& in_value) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringValue value(in_value);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Set(path, value);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrosSettings::AppendToList(const std::string& path,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const base::Value* value) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::Value* old_value = GetPref(path);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Value> new_value(
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      old_value ? old_value->DeepCopy() : new base::ListValue());
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static_cast<base::ListValue*>(new_value.get())->Append(value->DeepCopy());
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Set(path, *new_value);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrosSettings::RemoveFromList(const std::string& path,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const base::Value* value) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::Value* old_value = GetPref(path);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Value> new_value(
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      old_value ? old_value->DeepCopy() : new base::ListValue());
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static_cast<base::ListValue*>(new_value.get())->Remove(*value, NULL);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Set(path, *new_value);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CrosSettings::GetBoolean(const std::string& path,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              bool* bool_value) const {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::Value* value = GetPref(path);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (value)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return value->GetAsBoolean(bool_value);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CrosSettings::GetInteger(const std::string& path,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              int* out_value) const {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::Value* value = GetPref(path);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (value)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return value->GetAsInteger(out_value);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CrosSettings::GetDouble(const std::string& path,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             double* out_value) const {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::Value* value = GetPref(path);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (value)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return value->GetAsDouble(out_value);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CrosSettings::GetString(const std::string& path,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             std::string* out_value) const {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::Value* value = GetPref(path);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (value)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return value->GetAsString(out_value);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CrosSettings::GetList(const std::string& path,
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const base::ListValue** out_value) const {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::Value* value = GetPref(path);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (value)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return value->GetAsList(out_value);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool CrosSettings::GetDictionary(
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& path,
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue** out_value) const {
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(CalledOnValidThread());
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const base::Value* value = GetPref(path);
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (value)
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return value->GetAsDictionary(out_value);
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return false;
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CrosSettings::FindEmailInList(const std::string& path,
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const std::string& email) const {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string canonicalized_email(
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gaia::CanonicalizeEmail(gaia::SanitizeEmail(email)));
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string wildcard_email;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::size_type at_pos = canonicalized_email.find('@');
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (at_pos != std::string::npos) {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wildcard_email =
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string("*").append(canonicalized_email.substr(at_pos));
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::ListValue* list;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetList(path, &list))
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (base::ListValue::const_iterator entry(list->begin());
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       entry != list->end();
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++entry) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string entry_string;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(*entry)->GetAsString(&entry_string)) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string canonicalized_entry(
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        gaia::CanonicalizeEmail(gaia::SanitizeEmail(entry_string)));
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (canonicalized_entry == canonicalized_email ||
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        canonicalized_entry == wildcard_email) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CrosSettings::AddSettingsProvider(CrosSettingsProvider* provider) {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  providers_.push_back(provider);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allow the provider to notify this object when settings have changed.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Providers instantiated inside this class will have the same callback
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // passed to their constructor, but doing it here allows for providers
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to be instantiated outside this class.
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CrosSettingsProvider::NotifyObserversCallback notify_cb(
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&CrosSettings::FireObservers, base::Unretained(this)));
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  provider->SetNotifyObserversCallback(notify_cb);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CrosSettings::RemoveSettingsProvider(CrosSettingsProvider* provider) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<CrosSettingsProvider*>::iterator it =
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::find(providers_.begin(), providers_.end(), provider);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != providers_.end()) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    providers_.erase(it);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)scoped_ptr<CrosSettings::ObserverSubscription>
26268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)CrosSettings::AddSettingsObserver(const std::string& path,
26368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                  const base::Closure& callback) {
26468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(!path.empty());
26568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(!callback.is_null());
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!GetProvider(path)) {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Trying to add an observer for an unregistered setting: "
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << path;
27168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return scoped_ptr<CrosSettings::ObserverSubscription>();
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Get the callback registry associated with the path.
27568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  base::CallbackRegistry<void(void)>* registry = NULL;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SettingsObserverMap::iterator observer_iterator =
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      settings_observers_.find(path);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observer_iterator == settings_observers_.end()) {
27968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    registry = new base::CallbackRegistry<void(void)>;
28068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    settings_observers_[path] = registry;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
28268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    registry = observer_iterator->second;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return registry->Add(callback);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CrosSettingsProvider* CrosSettings::GetProvider(
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& path) const {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < providers_.size(); ++i) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (providers_[i]->HandlesSetting(path))
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return providers_[i];
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrosSettings::FireObservers(const std::string& path) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SettingsObserverMap::iterator observer_iterator =
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      settings_observers_.find(path);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observer_iterator == settings_observers_.end())
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  observer_iterator->second->Notify();
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ScopedTestCrosSettings::ScopedTestCrosSettings() {
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CrosSettings::Initialize();
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ScopedTestCrosSettings::~ScopedTestCrosSettings() {
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CrosSettings::Shutdown();
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chromeos
316