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

#include <string>
#include <vector>

#include "base/basictypes.h"
#include "base/strings/stringprintf.h"
#include "google_apis/gaia/gaia_urls.h"
#include "google_apis/gaia/oauth2_access_token_fetcher_impl.h"
#include "net/base/escape.h"
#include "net/base/load_flags.h"
#include "net/http/http_status_code.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_status.h"

using net::ResponseCookies;
using net::URLFetcher;
using net::URLFetcherDelegate;
using net::URLRequestContextGetter;
using net::URLRequestStatus;

namespace {
static const char kAuthorizationHeaderFormat[] =
    "Authorization: Bearer %s";

static std::string MakeAuthorizationHeader(const std::string& auth_token) {
  return base::StringPrintf(kAuthorizationHeaderFormat, auth_token.c_str());
}
}  // namespace

OAuth2ApiCallFlow::OAuth2ApiCallFlow(
    net::URLRequestContextGetter* context,
    const std::string& refresh_token,
    const std::string& access_token,
    const std::vector<std::string>& scopes)
    : context_(context),
      refresh_token_(refresh_token),
      access_token_(access_token),
      scopes_(scopes),
      state_(INITIAL),
      tried_mint_access_token_(false) {
}

OAuth2ApiCallFlow::~OAuth2ApiCallFlow() {}

void OAuth2ApiCallFlow::Start() {
  BeginApiCall();
}

void OAuth2ApiCallFlow::BeginApiCall() {
  CHECK(state_ == INITIAL || state_ == MINT_ACCESS_TOKEN_DONE);

  // If the access token is empty then directly try to mint one.
  if (access_token_.empty()) {
    BeginMintAccessToken();
  } else {
    state_ = API_CALL_STARTED;
    url_fetcher_.reset(CreateURLFetcher());
    url_fetcher_->Start();  // OnURLFetchComplete will be called.
  }
}

void OAuth2ApiCallFlow::EndApiCall(const net::URLFetcher* source) {
  CHECK_EQ(API_CALL_STARTED, state_);
  state_ = API_CALL_DONE;

  URLRequestStatus status = source->GetStatus();
  if (!status.is_success()) {
    state_ = ERROR_STATE;
    ProcessApiCallFailure(source);
    return;
  }

  // If the response code is 401 Unauthorized then access token may have
  // expired. So try generating a new access token.
  if (source->GetResponseCode() == net::HTTP_UNAUTHORIZED) {
    // If we already tried minting a new access token, don't do it again.
    if (tried_mint_access_token_) {
      state_ = ERROR_STATE;
      ProcessApiCallFailure(source);
    } else {
      BeginMintAccessToken();
    }

    return;
  }

  if (source->GetResponseCode() != net::HTTP_OK &&
      source->GetResponseCode() != net::HTTP_NO_CONTENT) {
    state_ = ERROR_STATE;
    ProcessApiCallFailure(source);
    return;
  }

  ProcessApiCallSuccess(source);
}

void OAuth2ApiCallFlow::BeginMintAccessToken() {
  CHECK(state_ == INITIAL || state_ == API_CALL_DONE);
  CHECK(!tried_mint_access_token_);
  state_ = MINT_ACCESS_TOKEN_STARTED;
  tried_mint_access_token_ = true;

  oauth2_access_token_fetcher_.reset(CreateAccessTokenFetcher());
  oauth2_access_token_fetcher_->Start(
      GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
      GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
      scopes_);
}

void OAuth2ApiCallFlow::EndMintAccessToken(
    const GoogleServiceAuthError* error) {
  CHECK_EQ(MINT_ACCESS_TOKEN_STARTED, state_);

  if (!error) {
    state_ = MINT_ACCESS_TOKEN_DONE;
    BeginApiCall();
  } else {
    state_ = ERROR_STATE;
    ProcessMintAccessTokenFailure(*error);
  }
}

std::string OAuth2ApiCallFlow::CreateApiCallBodyContentType() {
  return "application/x-www-form-urlencoded";
}

OAuth2AccessTokenFetcher* OAuth2ApiCallFlow::CreateAccessTokenFetcher() {
  return new OAuth2AccessTokenFetcherImpl(this, context_, refresh_token_);
}

void OAuth2ApiCallFlow::OnURLFetchComplete(const net::URLFetcher* source) {
  CHECK(source);
  CHECK_EQ(API_CALL_STARTED, state_);
  EndApiCall(source);
}

void OAuth2ApiCallFlow::OnGetTokenSuccess(const std::string& access_token,
                                          const base::Time& expiration_time) {
  access_token_ = access_token;
  EndMintAccessToken(NULL);
}

void OAuth2ApiCallFlow::OnGetTokenFailure(
    const GoogleServiceAuthError& error) {
  EndMintAccessToken(&error);
}

URLFetcher* OAuth2ApiCallFlow::CreateURLFetcher() {
  std::string body = CreateApiCallBody();
  bool empty_body = body.empty();
  URLFetcher* result = net::URLFetcher::Create(
      0,
      CreateApiCallUrl(),
      empty_body ? URLFetcher::GET : URLFetcher::POST,
      this);

  result->SetRequestContext(context_);
  result->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
                       net::LOAD_DO_NOT_SAVE_COOKIES);
  result->AddExtraRequestHeader(MakeAuthorizationHeader(access_token_));
  // Fetchers are sometimes cancelled because a network change was detected,
  // especially at startup and after sign-in on ChromeOS. Retrying once should
  // be enough in those cases; let the fetcher retry up to 3 times just in case.
  // http://crbug.com/163710
  result->SetAutomaticallyRetryOnNetworkChanges(3);

  if (!empty_body)
    result->SetUploadData(CreateApiCallBodyContentType(), body);

  return result;
}
