<commit_before>// 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 "chrome/browser/google_apis/operations_base.h"

#include "base/json/json_reader.h"
#include "base/metrics/histogram.h"
#include "base/string_number_conversions.h"
#include "base/stringprintf.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/common/net/url_util.h"
#include "content/public/browser/browser_thread.h"
#include "google_apis/gaia/gaia_urls.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "google_apis/gaia/oauth2_access_token_fetcher.h"
#include "net/base/load_flags.h"
#include "net/http/http_util.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request_status.h"

using content::BrowserThread;
using net::URLFetcher;

namespace {

// Used for success ratio histograms. 0 for failure, 1 for success,
// 2 for no connection (likely offline).
const int kSuccessRatioHistogramFailure = 0;
const int kSuccessRatioHistogramSuccess = 1;
const int kSuccessRatioHistogramNoConnection = 2;
const int kSuccessRatioHistogramMaxValue = 3;  // The max value is exclusive.

// Template for optional OAuth2 authorization HTTP header.
const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s";
// Template for GData API version HTTP header.
const char kGDataVersionHeader[] = "GData-Version: 3.0";

// Maximum number of attempts for re-authentication per operation.
const int kMaxReAuthenticateAttemptsPerOperation = 1;

// Parse JSON string to base::Value object.
void ParseJsonOnBlockingPool(const std::string& data,
                             scoped_ptr<base::Value>* value) {
  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));

  int error_code = -1;
  std::string error_message;
  value->reset(base::JSONReader::ReadAndReturnError(data,
                                                    base::JSON_PARSE_RFC,
                                                    &error_code,
                                                    &error_message));

  if (!value->get()) {
    LOG(ERROR) << "Error while parsing entry response: "
               << error_message
               << ", code: "
               << error_code
               << ", data:\n"
               << data;
  }
}

}  // namespace

namespace gdata {

//================================ AuthOperation ===============================

AuthOperation::AuthOperation(OperationRegistry* registry,
                             const AuthStatusCallback& callback,
                             const std::vector<std::string>& scopes,
                             const std::string& refresh_token)
    : OperationRegistry::Operation(registry),
      refresh_token_(refresh_token),
      callback_(callback),
      scopes_(scopes) {
}

AuthOperation::~AuthOperation() {}

void AuthOperation::Start() {
  DCHECK(!refresh_token_.empty());
  oauth2_access_token_fetcher_.reset(new OAuth2AccessTokenFetcher(
      this, g_browser_process->system_request_context()));
  NotifyStart();
  oauth2_access_token_fetcher_->Start(
      GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
      GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
      refresh_token_,
      scopes_);
}

void AuthOperation::DoCancel() {
  oauth2_access_token_fetcher_->CancelRequest();
  if (!callback_.is_null())
    callback_.Run(GDATA_CANCELLED, std::string());
}

// Callback for OAuth2AccessTokenFetcher on success. |access_token| is the token
// used to start fetching user data.
void AuthOperation::OnGetTokenSuccess(const std::string& access_token,
                                      const base::Time& expiration_time) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  UMA_HISTOGRAM_ENUMERATION("GData.AuthSuccess",
                            kSuccessRatioHistogramSuccess,
                            kSuccessRatioHistogramMaxValue);

  callback_.Run(HTTP_SUCCESS, access_token);
  NotifyFinish(OPERATION_COMPLETED);
}

// Callback for OAuth2AccessTokenFetcher on failure.
void AuthOperation::OnGetTokenFailure(const GoogleServiceAuthError& error) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  LOG(WARNING) << "AuthOperation: token request using refresh token failed"
               << error.ToString();

  // There are many ways to fail, but if the failure is due to connection,
  // it's likely that the device is off-line. We treat the error differently
  // so that the file manager works while off-line.
  if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED) {
    UMA_HISTOGRAM_ENUMERATION("GData.AuthSuccess",
                              kSuccessRatioHistogramNoConnection,
                              kSuccessRatioHistogramMaxValue);
    callback_.Run(GDATA_NO_CONNECTION, std::string());
  } else {
    UMA_HISTOGRAM_ENUMERATION("GData.AuthSuccess",
                              kSuccessRatioHistogramFailure,
                              kSuccessRatioHistogramMaxValue);
    callback_.Run(HTTP_UNAUTHORIZED, std::string());
  }
  NotifyFinish(OPERATION_FAILED);
}

//============================ UrlFetchOperationBase ===========================

UrlFetchOperationBase::UrlFetchOperationBase(OperationRegistry* registry)
    : OperationRegistry::Operation(registry),
      re_authenticate_count_(0),
      save_temp_file_(false),
      started_(false) {
}

UrlFetchOperationBase::UrlFetchOperationBase(OperationRegistry* registry,
                                             OperationType type,
                                             const FilePath& path)
    : OperationRegistry::Operation(registry, type, path),
      re_authenticate_count_(0),
      save_temp_file_(false) {
}

UrlFetchOperationBase::~UrlFetchOperationBase() {}

void UrlFetchOperationBase::Start(const std::string& auth_token) {<commit_msg>[Coverity] Fix uninitialized member in ctor<commit_after>// 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 "chrome/browser/google_apis/operations_base.h"

#include "base/json/json_reader.h"
#include "base/metrics/histogram.h"
#include "base/string_number_conversions.h"
#include "base/stringprintf.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/common/net/url_util.h"
#include "content/public/browser/browser_thread.h"
#include "google_apis/gaia/gaia_urls.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "google_apis/gaia/oauth2_access_token_fetcher.h"
#include "net/base/load_flags.h"
#include "net/http/http_util.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request_status.h"

using content::BrowserThread;
using net::URLFetcher;

namespace {

// Used for success ratio histograms. 0 for failure, 1 for success,
// 2 for no connection (likely offline).
const int kSuccessRatioHistogramFailure = 0;
const int kSuccessRatioHistogramSuccess = 1;
const int kSuccessRatioHistogramNoConnection = 2;
const int kSuccessRatioHistogramMaxValue = 3;  // The max value is exclusive.

// Template for optional OAuth2 authorization HTTP header.
const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s";
// Template for GData API version HTTP header.
const char kGDataVersionHeader[] = "GData-Version: 3.0";

// Maximum number of attempts for re-authentication per operation.
const int kMaxReAuthenticateAttemptsPerOperation = 1;

// Parse JSON string to base::Value object.
void ParseJsonOnBlockingPool(const std::string& data,
                             scoped_ptr<base::Value>* value) {
  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));

  int error_code = -1;
  std::string error_message;
  value->reset(base::JSONReader::ReadAndReturnError(data,
                                                    base::JSON_PARSE_RFC,
                                                    &error_code,
                                                    &error_message));

  if (!value->get()) {
    LOG(ERROR) << "Error while parsing entry response: "
               << error_message
               << ", code: "
               << error_code
               << ", data:\n"
               << data;
  }
}

}  // namespace

namespace gdata {

//================================ AuthOperation ===============================

AuthOperation::AuthOperation(OperationRegistry* registry,
                             const AuthStatusCallback& callback,
                             const std::vector<std::string>& scopes,
                             const std::string& refresh_token)
    : OperationRegistry::Operation(registry),
      refresh_token_(refresh_token),
      callback_(callback),
      scopes_(scopes) {
}

AuthOperation::~AuthOperation() {}

void AuthOperation::Start() {
  DCHECK(!refresh_token_.empty());
  oauth2_access_token_fetcher_.reset(new OAuth2AccessTokenFetcher(
      this, g_browser_process->system_request_context()));
  NotifyStart();
  oauth2_access_token_fetcher_->Start(
      GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
      GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
      refresh_token_,
      scopes_);
}

void AuthOperation::DoCancel() {
  oauth2_access_token_fetcher_->CancelRequest();
  if (!callback_.is_null())
    callback_.Run(GDATA_CANCELLED, std::string());
}

// Callback for OAuth2AccessTokenFetcher on success. |access_token| is the token
// used to start fetching user data.
void AuthOperation::OnGetTokenSuccess(const std::string& access_token,
                                      const base::Time& expiration_time) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  UMA_HISTOGRAM_ENUMERATION("GData.AuthSuccess",
                            kSuccessRatioHistogramSuccess,
                            kSuccessRatioHistogramMaxValue);

  callback_.Run(HTTP_SUCCESS, access_token);
  NotifyFinish(OPERATION_COMPLETED);
}

// Callback for OAuth2AccessTokenFetcher on failure.
void AuthOperation::OnGetTokenFailure(const GoogleServiceAuthError& error) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  LOG(WARNING) << "AuthOperation: token request using refresh token failed"
               << error.ToString();

  // There are many ways to fail, but if the failure is due to connection,
  // it's likely that the device is off-line. We treat the error differently
  // so that the file manager works while off-line.
  if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED) {
    UMA_HISTOGRAM_ENUMERATION("GData.AuthSuccess",
                              kSuccessRatioHistogramNoConnection,
                              kSuccessRatioHistogramMaxValue);
    callback_.Run(GDATA_NO_CONNECTION, std::string());
  } else {
    UMA_HISTOGRAM_ENUMERATION("GData.AuthSuccess",
                              kSuccessRatioHistogramFailure,
                              kSuccessRatioHistogramMaxValue);
    callback_.Run(HTTP_UNAUTHORIZED, std::string());
  }
  NotifyFinish(OPERATION_FAILED);
}

//============================ UrlFetchOperationBase ===========================

UrlFetchOperationBase::UrlFetchOperationBase(OperationRegistry* registry)
    : OperationRegistry::Operation(registry),
      re_authenticate_count_(0),
      save_temp_file_(false),
      started_(false) {
}

UrlFetchOperationBase::UrlFetchOperationBase(OperationRegistry* registry,
                                             OperationType type,
                                             const FilePath& path)
    : OperationRegistry::Operation(registry, type, path),
      re_authenticate_count_(0),
      save_temp_file_(false),
      started_(false) {
}

UrlFetchOperationBase::~UrlFetchOperationBase() {}

void UrlFetchOperationBase::Start(const std::string& auth_token) {
{'fraction_non_alphanumeric': 0.11840444332239333, 'fraction_numerical': 0.0045443069931835394, 'mean_word_length': 3.2367201426024956, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 22, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5207682', 'n_tokens_mistral': 3296, 'n_tokens_neox': 3240, 'n_words': 680}