// Copyright (c) 2012 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 "chromeos/cryptohome/async_method_caller.h"

#include "base/bind.h"
#include "base/containers/hash_tables.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chromeos/cryptohome/cryptohome_parameters.h"
#include "chromeos/dbus/dbus_thread_manager.h"

using chromeos::DBusThreadManager;

namespace cryptohome {

namespace {

AsyncMethodCaller* g_async_method_caller = NULL;

// The implementation of AsyncMethodCaller
class AsyncMethodCallerImpl : public AsyncMethodCaller {
 public:
  AsyncMethodCallerImpl() : weak_ptr_factory_(this) {
    DBusThreadManager::Get()->GetCryptohomeClient()->SetAsyncCallStatusHandlers(
        base::Bind(&AsyncMethodCallerImpl::HandleAsyncResponse,
                   weak_ptr_factory_.GetWeakPtr()),
        base::Bind(&AsyncMethodCallerImpl::HandleAsyncDataResponse,
                   weak_ptr_factory_.GetWeakPtr()));
  }

  ~AsyncMethodCallerImpl() override {
    DBusThreadManager::Get()->GetCryptohomeClient()->
        ResetAsyncCallStatusHandlers();
  }

  void AsyncCheckKey(const Identification& cryptohome_id,
                     const std::string& passhash,
                     Callback callback) override {
    DBusThreadManager::Get()->GetCryptohomeClient()->AsyncCheckKey(
        cryptohome_id, passhash,
        base::Bind(&AsyncMethodCallerImpl::RegisterAsyncCallback,
                   weak_ptr_factory_.GetWeakPtr(), callback,
                   "Couldn't initiate async check of user's key."));
  }

  void AsyncMigrateKey(const Identification& cryptohome_id,
                       const std::string& old_hash,
                       const std::string& new_hash,
                       Callback callback) override {
    DBusThreadManager::Get()->GetCryptohomeClient()->AsyncMigrateKey(
        cryptohome_id, old_hash, new_hash,
        base::Bind(&AsyncMethodCallerImpl::RegisterAsyncCallback,
                   weak_ptr_factory_.GetWeakPtr(), callback,
                   "Couldn't initiate aync migration of user's key"));
  }

  void AsyncMount(const Identification& cryptohome_id,
                  const std::string& passhash,
                  int flags,
                  Callback callback) override {
    DBusThreadManager::Get()->GetCryptohomeClient()->AsyncMount(
        cryptohome_id, passhash, flags,
        base::Bind(&AsyncMethodCallerImpl::RegisterAsyncCallback,
                   weak_ptr_factory_.GetWeakPtr(), callback,
                   "Couldn't initiate async mount of cryptohome."));
  }

  void AsyncAddKey(const Identification& cryptohome_id,
                   const std::string& passhash,
                   const std::string& new_passhash,
                   Callback callback) override {
    DBusThreadManager::Get()->GetCryptohomeClient()->AsyncAddKey(
        cryptohome_id, passhash, new_passhash,
        base::Bind(&AsyncMethodCallerImpl::RegisterAsyncCallback,
                   weak_ptr_factory_.GetWeakPtr(), callback,
                   "Couldn't initiate async key addition."));
  }

  void AsyncMountGuest(Callback callback) override {
    DBusThreadManager::Get()->GetCryptohomeClient()->
        AsyncMountGuest(base::Bind(
            &AsyncMethodCallerImpl::RegisterAsyncCallback,
            weak_ptr_factory_.GetWeakPtr(),
            callback,
            "Couldn't initiate async mount of cryptohome."));
  }

  void AsyncMountPublic(const Identification& public_mount_id,
                        int flags,
                        Callback callback) override {
    DBusThreadManager::Get()->GetCryptohomeClient()->AsyncMountPublic(
        public_mount_id, flags,
        base::Bind(&AsyncMethodCallerImpl::RegisterAsyncCallback,
                   weak_ptr_factory_.GetWeakPtr(), callback,
                   "Couldn't initiate async mount public of cryptohome."));
  }

  void AsyncRemove(const Identification& cryptohome_id,
                   Callback callback) override {
    DBusThreadManager::Get()->GetCryptohomeClient()->AsyncRemove(
        cryptohome_id,
        base::Bind(&AsyncMethodCallerImpl::RegisterAsyncCallback,
                   weak_ptr_factory_.GetWeakPtr(), callback,
                   "Couldn't initiate async removal of cryptohome."));
  }

  void AsyncTpmAttestationCreateEnrollRequest(
      chromeos::attestation::PrivacyCAType pca_type,
      const DataCallback& callback) override {
    DBusThreadManager::Get()->GetCryptohomeClient()->
        AsyncTpmAttestationCreateEnrollRequest(pca_type, base::Bind(
            &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
            weak_ptr_factory_.GetWeakPtr(),
            callback,
            "Couldn't initiate async attestation enroll request."));
  }

  void AsyncTpmAttestationEnroll(chromeos::attestation::PrivacyCAType pca_type,
                                 const std::string& pca_response,
                                 const Callback& callback) override {
    DBusThreadManager::Get()->GetCryptohomeClient()->
        AsyncTpmAttestationEnroll(pca_type, pca_response, base::Bind(
            &AsyncMethodCallerImpl::RegisterAsyncCallback,
            weak_ptr_factory_.GetWeakPtr(),
            callback,
            "Couldn't initiate async attestation enroll."));
  }

  void AsyncTpmAttestationCreateCertRequest(
      chromeos::attestation::PrivacyCAType pca_type,
      chromeos::attestation::AttestationCertificateProfile certificate_profile,
      const Identification& cryptohome_id,
      const std::string& request_origin,
      const DataCallback& callback) override {
    DBusThreadManager::Get()
        ->GetCryptohomeClient()
        ->AsyncTpmAttestationCreateCertRequest(
            pca_type, certificate_profile, cryptohome_id, request_origin,
            base::Bind(&AsyncMethodCallerImpl::RegisterAsyncDataCallback,
                       weak_ptr_factory_.GetWeakPtr(), callback,
                       "Couldn't initiate async attestation cert request."));
  }

  void AsyncTpmAttestationFinishCertRequest(
      const std::string& pca_response,
      chromeos::attestation::AttestationKeyType key_type,
      const Identification& cryptohome_id,
      const std::string& key_name,
      const DataCallback& callback) override {
    DBusThreadManager::Get()
        ->GetCryptohomeClient()
        ->AsyncTpmAttestationFinishCertRequest(
            pca_response, key_type, cryptohome_id, key_name,
            base::Bind(
                &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
                weak_ptr_factory_.GetWeakPtr(), callback,
                "Couldn't initiate async attestation finish cert request."));
  }

  void TpmAttestationRegisterKey(
      chromeos::attestation::AttestationKeyType key_type,
      const Identification& cryptohome_id,
      const std::string& key_name,
      const Callback& callback) override {
    DBusThreadManager::Get()->GetCryptohomeClient()->TpmAttestationRegisterKey(
        key_type, cryptohome_id, key_name,
        base::Bind(&AsyncMethodCallerImpl::RegisterAsyncCallback,
                   weak_ptr_factory_.GetWeakPtr(), callback,
                   "Couldn't initiate async attestation register key."));
  }

  void TpmAttestationSignEnterpriseChallenge(
      chromeos::attestation::AttestationKeyType key_type,
      const Identification& cryptohome_id,
      const std::string& key_name,
      const std::string& domain,
      const std::string& device_id,
      chromeos::attestation::AttestationChallengeOptions options,
      const std::string& challenge,
      const DataCallback& callback) override {
    DBusThreadManager::Get()
        ->GetCryptohomeClient()
        ->TpmAttestationSignEnterpriseChallenge(
            key_type, cryptohome_id, key_name, domain, device_id, options,
            challenge,
            base::Bind(
                &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
                weak_ptr_factory_.GetWeakPtr(), callback,
                "Couldn't initiate async attestation enterprise challenge."));
  }

  void TpmAttestationSignSimpleChallenge(
      chromeos::attestation::AttestationKeyType key_type,
      const Identification& cryptohome_id,
      const std::string& key_name,
      const std::string& challenge,
      const DataCallback& callback) override {
    DBusThreadManager::Get()
        ->GetCryptohomeClient()
        ->TpmAttestationSignSimpleChallenge(
            key_type, cryptohome_id, key_name, challenge,
            base::Bind(
                &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
                weak_ptr_factory_.GetWeakPtr(), callback,
                "Couldn't initiate async attestation simple challenge."));
  }

  void AsyncGetSanitizedUsername(const Identification& cryptohome_id,
                                 const DataCallback& callback) override {
    DBusThreadManager::Get()->GetCryptohomeClient()->GetSanitizedUsername(
        cryptohome_id,
        base::Bind(&AsyncMethodCallerImpl::GetSanitizedUsernameCallback,
                   weak_ptr_factory_.GetWeakPtr(), callback));
  }

  virtual void GetSanitizedUsernameCallback(
      const DataCallback& callback,
      const chromeos::DBusMethodCallStatus call_status,
      const std::string& result) {
    callback.Run(true, result);
  }

 private:
  struct CallbackElement {
    CallbackElement() {}
    explicit CallbackElement(const AsyncMethodCaller::Callback& callback)
        : callback(callback),
          task_runner(base::ThreadTaskRunnerHandle::Get()) {}
    AsyncMethodCaller::Callback callback;
    scoped_refptr<base::SingleThreadTaskRunner> task_runner;
  };

  struct DataCallbackElement {
    DataCallbackElement() {}
    explicit DataCallbackElement(
        const AsyncMethodCaller::DataCallback& callback)
        : data_callback(callback),
          task_runner(base::ThreadTaskRunnerHandle::Get()) {}
    AsyncMethodCaller::DataCallback data_callback;
    scoped_refptr<base::SingleThreadTaskRunner> task_runner;
  };

  typedef base::hash_map<int, CallbackElement> CallbackMap;
  typedef base::hash_map<int, DataCallbackElement> DataCallbackMap;

  // Handles the response for async calls.
  // Below is described how async calls work.
  // 1. CryptohomeClient::AsyncXXX returns "async ID".
  // 2. RegisterAsyncCallback registers the "async ID" with the user-provided
  //    callback.
  // 3. Cryptohome will return the result asynchronously as a signal with
  //    "async ID"
  // 4. "HandleAsyncResponse" handles the result signal and call the registered
  //    callback associated with the "async ID".
  void HandleAsyncResponse(int async_id, bool return_status, int return_code) {
    const CallbackMap::iterator it = callback_map_.find(async_id);
    if (it == callback_map_.end()) {
      LOG(ERROR) << "Received signal for unknown async_id " << async_id;
      return;
    }
    it->second.task_runner->PostTask(
        FROM_HERE, base::Bind(it->second.callback, return_status,
                              static_cast<MountError>(return_code)));
    callback_map_.erase(it);
  }

  // Similar to HandleAsyncResponse but for signals with a raw data payload.
  void HandleAsyncDataResponse(int async_id,
                               bool return_status,
                               const std::string& return_data) {
    const DataCallbackMap::iterator it = data_callback_map_.find(async_id);
    if (it == data_callback_map_.end()) {
      LOG(ERROR) << "Received signal for unknown async_id " << async_id;
      return;
    }
    it->second.task_runner->PostTask(
        FROM_HERE,
        base::Bind(it->second.data_callback, return_status, return_data));
    data_callback_map_.erase(it);
  }
  // Registers a callback which is called when the result for AsyncXXX is ready.
  void RegisterAsyncCallback(
      Callback callback, const char* error, int async_id) {
    if (async_id == chromeos::CryptohomeClient::kNotReadyAsyncId) {
      base::ThreadTaskRunnerHandle::Get()->PostTask(
          FROM_HERE, base::Bind(callback,
                                false,  // return status
                                cryptohome::MOUNT_ERROR_FATAL));
      return;
    }

    if (async_id == 0) {
      LOG(ERROR) << error;
      return;
    }
    VLOG(1) << "Adding handler for " << async_id;
    DCHECK_EQ(callback_map_.count(async_id), 0U);
    DCHECK_EQ(data_callback_map_.count(async_id), 0U);
    callback_map_[async_id] = CallbackElement(callback);
  }

  // Registers a callback which is called when the result for AsyncXXX is ready.
  void RegisterAsyncDataCallback(
      DataCallback callback, const char* error, int async_id) {
    if (async_id == chromeos::CryptohomeClient::kNotReadyAsyncId) {
      base::ThreadTaskRunnerHandle::Get()->PostTask(
          FROM_HERE, base::Bind(callback,
                                false,  // return status
                                std::string()));
      return;
    }
    if (async_id == 0) {
      LOG(ERROR) << error;
      return;
    }
    VLOG(1) << "Adding handler for " << async_id;
    DCHECK_EQ(callback_map_.count(async_id), 0U);
    DCHECK_EQ(data_callback_map_.count(async_id), 0U);
    data_callback_map_[async_id] = DataCallbackElement(callback);
  }

  CallbackMap callback_map_;
  DataCallbackMap data_callback_map_;
  base::WeakPtrFactory<AsyncMethodCallerImpl> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(AsyncMethodCallerImpl);
};

}  // namespace

// static
void AsyncMethodCaller::Initialize() {
  if (g_async_method_caller) {
    LOG(WARNING) << "AsyncMethodCaller was already initialized";
    return;
  }
  g_async_method_caller = new AsyncMethodCallerImpl();
  VLOG(1) << "AsyncMethodCaller initialized";
}

// static
void AsyncMethodCaller::InitializeForTesting(
    AsyncMethodCaller* async_method_caller) {
  if (g_async_method_caller) {
    LOG(WARNING) << "AsyncMethodCaller was already initialized";
    return;
  }
  g_async_method_caller = async_method_caller;
  VLOG(1) << "AsyncMethodCaller initialized";
}

// static
void AsyncMethodCaller::Shutdown() {
  if (!g_async_method_caller) {
    LOG(WARNING) << "AsyncMethodCaller::Shutdown() called with NULL manager";
    return;
  }
  delete g_async_method_caller;
  g_async_method_caller = NULL;
  VLOG(1) << "AsyncMethodCaller Shutdown completed";
}

// static
AsyncMethodCaller* AsyncMethodCaller::GetInstance() {
  return g_async_method_caller;
}

}  // namespace cryptohome
