1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/policy/device_local_account.h"
9 #include "base/basictypes.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_util.h"
14 #include "base/values.h"
15 #include "chrome/browser/chromeos/login/user_manager.h"
16 #include "chrome/browser/chromeos/settings/cros_settings.h"
17 #include "chromeos/settings/cros_settings_names.h"
18 #include "google_apis/gaia/gaia_auth_util.h"
24 const char kPublicAccountDomainPrefix
[] = "public-accounts";
25 const char kKioskAppAccountDomainPrefix
[] = "kiosk-apps";
26 const char kDeviceLocalAccountDomainSuffix
[] = ".device-local.localhost";
30 DeviceLocalAccount::DeviceLocalAccount(Type type
,
31 const std::string
& account_id
,
32 const std::string
& kiosk_app_id
)
34 account_id(account_id
),
35 user_id(GenerateDeviceLocalAccountUserId(account_id
, type
)),
36 kiosk_app_id(kiosk_app_id
) {
39 DeviceLocalAccount::~DeviceLocalAccount() {
42 std::string
GenerateDeviceLocalAccountUserId(const std::string
& account_id
,
43 DeviceLocalAccount::Type type
) {
44 std::string domain_prefix
;
46 case DeviceLocalAccount::TYPE_PUBLIC_SESSION
:
47 domain_prefix
= kPublicAccountDomainPrefix
;
49 case DeviceLocalAccount::TYPE_KIOSK_APP
:
50 domain_prefix
= kKioskAppAccountDomainPrefix
;
52 case DeviceLocalAccount::TYPE_COUNT
:
56 return gaia::CanonicalizeEmail(
57 base::HexEncode(account_id
.c_str(), account_id
.size()) + "@" +
58 domain_prefix
+ kDeviceLocalAccountDomainSuffix
);
61 bool IsDeviceLocalAccountUser(const std::string
& user_id
,
62 DeviceLocalAccount::Type
* type
) {
63 // For historical reasons, the guest user ID does not contain an @ symbol and
64 // therefore, cannot be parsed by gaia::ExtractDomainName().
65 if (user_id
== chromeos::UserManager::kGuestUserName
)
67 const std::string domain
= gaia::ExtractDomainName(user_id
);
68 if (!EndsWith(domain
, kDeviceLocalAccountDomainSuffix
, true))
71 const std::string domain_prefix
= domain
.substr(
72 0, domain
.size() - arraysize(kDeviceLocalAccountDomainSuffix
) + 1);
74 if (domain_prefix
== kPublicAccountDomainPrefix
) {
76 *type
= DeviceLocalAccount::TYPE_PUBLIC_SESSION
;
79 if (domain_prefix
== kKioskAppAccountDomainPrefix
) {
81 *type
= DeviceLocalAccount::TYPE_KIOSK_APP
;
85 // |user_id| is a device-local account but its type is not recognized.
88 *type
= DeviceLocalAccount::TYPE_COUNT
;
92 void SetDeviceLocalAccounts(
93 chromeos::CrosSettings
* cros_settings
,
94 const std::vector
<DeviceLocalAccount
>& accounts
) {
96 for (std::vector
<DeviceLocalAccount
>::const_iterator it
= accounts
.begin();
97 it
!= accounts
.end(); ++it
) {
98 scoped_ptr
<base::DictionaryValue
> entry(new base::DictionaryValue
);
99 entry
->SetStringWithoutPathExpansion(
100 chromeos::kAccountsPrefDeviceLocalAccountsKeyId
,
102 entry
->SetIntegerWithoutPathExpansion(
103 chromeos::kAccountsPrefDeviceLocalAccountsKeyType
,
105 if (it
->type
== DeviceLocalAccount::TYPE_KIOSK_APP
) {
106 entry
->SetStringWithoutPathExpansion(
107 chromeos::kAccountsPrefDeviceLocalAccountsKeyKioskAppId
,
110 list
.Append(entry
.release());
113 cros_settings
->Set(chromeos::kAccountsPrefDeviceLocalAccounts
, list
);
116 std::vector
<DeviceLocalAccount
> GetDeviceLocalAccounts(
117 chromeos::CrosSettings
* cros_settings
) {
118 std::vector
<DeviceLocalAccount
> accounts
;
120 const base::ListValue
* list
= NULL
;
121 cros_settings
->GetList(chromeos::kAccountsPrefDeviceLocalAccounts
, &list
);
125 std::set
<std::string
> account_ids
;
126 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
127 const base::DictionaryValue
* entry
= NULL
;
128 if (!list
->GetDictionary(i
, &entry
)) {
129 LOG(ERROR
) << "Corrupt entry in device-local account list at index " << i
134 std::string account_id
;
135 if (!entry
->GetStringWithoutPathExpansion(
136 chromeos::kAccountsPrefDeviceLocalAccountsKeyId
, &account_id
) ||
137 account_id
.empty()) {
138 LOG(ERROR
) << "Missing account ID in device-local account list at index "
144 if (!entry
->GetIntegerWithoutPathExpansion(
145 chromeos::kAccountsPrefDeviceLocalAccountsKeyType
, &type
) ||
146 type
< 0 || type
>= DeviceLocalAccount::TYPE_COUNT
) {
147 LOG(ERROR
) << "Missing or invalid account type in device-local account "
148 << "list at index " << i
<< ".";
152 std::string kiosk_app_id
;
153 if (type
== DeviceLocalAccount::TYPE_KIOSK_APP
) {
154 if (!entry
->GetStringWithoutPathExpansion(
155 chromeos::kAccountsPrefDeviceLocalAccountsKeyKioskAppId
,
157 LOG(ERROR
) << "Missing app ID in device-local account entry at index "
163 if (!account_ids
.insert(account_id
).second
) {
164 LOG(ERROR
) << "Duplicate entry in device-local account list at index "
165 << i
<< ": " << account_id
<< ".";
169 accounts
.push_back(DeviceLocalAccount(
170 static_cast<DeviceLocalAccount::Type
>(type
), account_id
, kiosk_app_id
));
175 } // namespace policy