• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h"
6 
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/login/users/user.h"
15 #include "chrome/browser/chromeos/login/users/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"
22 
23 namespace chromeos {
24 
25 namespace {
26 
SanitizeBehaviorValue(const std::string & value)27 std::string SanitizeBehaviorValue(const std::string& value) {
28   if (value == MultiProfileUserController::kBehaviorUnrestricted ||
29       value == MultiProfileUserController::kBehaviorPrimaryOnly ||
30       value == MultiProfileUserController::kBehaviorNotAllowed ||
31       value == MultiProfileUserController::kBehaviorOwnerPrimaryOnly) {
32     return value;
33   }
34 
35   return std::string(MultiProfileUserController::kBehaviorUnrestricted);
36 }
37 
38 }  // namespace
39 
40 // static
41 const char MultiProfileUserController::kBehaviorUnrestricted[] = "unrestricted";
42 const char MultiProfileUserController::kBehaviorPrimaryOnly[] = "primary-only";
43 const char MultiProfileUserController::kBehaviorNotAllowed[] = "not-allowed";
44 
45 // Note: this policy value is not a real one an is only returned locally for
46 // owner users instead of default one kBehaviorUnrestricted.
47 const char MultiProfileUserController::kBehaviorOwnerPrimaryOnly[] =
48     "owner-primary-only";
49 
MultiProfileUserController(MultiProfileUserControllerDelegate * delegate,PrefService * local_state)50 MultiProfileUserController::MultiProfileUserController(
51     MultiProfileUserControllerDelegate* delegate,
52     PrefService* local_state)
53     : delegate_(delegate),
54       local_state_(local_state) {
55 }
56 
~MultiProfileUserController()57 MultiProfileUserController::~MultiProfileUserController() {}
58 
59 // static
RegisterPrefs(PrefRegistrySimple * registry)60 void MultiProfileUserController::RegisterPrefs(
61     PrefRegistrySimple* registry) {
62   registry->RegisterDictionaryPref(prefs::kCachedMultiProfileUserBehavior);
63 }
64 
65 // static
RegisterProfilePrefs(user_prefs::PrefRegistrySyncable * registry)66 void MultiProfileUserController::RegisterProfilePrefs(
67     user_prefs::PrefRegistrySyncable* registry) {
68   registry->RegisterStringPref(
69       prefs::kMultiProfileUserBehavior,
70       kBehaviorUnrestricted,
71       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
72   registry->RegisterBooleanPref(
73       prefs::kMultiProfileNeverShowIntro,
74       false,
75       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
76   registry->RegisterBooleanPref(
77       prefs::kMultiProfileWarningShowDismissed,
78       false,
79       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
80 }
81 
82 MultiProfileUserController::UserAllowedInSessionResult
IsUserAllowedInSession(const std::string & user_email) const83 MultiProfileUserController::IsUserAllowedInSession(
84     const std::string& user_email) const {
85   UserManager* user_manager = UserManager::Get();
86   CHECK(user_manager);
87 
88   const User* primary_user = user_manager->GetPrimaryUser();
89   std::string primary_user_email;
90   if (primary_user)
91     primary_user_email = primary_user->email();
92 
93   // Always allow if there is no primary user or user being checked is the
94   // primary user.
95   if (primary_user_email.empty() || primary_user_email == user_email)
96     return ALLOWED;
97 
98   // Owner is not allowed to be secondary user.
99   if (user_manager->GetOwnerEmail() == user_email)
100     return NOT_ALLOWED_OWNER_AS_SECONDARY;
101 
102   // Don't allow profiles potentially tainted by data fetched with policy-pushed
103   // certificates to join a multiprofile session.
104   if (policy::PolicyCertServiceFactory::UsedPolicyCertificates(user_email))
105     return NOT_ALLOWED_POLICY_CERT_TAINTED;
106 
107   // Don't allow any secondary profiles if the primary profile is tainted.
108   if (policy::PolicyCertServiceFactory::UsedPolicyCertificates(
109           primary_user_email)) {
110     // Check directly in local_state before checking if the primary user has
111     // a PolicyCertService. His profile may have been tainted previously though
112     // he didn't get a PolicyCertService created for this session.
113     return NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED;
114   }
115 
116   // If the primary profile already has policy certificates installed but hasn't
117   // used them yet then it can become tainted at any time during this session;
118   // disable secondary profiles in this case too.
119   Profile* primary_user_profile =
120       primary_user ? user_manager->GetProfileByUser(primary_user) : NULL;
121   policy::PolicyCertService* service =
122       primary_user_profile ? policy::PolicyCertServiceFactory::GetForProfile(
123                                  primary_user_profile)
124                            : NULL;
125   if (service && service->has_policy_certificates())
126     return NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED;
127 
128   // No user is allowed if the primary user policy forbids it.
129   const std::string primary_user_behavior =
130       primary_user_profile->GetPrefs()->GetString(
131           prefs::kMultiProfileUserBehavior);
132   if (primary_user_behavior == kBehaviorNotAllowed)
133     return NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS;
134 
135   // The user must have 'unrestricted' policy to be a secondary user.
136   const std::string behavior = GetCachedValue(user_email);
137   return behavior == kBehaviorUnrestricted ? ALLOWED :
138                                              NOT_ALLOWED_POLICY_FORBIDS;
139 }
140 
StartObserving(Profile * user_profile)141 void MultiProfileUserController::StartObserving(Profile* user_profile) {
142   // Profile name could be empty during tests.
143   if (user_profile->GetProfileName().empty())
144     return;
145 
146   scoped_ptr<PrefChangeRegistrar> registrar(new PrefChangeRegistrar);
147   registrar->Init(user_profile->GetPrefs());
148   registrar->Add(
149       prefs::kMultiProfileUserBehavior,
150       base::Bind(&MultiProfileUserController::OnUserPrefChanged,
151                  base::Unretained(this),
152                  user_profile));
153   pref_watchers_.push_back(registrar.release());
154 
155   OnUserPrefChanged(user_profile);
156 }
157 
RemoveCachedValues(const std::string & user_email)158 void MultiProfileUserController::RemoveCachedValues(
159     const std::string& user_email) {
160   DictionaryPrefUpdate update(local_state_,
161                               prefs::kCachedMultiProfileUserBehavior);
162   update->RemoveWithoutPathExpansion(user_email, NULL);
163   policy::PolicyCertServiceFactory::ClearUsedPolicyCertificates(user_email);
164 }
165 
GetCachedValue(const std::string & user_email) const166 std::string MultiProfileUserController::GetCachedValue(
167     const std::string& user_email) const {
168   const base::DictionaryValue* dict =
169       local_state_->GetDictionary(prefs::kCachedMultiProfileUserBehavior);
170   std::string value;
171   if (dict && dict->GetStringWithoutPathExpansion(user_email, &value))
172     return SanitizeBehaviorValue(value);
173 
174   // Owner is not allowed to be secondary user (see http://crbug.com/385034).
175   if (UserManager::Get()->GetOwnerEmail() == user_email)
176     return std::string(kBehaviorOwnerPrimaryOnly);
177 
178   return std::string(kBehaviorUnrestricted);
179 }
180 
SetCachedValue(const std::string & user_email,const std::string & behavior)181 void MultiProfileUserController::SetCachedValue(
182     const std::string& user_email,
183     const std::string& behavior) {
184   DictionaryPrefUpdate update(local_state_,
185                               prefs::kCachedMultiProfileUserBehavior);
186   update->SetStringWithoutPathExpansion(user_email,
187                                         SanitizeBehaviorValue(behavior));
188 }
189 
CheckSessionUsers()190 void MultiProfileUserController::CheckSessionUsers() {
191   const UserList& users = UserManager::Get()->GetLoggedInUsers();
192   for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
193     if (IsUserAllowedInSession((*it)->email()) != ALLOWED) {
194       delegate_->OnUserNotAllowed((*it)->email());
195       return;
196     }
197   }
198 }
199 
OnUserPrefChanged(Profile * user_profile)200 void MultiProfileUserController::OnUserPrefChanged(
201     Profile* user_profile) {
202   std::string user_email = user_profile->GetProfileName();
203   CHECK(!user_email.empty());
204   user_email = gaia::CanonicalizeEmail(user_email);
205 
206   PrefService* prefs = user_profile->GetPrefs();
207   if (prefs->FindPreference(prefs::kMultiProfileUserBehavior)
208           ->IsDefaultValue()) {
209     // Migration code to clear cached default behavior.
210     // TODO(xiyuan): Remove this after M35.
211     DictionaryPrefUpdate update(local_state_,
212                                 prefs::kCachedMultiProfileUserBehavior);
213     update->RemoveWithoutPathExpansion(user_email, NULL);
214   } else {
215     const std::string behavior =
216         prefs->GetString(prefs::kMultiProfileUserBehavior);
217     SetCachedValue(user_email, behavior);
218   }
219 
220   CheckSessionUsers();
221 }
222 
223 }  // namespace chromeos
224