1 // Copyright 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/login/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/multi_profile_user_controller_delegate.h"
14 #include "chrome/browser/chromeos/login/user.h"
15 #include "chrome/browser/chromeos/login/user_manager.h"
16 #include "chrome/browser/chromeos/policy/policy_cert_service.h"
17 #include "chrome/browser/chromeos/policy/policy_cert_service_factory.h"
18 #include "chrome/browser/prefs/pref_service_syncable.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/common/pref_names.h"
21 #include "google_apis/gaia/gaia_auth_util.h"
27 std::string
SanitizeBehaviorValue(const std::string
& value
) {
28 if (value
== MultiProfileUserController::kBehaviorUnrestricted
||
29 value
== MultiProfileUserController::kBehaviorPrimaryOnly
||
30 value
== MultiProfileUserController::kBehaviorNotAllowed
) {
34 return std::string(MultiProfileUserController::kBehaviorUnrestricted
);
40 const char MultiProfileUserController::kBehaviorUnrestricted
[] = "unrestricted";
41 const char MultiProfileUserController::kBehaviorPrimaryOnly
[] = "primary-only";
42 const char MultiProfileUserController::kBehaviorNotAllowed
[] = "not-allowed";
44 MultiProfileUserController::MultiProfileUserController(
45 MultiProfileUserControllerDelegate
* delegate
,
46 PrefService
* local_state
)
47 : delegate_(delegate
),
48 local_state_(local_state
) {
51 MultiProfileUserController::~MultiProfileUserController() {}
54 void MultiProfileUserController::RegisterPrefs(
55 PrefRegistrySimple
* registry
) {
56 registry
->RegisterDictionaryPref(prefs::kCachedMultiProfileUserBehavior
);
60 void MultiProfileUserController::RegisterProfilePrefs(
61 user_prefs::PrefRegistrySyncable
* registry
) {
62 registry
->RegisterStringPref(
63 prefs::kMultiProfileUserBehavior
,
64 kBehaviorUnrestricted
,
65 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
66 registry
->RegisterBooleanPref(
67 prefs::kMultiProfileNeverShowIntro
,
69 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF
);
70 registry
->RegisterBooleanPref(
71 prefs::kMultiProfileWarningShowDismissed
,
73 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF
);
76 MultiProfileUserController::UserAllowedInSessionResult
77 MultiProfileUserController::IsUserAllowedInSession(
78 const std::string
& user_email
) const {
79 UserManager
* user_manager
= UserManager::Get();
82 const User
* primary_user
= user_manager
->GetPrimaryUser();
83 std::string primary_user_email
;
85 primary_user_email
= primary_user
->email();
87 // Always allow if there is no primary user or user being checked is the
89 if (primary_user_email
.empty() || primary_user_email
== user_email
)
92 // Owner is not allowed to be secondary user.
93 if (user_manager
->GetOwnerEmail() == user_email
)
94 return NOT_ALLOWED_OWNER_AS_SECONDARY
;
96 // Don't allow profiles potentially tainted by data fetched with policy-pushed
97 // certificates to join a multiprofile session.
98 if (policy::PolicyCertServiceFactory::UsedPolicyCertificates(user_email
))
99 return NOT_ALLOWED_POLICY_CERT_TAINTED
;
101 // Don't allow any secondary profiles if the primary profile is tainted.
102 if (policy::PolicyCertServiceFactory::UsedPolicyCertificates(
103 primary_user_email
)) {
104 // Check directly in local_state before checking if the primary user has
105 // a PolicyCertService. His profile may have been tainted previously though
106 // he didn't get a PolicyCertService created for this session.
107 return NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED
;
110 // If the primary profile already has policy certificates installed but hasn't
111 // used them yet then it can become tainted at any time during this session;
112 // disable secondary profiles in this case too.
113 Profile
* primary_user_profile
=
114 primary_user
? user_manager
->GetProfileByUser(primary_user
) : NULL
;
115 policy::PolicyCertService
* service
=
116 primary_user_profile
? policy::PolicyCertServiceFactory::GetForProfile(
117 primary_user_profile
)
119 if (service
&& service
->has_policy_certificates())
120 return NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED
;
122 // No user is allowed if the primary user policy forbids it.
123 const std::string primary_user_behavior
=
124 primary_user_profile
->GetPrefs()->GetString(
125 prefs::kMultiProfileUserBehavior
);
126 if (primary_user_behavior
== kBehaviorNotAllowed
)
127 return NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS
;
129 // The user must have 'unrestricted' policy to be a secondary user.
130 const std::string behavior
= GetCachedValue(user_email
);
131 return behavior
== kBehaviorUnrestricted
? ALLOWED
:
132 NOT_ALLOWED_POLICY_FORBIDS
;
135 void MultiProfileUserController::StartObserving(Profile
* user_profile
) {
136 // Profile name could be empty during tests.
137 if (user_profile
->GetProfileName().empty())
140 scoped_ptr
<PrefChangeRegistrar
> registrar(new PrefChangeRegistrar
);
141 registrar
->Init(user_profile
->GetPrefs());
143 prefs::kMultiProfileUserBehavior
,
144 base::Bind(&MultiProfileUserController::OnUserPrefChanged
,
145 base::Unretained(this),
147 pref_watchers_
.push_back(registrar
.release());
149 OnUserPrefChanged(user_profile
);
152 void MultiProfileUserController::RemoveCachedValues(
153 const std::string
& user_email
) {
154 DictionaryPrefUpdate
update(local_state_
,
155 prefs::kCachedMultiProfileUserBehavior
);
156 update
->RemoveWithoutPathExpansion(user_email
, NULL
);
157 policy::PolicyCertServiceFactory::ClearUsedPolicyCertificates(user_email
);
160 std::string
MultiProfileUserController::GetCachedValue(
161 const std::string
& user_email
) const {
162 const base::DictionaryValue
* dict
=
163 local_state_
->GetDictionary(prefs::kCachedMultiProfileUserBehavior
);
165 if (dict
&& dict
->GetStringWithoutPathExpansion(user_email
, &value
))
166 return SanitizeBehaviorValue(value
);
168 return std::string(kBehaviorUnrestricted
);
171 void MultiProfileUserController::SetCachedValue(
172 const std::string
& user_email
,
173 const std::string
& behavior
) {
174 DictionaryPrefUpdate
update(local_state_
,
175 prefs::kCachedMultiProfileUserBehavior
);
176 update
->SetStringWithoutPathExpansion(user_email
,
177 SanitizeBehaviorValue(behavior
));
180 void MultiProfileUserController::CheckSessionUsers() {
181 const UserList
& users
= UserManager::Get()->GetLoggedInUsers();
182 for (UserList::const_iterator it
= users
.begin(); it
!= users
.end(); ++it
) {
183 if (IsUserAllowedInSession((*it
)->email()) != ALLOWED
) {
184 delegate_
->OnUserNotAllowed((*it
)->email());
190 void MultiProfileUserController::OnUserPrefChanged(
191 Profile
* user_profile
) {
192 std::string user_email
= user_profile
->GetProfileName();
193 CHECK(!user_email
.empty());
194 user_email
= gaia::CanonicalizeEmail(user_email
);
196 PrefService
* prefs
= user_profile
->GetPrefs();
197 if (prefs
->FindPreference(prefs::kMultiProfileUserBehavior
)
198 ->IsDefaultValue()) {
199 // Migration code to clear cached default behavior.
200 // TODO(xiyuan): Remove this after M35.
201 DictionaryPrefUpdate
update(local_state_
,
202 prefs::kCachedMultiProfileUserBehavior
);
203 update
->RemoveWithoutPathExpansion(user_email
, NULL
);
205 const std::string behavior
=
206 prefs
->GetString(prefs::kMultiProfileUserBehavior
);
207 SetCachedValue(user_email
, behavior
);
213 } // namespace chromeos