// Copyright (c) 2011 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/service/cloud_print/cloud_print_url_fetcher.h"

#include "base/stringprintf.h"
#include "base/values.h"
#include "chrome/common/net/http_return.h"
#include "chrome/service/cloud_print/cloud_print_consts.h"
#include "chrome/service/cloud_print/cloud_print_helpers.h"
#include "chrome/service/cloud_print/cloud_print_token_store.h"
#include "chrome/service/net/service_url_request_context.h"
#include "chrome/service/service_process.h"
#include "googleurl/src/gurl.h"
#include "net/url_request/url_request_status.h"

CloudPrintURLFetcher::CloudPrintURLFetcher()
    : delegate_(NULL),
      num_retries_(0) {
}

void CloudPrintURLFetcher::StartGetRequest(
    const GURL& url,
    Delegate* delegate,
    int max_retries,
    const std::string& additional_headers) {
  StartRequestHelper(url,
                     URLFetcher::GET,
                     delegate,
                     max_retries,
                     std::string(),
                     std::string(),
                     additional_headers);
}

void CloudPrintURLFetcher::StartPostRequest(
    const GURL& url,
    Delegate* delegate,
    int max_retries,
    const std::string& post_data_mime_type,
    const std::string& post_data,
    const std::string& additional_headers) {
  StartRequestHelper(url,
                     URLFetcher::POST,
                     delegate,
                     max_retries,
                     post_data_mime_type,
                     post_data,
                     additional_headers);
}

void CloudPrintURLFetcher::OnURLFetchComplete(
    const content::URLFetcher* source) {
  VLOG(1) << "CP_PROXY: OnURLFetchComplete, url: " << source->GetUrl()
          << ", response code: " << source->GetResponseCode();
  // Make sure we stay alive through the body of this function.
  scoped_refptr<CloudPrintURLFetcher> keep_alive(this);
  std::string data;
  source->GetResponseAsString(&data);
  ResponseAction action = delegate_->HandleRawResponse(
      source,
      source->GetUrl(),
      source->GetStatus(),
      source->GetResponseCode(),
      source->GetCookies(),
      data);
  if (action == CONTINUE_PROCESSING) {
    // If we are not using an OAuth token, and we got an auth error, we are
    // done. Else, the token may have been refreshed. Let us try again.
    if ((RC_FORBIDDEN == source->GetResponseCode()) &&
        (!CloudPrintTokenStore::current() ||
         !CloudPrintTokenStore::current()->token_is_oauth())) {
      delegate_->OnRequestAuthError();
      return;
    }
    // We need to retry on all network errors.
    if (!source->GetStatus().is_success() || (source->GetResponseCode() != 200))
      action = RETRY_REQUEST;
    else
      action = delegate_->HandleRawData(source, source->GetUrl(), data);

    if (action == CONTINUE_PROCESSING) {
      // If the delegate is not interested in handling the raw response data,
      // we assume that a JSON response is expected. If we do not get a JSON
      // response, we will retry (to handle the case where we got redirected
      // to a non-cloudprint-server URL eg. for authentication).
      bool succeeded = false;
      DictionaryValue* response_dict = NULL;
      CloudPrintHelpers::ParseResponseJSON(data, &succeeded, &response_dict);
      if (response_dict)
        action = delegate_->HandleJSONData(source,
                                           source->GetUrl(),
                                           response_dict,
                                           succeeded);
      else
        action = RETRY_REQUEST;
    }
  }
  // Retry the request if needed.
  if (action == RETRY_REQUEST) {
    // Explicitly call ReceivedContentWasMalformed() to ensure the current
    // request gets counted as a failure for calculation of the back-off
    // period.  If it was already a failure by status code, this call will
    // be ignored.
    request_->ReceivedContentWasMalformed();

    ++num_retries_;
    if ((-1 != source->GetMaxRetries()) &&
        (num_retries_ > source->GetMaxRetries())) {
      // Retry limit reached. Give up.
      delegate_->OnRequestGiveUp();
    } else {
      // Either no retry limit specified or retry limit has not yet been
      // reached. Try again. Set up the request headers again because the token
      // may have changed.
      SetupRequestHeaders();
      request_->StartWithRequestContextGetter(GetRequestContextGetter());
    }
  }
}

void CloudPrintURLFetcher::StartRequestHelper(
    const GURL& url,
    content::URLFetcher::RequestType request_type,
    Delegate* delegate,
    int max_retries,
    const std::string& post_data_mime_type,
    const std::string& post_data,
    const std::string& additional_headers) {
  DCHECK(delegate);
  // Persist the additional headers in case we need to retry the request.
  additional_headers_ = additional_headers;
  request_.reset(new URLFetcher(url, request_type, this));
  request_->SetRequestContext(GetRequestContextGetter());
  // Since we implement our own retry logic, disable the retry in URLFetcher.
  request_->SetAutomaticallyRetryOn5xx(false);
  request_->SetMaxRetries(max_retries);
  SetupRequestHeaders();
  delegate_ = delegate;
  if (request_type == URLFetcher::POST) {
    request_->SetUploadData(post_data_mime_type, post_data);
  }

  request_->Start();
}

void CloudPrintURLFetcher::SetupRequestHeaders() {
  std::string headers;
  CloudPrintTokenStore* token_store = CloudPrintTokenStore::current();
  if (token_store) {
    headers = token_store->token_is_oauth() ?
        "Authorization: OAuth " : "Authorization: GoogleLogin auth=";
    headers += token_store->token();
    headers += "\r\n";
  }
  headers += kChromeCloudPrintProxyHeader;
  if (!additional_headers_.empty()) {
    headers += "\r\n";
    headers += additional_headers_;
  }
  request_->SetExtraRequestHeaders(headers);
}

CloudPrintURLFetcher::~CloudPrintURLFetcher() {}

net::URLRequestContextGetter* CloudPrintURLFetcher::GetRequestContextGetter() {
  ServiceURLRequestContextGetter* getter =
      g_service_process->GetServiceURLRequestContextGetter();
  // Now set up the user agent for cloudprint.
  std::string user_agent = getter->user_agent();
  base::StringAppendF(&user_agent, " %s", kCloudPrintUserAgent);
  getter->set_user_agent(user_agent);
  return getter;
}
