Home | History | Annotate | Download | only in users
      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 
     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 
     50 MultiProfileUserController::MultiProfileUserController(
     51     MultiProfileUserControllerDelegate* delegate,
     52     PrefService* local_state)
     53     : delegate_(delegate),
     54       local_state_(local_state) {
     55 }
     56 
     57 MultiProfileUserController::~MultiProfileUserController() {}
     58 
     59 // static
     60 void MultiProfileUserController::RegisterPrefs(
     61     PrefRegistrySimple* registry) {
     62   registry->RegisterDictionaryPref(prefs::kCachedMultiProfileUserBehavior);
     63 }
     64 
     65 // static
     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
     83 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 
    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 
    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 
    166 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 
    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 
    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 
    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