Home | History | Annotate | Download | only in supervised_user
      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/supervised_user/supervised_user_registration_utility.h"
      6 
      7 #include "base/base64.h"
      8 #include "base/bind.h"
      9 #include "base/command_line.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "base/prefs/pref_service.h"
     12 #include "base/rand_util.h"
     13 #include "base/strings/utf_string_conversions.h"
     14 #include "chrome/browser/profiles/profile.h"
     15 #include "chrome/browser/signin/chrome_signin_client_factory.h"
     16 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
     17 #include "chrome/browser/signin/signin_manager_factory.h"
     18 #include "chrome/browser/supervised_user/supervised_user_constants.h"
     19 #include "chrome/browser/supervised_user/supervised_user_refresh_token_fetcher.h"
     20 #include "chrome/browser/supervised_user/supervised_user_shared_settings_service.h"
     21 #include "chrome/browser/supervised_user/supervised_user_shared_settings_service_factory.h"
     22 #include "chrome/browser/supervised_user/supervised_user_shared_settings_update.h"
     23 #include "chrome/browser/supervised_user/supervised_user_sync_service.h"
     24 #include "chrome/browser/supervised_user/supervised_user_sync_service_factory.h"
     25 #include "chrome/common/chrome_switches.h"
     26 #include "chrome/common/pref_names.h"
     27 #include "components/signin/core/browser/profile_oauth2_token_service.h"
     28 #include "components/signin/core/browser/signin_client.h"
     29 #include "components/signin/core/browser/signin_manager.h"
     30 #include "content/public/browser/browser_thread.h"
     31 #include "google_apis/gaia/gaia_urls.h"
     32 #include "google_apis/gaia/google_service_auth_error.h"
     33 #include "sync/util/get_session_name.h"
     34 
     35 using base::DictionaryValue;
     36 
     37 namespace {
     38 
     39 SupervisedUserRegistrationUtility* g_instance_for_tests = NULL;
     40 
     41 // Actual implementation of SupervisedUserRegistrationUtility.
     42 class SupervisedUserRegistrationUtilityImpl
     43     : public SupervisedUserRegistrationUtility,
     44       public SupervisedUserSyncServiceObserver {
     45  public:
     46   SupervisedUserRegistrationUtilityImpl(
     47       PrefService* prefs,
     48       scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher,
     49       SupervisedUserSyncService* service,
     50       SupervisedUserSharedSettingsService* shared_settings_service);
     51 
     52   virtual ~SupervisedUserRegistrationUtilityImpl();
     53 
     54   // Registers a new supervised user with the server. |supervised_user_id| is a
     55   // new unique ID for the new supervised user. If its value is the same as that
     56   // of one of the existing supervised users, then the same user will be created
     57   // on this machine (and if he has no avatar in sync, his avatar will be
     58   // updated). |info| contains necessary information like the display name of
     59   // the user and his avatar. |callback| is called with the result of the
     60   // registration. We use the info here and not the profile, because on Chrome
     61   // OS the profile of the supervised user does not yet exist.
     62   virtual void Register(const std::string& supervised_user_id,
     63                         const SupervisedUserRegistrationInfo& info,
     64                         const RegistrationCallback& callback) OVERRIDE;
     65 
     66   // SupervisedUserSyncServiceObserver:
     67   virtual void OnSupervisedUserAcknowledged(
     68       const std::string& supervised_user_id) OVERRIDE;
     69   virtual void OnSupervisedUsersSyncingStopped() OVERRIDE;
     70   virtual void OnSupervisedUsersChanged() OVERRIDE;
     71 
     72  private:
     73   // Fetches the supervised user token when we have the device name.
     74   void FetchToken(const std::string& client_name);
     75 
     76   // Called when we have received a token for the supervised user.
     77   void OnReceivedToken(const GoogleServiceAuthError& error,
     78                        const std::string& token);
     79 
     80   // Dispatches the callback and cleans up if all the conditions have been met.
     81   void CompleteRegistrationIfReady();
     82 
     83   // Aborts any registration currently in progress. If |run_callback| is true,
     84   // calls the callback specified in Register() with the given |error|.
     85   void AbortPendingRegistration(bool run_callback,
     86                                 const GoogleServiceAuthError& error);
     87 
     88   // If |run_callback| is true, dispatches the callback with the saved token
     89   // (which may be empty) and the given |error|. In any case, resets internal
     90   // variables to be ready for the next registration.
     91   void CompleteRegistration(bool run_callback,
     92                             const GoogleServiceAuthError& error);
     93 
     94   // Cancels any registration currently in progress, without calling the
     95   // callback or reporting an error.
     96   void CancelPendingRegistration();
     97 
     98   // SupervisedUserSharedSettingsUpdate acknowledgment callback for password
     99   // data in shared settings.
    100   void OnPasswordChangeAcknowledged(bool success);
    101 
    102   PrefService* prefs_;
    103   scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher_;
    104 
    105   // A |KeyedService| owned by the custodian profile.
    106   SupervisedUserSyncService* supervised_user_sync_service_;
    107 
    108   // A |KeyedService| owned by the custodian profile.
    109   SupervisedUserSharedSettingsService* supervised_user_shared_settings_service_;
    110 
    111   std::string pending_supervised_user_id_;
    112   std::string pending_supervised_user_token_;
    113   bool pending_supervised_user_acknowledged_;
    114   bool is_existing_supervised_user_;
    115   bool avatar_updated_;
    116   RegistrationCallback callback_;
    117   scoped_ptr<SupervisedUserSharedSettingsUpdate> password_update_;
    118 
    119   base::WeakPtrFactory<SupervisedUserRegistrationUtilityImpl> weak_ptr_factory_;
    120 
    121   DISALLOW_COPY_AND_ASSIGN(SupervisedUserRegistrationUtilityImpl);
    122 };
    123 
    124 } // namespace
    125 
    126 SupervisedUserRegistrationInfo::SupervisedUserRegistrationInfo(
    127     const base::string16& name,
    128     int avatar_index)
    129     : avatar_index(avatar_index),
    130       name(name) {
    131 }
    132 
    133 SupervisedUserRegistrationInfo::~SupervisedUserRegistrationInfo() {}
    134 
    135 ScopedTestingSupervisedUserRegistrationUtility::
    136     ScopedTestingSupervisedUserRegistrationUtility(
    137         SupervisedUserRegistrationUtility* instance) {
    138   SupervisedUserRegistrationUtility::SetUtilityForTests(instance);
    139 }
    140 
    141 ScopedTestingSupervisedUserRegistrationUtility::
    142     ~ScopedTestingSupervisedUserRegistrationUtility() {
    143   SupervisedUserRegistrationUtility::SetUtilityForTests(NULL);
    144 }
    145 
    146 // static
    147 scoped_ptr<SupervisedUserRegistrationUtility>
    148 SupervisedUserRegistrationUtility::Create(Profile* profile) {
    149   if (g_instance_for_tests) {
    150     SupervisedUserRegistrationUtility* result = g_instance_for_tests;
    151     g_instance_for_tests = NULL;
    152     return make_scoped_ptr(result);
    153   }
    154 
    155   ProfileOAuth2TokenService* token_service =
    156       ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
    157   SigninManagerBase* signin_manager =
    158       SigninManagerFactory::GetForProfile(profile);
    159   SigninClient* signin_client =
    160       ChromeSigninClientFactory::GetForProfile(profile);
    161   std::string signin_scoped_device_id =
    162       signin_client->GetSigninScopedDeviceId();
    163   scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher =
    164       SupervisedUserRefreshTokenFetcher::Create(
    165           token_service,
    166           signin_manager->GetAuthenticatedAccountId(),
    167           signin_scoped_device_id,
    168           profile->GetRequestContext());
    169   SupervisedUserSyncService* supervised_user_sync_service =
    170       SupervisedUserSyncServiceFactory::GetForProfile(profile);
    171   SupervisedUserSharedSettingsService* supervised_user_shared_settings_service =
    172       SupervisedUserSharedSettingsServiceFactory::GetForBrowserContext(profile);
    173   return make_scoped_ptr(SupervisedUserRegistrationUtility::CreateImpl(
    174       profile->GetPrefs(),
    175       token_fetcher.Pass(),
    176       supervised_user_sync_service,
    177       supervised_user_shared_settings_service));
    178 }
    179 
    180 // static
    181 std::string SupervisedUserRegistrationUtility::GenerateNewSupervisedUserId() {
    182   std::string new_supervised_user_id;
    183   base::Base64Encode(base::RandBytesAsString(8), &new_supervised_user_id);
    184   return new_supervised_user_id;
    185 }
    186 
    187 // static
    188 void SupervisedUserRegistrationUtility::SetUtilityForTests(
    189     SupervisedUserRegistrationUtility* utility) {
    190   if (g_instance_for_tests)
    191     delete g_instance_for_tests;
    192   g_instance_for_tests = utility;
    193 }
    194 
    195 // static
    196 SupervisedUserRegistrationUtility*
    197 SupervisedUserRegistrationUtility::CreateImpl(
    198       PrefService* prefs,
    199       scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher,
    200       SupervisedUserSyncService* service,
    201       SupervisedUserSharedSettingsService* shared_settings_service) {
    202   return new SupervisedUserRegistrationUtilityImpl(prefs,
    203                                                    token_fetcher.Pass(),
    204                                                    service,
    205                                                    shared_settings_service);
    206 }
    207 
    208 namespace {
    209 
    210 SupervisedUserRegistrationUtilityImpl::SupervisedUserRegistrationUtilityImpl(
    211     PrefService* prefs,
    212     scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher,
    213     SupervisedUserSyncService* service,
    214     SupervisedUserSharedSettingsService* shared_settings_service)
    215     : prefs_(prefs),
    216       token_fetcher_(token_fetcher.Pass()),
    217       supervised_user_sync_service_(service),
    218       supervised_user_shared_settings_service_(shared_settings_service),
    219       pending_supervised_user_acknowledged_(false),
    220       is_existing_supervised_user_(false),
    221       avatar_updated_(false),
    222       weak_ptr_factory_(this) {
    223   supervised_user_sync_service_->AddObserver(this);
    224 }
    225 
    226 SupervisedUserRegistrationUtilityImpl::
    227 ~SupervisedUserRegistrationUtilityImpl() {
    228   supervised_user_sync_service_->RemoveObserver(this);
    229   CancelPendingRegistration();
    230 }
    231 
    232 void SupervisedUserRegistrationUtilityImpl::Register(
    233     const std::string& supervised_user_id,
    234     const SupervisedUserRegistrationInfo& info,
    235     const RegistrationCallback& callback) {
    236   DCHECK(pending_supervised_user_id_.empty());
    237   callback_ = callback;
    238   pending_supervised_user_id_ = supervised_user_id;
    239 
    240   bool need_password_update = !info.password_data.empty();
    241   const base::DictionaryValue* dict =
    242       prefs_->GetDictionary(prefs::kSupervisedUsers);
    243   is_existing_supervised_user_ = dict->HasKey(supervised_user_id);
    244   if (!is_existing_supervised_user_) {
    245     supervised_user_sync_service_->AddSupervisedUser(
    246         pending_supervised_user_id_,
    247         base::UTF16ToUTF8(info.name),
    248         info.master_key,
    249         info.password_signature_key,
    250         info.password_encryption_key,
    251         info.avatar_index);
    252   } else {
    253     const base::DictionaryValue* value = NULL;
    254     bool success =
    255         dict->GetDictionaryWithoutPathExpansion(supervised_user_id, &value);
    256     DCHECK(success);
    257     std::string key;
    258     bool need_keys = !info.password_signature_key.empty() ||
    259                      !info.password_encryption_key.empty();
    260     bool have_keys =
    261         value->GetString(SupervisedUserSyncService::kPasswordSignatureKey,
    262                          &key) &&
    263         !key.empty() &&
    264         value->GetString(SupervisedUserSyncService::kPasswordEncryptionKey,
    265                          &key) &&
    266         !key.empty();
    267 
    268     bool keys_need_update = need_keys && !have_keys;
    269 
    270     if (keys_need_update) {
    271       supervised_user_sync_service_->UpdateSupervisedUser(
    272           pending_supervised_user_id_,
    273           base::UTF16ToUTF8(info.name),
    274           info.master_key,
    275           info.password_signature_key,
    276           info.password_encryption_key,
    277           info.avatar_index);
    278     } else {
    279       // The user already exists and does not need to be updated.
    280       need_password_update = false;
    281       OnSupervisedUserAcknowledged(supervised_user_id);
    282     }
    283     avatar_updated_ =
    284         supervised_user_sync_service_->UpdateSupervisedUserAvatarIfNeeded(
    285             supervised_user_id,
    286             info.avatar_index);
    287   }
    288 #if defined(OS_CHROMEOS)
    289   const char* kAvatarKey = supervised_users::kChromeOSAvatarIndex;
    290 #else
    291   const char* kAvatarKey = supervised_users::kChromeAvatarIndex;
    292 #endif
    293   supervised_user_shared_settings_service_->SetValue(
    294       pending_supervised_user_id_, kAvatarKey,
    295       base::FundamentalValue(info.avatar_index));
    296   if (need_password_update) {
    297     password_update_.reset(new SupervisedUserSharedSettingsUpdate(
    298         supervised_user_shared_settings_service_,
    299         pending_supervised_user_id_,
    300         supervised_users::kChromeOSPasswordData,
    301         scoped_ptr<base::Value>(info.password_data.DeepCopy()),
    302         base::Bind(
    303             &SupervisedUserRegistrationUtilityImpl::
    304                 OnPasswordChangeAcknowledged,
    305             weak_ptr_factory_.GetWeakPtr())));
    306   }
    307 
    308   syncer::GetSessionName(
    309       content::BrowserThread::GetBlockingPool(),
    310       base::Bind(&SupervisedUserRegistrationUtilityImpl::FetchToken,
    311                  weak_ptr_factory_.GetWeakPtr()));
    312 }
    313 
    314 void SupervisedUserRegistrationUtilityImpl::CancelPendingRegistration() {
    315   AbortPendingRegistration(
    316       false,  // Don't run the callback. The error will be ignored.
    317       GoogleServiceAuthError(GoogleServiceAuthError::NONE));
    318 }
    319 
    320 void SupervisedUserRegistrationUtilityImpl::OnSupervisedUserAcknowledged(
    321     const std::string& supervised_user_id) {
    322   DCHECK_EQ(pending_supervised_user_id_, supervised_user_id);
    323   DCHECK(!pending_supervised_user_acknowledged_);
    324   pending_supervised_user_acknowledged_ = true;
    325   CompleteRegistrationIfReady();
    326 }
    327 
    328 void SupervisedUserRegistrationUtilityImpl::OnPasswordChangeAcknowledged(
    329     bool success) {
    330   DCHECK(password_update_);
    331   DCHECK(success);
    332   password_update_.reset();
    333   CompleteRegistrationIfReady();
    334 }
    335 
    336 void SupervisedUserRegistrationUtilityImpl::OnSupervisedUsersSyncingStopped() {
    337   AbortPendingRegistration(
    338       true,  // Run the callback.
    339       GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
    340 }
    341 
    342 void SupervisedUserRegistrationUtilityImpl::OnSupervisedUsersChanged() {}
    343 
    344 void SupervisedUserRegistrationUtilityImpl::FetchToken(
    345     const std::string& client_name) {
    346   token_fetcher_->Start(
    347       pending_supervised_user_id_, client_name,
    348       base::Bind(&SupervisedUserRegistrationUtilityImpl::OnReceivedToken,
    349                  weak_ptr_factory_.GetWeakPtr()));
    350 }
    351 
    352 void SupervisedUserRegistrationUtilityImpl::OnReceivedToken(
    353     const GoogleServiceAuthError& error,
    354     const std::string& token) {
    355   if (error.state() != GoogleServiceAuthError::NONE) {
    356     CompleteRegistration(true, error);
    357     return;
    358   }
    359 
    360   DCHECK(!token.empty());
    361   pending_supervised_user_token_ = token;
    362   CompleteRegistrationIfReady();
    363 }
    364 
    365 void SupervisedUserRegistrationUtilityImpl::CompleteRegistrationIfReady() {
    366   bool skip_check = CommandLine::ForCurrentProcess()->HasSwitch(
    367       switches::kNoSupervisedUserAcknowledgmentCheck);
    368 
    369   if (!pending_supervised_user_acknowledged_ && !skip_check)
    370     return;
    371   if (password_update_ && !skip_check)
    372     return;
    373   if (pending_supervised_user_token_.empty())
    374     return;
    375 
    376   GoogleServiceAuthError error(GoogleServiceAuthError::NONE);
    377   CompleteRegistration(true, error);
    378 }
    379 
    380 void SupervisedUserRegistrationUtilityImpl::AbortPendingRegistration(
    381     bool run_callback,
    382     const GoogleServiceAuthError& error) {
    383   pending_supervised_user_token_.clear();
    384   CompleteRegistration(run_callback, error);
    385 }
    386 
    387 void SupervisedUserRegistrationUtilityImpl::CompleteRegistration(
    388     bool run_callback,
    389     const GoogleServiceAuthError& error) {
    390   if (callback_.is_null())
    391     return;
    392 
    393   if (pending_supervised_user_token_.empty()) {
    394     DCHECK(!pending_supervised_user_id_.empty());
    395 
    396     if (!is_existing_supervised_user_) {
    397       // Remove the pending supervised user if we weren't successful.
    398       // However, check that we are not importing a supervised user
    399       // before deleting it from sync to avoid accidental deletion of
    400       // existing supervised users by just canceling the registration for
    401       // example.
    402       supervised_user_sync_service_->DeleteSupervisedUser(
    403           pending_supervised_user_id_);
    404     } else if (avatar_updated_) {
    405       // Canceling (or failing) a supervised user import that did set the avatar
    406       // should undo this change.
    407       supervised_user_sync_service_->ClearSupervisedUserAvatar(
    408           pending_supervised_user_id_);
    409     }
    410   }
    411 
    412   if (run_callback)
    413     callback_.Run(error, pending_supervised_user_token_);
    414   callback_.Reset();
    415 }
    416 
    417 } // namespace
    418