blob: d94de803e5b632ea0e30db8b23f5b13bab9ae75b [file] [log] [blame]
// Copyright 2019 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 "remoting/base/offline_token_exchanger.h"
#include <utility>
#include "base/logging.h"
#include "google_apis/google_api_keys.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace remoting {
namespace {
// Maximum number of retries on network/500 errors.
const int kMaxRetries = 3;
} // namespace
OfflineTokenExchanger::OfflineTokenExchanger(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
: gaia_oauth_client_(
std::make_unique<gaia::GaiaOAuthClient>(url_loader_factory)),
token_exchanger_(url_loader_factory) {
token_exchanger_.set_offline_mode(true);
}
OfflineTokenExchanger::~OfflineTokenExchanger() = default;
void OfflineTokenExchanger::ExchangeRefreshToken(
const std::string& refresh_token,
TokenCallback callback) {
DCHECK(callback_.is_null());
callback_ = std::move(callback);
// Get access token from refresh token, needed by OAuthTokenExchanger.
gaia::OAuthClientInfo client_info = {
google_apis::GetOAuth2ClientID(google_apis::CLIENT_REMOTING_HOST),
google_apis::GetOAuth2ClientSecret(google_apis::CLIENT_REMOTING_HOST),
// Redirect URL is only used when getting tokens from auth code. It
// is not required when getting access tokens from refresh tokens.
""};
std::vector<std::string> empty_scope_list; // Use scope from refresh token.
gaia_oauth_client_->RefreshToken(client_info, refresh_token, empty_scope_list,
kMaxRetries, this);
}
void OfflineTokenExchanger::OnRefreshTokenResponse(
const std::string& access_token,
int expires_in_seconds) {
access_token_ = access_token;
token_exchanger_.ExchangeToken(
access_token,
base::BindOnce(&OfflineTokenExchanger::OnExchangeTokenResponse,
base::Unretained(this)));
}
void OfflineTokenExchanger::OnOAuthError() {
LOG(ERROR) << "OAuth error.";
std::move(callback_).Run(FAILURE, std::string());
}
void OfflineTokenExchanger::OnNetworkError(int response_code) {
LOG(ERROR) << "Network error: " << response_code;
std::move(callback_).Run(FAILURE, std::string());
}
void OfflineTokenExchanger::OnExchangeTokenResponse(
OAuthTokenGetter::Status status,
const std::string& refresh_token,
const std::string& access_token) {
if (status == OAuthTokenGetter::SUCCESS) {
if (access_token_ == access_token) {
std::move(callback_).Run(NO_EXCHANGE, std::string());
} else {
std::move(callback_).Run(SUCCESS, refresh_token);
}
} else {
LOG(ERROR) << "Error exchanging token.";
std::move(callback_).Run(FAILURE, std::string());
}
}
} // namespace remoting