blob: 2c0f61aa8aa0c4e27fddb6458c5fd921b3e326fa [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/quick_pair/repository/oauth_http_fetcher.h"
#include "ash/quick_pair/common/fast_pair/fast_pair_http_result.h"
#include "ash/quick_pair/common/logging.h"
#include "ash/quick_pair/common/quick_pair_browser_delegate.h"
#include "components/signin/public/base/consent_level.h"
#include "components/signin/public/identity_manager/access_token_info.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/primary_account_access_token_fetcher.h"
#include "google_apis/gaia/gaia_constants.h"
#include "net/base/net_errors.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
namespace ash {
namespace quick_pair {
OAuthHttpFetcher::OAuthHttpFetcher(
const net::PartialNetworkTrafficAnnotationTag& traffic_annotation,
const std::string& oauth_scope)
: traffic_annotation_(traffic_annotation) {
oauth_scopes_.insert(oauth_scope);
}
OAuthHttpFetcher::~OAuthHttpFetcher() = default;
void OAuthHttpFetcher::ExecuteGetRequest(const GURL& url,
FetchCompleteCallback callback) {
request_type_ = RequestType::GET;
StartRequest(url, std::move(callback));
}
void OAuthHttpFetcher::ExecutePostRequest(const GURL& url,
const std::string& body,
FetchCompleteCallback callback) {
request_type_ = RequestType::POST;
body_ = body;
StartRequest(url, std::move(callback));
}
void OAuthHttpFetcher::ExecuteDeleteRequest(const GURL& url,
FetchCompleteCallback callback) {
request_type_ = RequestType::DELETE;
StartRequest(url, std::move(callback));
}
void OAuthHttpFetcher::StartRequest(const GURL& url,
FetchCompleteCallback callback) {
QP_LOG(VERBOSE) << __func__ << ": executing request to: " << url;
if (has_call_started_) {
QP_LOG(ERROR) << __func__
<< ": Attempted to make an API call, but there is already a "
"request in progress.";
NOTREACHED();
return;
}
signin::IdentityManager* identity_manager =
QuickPairBrowserDelegate::Get()->GetIdentityManager();
if (!identity_manager) {
QP_LOG(ERROR) << __func__ << ": IdentityManager is not available.";
NOTREACHED();
return;
}
has_call_started_ = true;
url_ = url;
callback_ = std::move(callback);
access_token_fetcher_ =
std::make_unique<signin::PrimaryAccountAccessTokenFetcher>(
"fastpair_client", identity_manager, oauth_scopes_,
base::BindOnce(&OAuthHttpFetcher::OnAccessTokenFetched,
weak_ptr_factory_.GetWeakPtr()),
signin::PrimaryAccountAccessTokenFetcher::Mode::kImmediate,
signin::ConsentLevel::kSignin);
}
void OAuthHttpFetcher::OnAccessTokenFetched(
GoogleServiceAuthError error,
signin::AccessTokenInfo access_token_info) {
access_token_fetcher_.reset();
if (error.state() != GoogleServiceAuthError::NONE) {
QP_LOG(WARNING) << __func__ << ": Failed to retrieve access token. "
<< error.ToString();
std::move(callback_).Run(nullptr, nullptr);
return;
}
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory =
QuickPairBrowserDelegate::Get()->GetURLLoaderFactory();
if (!url_loader_factory) {
QP_LOG(WARNING) << __func__ << ": URLLoaderFactory is not available.";
std::move(callback_).Run(nullptr, nullptr);
return;
}
QP_LOG(VERBOSE) << "Access token fetched successfully.";
OAuth2ApiCallFlow::Start(std::move(url_loader_factory),
access_token_info.token);
}
GURL OAuthHttpFetcher::CreateApiCallUrl() {
return url_;
}
std::string OAuthHttpFetcher::CreateApiCallBody() {
switch (request_type_) {
case RequestType::GET:
case RequestType::DELETE:
return std::string();
case RequestType::POST:
return body_;
}
}
std::string OAuthHttpFetcher::CreateApiCallBodyContentType() {
switch (request_type_) {
case RequestType::GET:
case RequestType::DELETE:
return std::string();
case RequestType::POST:
return "application/x-protobuf";
}
}
std::string OAuthHttpFetcher::GetRequestTypeForBody(const std::string& body) {
switch (request_type_) {
case RequestType::GET:
return "GET";
case RequestType::POST:
return "POST";
case RequestType::DELETE:
return "DELETE";
}
}
void OAuthHttpFetcher::ProcessApiCallSuccess(
const network::mojom::URLResponseHead* head,
std::unique_ptr<std::string> body) {
QP_LOG(INFO) << __func__;
std::move(callback_).Run(
std::move(body),
std::make_unique<FastPairHttpResult>(/*net_error=*/net::OK,
/*head=*/head));
}
void OAuthHttpFetcher::ProcessApiCallFailure(
int net_error,
const network::mojom::URLResponseHead* head,
std::unique_ptr<std::string> body) {
QP_LOG(WARNING) << __func__ << ": net_err=" << net_error;
std::move(callback_).Run(
nullptr, std::make_unique<FastPairHttpResult>(/*net_error=*/net_error,
/*head=*/head));
}
net::PartialNetworkTrafficAnnotationTag
OAuthHttpFetcher::GetNetworkTrafficAnnotationTag() {
return traffic_annotation_;
}
} // namespace quick_pair
} // namespace ash