1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Use of this source code is governed by a BSD-style license that can be
3bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// found in the LICENSE file.
4bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
54a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/chromeos/user_cros_settings_provider.h"
6bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <map>
821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <set>
921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
1021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/hash_tables.h"
11bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/logging.h"
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/singleton.h"
13bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/string_util.h"
1421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/task.h"
15bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/values.h"
16bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/browser_process.h"
17bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/chromeos/cros/cros_library.h"
18bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/chromeos/cros/login_library.h"
19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/chromeos/cros/network_library.h"
20bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/chromeos/cros_settings.h"
21bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/chromeos/cros_settings_names.h"
2221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/chromeos/login/ownership_service.h"
23bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/chromeos/login/user_manager.h"
24bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/prefs/pref_service.h"
25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/prefs/scoped_user_pref_update.h"
26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
27bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
28731df977c0511bca2206b5f333555b1205ff1f43Iain Merricknamespace chromeos {
29731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
30bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsennamespace {
31bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
3221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst char kTrueIncantation[] = "true";
3321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst char kFalseIncantation[] = "false";
3421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst char kTrustedSuffix[] = "/trusted";
3521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
3621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// For all our boolean settings following is applicable:
3721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// true is default permissive value and false is safe prohibitic value.
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Exception: kSignedDataRoamingEnabled which has default value of false.
3921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst char* kBooleanSettings[] = {
4021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  kAccountsPrefAllowNewUser,
4121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  kAccountsPrefAllowGuest,
42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  kAccountsPrefShowUserNamesOnSignIn,
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  kSignedDataRoamingEnabled,
4421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen};
4521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
4621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst char* kStringSettings[] = {
4721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  kDeviceOwner
4821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen};
4921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
5021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst char* kListSettings[] = {
5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  kAccountsPrefUsers
5221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen};
5321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool IsControlledBooleanSetting(const std::string& pref_path) {
55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // TODO(nkostylev): Using std::find for 4 value array generates this warning
56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // in chroot stl_algo.h:231: error: array subscript is above array bounds.
57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // GCC 4.4.3
58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return (pref_path == kAccountsPrefAllowNewUser) ||
59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen         (pref_path == kAccountsPrefAllowGuest) ||
60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen         (pref_path == kAccountsPrefShowUserNamesOnSignIn) ||
61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen         (pref_path == kSignedDataRoamingEnabled);
6221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
6321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
6421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool IsControlledStringSetting(const std::string& pref_path) {
6521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return std::find(kStringSettings,
6621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                   kStringSettings + arraysize(kStringSettings),
6721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                   pref_path) !=
6821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      kStringSettings + arraysize(kStringSettings);
6921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
7021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
7121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool IsControlledListSetting(const std::string& pref_path) {
7221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return std::find(kListSettings,
7321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                   kListSettings + arraysize(kListSettings),
7421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                   pref_path) !=
7521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      kListSettings + arraysize(kListSettings);
7621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
7721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
7821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid RegisterSetting(PrefService* local_state, const std::string& pref_path) {
7921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  local_state->RegisterBooleanPref((pref_path + kTrustedSuffix).c_str(),
8021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                   false);
8121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (IsControlledBooleanSetting(pref_path)) {
82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (pref_path == kSignedDataRoamingEnabled)
83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      local_state->RegisterBooleanPref(pref_path.c_str(), false);
84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    else
85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      local_state->RegisterBooleanPref(pref_path.c_str(), true);
8621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  } else if (IsControlledStringSetting(pref_path)) {
8721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    local_state->RegisterStringPref(pref_path.c_str(), "");
8821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  } else {
8921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    DCHECK(IsControlledListSetting(pref_path));
9021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    local_state->RegisterListPref(pref_path.c_str());
9121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
9321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Create a settings boolean value with "managed" and "disabled" property.
95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// "managed" property is true if the setting is managed by administrator.
96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// "disabled" property is true if the UI for the setting should be disabled.
97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenValue* CreateSettingsBooleanValue(bool value, bool managed, bool disabled) {
98bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  DictionaryValue* dict = new DictionaryValue;
99bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  dict->Set("value", Value::CreateBooleanValue(value));
100bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  dict->Set("managed", Value::CreateBooleanValue(managed));
101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  dict->Set("disabled", Value::CreateBooleanValue(disabled));
102bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return dict;
103bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
104bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
10521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenenum UseValue {
10621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  USE_VALUE_SUPPLIED,
10721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  USE_VALUE_DEFAULT
10821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen};
10921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
11021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid UpdateCacheBool(const std::string& name,
11121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                     bool value,
11221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                     UseValue use_value) {
113bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  PrefService* prefs = g_browser_process->local_state();
11421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (use_value == USE_VALUE_DEFAULT)
11521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    prefs->ClearPref(name.c_str());
11621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  else
11721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    prefs->SetBoolean(name.c_str(), value);
118bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  prefs->ScheduleSavePersistentPrefs();
119bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
120bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
12121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid UpdateCacheString(const std::string& name,
12221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                       const std::string& value,
12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                       UseValue use_value) {
124731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  PrefService* prefs = g_browser_process->local_state();
12521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (use_value == USE_VALUE_DEFAULT)
12621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    prefs->ClearPref(name.c_str());
12721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  else
12821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    prefs->SetString(name.c_str(), value);
129731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  prefs->ScheduleSavePersistentPrefs();
130731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
131bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
132731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool GetUserWhitelist(ListValue* user_list) {
13372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  PrefService* prefs = g_browser_process->local_state();
13472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(!prefs->IsManagedPreference(kAccountsPrefUsers));
13572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
136731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  std::vector<std::string> whitelist;
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!SignedSettings::EnumerateWhitelist(&whitelist)) {
138731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    LOG(WARNING) << "Failed to retrieve user whitelist.";
139731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return false;
140731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
141bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ListPrefUpdate cached_whitelist_update(prefs, kAccountsPrefUsers);
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  cached_whitelist_update->Clear();
144731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
145731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const UserManager::User& self = UserManager::Get()->logged_in_user();
146731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  bool is_owner = UserManager::Get()->current_user_is_owner();
147731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
148731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  for (size_t i = 0; i < whitelist.size(); ++i) {
149731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& email = whitelist[i];
150731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
151731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (user_list) {
152731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      DictionaryValue* user = new DictionaryValue;
153731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      user->SetString("email", email);
154731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      user->SetString("name", "");
155731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      user->SetBoolean("owner", is_owner && email == self.email());
156731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      user_list->Append(user);
157731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
158bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    cached_whitelist_update->Append(Value::CreateStringValue(email));
160731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
161731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
162731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  prefs->ScheduleSavePersistentPrefs();
163731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return true;
164731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
165731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
166dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenclass UserCrosSettingsTrust : public SignedSettingsHelper::Callback {
16721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen public:
16821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  static UserCrosSettingsTrust* GetInstance() {
16921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return Singleton<UserCrosSettingsTrust>::get();
17021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
17121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
17221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Working horse for UserCrosSettingsProvider::RequestTrusted* family.
17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  bool RequestTrustedEntity(const std::string& name) {
174dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    OwnershipService::Status ownership_status =
175dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        ownership_service_->GetStatus(false);
176dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (ownership_status == OwnershipService::OWNERSHIP_NONE)
17721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return true;
17872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    PrefService* prefs = g_browser_process->local_state();
17972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (prefs->IsManagedPreference(name.c_str()))
18072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return true;
181dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (ownership_status == OwnershipService::OWNERSHIP_TAKEN) {
18221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      DCHECK(g_browser_process);
18321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      PrefService* prefs = g_browser_process->local_state();
18421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      DCHECK(prefs);
18521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      if (prefs->GetBoolean((name + kTrustedSuffix).c_str()))
18621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        return true;
18721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
18821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return false;
18921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
19021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
19172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  bool RequestTrustedEntity(const std::string& name, Task* callback) {
19272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (RequestTrustedEntity(name)) {
19372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      delete callback;
19472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return true;
19572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    } else {
19672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (callback)
19772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        callbacks_[name].push_back(callback);
19872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return false;
19972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
20072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
20172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void Reload() {
203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    for (size_t i = 0; i < arraysize(kBooleanSettings); ++i)
204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      StartFetchingSetting(kBooleanSettings[i]);
205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    for (size_t i = 0; i < arraysize(kStringSettings); ++i)
206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      StartFetchingSetting(kStringSettings[i]);
207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
20921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  void Set(const std::string& path, Value* in_value) {
21072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    PrefService* prefs = g_browser_process->local_state();
21172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DCHECK(!prefs->IsManagedPreference(path.c_str()));
21272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
21321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (!UserManager::Get()->current_user_is_owner()) {
21421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      LOG(WARNING) << "Changing settings from non-owner, setting=" << path;
21521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
21621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // Revert UI change.
21721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      CrosSettings::Get()->FireObservers(path.c_str());
21821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return;
21921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
22021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
22121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (IsControlledBooleanSetting(path)) {
22221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      bool bool_value = false;
22321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      if (in_value->GetAsBoolean(&bool_value)) {
224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        OnBooleanPropertyChange(path, bool_value);
22521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        std::string value = bool_value ? kTrueIncantation : kFalseIncantation;
22621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        SignedSettingsHelper::Get()->StartStorePropertyOp(path, value, this);
22721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        UpdateCacheBool(path, bool_value, USE_VALUE_SUPPLIED);
22821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
22921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        VLOG(1) << "Set cros setting " << path << "=" << value;
23021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      }
23121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    } else if (path == kDeviceOwner) {
23221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      VLOG(1) << "Setting owner is not supported. Please use "
23321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                 "'UpdateCachedOwner' instead.";
23421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    } else if (path == kAccountsPrefUsers) {
23521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      VLOG(1) << "Setting user whitelist is not implemented.  Please use "
23621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                 "whitelist/unwhitelist instead.";
23721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    } else {
23821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      LOG(WARNING) << "Try to set unhandled cros setting " << path;
23921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
24021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
24121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
24221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen private:
24321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // upper bound for number of retries to fetch a signed setting.
24421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  static const int kNumRetriesLimit = 9;
24521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
246dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  UserCrosSettingsTrust()
247dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      : ownership_service_(OwnershipService::GetSharedInstance()),
248dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        retries_left_(kNumRetriesLimit) {
249dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Start prefetching Boolean and String preferences.
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Reload();
25121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
25221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
25321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  ~UserCrosSettingsTrust() {
25421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (BrowserThread::CurrentlyOn(BrowserThread::UI) &&
25521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        CrosLibrary::Get()->EnsureLoaded()) {
25621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // Cancels all pending callbacks from us.
25721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      SignedSettingsHelper::Get()->CancelCallback(this);
25821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
25921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
26021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Called right before boolean property is changed.
262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void OnBooleanPropertyChange(const std::string& path, bool new_value) {
263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (path == kSignedDataRoamingEnabled) {
264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!CrosLibrary::Get()->EnsureLoaded())
265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        return;
266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      cros->SetCellularDataRoamingAllowed(new_value);
269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Called right after signed value was checked.
273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void OnBooleanPropertyRetrieve(const std::string& path,
274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                 bool value,
275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                 UseValue use_value) {
276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (path == kSignedDataRoamingEnabled) {
277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!CrosLibrary::Get()->EnsureLoaded())
278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        return;
279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const NetworkDevice* cellular = cros->FindCellularDevice();
282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (cellular) {
283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        bool device_value = cellular->data_roaming_allowed();
284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        bool new_value = (use_value == USE_VALUE_SUPPLIED) ? value : false;
285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        if (device_value != new_value)
286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          cros->SetCellularDataRoamingAllowed(new_value);
287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
29121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  void StartFetchingSetting(const std::string& name) {
29221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    DCHECK(g_browser_process);
29321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    PrefService* prefs = g_browser_process->local_state();
29421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (!prefs)
29521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return;
29621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Do not trust before fetching complete.
29721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    prefs->ClearPref((name + kTrustedSuffix).c_str());
29821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    prefs->ScheduleSavePersistentPrefs();
29921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (CrosLibrary::Get()->EnsureLoaded()) {
30021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      SignedSettingsHelper::Get()->StartRetrieveProperty(name, this);
30121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
30221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
30321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
30421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Implementation of SignedSettingsHelper::Callback.
30521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  virtual void OnRetrievePropertyCompleted(SignedSettings::ReturnCode code,
30621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                           const std::string& name,
30721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                           const std::string& value) {
30821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (!IsControlledBooleanSetting(name) && !IsControlledStringSetting(name)) {
30921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      NOTREACHED();
31021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return;
31121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
31221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
313dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    bool is_owned = ownership_service_->GetStatus(true) ==
314dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        OwnershipService::OWNERSHIP_TAKEN;
31521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    PrefService* prefs = g_browser_process->local_state();
31621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    switch (code) {
31721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      case SignedSettings::SUCCESS:
31821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      case SignedSettings::NOT_FOUND:
31921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      case SignedSettings::KEY_UNAVAILABLE: {
320dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        bool fallback_to_default = !is_owned
321dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            || (code == SignedSettings::NOT_FOUND);
32221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        DCHECK(fallback_to_default || code == SignedSettings::SUCCESS);
32321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        if (fallback_to_default)
32421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          VLOG(1) << "Going default for cros setting " << name;
32521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        else
32621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          VLOG(1) << "Retrieved cros setting " << name << "=" << value;
32721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        if (IsControlledBooleanSetting(name)) {
328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          OnBooleanPropertyRetrieve(name, (value == kTrueIncantation),
329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              fallback_to_default ? USE_VALUE_DEFAULT : USE_VALUE_SUPPLIED);
33021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          UpdateCacheBool(name, (value == kTrueIncantation),
33121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen              fallback_to_default ? USE_VALUE_DEFAULT : USE_VALUE_SUPPLIED);
33221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        } else if (IsControlledStringSetting(name)) {
33321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          UpdateCacheString(name, value,
33421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen              fallback_to_default ? USE_VALUE_DEFAULT : USE_VALUE_SUPPLIED);
33521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        }
33621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        break;
33721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      }
33821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      case SignedSettings::OPERATION_FAILED:
33921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      default: {
34021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        DCHECK(code == SignedSettings::OPERATION_FAILED);
341dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        DCHECK(is_owned);
34221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        LOG(ERROR) << "On owned device: failed to retrieve cros "
34321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                      "setting, name=" << name;
34421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        if (retries_left_ > 0) {
34521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          retries_left_ -= 1;
34621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          StartFetchingSetting(name);
34721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          return;
34821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        }
34921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        LOG(ERROR) << "No retries left";
35021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        if (IsControlledBooleanSetting(name)) {
35121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          // For boolean settings we can just set safe (false) values
35221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          // and continue as trusted.
353ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          OnBooleanPropertyRetrieve(name, false, USE_VALUE_SUPPLIED);
35421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          UpdateCacheBool(name, false, USE_VALUE_SUPPLIED);
35521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        } else {
35621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          prefs->ClearPref((name + kTrustedSuffix).c_str());
35721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          return;
35821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        }
35921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        break;
36021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      }
36121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
36221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    prefs->SetBoolean((name + kTrustedSuffix).c_str(), true);
36321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    {
36421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      std::vector<Task*>& callbacks_vector = callbacks_[name];
36521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      for (size_t i = 0; i < callbacks_vector.size(); ++i)
36621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        MessageLoop::current()->PostTask(FROM_HERE, callbacks_vector[i]);
36721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      callbacks_vector.clear();
36821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
36921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (code == SignedSettings::SUCCESS)
37021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      CrosSettings::Get()->FireObservers(name.c_str());
37121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
37221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
37321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Implementation of SignedSettingsHelper::Callback.
37421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  virtual void OnStorePropertyCompleted(SignedSettings::ReturnCode code,
37521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                        const std::string& name,
37621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                        const std::string& value) {
37721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    VLOG(1) << "Store cros setting " << name << "=" << value << ", code="
37821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            << code;
37921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
38021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Reload the setting if store op fails.
38121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (code != SignedSettings::SUCCESS)
38221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      SignedSettingsHelper::Get()->StartRetrieveProperty(name, this);
38321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
38421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
38521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Implementation of SignedSettingsHelper::Callback.
38621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  virtual void OnWhitelistCompleted(SignedSettings::ReturnCode code,
38721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                    const std::string& email) {
38821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    VLOG(1) << "Add " << email << " to whitelist, code=" << code;
38921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
39021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Reload the whitelist on settings op failure.
39121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (code != SignedSettings::SUCCESS)
39221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      CrosSettings::Get()->FireObservers(kAccountsPrefUsers);
39321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
39421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
39521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Implementation of SignedSettingsHelper::Callback.
39621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  virtual void OnUnwhitelistCompleted(SignedSettings::ReturnCode code,
39721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                      const std::string& email) {
39821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    VLOG(1) << "Remove " << email << " from whitelist, code=" << code;
39921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
40021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Reload the whitelist on settings op failure.
40121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (code != SignedSettings::SUCCESS)
40221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      CrosSettings::Get()->FireObservers(kAccountsPrefUsers);
40321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
40421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
40521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Pending callbacks that need to be invoked after settings verification.
40621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  base::hash_map< std::string, std::vector< Task* > > callbacks_;
40721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
408dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  OwnershipService* ownership_service_;
40921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
41021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // In order to guard against occasional failure to fetch a property
41121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // we allow for some number of retries.
41221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int retries_left_;
41321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
41421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  friend class SignedSettingsHelper;
41521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  friend struct DefaultSingletonTraits<UserCrosSettingsTrust>;
41621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
41721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DISALLOW_COPY_AND_ASSIGN(UserCrosSettingsTrust);
41821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen};
41921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
420731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}  // namespace
421731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
42221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}  // namespace chromeos
423bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
42421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// We want to use NewRunnableMethod with this class but need to disable
42521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// reference counting since it is singleton.
42621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenDISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::UserCrosSettingsTrust);
42721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
42821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsennamespace chromeos {
42921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
43021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenUserCrosSettingsProvider::UserCrosSettingsProvider() {
43121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Trigger prefetching of settings.
43221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  UserCrosSettingsTrust::GetInstance();
433bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
434bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
435513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
436bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid UserCrosSettingsProvider::RegisterPrefs(PrefService* local_state) {
43721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  for (size_t i = 0; i < arraysize(kBooleanSettings); ++i)
43821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    RegisterSetting(local_state, kBooleanSettings[i]);
43921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  for (size_t i = 0; i < arraysize(kStringSettings); ++i)
44021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    RegisterSetting(local_state, kStringSettings[i]);
44121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  for (size_t i = 0; i < arraysize(kListSettings); ++i)
44221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    RegisterSetting(local_state, kListSettings[i]);
44321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
44421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
44521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool UserCrosSettingsProvider::RequestTrustedAllowGuest(Task* callback) {
44621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return UserCrosSettingsTrust::GetInstance()->RequestTrustedEntity(
44721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      kAccountsPrefAllowGuest, callback);
44821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
44921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
45021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool UserCrosSettingsProvider::RequestTrustedAllowNewUser(Task* callback) {
45121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return UserCrosSettingsTrust::GetInstance()->RequestTrustedEntity(
45221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      kAccountsPrefAllowNewUser, callback);
45321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
45421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
45521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool UserCrosSettingsProvider::RequestTrustedShowUsersOnSignin(Task* callback) {
45621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return UserCrosSettingsTrust::GetInstance()->RequestTrustedEntity(
45721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      kAccountsPrefShowUserNamesOnSignIn, callback);
45821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
45921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
460ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool UserCrosSettingsProvider::RequestTrustedDataRoamingEnabled(
461ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Task* callback) {
462ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return UserCrosSettingsTrust::GetInstance()->RequestTrustedEntity(
463ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      kSignedDataRoamingEnabled, callback);
464ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
465ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
46621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool UserCrosSettingsProvider::RequestTrustedOwner(Task* callback) {
46721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return UserCrosSettingsTrust::GetInstance()->RequestTrustedEntity(
46821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      kDeviceOwner, callback);
469bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
470bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
471ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid UserCrosSettingsProvider::Reload() {
472ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  UserCrosSettingsTrust::GetInstance()->Reload();
473ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
474ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
475513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
476bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool UserCrosSettingsProvider::cached_allow_guest() {
47721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Trigger prefetching if singleton object still does not exist.
47821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  UserCrosSettingsTrust::GetInstance();
479bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return g_browser_process->local_state()->GetBoolean(kAccountsPrefAllowGuest);
480bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
481bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
482513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
483731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool UserCrosSettingsProvider::cached_allow_new_user() {
48421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Trigger prefetching if singleton object still does not exist.
48521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  UserCrosSettingsTrust::GetInstance();
486731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return g_browser_process->local_state()->GetBoolean(
487ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      kAccountsPrefAllowNewUser);
488ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
489ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
490ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static
491ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool UserCrosSettingsProvider::cached_data_roaming_enabled() {
492ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Trigger prefetching if singleton object still does not exist.
493ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  UserCrosSettingsTrust::GetInstance();
494ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return g_browser_process->local_state()->GetBoolean(
495ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      kSignedDataRoamingEnabled);
496731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
497731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
498513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
499bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool UserCrosSettingsProvider::cached_show_users_on_signin() {
50021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Trigger prefetching if singleton object still does not exist.
50121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  UserCrosSettingsTrust::GetInstance();
502bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return g_browser_process->local_state()->GetBoolean(
503bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      kAccountsPrefShowUserNamesOnSignIn);
504bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
505bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
506513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
507bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst ListValue* UserCrosSettingsProvider::cached_whitelist() {
508731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  PrefService* prefs = g_browser_process->local_state();
509731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const ListValue* cached_users = prefs->GetList(kAccountsPrefUsers);
51072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!prefs->IsManagedPreference(kAccountsPrefUsers)) {
51172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (cached_users == NULL) {
51272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // Update whitelist cache.
51372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      GetUserWhitelist(NULL);
51472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      cached_users = prefs->GetList(kAccountsPrefUsers);
51572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
51672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
51772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (cached_users == NULL) {
51872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    NOTREACHED();
51972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    cached_users = new ListValue;
520731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
521731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return cached_users;
522731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
523731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
524513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
525731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstd::string UserCrosSettingsProvider::cached_owner() {
52621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Trigger prefetching if singleton object still does not exist.
52721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  UserCrosSettingsTrust::GetInstance();
5284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (!g_browser_process || !g_browser_process->local_state())
5294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return std::string();
530731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return g_browser_process->local_state()->GetString(kDeviceOwner);
531bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
532bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
533513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
534513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool UserCrosSettingsProvider::IsEmailInCachedWhitelist(
535513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    const std::string& email) {
536513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const ListValue* whitelist = cached_whitelist();
537513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (whitelist) {
538513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    StringValue email_value(email);
539513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    for (ListValue::const_iterator i(whitelist->begin());
540513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        i != whitelist->end(); ++i) {
541513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      if ((*i)->Equals(&email_value))
542513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        return true;
543513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
544513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
545513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return false;
546513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
547513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
548513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid UserCrosSettingsProvider::DoSet(const std::string& path,
549513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                     Value* in_value) {
55021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  UserCrosSettingsTrust::GetInstance()->Set(path, in_value);
551bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
552bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
553bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool UserCrosSettingsProvider::Get(const std::string& path,
554bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                                   Value** out_value) const {
55521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (IsControlledBooleanSetting(path)) {
556ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    PrefService* prefs = g_browser_process->local_state();
557bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    *out_value = CreateSettingsBooleanValue(
558ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        prefs->GetBoolean(path.c_str()),
559ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        prefs->IsManagedPreference(path.c_str()),
560731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        !UserManager::Get()->current_user_is_owner());
561bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return true;
562bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  } else if (path == kAccountsPrefUsers) {
563731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    ListValue* user_list = new ListValue;
564731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    GetUserWhitelist(user_list);
565731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    *out_value = user_list;
566bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return true;
567bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
568bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
569bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return false;
570bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
571bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
572bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool UserCrosSettingsProvider::HandlesSetting(const std::string& path) {
573ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return ::StartsWithASCII(path, "cros.accounts.", true) ||
574ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ::StartsWithASCII(path, "cros.signed.", true);
575bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
576bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
577bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid UserCrosSettingsProvider::WhitelistUser(const std::string& email) {
57821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  SignedSettingsHelper::Get()->StartWhitelistOp(
57921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      email, true, UserCrosSettingsTrust::GetInstance());
580bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  PrefService* prefs = g_browser_process->local_state();
581ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ListPrefUpdate cached_whitelist_update(prefs, kAccountsPrefUsers);
582ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  cached_whitelist_update->Append(Value::CreateStringValue(email));
583bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  prefs->ScheduleSavePersistentPrefs();
584bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
585bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
586bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid UserCrosSettingsProvider::UnwhitelistUser(const std::string& email) {
58721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  SignedSettingsHelper::Get()->StartWhitelistOp(
58821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      email, false, UserCrosSettingsTrust::GetInstance());
589bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
590bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  PrefService* prefs = g_browser_process->local_state();
591ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ListPrefUpdate cached_whitelist_update(prefs, kAccountsPrefUsers);
592bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  StringValue email_value(email);
593ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (cached_whitelist_update->Remove(email_value) != -1)
594bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    prefs->ScheduleSavePersistentPrefs();
595bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
596bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
597731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// static
598731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid UserCrosSettingsProvider::UpdateCachedOwner(const std::string& email) {
59921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  UpdateCacheString(kDeviceOwner, email, USE_VALUE_SUPPLIED);
600bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
601bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
602bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}  // namespace chromeos
603