// 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.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_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::NonThreadSafe,
      public base::RefCountedThreadSafe<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;

  base::SingleThreadTaskRunner* token_service_task_runner();
  OAuth2TokenService* token_service();
  OAuth2TokenServiceRequest* owner();

 private:
  friend class base::RefCountedThreadSafe<OAuth2TokenServiceRequest::Core>;

  void DoNothing();

  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)
    : owner_(owner), provider_(provider) {
  DCHECK(owner_);
  DCHECK(provider_.get());
  token_service_task_runner_ = provider_->GetTokenServiceTaskRunner();
  DCHECK(token_service_task_runner_.get());
}

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

void OAuth2TokenServiceRequest::Core::Start() {
  DCHECK(CalledOnValidThread());
  token_service_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&OAuth2TokenServiceRequest::Core::StartOnTokenServiceThread,
                 this));
}

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

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

  // We are stopping and will likely be destroyed soon.  Use a reply closure
  // (DoNothing) to retain "this" and ensure we are destroyed in the owner
  // thread, not the task runner thread.  PostTaskAndReply guarantees that the
  // reply closure will execute after StopOnTokenServiceThread has completed.
  token_service_task_runner_->PostTaskAndReply(
      FROM_HERE,
      base::Bind(&OAuth2TokenServiceRequest::Core::StopOnTokenServiceThread,
                 this),
      base::Bind(&OAuth2TokenServiceRequest::Core::DoNothing, this));
}

bool OAuth2TokenServiceRequest::Core::IsStopped() const {
  DCHECK(CalledOnValidThread());
  return owner_ == NULL;
}

base::SingleThreadTaskRunner*
OAuth2TokenServiceRequest::Core::token_service_task_runner() {
  return token_service_task_runner_.get();
}

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

OAuth2TokenServiceRequest* OAuth2TokenServiceRequest::Core::owner() {
  DCHECK(CalledOnValidThread());
  return owner_;
}

void OAuth2TokenServiceRequest::Core::DoNothing() {
  DCHECK(CalledOnValidThread());
}

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 std::string& access_token,
                         const base::Time& expiration_time) 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(std::string access_token,
                                    base::Time expiration_time);
  void InformOwnerOnGetTokenFailure(GoogleServiceAuthError error);

  scoped_refptr<base::SingleThreadTaskRunner> owner_task_runner_;
  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"),
      owner_task_runner_(base::ThreadTaskRunnerHandle::Get()),
      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()->BelongsToCurrentThread());
  request_ = token_service()->StartRequest(account_id_, scopes_, this);
}

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

void RequestCore::OnGetTokenSuccess(const OAuth2TokenService::Request* request,
                                    const std::string& access_token,
                                    const base::Time& expiration_time) {
  DCHECK(token_service_task_runner()->BelongsToCurrentThread());
  DCHECK_EQ(request_.get(), request);
  owner_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&RequestCore::InformOwnerOnGetTokenSuccess,
                 this,
                 access_token,
                 expiration_time));
  request_.reset();
}

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

void RequestCore::InformOwnerOnGetTokenSuccess(std::string access_token,
                                               base::Time expiration_time) {
  DCHECK(CalledOnValidThread());
  if (!IsStopped()) {
    consumer_->OnGetTokenSuccess(owner(), access_token, expiration_time);
  }
}

void RequestCore::InformOwnerOnGetTokenFailure(GoogleServiceAuthError error) {
  DCHECK(CalledOnValidThread());
  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()->BelongsToCurrentThread());
  token_service()->InvalidateAccessToken(account_id_, scopes_, access_token_);
}

void InvalidateCore::StopOnTokenServiceThread() {
  DCHECK(token_service_task_runner()->BelongsToCurrentThread());
  // 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() {
  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();
}
