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/settings/cros_settings.h"
16 #include "chromeos/login/user_names.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
,
33 const std::string
& kiosk_app_update_url
)
35 account_id(account_id
),
36 user_id(GenerateDeviceLocalAccountUserId(account_id
, type
)),
37 kiosk_app_id(kiosk_app_id
),
38 kiosk_app_update_url(kiosk_app_update_url
) {
41 DeviceLocalAccount::~DeviceLocalAccount() {
44 std::string
GenerateDeviceLocalAccountUserId(const std::string
& account_id
,
45 DeviceLocalAccount::Type type
) {
46 std::string domain_prefix
;
48 case DeviceLocalAccount::TYPE_PUBLIC_SESSION
:
49 domain_prefix
= kPublicAccountDomainPrefix
;
51 case DeviceLocalAccount::TYPE_KIOSK_APP
:
52 domain_prefix
= kKioskAppAccountDomainPrefix
;
54 case DeviceLocalAccount::TYPE_COUNT
:
58 return gaia::CanonicalizeEmail(
59 base::HexEncode(account_id
.c_str(), account_id
.size()) + "@" +
60 domain_prefix
+ kDeviceLocalAccountDomainSuffix
);
63 bool IsDeviceLocalAccountUser(const std::string
& user_id
,
64 DeviceLocalAccount::Type
* type
) {
65 // For historical reasons, the guest user ID does not contain an @ symbol and
66 // therefore, cannot be parsed by gaia::ExtractDomainName().
67 if (user_id
== chromeos::login::kGuestUserName
)
69 const std::string domain
= gaia::ExtractDomainName(user_id
);
70 if (!EndsWith(domain
, kDeviceLocalAccountDomainSuffix
, true))
73 const std::string domain_prefix
= domain
.substr(
74 0, domain
.size() - arraysize(kDeviceLocalAccountDomainSuffix
) + 1);
76 if (domain_prefix
== kPublicAccountDomainPrefix
) {
78 *type
= DeviceLocalAccount::TYPE_PUBLIC_SESSION
;
81 if (domain_prefix
== kKioskAppAccountDomainPrefix
) {
83 *type
= DeviceLocalAccount::TYPE_KIOSK_APP
;
87 // |user_id| is a device-local account but its type is not recognized.
90 *type
= DeviceLocalAccount::TYPE_COUNT
;
94 void SetDeviceLocalAccounts(
95 chromeos::CrosSettings
* cros_settings
,
96 const std::vector
<DeviceLocalAccount
>& accounts
) {
98 for (std::vector
<DeviceLocalAccount
>::const_iterator it
= accounts
.begin();
99 it
!= accounts
.end(); ++it
) {
100 scoped_ptr
<base::DictionaryValue
> entry(new base::DictionaryValue
);
101 entry
->SetStringWithoutPathExpansion(
102 chromeos::kAccountsPrefDeviceLocalAccountsKeyId
,
104 entry
->SetIntegerWithoutPathExpansion(
105 chromeos::kAccountsPrefDeviceLocalAccountsKeyType
,
107 if (it
->type
== DeviceLocalAccount::TYPE_KIOSK_APP
) {
108 entry
->SetStringWithoutPathExpansion(
109 chromeos::kAccountsPrefDeviceLocalAccountsKeyKioskAppId
,
111 if (!it
->kiosk_app_update_url
.empty()) {
112 entry
->SetStringWithoutPathExpansion(
113 chromeos::kAccountsPrefDeviceLocalAccountsKeyKioskAppUpdateURL
,
114 it
->kiosk_app_update_url
);
117 list
.Append(entry
.release());
120 cros_settings
->Set(chromeos::kAccountsPrefDeviceLocalAccounts
, list
);
123 std::vector
<DeviceLocalAccount
> GetDeviceLocalAccounts(
124 chromeos::CrosSettings
* cros_settings
) {
125 std::vector
<DeviceLocalAccount
> accounts
;
127 const base::ListValue
* list
= NULL
;
128 cros_settings
->GetList(chromeos::kAccountsPrefDeviceLocalAccounts
, &list
);
132 std::set
<std::string
> account_ids
;
133 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
134 const base::DictionaryValue
* entry
= NULL
;
135 if (!list
->GetDictionary(i
, &entry
)) {
136 LOG(ERROR
) << "Corrupt entry in device-local account list at index " << i
141 std::string account_id
;
142 if (!entry
->GetStringWithoutPathExpansion(
143 chromeos::kAccountsPrefDeviceLocalAccountsKeyId
, &account_id
) ||
144 account_id
.empty()) {
145 LOG(ERROR
) << "Missing account ID in device-local account list at index "
151 if (!entry
->GetIntegerWithoutPathExpansion(
152 chromeos::kAccountsPrefDeviceLocalAccountsKeyType
, &type
) ||
153 type
< 0 || type
>= DeviceLocalAccount::TYPE_COUNT
) {
154 LOG(ERROR
) << "Missing or invalid account type in device-local account "
155 << "list at index " << i
<< ".";
159 std::string kiosk_app_id
;
160 std::string kiosk_app_update_url
;
161 if (type
== DeviceLocalAccount::TYPE_KIOSK_APP
) {
162 if (!entry
->GetStringWithoutPathExpansion(
163 chromeos::kAccountsPrefDeviceLocalAccountsKeyKioskAppId
,
165 LOG(ERROR
) << "Missing app ID in device-local account entry at index "
169 entry
->GetStringWithoutPathExpansion(
170 chromeos::kAccountsPrefDeviceLocalAccountsKeyKioskAppUpdateURL
,
171 &kiosk_app_update_url
);
174 if (!account_ids
.insert(account_id
).second
) {
175 LOG(ERROR
) << "Duplicate entry in device-local account list at index "
176 << i
<< ": " << account_id
<< ".";
181 DeviceLocalAccount(static_cast<DeviceLocalAccount::Type
>(type
),
184 kiosk_app_update_url
));
189 } // namespace policy