blob: 4cbcd5ae034440014b8e7b2e5148196e64df055e [file] [log] [blame]
// Copyright 2014 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/ash/login/users/supervised_user_manager_impl.h"
#include <memory>
#include "ash/components/settings/cros_settings_names.h"
#include "base/bind.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/ash/login/users/chrome_user_manager_impl.h"
#include "chrome/browser/ash/settings/cros_settings.h"
#include "chrome/browser/browser_process.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/user_manager/user_type.h"
#include "content/public/browser/browser_thread.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
using content::BrowserThread;
namespace {
// Names for pref keys in Local State.
// A map from supervised user local user id to sync user id.
const char kSupervisedUserSyncId[] = "ManagedUserSyncId";
// A map from supervised user id to manager user id.
const char kSupervisedUserManagers[] = "ManagedUserManagers";
// A map from supervised user id to manager display name.
const char kSupervisedUserManagerNames[] = "ManagedUserManagerNames";
// A map from supervised user id to manager display e-mail.
const char kSupervisedUserManagerDisplayEmails[] =
"ManagedUserManagerDisplayEmails";
// A vector pref of the supervised accounts defined on this device, that had
// not logged in yet.
const char kSupervisedUsersFirstRun[] = "LocallyManagedUsersFirstRun";
// A map from user id to password schema id.
const char kSupervisedUserPasswordSchema[] = "SupervisedUserPasswordSchema";
// A map from user id to password salt.
const char kSupervisedUserPasswordSalt[] = "SupervisedUserPasswordSalt";
// A map from user id to password revision.
const char kSupervisedUserPasswordRevision[] = "SupervisedUserPasswordRevision";
// A map from user id to flag indicating if password should be updated upon
// signin.
const char kSupervisedUserNeedPasswordUpdate[] =
"SupervisedUserNeedPasswordUpdate";
// A map from user id to flag indicating if cryptohome does not have signature
// key.
const char kSupervisedUserIncompleteKey[] = "SupervisedUserHasIncompleteKey";
} // namespace
namespace ash {
const char kSchemaVersion[] = "SchemaVersion";
const char kPasswordRevision[] = "PasswordRevision";
const char kSalt[] = "PasswordSalt";
const char kRequirePasswordUpdate[] = "RequirePasswordUpdate";
const char kHasIncompleteKey[] = "HasIncompleteKey";
// static
void SupervisedUserManager::RegisterLocalStatePrefs(
PrefRegistrySimple* registry) {
registry->RegisterListPref(kSupervisedUsersFirstRun);
registry->RegisterDictionaryPref(kSupervisedUserSyncId);
registry->RegisterDictionaryPref(kSupervisedUserManagers);
registry->RegisterDictionaryPref(kSupervisedUserManagerNames);
registry->RegisterDictionaryPref(kSupervisedUserManagerDisplayEmails);
registry->RegisterDictionaryPref(kSupervisedUserPasswordSchema);
registry->RegisterDictionaryPref(kSupervisedUserPasswordSalt);
registry->RegisterDictionaryPref(kSupervisedUserPasswordRevision);
registry->RegisterDictionaryPref(kSupervisedUserNeedPasswordUpdate);
registry->RegisterDictionaryPref(kSupervisedUserIncompleteKey);
}
SupervisedUserManagerImpl::SupervisedUserManagerImpl(
ChromeUserManagerImpl* owner)
: owner_(owner), cros_settings_(CrosSettings::Get()) {
// SupervisedUserManager instance should be used only on UI thread.
// (or in unit_tests)
if (base::ThreadTaskRunnerHandle::IsSet())
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
SupervisedUserManagerImpl::~SupervisedUserManagerImpl() {}
std::string SupervisedUserManagerImpl::GetUserSyncId(
const std::string& user_id) const {
std::string result;
GetUserStringValue(user_id, kSupervisedUserSyncId, &result);
return result;
}
std::u16string SupervisedUserManagerImpl::GetManagerDisplayName(
const std::string& user_id) const {
PrefService* local_state = g_browser_process->local_state();
const base::Value* manager_names =
local_state->GetDictionary(kSupervisedUserManagerNames);
const std::string* result = manager_names->FindStringKey(user_id);
if (result && !result->empty())
return base::UTF8ToUTF16(*result);
return base::UTF8ToUTF16(GetManagerDisplayEmail(user_id));
}
std::string SupervisedUserManagerImpl::GetManagerUserId(
const std::string& user_id) const {
std::string result;
GetUserStringValue(user_id, kSupervisedUserManagers, &result);
return result;
}
std::string SupervisedUserManagerImpl::GetManagerDisplayEmail(
const std::string& user_id) const {
std::string result;
if (GetUserStringValue(user_id, kSupervisedUserManagerDisplayEmails,
&result) &&
!result.empty())
return result;
return GetManagerUserId(user_id);
}
void SupervisedUserManagerImpl::GetPasswordInformation(
const std::string& user_id,
base::DictionaryValue* result) {
int value;
if (GetUserIntegerValue(user_id, kSupervisedUserPasswordSchema, &value))
result->SetKey(kSchemaVersion, base::Value(value));
if (GetUserIntegerValue(user_id, kSupervisedUserPasswordRevision, &value))
result->SetKey(kPasswordRevision, base::Value(value));
bool flag;
if (GetUserBooleanValue(user_id, kSupervisedUserNeedPasswordUpdate, &flag))
result->SetKey(kRequirePasswordUpdate, base::Value(flag));
if (GetUserBooleanValue(user_id, kSupervisedUserIncompleteKey, &flag))
result->SetKey(kHasIncompleteKey, base::Value(flag));
std::string salt;
if (GetUserStringValue(user_id, kSupervisedUserPasswordSalt, &salt))
result->SetKey(kSalt, base::Value(salt));
}
void SupervisedUserManagerImpl::SetPasswordInformation(
const std::string& user_id,
const base::DictionaryValue* password_info) {
absl::optional<int> schema_version =
password_info->FindIntKey(kSchemaVersion);
if (schema_version.has_value())
SetUserIntegerValue(user_id, kSupervisedUserPasswordSchema,
schema_version.value());
absl::optional<int> password_revision =
password_info->FindIntKey(kPasswordRevision);
if (password_revision.has_value())
SetUserIntegerValue(user_id, kSupervisedUserPasswordRevision,
password_revision.value());
absl::optional<bool> flag =
password_info->FindBoolKey(kRequirePasswordUpdate);
if (flag.has_value()) {
SetUserBooleanValue(user_id, kSupervisedUserNeedPasswordUpdate,
flag.value());
}
flag = password_info->FindBoolKey(kHasIncompleteKey);
if (flag.has_value())
SetUserBooleanValue(user_id, kSupervisedUserIncompleteKey, flag.value());
const std::string* salt = password_info->FindStringKey(kSalt);
if (salt)
SetUserStringValue(user_id, kSupervisedUserPasswordSalt, *salt);
g_browser_process->local_state()->CommitPendingWrite();
}
bool SupervisedUserManagerImpl::GetUserStringValue(
const std::string& user_id,
const char* key,
std::string* out_value) const {
PrefService* local_state = g_browser_process->local_state();
const base::Value* dictionary = local_state->GetDictionary(key);
const std::string* value = dictionary->FindStringKey(user_id);
if (!value)
return false;
*out_value = *value;
return true;
}
bool SupervisedUserManagerImpl::GetUserIntegerValue(const std::string& user_id,
const char* key,
int* out_value) const {
PrefService* local_state = g_browser_process->local_state();
const base::Value* dictionary = local_state->GetDictionary(key);
absl::optional<int> value = dictionary->FindIntKey(user_id);
if (!value)
return false;
*out_value = value.value();
return true;
}
bool SupervisedUserManagerImpl::GetUserBooleanValue(const std::string& user_id,
const char* key,
bool* out_value) const {
PrefService* local_state = g_browser_process->local_state();
const base::Value* dictionary = local_state->GetDictionary(key);
absl::optional<bool> flag = dictionary->FindBoolKey(user_id);
if (!flag)
return false;
*out_value = flag.value();
return true;
}
void SupervisedUserManagerImpl::SetUserStringValue(const std::string& user_id,
const char* key,
const std::string& value) {
PrefService* local_state = g_browser_process->local_state();
DictionaryPrefUpdate update(local_state, key);
update->SetStringKey(user_id, value);
}
void SupervisedUserManagerImpl::SetUserIntegerValue(const std::string& user_id,
const char* key,
const int value) {
PrefService* local_state = g_browser_process->local_state();
DictionaryPrefUpdate update(local_state, key);
update->SetIntKey(user_id, value);
}
void SupervisedUserManagerImpl::SetUserBooleanValue(const std::string& user_id,
const char* key,
const bool value) {
PrefService* local_state = g_browser_process->local_state();
DictionaryPrefUpdate update(local_state, key);
update->SetBoolKey(user_id, value);
}
void SupervisedUserManagerImpl::RemoveNonCryptohomeData(
const std::string& user_id) {
PrefService* prefs = g_browser_process->local_state();
ListPrefUpdate prefs_new_users_update(prefs, kSupervisedUsersFirstRun);
prefs_new_users_update->EraseListValue(base::Value(user_id));
CleanPref(user_id, kSupervisedUserSyncId);
CleanPref(user_id, kSupervisedUserManagers);
CleanPref(user_id, kSupervisedUserManagerNames);
CleanPref(user_id, kSupervisedUserManagerDisplayEmails);
CleanPref(user_id, kSupervisedUserPasswordSalt);
CleanPref(user_id, kSupervisedUserPasswordSchema);
CleanPref(user_id, kSupervisedUserPasswordRevision);
CleanPref(user_id, kSupervisedUserNeedPasswordUpdate);
CleanPref(user_id, kSupervisedUserIncompleteKey);
}
void SupervisedUserManagerImpl::CleanPref(const std::string& user_id,
const char* key) {
PrefService* prefs = g_browser_process->local_state();
DictionaryPrefUpdate dict_update(prefs, key);
dict_update->RemoveKey(user_id);
}
bool SupervisedUserManagerImpl::CheckForFirstRun(const std::string& user_id) {
ListPrefUpdate prefs_new_users_update(g_browser_process->local_state(),
kSupervisedUsersFirstRun);
return prefs_new_users_update->EraseListValue(base::Value(user_id));
}
} // namespace ash