// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/supervised_user/supervised_user_registration_utility.h"

#include "base/base64.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/memory/scoped_ptr.h"
#include "base/prefs/pref_service.h"
#include "base/rand_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/supervised_user/supervised_user_constants.h"
#include "chrome/browser/supervised_user/supervised_user_refresh_token_fetcher.h"
#include "chrome/browser/supervised_user/supervised_user_shared_settings_service.h"
#include "chrome/browser/supervised_user/supervised_user_shared_settings_service_factory.h"
#include "chrome/browser/supervised_user/supervised_user_shared_settings_update.h"
#include "chrome/browser/supervised_user/supervised_user_sync_service.h"
#include "chrome/browser/supervised_user/supervised_user_sync_service_factory.h"
#include "chrome/browser/sync/glue/device_info.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h"
#include "components/signin/core/browser/signin_manager.h"
#include "google_apis/gaia/gaia_urls.h"
#include "google_apis/gaia/google_service_auth_error.h"

using base::DictionaryValue;

namespace {

SupervisedUserRegistrationUtility* g_instance_for_tests = NULL;

// Actual implementation of SupervisedUserRegistrationUtility.
class SupervisedUserRegistrationUtilityImpl
    : public SupervisedUserRegistrationUtility,
      public SupervisedUserSyncServiceObserver {
 public:
  SupervisedUserRegistrationUtilityImpl(
      PrefService* prefs,
      scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher,
      SupervisedUserSyncService* service,
      SupervisedUserSharedSettingsService* shared_settings_service);

  virtual ~SupervisedUserRegistrationUtilityImpl();

  // Registers a new supervised user with the server. |supervised_user_id| is a
  // new unique ID for the new supervised user. If its value is the same as that
  // of one of the existing supervised users, then the same user will be created
  // on this machine (and if he has no avatar in sync, his avatar will be
  // updated). |info| contains necessary information like the display name of
  // the user and his avatar. |callback| is called with the result of the
  // registration. We use the info here and not the profile, because on Chrome
  // OS the profile of the supervised user does not yet exist.
  virtual void Register(const std::string& supervised_user_id,
                        const SupervisedUserRegistrationInfo& info,
                        const RegistrationCallback& callback) OVERRIDE;

  // SupervisedUserSyncServiceObserver:
  virtual void OnSupervisedUserAcknowledged(
      const std::string& supervised_user_id) OVERRIDE;
  virtual void OnSupervisedUsersSyncingStopped() OVERRIDE;
  virtual void OnSupervisedUsersChanged() OVERRIDE;

 private:
  // Fetches the supervised user token when we have the device name.
  void FetchToken(const std::string& client_name);

  // Called when we have received a token for the supervised user.
  void OnReceivedToken(const GoogleServiceAuthError& error,
                       const std::string& token);

  // Dispatches the callback and cleans up if all the conditions have been met.
  void CompleteRegistrationIfReady();

  // Aborts any registration currently in progress. If |run_callback| is true,
  // calls the callback specified in Register() with the given |error|.
  void AbortPendingRegistration(bool run_callback,
                                const GoogleServiceAuthError& error);

  // If |run_callback| is true, dispatches the callback with the saved token
  // (which may be empty) and the given |error|. In any case, resets internal
  // variables to be ready for the next registration.
  void CompleteRegistration(bool run_callback,
                            const GoogleServiceAuthError& error);

  // Cancels any registration currently in progress, without calling the
  // callback or reporting an error.
  void CancelPendingRegistration();

  // SupervisedUserSharedSettingsUpdate acknowledgment callback for password
  // data in shared settings.
  void OnPasswordChangeAcknowledged(bool success);

  PrefService* prefs_;
  scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher_;

  // A |KeyedService| owned by the custodian profile.
  SupervisedUserSyncService* supervised_user_sync_service_;

  // A |KeyedService| owned by the custodian profile.
  SupervisedUserSharedSettingsService* supervised_user_shared_settings_service_;

  std::string pending_supervised_user_id_;
  std::string pending_supervised_user_token_;
  bool pending_supervised_user_acknowledged_;
  bool is_existing_supervised_user_;
  bool avatar_updated_;
  RegistrationCallback callback_;
  scoped_ptr<SupervisedUserSharedSettingsUpdate> password_update_;

  base::WeakPtrFactory<SupervisedUserRegistrationUtilityImpl> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(SupervisedUserRegistrationUtilityImpl);
};

} // namespace

SupervisedUserRegistrationInfo::SupervisedUserRegistrationInfo(
    const base::string16& name,
    int avatar_index)
    : avatar_index(avatar_index),
      name(name) {
}

SupervisedUserRegistrationInfo::~SupervisedUserRegistrationInfo() {}

ScopedTestingSupervisedUserRegistrationUtility::
    ScopedTestingSupervisedUserRegistrationUtility(
        SupervisedUserRegistrationUtility* instance) {
  SupervisedUserRegistrationUtility::SetUtilityForTests(instance);
}

ScopedTestingSupervisedUserRegistrationUtility::
    ~ScopedTestingSupervisedUserRegistrationUtility() {
  SupervisedUserRegistrationUtility::SetUtilityForTests(NULL);
}

// static
scoped_ptr<SupervisedUserRegistrationUtility>
SupervisedUserRegistrationUtility::Create(Profile* profile) {
  if (g_instance_for_tests) {
    SupervisedUserRegistrationUtility* result = g_instance_for_tests;
    g_instance_for_tests = NULL;
    return make_scoped_ptr(result);
  }

  ProfileOAuth2TokenService* token_service =
      ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
  SigninManagerBase* signin_manager =
      SigninManagerFactory::GetForProfile(profile);
  scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher =
      SupervisedUserRefreshTokenFetcher::Create(
          token_service,
          signin_manager->GetAuthenticatedAccountId(),
          profile->GetRequestContext());
  SupervisedUserSyncService* supervised_user_sync_service =
      SupervisedUserSyncServiceFactory::GetForProfile(profile);
  SupervisedUserSharedSettingsService* supervised_user_shared_settings_service =
      SupervisedUserSharedSettingsServiceFactory::GetForBrowserContext(profile);
  return make_scoped_ptr(SupervisedUserRegistrationUtility::CreateImpl(
      profile->GetPrefs(),
      token_fetcher.Pass(),
      supervised_user_sync_service,
      supervised_user_shared_settings_service));
}

// static
std::string SupervisedUserRegistrationUtility::GenerateNewSupervisedUserId() {
  std::string new_supervised_user_id;
  base::Base64Encode(base::RandBytesAsString(8), &new_supervised_user_id);
  return new_supervised_user_id;
}

// static
void SupervisedUserRegistrationUtility::SetUtilityForTests(
    SupervisedUserRegistrationUtility* utility) {
  if (g_instance_for_tests)
    delete g_instance_for_tests;
  g_instance_for_tests = utility;
}

// static
SupervisedUserRegistrationUtility*
SupervisedUserRegistrationUtility::CreateImpl(
      PrefService* prefs,
      scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher,
      SupervisedUserSyncService* service,
      SupervisedUserSharedSettingsService* shared_settings_service) {
  return new SupervisedUserRegistrationUtilityImpl(prefs,
                                                   token_fetcher.Pass(),
                                                   service,
                                                   shared_settings_service);
}

namespace {

SupervisedUserRegistrationUtilityImpl::SupervisedUserRegistrationUtilityImpl(
    PrefService* prefs,
    scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher,
    SupervisedUserSyncService* service,
    SupervisedUserSharedSettingsService* shared_settings_service)
    : prefs_(prefs),
      token_fetcher_(token_fetcher.Pass()),
      supervised_user_sync_service_(service),
      supervised_user_shared_settings_service_(shared_settings_service),
      pending_supervised_user_acknowledged_(false),
      is_existing_supervised_user_(false),
      avatar_updated_(false),
      weak_ptr_factory_(this) {
  supervised_user_sync_service_->AddObserver(this);
}

SupervisedUserRegistrationUtilityImpl::
~SupervisedUserRegistrationUtilityImpl() {
  supervised_user_sync_service_->RemoveObserver(this);
  CancelPendingRegistration();
}

void SupervisedUserRegistrationUtilityImpl::Register(
    const std::string& supervised_user_id,
    const SupervisedUserRegistrationInfo& info,
    const RegistrationCallback& callback) {
  DCHECK(pending_supervised_user_id_.empty());
  callback_ = callback;
  pending_supervised_user_id_ = supervised_user_id;

  bool need_password_update = !info.password_data.empty();
  const base::DictionaryValue* dict =
      prefs_->GetDictionary(prefs::kSupervisedUsers);
  is_existing_supervised_user_ = dict->HasKey(supervised_user_id);
  if (!is_existing_supervised_user_) {
    supervised_user_sync_service_->AddSupervisedUser(
        pending_supervised_user_id_,
        base::UTF16ToUTF8(info.name),
        info.master_key,
        info.password_signature_key,
        info.password_encryption_key,
        info.avatar_index);
  } else {
    const base::DictionaryValue* value = NULL;
    bool success =
        dict->GetDictionaryWithoutPathExpansion(supervised_user_id, &value);
    DCHECK(success);
    std::string key;
    bool need_keys = !info.password_signature_key.empty() ||
                     !info.password_encryption_key.empty();
    bool have_keys =
        value->GetString(SupervisedUserSyncService::kPasswordSignatureKey,
                         &key) &&
        !key.empty() &&
        value->GetString(SupervisedUserSyncService::kPasswordEncryptionKey,
                         &key) &&
        !key.empty();

    bool keys_need_update = need_keys && !have_keys;

    if (keys_need_update) {
      supervised_user_sync_service_->UpdateSupervisedUser(
          pending_supervised_user_id_,
          base::UTF16ToUTF8(info.name),
          info.master_key,
          info.password_signature_key,
          info.password_encryption_key,
          info.avatar_index);
    } else {
      // The user already exists and does not need to be updated.
      need_password_update = false;
      OnSupervisedUserAcknowledged(supervised_user_id);
    }
    avatar_updated_ =
        supervised_user_sync_service_->UpdateSupervisedUserAvatarIfNeeded(
            supervised_user_id,
            info.avatar_index);
  }
#if defined(OS_CHROMEOS)
  const char* kAvatarKey = supervised_users::kChromeOSAvatarIndex;
#else
  const char* kAvatarKey = supervised_users::kChromeAvatarIndex;
#endif
  supervised_user_shared_settings_service_->SetValue(
      pending_supervised_user_id_, kAvatarKey,
      base::FundamentalValue(info.avatar_index));
  if (need_password_update) {
    password_update_.reset(new SupervisedUserSharedSettingsUpdate(
        supervised_user_shared_settings_service_,
        pending_supervised_user_id_,
        supervised_users::kChromeOSPasswordData,
        scoped_ptr<base::Value>(info.password_data.DeepCopy()),
        base::Bind(
            &SupervisedUserRegistrationUtilityImpl::
                OnPasswordChangeAcknowledged,
            weak_ptr_factory_.GetWeakPtr())));
  }

  browser_sync::DeviceInfo::GetClientName(
      base::Bind(&SupervisedUserRegistrationUtilityImpl::FetchToken,
                 weak_ptr_factory_.GetWeakPtr()));
}

void SupervisedUserRegistrationUtilityImpl::CancelPendingRegistration() {
  AbortPendingRegistration(
      false,  // Don't run the callback. The error will be ignored.
      GoogleServiceAuthError(GoogleServiceAuthError::NONE));
}

void SupervisedUserRegistrationUtilityImpl::OnSupervisedUserAcknowledged(
    const std::string& supervised_user_id) {
  DCHECK_EQ(pending_supervised_user_id_, supervised_user_id);
  DCHECK(!pending_supervised_user_acknowledged_);
  pending_supervised_user_acknowledged_ = true;
  CompleteRegistrationIfReady();
}

void SupervisedUserRegistrationUtilityImpl::OnPasswordChangeAcknowledged(
    bool success) {
  DCHECK(password_update_);
  DCHECK(success);
  password_update_.reset();
  CompleteRegistrationIfReady();
}

void SupervisedUserRegistrationUtilityImpl::OnSupervisedUsersSyncingStopped() {
  AbortPendingRegistration(
      true,  // Run the callback.
      GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
}

void SupervisedUserRegistrationUtilityImpl::OnSupervisedUsersChanged() {}

void SupervisedUserRegistrationUtilityImpl::FetchToken(
    const std::string& client_name) {
  token_fetcher_->Start(
      pending_supervised_user_id_, client_name,
      base::Bind(&SupervisedUserRegistrationUtilityImpl::OnReceivedToken,
                 weak_ptr_factory_.GetWeakPtr()));
}

void SupervisedUserRegistrationUtilityImpl::OnReceivedToken(
    const GoogleServiceAuthError& error,
    const std::string& token) {
  if (error.state() != GoogleServiceAuthError::NONE) {
    CompleteRegistration(true, error);
    return;
  }

  DCHECK(!token.empty());
  pending_supervised_user_token_ = token;
  CompleteRegistrationIfReady();
}

void SupervisedUserRegistrationUtilityImpl::CompleteRegistrationIfReady() {
  bool skip_check = CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kNoSupervisedUserAcknowledgmentCheck);

  if (!pending_supervised_user_acknowledged_ && !skip_check)
    return;
  if (password_update_ && !skip_check)
    return;
  if (pending_supervised_user_token_.empty())
    return;

  GoogleServiceAuthError error(GoogleServiceAuthError::NONE);
  CompleteRegistration(true, error);
}

void SupervisedUserRegistrationUtilityImpl::AbortPendingRegistration(
    bool run_callback,
    const GoogleServiceAuthError& error) {
  pending_supervised_user_token_.clear();
  CompleteRegistration(run_callback, error);
}

void SupervisedUserRegistrationUtilityImpl::CompleteRegistration(
    bool run_callback,
    const GoogleServiceAuthError& error) {
  if (callback_.is_null())
    return;

  if (pending_supervised_user_token_.empty()) {
    DCHECK(!pending_supervised_user_id_.empty());

    if (!is_existing_supervised_user_) {
      // Remove the pending supervised user if we weren't successful.
      // However, check that we are not importing a supervised user
      // before deleting it from sync to avoid accidental deletion of
      // existing supervised users by just canceling the registration for
      // example.
      supervised_user_sync_service_->DeleteSupervisedUser(
          pending_supervised_user_id_);
    } else if (avatar_updated_) {
      // Canceling (or failing) a supervised user import that did set the avatar
      // should undo this change.
      supervised_user_sync_service_->ClearSupervisedUserAvatar(
          pending_supervised_user_id_);
    }
  }

  if (run_callback)
    callback_.Run(error, pending_supervised_user_token_);
  callback_.Reset();
}

} // namespace
