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(
77 prefs::kMultiProfileUserBehavior
,
78 kBehaviorUnrestricted
,
79 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
80 registry
->RegisterBooleanPref(
81 prefs::kMultiProfileNeverShowIntro
,
83 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF
);
84 registry
->RegisterBooleanPref(
85 prefs::kMultiProfileWarningShowDismissed
,
87 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF
);
91 MultiProfileUserController::UserAllowedInSessionReason
92 MultiProfileUserController::GetPrimaryUserPolicy() {
93 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
96 const user_manager::User
* user
= user_manager
->GetPrimaryUser();
100 // Don't allow any secondary profiles if the primary profile is tainted.
101 if (policy::PolicyCertServiceFactory::UsedPolicyCertificates(user
->email())) {
102 // Check directly in local_state before checking if the primary user has
103 // a PolicyCertService. His profile may have been tainted previously though
104 // he didn't get a PolicyCertService created for this session.
105 return NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED
;
108 Profile
* profile
= ProfileHelper::Get()->GetProfileByUser(user
);
112 // If the primary profile already has policy certificates installed but
113 // hasn't used them yet then it can become tainted at any time during this
114 // session disable secondary profiles in this case too.
115 policy::PolicyCertService
* service
=
116 policy::PolicyCertServiceFactory::GetForProfile(profile
);
117 if (service
&& service
->has_policy_certificates())
118 return NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED
;
120 // No user is allowed if the primary user policy forbids it.
121 const std::string behavior
= profile
->GetPrefs()->GetString(
122 prefs::kMultiProfileUserBehavior
);
123 if (behavior
== kBehaviorNotAllowed
)
124 return NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS
;
129 bool MultiProfileUserController::IsUserAllowedInSession(
130 const std::string
& user_email
,
131 MultiProfileUserController::UserAllowedInSessionReason
* reason
) const {
132 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
135 const user_manager::User
* primary_user
= user_manager
->GetPrimaryUser();
136 std::string primary_user_email
;
138 primary_user_email
= primary_user
->email();
140 // Always allow if there is no primary user or user being checked is the
142 if (primary_user_email
.empty() || primary_user_email
== user_email
)
143 return SetUserAllowedReason(reason
, ALLOWED
);
145 // Don't allow profiles potentially tainted by data fetched with policy-pushed
146 // certificates to join a multiprofile session.
147 if (policy::PolicyCertServiceFactory::UsedPolicyCertificates(user_email
))
148 return SetUserAllowedReason(reason
, NOT_ALLOWED_POLICY_CERT_TAINTED
);
150 UserAllowedInSessionReason primary_user_policy
= GetPrimaryUserPolicy();
151 if (primary_user_policy
!= ALLOWED
)
152 return SetUserAllowedReason(reason
, primary_user_policy
);
154 // The user must have 'unrestricted' policy to be a secondary user.
155 const std::string behavior
= GetCachedValue(user_email
);
156 return SetUserAllowedReason(
158 behavior
== kBehaviorUnrestricted
? ALLOWED
: NOT_ALLOWED_POLICY_FORBIDS
);
161 void MultiProfileUserController::StartObserving(Profile
* user_profile
) {
162 // Profile name could be empty during tests.
163 if (user_profile
->GetProfileUserName().empty())
166 scoped_ptr
<PrefChangeRegistrar
> registrar(new PrefChangeRegistrar
);
167 registrar
->Init(user_profile
->GetPrefs());
169 prefs::kMultiProfileUserBehavior
,
170 base::Bind(&MultiProfileUserController::OnUserPrefChanged
,
171 base::Unretained(this),
173 pref_watchers_
.push_back(registrar
.release());
175 OnUserPrefChanged(user_profile
);
178 void MultiProfileUserController::RemoveCachedValues(
179 const std::string
& user_email
) {
180 DictionaryPrefUpdate
update(local_state_
,
181 prefs::kCachedMultiProfileUserBehavior
);
182 update
->RemoveWithoutPathExpansion(user_email
, NULL
);
183 policy::PolicyCertServiceFactory::ClearUsedPolicyCertificates(user_email
);
186 std::string
MultiProfileUserController::GetCachedValue(
187 const std::string
& user_email
) const {
188 const base::DictionaryValue
* dict
=
189 local_state_
->GetDictionary(prefs::kCachedMultiProfileUserBehavior
);
191 if (dict
&& dict
->GetStringWithoutPathExpansion(user_email
, &value
))
192 return SanitizeBehaviorValue(value
);
194 return std::string(kBehaviorUnrestricted
);
197 void MultiProfileUserController::SetCachedValue(
198 const std::string
& user_email
,
199 const std::string
& behavior
) {
200 DictionaryPrefUpdate
update(local_state_
,
201 prefs::kCachedMultiProfileUserBehavior
);
202 update
->SetStringWithoutPathExpansion(user_email
,
203 SanitizeBehaviorValue(behavior
));
206 void MultiProfileUserController::CheckSessionUsers() {
207 const user_manager::UserList
& users
=
208 user_manager::UserManager::Get()->GetLoggedInUsers();
209 for (user_manager::UserList::const_iterator it
= users
.begin();
212 if (!IsUserAllowedInSession((*it
)->email(), NULL
)) {
213 delegate_
->OnUserNotAllowed((*it
)->email());
219 void MultiProfileUserController::OnUserPrefChanged(
220 Profile
* user_profile
) {
221 std::string user_email
= user_profile
->GetProfileUserName();
222 CHECK(!user_email
.empty());
223 user_email
= gaia::CanonicalizeEmail(user_email
);
225 PrefService
* prefs
= user_profile
->GetPrefs();
226 if (prefs
->FindPreference(prefs::kMultiProfileUserBehavior
)
227 ->IsDefaultValue()) {
228 // Migration code to clear cached default behavior.
229 // TODO(xiyuan): Remove this after M35.
230 DictionaryPrefUpdate
update(local_state_
,
231 prefs::kCachedMultiProfileUserBehavior
);
232 update
->RemoveWithoutPathExpansion(user_email
, NULL
);
234 const std::string behavior
=
235 prefs
->GetString(prefs::kMultiProfileUserBehavior
);
236 SetCachedValue(user_email
, behavior
);
242 } // namespace chromeos