Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / chromeos / login / users / multi_profile_user_controller.cc
blob8b0a90fafda1deea091f672c8422265b32c095b3
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"
7 #include "base/bind.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/profiles/profile.h"
18 #include "chrome/common/pref_names.h"
19 #include "components/syncable_prefs/pref_service_syncable.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"
24 namespace chromeos {
26 namespace {
28 std::string SanitizeBehaviorValue(const std::string& value) {
29 if (value == MultiProfileUserController::kBehaviorUnrestricted ||
30 value == MultiProfileUserController::kBehaviorPrimaryOnly ||
31 value == MultiProfileUserController::kBehaviorNotAllowed) {
32 return value;
35 return std::string(MultiProfileUserController::kBehaviorUnrestricted);
38 bool SetUserAllowedReason(
39 MultiProfileUserController::UserAllowedInSessionReason* reason,
40 MultiProfileUserController::UserAllowedInSessionReason value) {
41 if (reason)
42 *reason = value;
43 return value == MultiProfileUserController::ALLOWED;
46 } // namespace
48 // static
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[] =
56 "owner-primary-only";
58 MultiProfileUserController::MultiProfileUserController(
59 MultiProfileUserControllerDelegate* delegate,
60 PrefService* local_state)
61 : delegate_(delegate),
62 local_state_(local_state) {
65 MultiProfileUserController::~MultiProfileUserController() {}
67 // static
68 void MultiProfileUserController::RegisterPrefs(
69 PrefRegistrySimple* registry) {
70 registry->RegisterDictionaryPref(prefs::kCachedMultiProfileUserBehavior);
73 // static
74 void MultiProfileUserController::RegisterProfilePrefs(
75 user_prefs::PrefRegistrySyncable* registry) {
76 registry->RegisterStringPref(prefs::kMultiProfileUserBehavior,
77 kBehaviorUnrestricted);
78 registry->RegisterBooleanPref(
79 prefs::kMultiProfileNeverShowIntro,
80 false,
81 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
82 registry->RegisterBooleanPref(
83 prefs::kMultiProfileWarningShowDismissed,
84 false,
85 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
88 // static
89 MultiProfileUserController::UserAllowedInSessionReason
90 MultiProfileUserController::GetPrimaryUserPolicy() {
91 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
92 CHECK(user_manager);
94 const user_manager::User* user = user_manager->GetPrimaryUser();
95 if (!user)
96 return ALLOWED;
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);
107 if (!profile)
108 return ALLOWED;
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;
124 return ALLOWED;
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();
131 CHECK(user_manager);
133 const user_manager::User* primary_user = user_manager->GetPrimaryUser();
134 std::string primary_user_email;
135 if (primary_user)
136 primary_user_email = primary_user->email();
138 // Always allow if there is no primary user or user being checked is the
139 // primary user.
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(
155 reason,
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())
162 return;
164 scoped_ptr<PrefChangeRegistrar> registrar(new PrefChangeRegistrar);
165 registrar->Init(user_profile->GetPrefs());
166 registrar->Add(
167 prefs::kMultiProfileUserBehavior,
168 base::Bind(&MultiProfileUserController::OnUserPrefChanged,
169 base::Unretained(this),
170 user_profile));
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);
188 std::string value;
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();
208 it != users.end();
209 ++it) {
210 if (!IsUserAllowedInSession((*it)->email(), NULL)) {
211 delegate_->OnUserNotAllowed((*it)->email());
212 return;
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);
231 } else {
232 const std::string behavior =
233 prefs->GetString(prefs::kMultiProfileUserBehavior);
234 SetCachedValue(user_email, behavior);
237 CheckSessionUsers();
240 } // namespace chromeos