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/ownership/owner_settings_service_chromeos.h"
16 #include "chrome/browser/chromeos/settings/cros_settings.h"
17 #include "chromeos/login/user_names.h"
18 #include "chromeos/settings/cros_settings_names.h"
19 #include "google_apis/gaia/gaia_auth_util.h"
25 const char kPublicAccountDomainPrefix
[] = "public-accounts";
26 const char kKioskAppAccountDomainPrefix
[] = "kiosk-apps";
27 const char kDeviceLocalAccountDomainSuffix
[] = ".device-local.localhost";
31 DeviceLocalAccount::DeviceLocalAccount(Type type
,
32 const std::string
& account_id
,
33 const std::string
& kiosk_app_id
,
34 const std::string
& kiosk_app_update_url
)
36 account_id(account_id
),
37 user_id(GenerateDeviceLocalAccountUserId(account_id
, type
)),
38 kiosk_app_id(kiosk_app_id
),
39 kiosk_app_update_url(kiosk_app_update_url
) {
42 DeviceLocalAccount::~DeviceLocalAccount() {
45 std::string
GenerateDeviceLocalAccountUserId(const std::string
& account_id
,
46 DeviceLocalAccount::Type type
) {
47 std::string domain_prefix
;
49 case DeviceLocalAccount::TYPE_PUBLIC_SESSION
:
50 domain_prefix
= kPublicAccountDomainPrefix
;
52 case DeviceLocalAccount::TYPE_KIOSK_APP
:
53 domain_prefix
= kKioskAppAccountDomainPrefix
;
55 case DeviceLocalAccount::TYPE_COUNT
:
59 return gaia::CanonicalizeEmail(
60 base::HexEncode(account_id
.c_str(), account_id
.size()) + "@" +
61 domain_prefix
+ kDeviceLocalAccountDomainSuffix
);
64 bool IsDeviceLocalAccountUser(const std::string
& user_id
,
65 DeviceLocalAccount::Type
* type
) {
66 // For historical reasons, the guest user ID does not contain an @ symbol and
67 // therefore, cannot be parsed by gaia::ExtractDomainName().
68 if (user_id
== chromeos::login::kGuestUserName
)
70 const std::string domain
= gaia::ExtractDomainName(user_id
);
71 if (!base::EndsWith(domain
, kDeviceLocalAccountDomainSuffix
,
72 base::CompareCase::SENSITIVE
))
75 const std::string domain_prefix
= domain
.substr(
76 0, domain
.size() - arraysize(kDeviceLocalAccountDomainSuffix
) + 1);
78 if (domain_prefix
== kPublicAccountDomainPrefix
) {
80 *type
= DeviceLocalAccount::TYPE_PUBLIC_SESSION
;
83 if (domain_prefix
== kKioskAppAccountDomainPrefix
) {
85 *type
= DeviceLocalAccount::TYPE_KIOSK_APP
;
89 // |user_id| is a device-local account but its type is not recognized.
92 *type
= DeviceLocalAccount::TYPE_COUNT
;
96 void SetDeviceLocalAccounts(chromeos::OwnerSettingsServiceChromeOS
* service
,
97 const std::vector
<DeviceLocalAccount
>& accounts
) {
99 for (std::vector
<DeviceLocalAccount
>::const_iterator it
= accounts
.begin();
100 it
!= accounts
.end(); ++it
) {
101 scoped_ptr
<base::DictionaryValue
> entry(new base::DictionaryValue
);
102 entry
->SetStringWithoutPathExpansion(
103 chromeos::kAccountsPrefDeviceLocalAccountsKeyId
,
105 entry
->SetIntegerWithoutPathExpansion(
106 chromeos::kAccountsPrefDeviceLocalAccountsKeyType
,
108 if (it
->type
== DeviceLocalAccount::TYPE_KIOSK_APP
) {
109 entry
->SetStringWithoutPathExpansion(
110 chromeos::kAccountsPrefDeviceLocalAccountsKeyKioskAppId
,
112 if (!it
->kiosk_app_update_url
.empty()) {
113 entry
->SetStringWithoutPathExpansion(
114 chromeos::kAccountsPrefDeviceLocalAccountsKeyKioskAppUpdateURL
,
115 it
->kiosk_app_update_url
);
118 list
.Append(entry
.release());
121 service
->Set(chromeos::kAccountsPrefDeviceLocalAccounts
, list
);
124 std::vector
<DeviceLocalAccount
> GetDeviceLocalAccounts(
125 chromeos::CrosSettings
* cros_settings
) {
126 std::vector
<DeviceLocalAccount
> accounts
;
128 const base::ListValue
* list
= NULL
;
129 cros_settings
->GetList(chromeos::kAccountsPrefDeviceLocalAccounts
, &list
);
133 std::set
<std::string
> account_ids
;
134 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
135 const base::DictionaryValue
* entry
= NULL
;
136 if (!list
->GetDictionary(i
, &entry
)) {
137 LOG(ERROR
) << "Corrupt entry in device-local account list at index " << i
142 std::string account_id
;
143 if (!entry
->GetStringWithoutPathExpansion(
144 chromeos::kAccountsPrefDeviceLocalAccountsKeyId
, &account_id
) ||
145 account_id
.empty()) {
146 LOG(ERROR
) << "Missing account ID in device-local account list at index "
152 if (!entry
->GetIntegerWithoutPathExpansion(
153 chromeos::kAccountsPrefDeviceLocalAccountsKeyType
, &type
) ||
154 type
< 0 || type
>= DeviceLocalAccount::TYPE_COUNT
) {
155 LOG(ERROR
) << "Missing or invalid account type in device-local account "
156 << "list at index " << i
<< ".";
160 std::string kiosk_app_id
;
161 std::string kiosk_app_update_url
;
162 if (type
== DeviceLocalAccount::TYPE_KIOSK_APP
) {
163 if (!entry
->GetStringWithoutPathExpansion(
164 chromeos::kAccountsPrefDeviceLocalAccountsKeyKioskAppId
,
166 LOG(ERROR
) << "Missing app ID in device-local account entry at index "
170 entry
->GetStringWithoutPathExpansion(
171 chromeos::kAccountsPrefDeviceLocalAccountsKeyKioskAppUpdateURL
,
172 &kiosk_app_update_url
);
175 if (!account_ids
.insert(account_id
).second
) {
176 LOG(ERROR
) << "Duplicate entry in device-local account list at index "
177 << i
<< ": " << account_id
<< ".";
182 DeviceLocalAccount(static_cast<DeviceLocalAccount::Type
>(type
),
185 kiosk_app_update_url
));
190 } // namespace policy