1 // Copyright 2014 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/login/users/multi_profile_user_controller.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/prefs/pref_change_registrar.h"
10 #include "base/prefs/pref_registry_simple.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/prefs/scoped_user_pref_update.h"
13 #include "chrome/browser/chromeos/login/users/multi_profile_user_controller_delegate.h"
14 #include "chrome/browser/chromeos/policy/policy_cert_service.h"
15 #include "chrome/browser/chromeos/policy/policy_cert_service_factory.h"
16 #include "chrome/browser/chromeos/profiles/profile_helper.h"
17 #include "chrome/browser/prefs/pref_service_syncable.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/common/pref_names.h"
20 #include "components/user_manager/user.h"
21 #include "components/user_manager/user_manager.h"
22 #include "google_apis/gaia/gaia_auth_util.h"
28 std::string
SanitizeBehaviorValue(const std::string
& value
) {
29 if (value
== MultiProfileUserController::kBehaviorUnrestricted
||
30 value
== MultiProfileUserController::kBehaviorPrimaryOnly
||
31 value
== MultiProfileUserController::kBehaviorNotAllowed
) {
35 return std::string(MultiProfileUserController::kBehaviorUnrestricted
);
38 bool SetUserAllowedReason(
39 MultiProfileUserController::UserAllowedInSessionReason
* reason
,
40 MultiProfileUserController::UserAllowedInSessionReason value
) {
43 return value
== MultiProfileUserController::ALLOWED
;
49 const char MultiProfileUserController::kBehaviorUnrestricted
[] = "unrestricted";
50 const char MultiProfileUserController::kBehaviorPrimaryOnly
[] = "primary-only";
51 const char MultiProfileUserController::kBehaviorNotAllowed
[] = "not-allowed";
53 // Note: this policy value is not a real one an is only returned locally for
54 // owner users instead of default one kBehaviorUnrestricted.
55 const char MultiProfileUserController::kBehaviorOwnerPrimaryOnly
[] =
58 MultiProfileUserController::MultiProfileUserController(
59 MultiProfileUserControllerDelegate
* delegate
,
60 PrefService
* local_state
)
61 : delegate_(delegate
),
62 local_state_(local_state
) {
65 MultiProfileUserController::~MultiProfileUserController() {}
68 void MultiProfileUserController::RegisterPrefs(
69 PrefRegistrySimple
* registry
) {
70 registry
->RegisterDictionaryPref(prefs::kCachedMultiProfileUserBehavior
);
74 void MultiProfileUserController::RegisterProfilePrefs(
75 user_prefs::PrefRegistrySyncable
* registry
) {
76 registry
->RegisterStringPref(prefs::kMultiProfileUserBehavior
,
77 kBehaviorUnrestricted
);
78 registry
->RegisterBooleanPref(
79 prefs::kMultiProfileNeverShowIntro
,
81 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF
);
82 registry
->RegisterBooleanPref(
83 prefs::kMultiProfileWarningShowDismissed
,
85 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF
);
89 MultiProfileUserController::UserAllowedInSessionReason
90 MultiProfileUserController::GetPrimaryUserPolicy() {
91 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
94 const user_manager::User
* user
= user_manager
->GetPrimaryUser();
98 // Don't allow any secondary profiles if the primary profile is tainted.
99 if (policy::PolicyCertServiceFactory::UsedPolicyCertificates(user
->email())) {
100 // Check directly in local_state before checking if the primary user has
101 // a PolicyCertService. His profile may have been tainted previously though
102 // he didn't get a PolicyCertService created for this session.
103 return NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED
;
106 Profile
* profile
= ProfileHelper::Get()->GetProfileByUser(user
);
110 // If the primary profile already has policy certificates installed but
111 // hasn't used them yet then it can become tainted at any time during this
112 // session disable secondary profiles in this case too.
113 policy::PolicyCertService
* service
=
114 policy::PolicyCertServiceFactory::GetForProfile(profile
);
115 if (service
&& service
->has_policy_certificates())
116 return NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED
;
118 // No user is allowed if the primary user policy forbids it.
119 const std::string behavior
= profile
->GetPrefs()->GetString(
120 prefs::kMultiProfileUserBehavior
);
121 if (behavior
== kBehaviorNotAllowed
)
122 return NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS
;
127 bool MultiProfileUserController::IsUserAllowedInSession(
128 const std::string
& user_email
,
129 MultiProfileUserController::UserAllowedInSessionReason
* reason
) const {
130 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
133 const user_manager::User
* primary_user
= user_manager
->GetPrimaryUser();
134 std::string primary_user_email
;
136 primary_user_email
= primary_user
->email();
138 // Always allow if there is no primary user or user being checked is the
140 if (primary_user_email
.empty() || primary_user_email
== user_email
)
141 return SetUserAllowedReason(reason
, ALLOWED
);
143 // Don't allow profiles potentially tainted by data fetched with policy-pushed
144 // certificates to join a multiprofile session.
145 if (policy::PolicyCertServiceFactory::UsedPolicyCertificates(user_email
))
146 return SetUserAllowedReason(reason
, NOT_ALLOWED_POLICY_CERT_TAINTED
);
148 UserAllowedInSessionReason primary_user_policy
= GetPrimaryUserPolicy();
149 if (primary_user_policy
!= ALLOWED
)
150 return SetUserAllowedReason(reason
, primary_user_policy
);
152 // The user must have 'unrestricted' policy to be a secondary user.
153 const std::string behavior
= GetCachedValue(user_email
);
154 return SetUserAllowedReason(
156 behavior
== kBehaviorUnrestricted
? ALLOWED
: NOT_ALLOWED_POLICY_FORBIDS
);
159 void MultiProfileUserController::StartObserving(Profile
* user_profile
) {
160 // Profile name could be empty during tests.
161 if (user_profile
->GetProfileUserName().empty())
164 scoped_ptr
<PrefChangeRegistrar
> registrar(new PrefChangeRegistrar
);
165 registrar
->Init(user_profile
->GetPrefs());
167 prefs::kMultiProfileUserBehavior
,
168 base::Bind(&MultiProfileUserController::OnUserPrefChanged
,
169 base::Unretained(this),
171 pref_watchers_
.push_back(registrar
.release());
173 OnUserPrefChanged(user_profile
);
176 void MultiProfileUserController::RemoveCachedValues(
177 const std::string
& user_email
) {
178 DictionaryPrefUpdate
update(local_state_
,
179 prefs::kCachedMultiProfileUserBehavior
);
180 update
->RemoveWithoutPathExpansion(user_email
, NULL
);
181 policy::PolicyCertServiceFactory::ClearUsedPolicyCertificates(user_email
);
184 std::string
MultiProfileUserController::GetCachedValue(
185 const std::string
& user_email
) const {
186 const base::DictionaryValue
* dict
=
187 local_state_
->GetDictionary(prefs::kCachedMultiProfileUserBehavior
);
189 if (dict
&& dict
->GetStringWithoutPathExpansion(user_email
, &value
))
190 return SanitizeBehaviorValue(value
);
192 return std::string(kBehaviorUnrestricted
);
195 void MultiProfileUserController::SetCachedValue(
196 const std::string
& user_email
,
197 const std::string
& behavior
) {
198 DictionaryPrefUpdate
update(local_state_
,
199 prefs::kCachedMultiProfileUserBehavior
);
200 update
->SetStringWithoutPathExpansion(user_email
,
201 SanitizeBehaviorValue(behavior
));
204 void MultiProfileUserController::CheckSessionUsers() {
205 const user_manager::UserList
& users
=
206 user_manager::UserManager::Get()->GetLoggedInUsers();
207 for (user_manager::UserList::const_iterator it
= users
.begin();
210 if (!IsUserAllowedInSession((*it
)->email(), NULL
)) {
211 delegate_
->OnUserNotAllowed((*it
)->email());
217 void MultiProfileUserController::OnUserPrefChanged(
218 Profile
* user_profile
) {
219 std::string user_email
= user_profile
->GetProfileUserName();
220 CHECK(!user_email
.empty());
221 user_email
= gaia::CanonicalizeEmail(user_email
);
223 PrefService
* prefs
= user_profile
->GetPrefs();
224 if (prefs
->FindPreference(prefs::kMultiProfileUserBehavior
)
225 ->IsDefaultValue()) {
226 // Migration code to clear cached default behavior.
227 // TODO(xiyuan): Remove this after M35.
228 DictionaryPrefUpdate
update(local_state_
,
229 prefs::kCachedMultiProfileUserBehavior
);
230 update
->RemoveWithoutPathExpansion(user_email
, NULL
);
232 const std::string behavior
=
233 prefs
->GetString(prefs::kMultiProfileUserBehavior
);
234 SetCachedValue(user_email
, behavior
);
240 } // namespace chromeos