// 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 "google_apis/gaia/oauth2_token_service_request.h"

#include <memory>

#include "base/bind.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ref_counted_delete_on_sequence.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "google_apis/gaia/oauth2_access_token_consumer.h"

OAuth2TokenServiceRequest::TokenServiceProvider::TokenServiceProvider() {
}

OAuth2TokenServiceRequest::TokenServiceProvider::~TokenServiceProvider() {
}

// Core serves as the base class for OAuth2TokenService operations.  Each
// operation should be modeled as a derived type.
//
// Core is used like this:
//
// 1. Constructed on owner thread.
//
// 2. Start() is called on owner thread, which calls StartOnTokenServiceThread()
// on token service thread.
//
// 3. Request is executed.
//
// 4. Stop() is called on owner thread, which calls StopOnTokenServiceThread()
// on token service thread.
//
// 5. Core is destroyed on owner thread.
class OAuth2TokenServiceRequest::Core
    : public base::RefCountedDeleteOnSequence<OAuth2TokenServiceRequest::Core> {
 public:
  // Note the thread where an instance of Core is constructed is referred to as
  // the "owner thread" here.
  Core(OAuth2TokenServiceRequest* owner,
       const scoped_refptr<TokenServiceProvider>& provider);

  // Starts the core.  Must be called on the owner thread.
  void Start();

  // Stops the core.  Must be called on the owner thread.
  void Stop();

  // Returns true if this object has been stopped.  Must be called on the owner
  // thread.
  bool IsStopped() const;

 protected:
  // Core must be destroyed on the owner thread.  If data members must be
  // cleaned up or destroyed on the token service thread, do so in the
  // StopOnTokenServiceThread method.
  virtual ~Core();

  // Called on the token service thread.
  virtual void StartOnTokenServiceThread() = 0;

  // Called on the token service thread.
  virtual void StopOnTokenServiceThread() = 0;

  const base::SingleThreadTaskRunner* token_service_task_runner() const {
    return token_service_task_runner_.get();
  }
  OAuth2TokenService* token_service();
  OAuth2TokenServiceRequest* owner();

  SEQUENCE_CHECKER(sequence_checker_);

 private:
  friend class base::RefCountedDeleteOnSequence<
      OAuth2TokenServiceRequest::Core>;
  friend class base::DeleteHelper<OAuth2TokenServiceRequest::Core>;

  scoped_refptr<base::SingleThreadTaskRunner> token_service_task_runner_;
  OAuth2TokenServiceRequest* owner_;

  // Clear on owner thread.  OAuth2TokenServiceRequest promises to clear its
  // last reference to TokenServiceProvider on the owner thread so the caller
  // can ensure it is destroyed on the owner thread if desired.
  scoped_refptr<TokenServiceProvider> provider_;

  DISALLOW_COPY_AND_ASSIGN(Core);
};

OAuth2TokenServiceRequest::Core::Core(
    OAuth2TokenServiceRequest* owner,
    const scoped_refptr<TokenServiceProvider>& provider)
    : RefCountedDeleteOnSequence<OAuth2TokenServiceRequest::Core>(
          base::SequencedTaskRunnerHandle::Get()),
      owner_(owner),
      provider_(provider) {
  DCHECK(owner_);
  DCHECK(provider_.get());
  token_service_task_runner_ = provider_->GetTokenServiceTaskRunner();
  DCHECK(token_service_task_runner());
}

OAuth2TokenServiceRequest::Core::~Core() {
}

void OAuth2TokenServiceRequest::Core::Start() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  token_service_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(
          &OAuth2TokenServiceRequest::Core::StartOnTokenServiceThread, this));
}

void OAuth2TokenServiceRequest::Core::Stop() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(!IsStopped());

  // Detaches |owner_| from this instance so |owner_| will be called back only
  // if |Stop()| has never been called.
  owner_ = nullptr;

  // Stop on the token service thread.  RefCountedDeleteOnSequence ensures we
  // will be destroyed on the owner thread.
  token_service_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&OAuth2TokenServiceRequest::Core::StopOnTokenServiceThread,
                     this));
}

bool OAuth2TokenServiceRequest::Core::IsStopped() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return owner_ == nullptr;
}

OAuth2TokenService* OAuth2TokenServiceRequest::Core::token_service() {
  DCHECK(token_service_task_runner()->RunsTasksInCurrentSequence());
  return provider_->GetTokenService();
}

OAuth2TokenServiceRequest* OAuth2TokenServiceRequest::Core::owner() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return owner_;
}

namespace {

// An implementation of Core for getting an access token.
class RequestCore : public OAuth2TokenServiceRequest::Core,
                    public OAuth2TokenService::Consumer {
 public:
  RequestCore(OAuth2TokenServiceRequest* owner,
              const scoped_refptr<
                  OAuth2TokenServiceRequest::TokenServiceProvider>& provider,
              OAuth2TokenService::Consumer* consumer,
              const std::string& account_id,
              const OAuth2TokenService::ScopeSet& scopes);

  // OAuth2TokenService::Consumer.  Must be called on the token service thread.
  void OnGetTokenSuccess(
      const OAuth2TokenService::Request* request,
      const OAuth2AccessTokenConsumer::TokenResponse& token_response) override;
  void OnGetTokenFailure(const OAuth2TokenService::Request* request,
                         const GoogleServiceAuthError& error) override;

 private:
  friend class base::RefCountedThreadSafe<RequestCore>;

  // Must be destroyed on the owner thread.
  ~RequestCore() override;

  // Core implementation.
  void StartOnTokenServiceThread() override;
  void StopOnTokenServiceThread() override;

  void InformOwnerOnGetTokenSuccess(
      const OAuth2AccessTokenConsumer::TokenResponse& token_response);
  void InformOwnerOnGetTokenFailure(GoogleServiceAuthError error);

  OAuth2TokenService::Consumer* const consumer_;
  std::string account_id_;
  OAuth2TokenService::ScopeSet scopes_;

  // OAuth2TokenService request for fetching OAuth2 access token; it should be
  // created, reset and accessed only on the token service thread.
  std::unique_ptr<OAuth2TokenService::Request> request_;

  DISALLOW_COPY_AND_ASSIGN(RequestCore);
};

RequestCore::RequestCore(
    OAuth2TokenServiceRequest* owner,
    const scoped_refptr<OAuth2TokenServiceRequest::TokenServiceProvider>&
        provider,
    OAuth2TokenService::Consumer* consumer,
    const std::string& account_id,
    const OAuth2TokenService::ScopeSet& scopes)
    : OAuth2TokenServiceRequest::Core(owner, provider),
      OAuth2TokenService::Consumer("oauth2_token_service"),
      consumer_(consumer),
      account_id_(account_id),
      scopes_(scopes) {
  DCHECK(consumer_);
  DCHECK(!account_id_.empty());
  DCHECK(!scopes_.empty());
}

RequestCore::~RequestCore() {
}

void RequestCore::StartOnTokenServiceThread() {
  DCHECK(token_service_task_runner()->RunsTasksInCurrentSequence());
  request_ = token_service()->StartRequest(account_id_, scopes_, this);
}

void RequestCore::StopOnTokenServiceThread() {
  DCHECK(token_service_task_runner()->RunsTasksInCurrentSequence());
  request_.reset();
}

void RequestCore::OnGetTokenSuccess(
    const OAuth2TokenService::Request* request,
    const OAuth2AccessTokenConsumer::TokenResponse& token_response) {
  DCHECK(token_service_task_runner()->RunsTasksInCurrentSequence());
  DCHECK_EQ(request_.get(), request);
  owning_task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&RequestCore::InformOwnerOnGetTokenSuccess,
                                this, token_response));
  request_.reset();
}

void RequestCore::OnGetTokenFailure(const OAuth2TokenService::Request* request,
                                    const GoogleServiceAuthError& error) {
  DCHECK(token_service_task_runner()->RunsTasksInCurrentSequence());
  DCHECK_EQ(request_.get(), request);
  owning_task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&RequestCore::InformOwnerOnGetTokenFailure, this, error));
  request_.reset();
}

void RequestCore::InformOwnerOnGetTokenSuccess(
    const OAuth2AccessTokenConsumer::TokenResponse& token_response) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (!IsStopped()) {
    consumer_->OnGetTokenSuccess(owner(), token_response);
  }
}

void RequestCore::InformOwnerOnGetTokenFailure(GoogleServiceAuthError error) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (!IsStopped()) {
    consumer_->OnGetTokenFailure(owner(), error);
  }
}

// An implementation of Core for invalidating an access token.
class InvalidateCore : public OAuth2TokenServiceRequest::Core {
 public:
  InvalidateCore(OAuth2TokenServiceRequest* owner,
                 const scoped_refptr<
                     OAuth2TokenServiceRequest::TokenServiceProvider>& provider,
                 const std::string& access_token,
                 const std::string& account_id,
                 const OAuth2TokenService::ScopeSet& scopes);

 private:
  friend class base::RefCountedThreadSafe<InvalidateCore>;

  // Must be destroyed on the owner thread.
  ~InvalidateCore() override;

  // Core implementation.
  void StartOnTokenServiceThread() override;
  void StopOnTokenServiceThread() override;

  std::string access_token_;
  std::string account_id_;
  OAuth2TokenService::ScopeSet scopes_;

  DISALLOW_COPY_AND_ASSIGN(InvalidateCore);
};

InvalidateCore::InvalidateCore(
    OAuth2TokenServiceRequest* owner,
    const scoped_refptr<OAuth2TokenServiceRequest::TokenServiceProvider>&
        provider,
    const std::string& access_token,
    const std::string& account_id,
    const OAuth2TokenService::ScopeSet& scopes)
    : OAuth2TokenServiceRequest::Core(owner, provider),
      access_token_(access_token),
      account_id_(account_id),
      scopes_(scopes) {
  DCHECK(!access_token_.empty());
  DCHECK(!account_id_.empty());
  DCHECK(!scopes.empty());
}

InvalidateCore::~InvalidateCore() {
}

void InvalidateCore::StartOnTokenServiceThread() {
  DCHECK(token_service_task_runner()->RunsTasksInCurrentSequence());
  token_service()->InvalidateAccessToken(account_id_, scopes_, access_token_);
}

void InvalidateCore::StopOnTokenServiceThread() {
  DCHECK(token_service_task_runner()->RunsTasksInCurrentSequence());
  // Nothing to do.
}

}  // namespace

// static
std::unique_ptr<OAuth2TokenServiceRequest>
OAuth2TokenServiceRequest::CreateAndStart(
    const scoped_refptr<TokenServiceProvider>& provider,
    const std::string& account_id,
    const OAuth2TokenService::ScopeSet& scopes,
    OAuth2TokenService::Consumer* consumer) {
  std::unique_ptr<OAuth2TokenServiceRequest> request(
      new OAuth2TokenServiceRequest(account_id));
  scoped_refptr<Core> core(
      new RequestCore(request.get(), provider, consumer, account_id, scopes));
  request->StartWithCore(core);
  return request;
}

// static
void OAuth2TokenServiceRequest::InvalidateToken(
    const scoped_refptr<TokenServiceProvider>& provider,
    const std::string& account_id,
    const OAuth2TokenService::ScopeSet& scopes,
    const std::string& access_token) {
  std::unique_ptr<OAuth2TokenServiceRequest> request(
      new OAuth2TokenServiceRequest(account_id));
  scoped_refptr<Core> core(new InvalidateCore(
      request.get(), provider, access_token, account_id, scopes));
  request->StartWithCore(core);
}

OAuth2TokenServiceRequest::~OAuth2TokenServiceRequest() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  core_->Stop();
}

std::string OAuth2TokenServiceRequest::GetAccountId() const {
  return account_id_;
}

OAuth2TokenServiceRequest::OAuth2TokenServiceRequest(
    const std::string& account_id)
    : account_id_(account_id) {
  DCHECK(!account_id_.empty());
}

void OAuth2TokenServiceRequest::StartWithCore(const scoped_refptr<Core>& core) {
  DCHECK(core.get());
  core_ = core;
  core_->Start();
}
