blob: a71c37981b97852b06f062e5d788740ee9d8653a [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/quick_pair_browser_delegate.h"
#include "components/cross_device/logging/logging.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,
signin::OAuthConsumerId oauth_consumer_id)
: traffic_annotation_(traffic_annotation),
oauth_consumer_id_(oauth_consumer_id) {}
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) {
CD_LOG(VERBOSE, Feature::FP) << __func__ << ": executing request to: " << url;
CHECK(!has_call_started_)
<< __func__
<< ": Attempted to make an API call, but there is already a "
"request in progress.";
signin::IdentityManager* const identity_manager =
QuickPairBrowserDelegate::Get()->GetIdentityManager();
CHECK(identity_manager) << __func__ << ": IdentityManager is not available.";
has_call_started_ = true;
url_ = url;
callback_ = std::move(callback);
access_token_fetcher_ =
std::make_unique<signin::PrimaryAccountAccessTokenFetcher>(
oauth_consumer_id_, identity_manager,
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) {
CD_LOG(WARNING, Feature::FP)
<< __func__ << ": Failed to retrieve access token. "
<< error.ToString();
std::move(callback_).Run(std::nullopt, nullptr);
return;
}
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory =
QuickPairBrowserDelegate::Get()->GetURLLoaderFactory();
if (!url_loader_factory) {
CD_LOG(WARNING, Feature::FP)
<< __func__ << ": URLLoaderFactory is not available.";
std::move(callback_).Run(std::nullopt, nullptr);
return;
}
CD_LOG(VERBOSE, Feature::FP) << "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(std::string_view 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::optional<std::string> body) {
CD_LOG(INFO, Feature::FP) << __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::optional<std::string> body) {
CD_LOG(WARNING, Feature::FP) << __func__ << ": net_err=" << net_error;
std::move(callback_).Run(std::nullopt, std::make_unique<FastPairHttpResult>(
/*net_error=*/net_error,
/*head=*/head));
}
net::PartialNetworkTrafficAnnotationTag
OAuthHttpFetcher::GetNetworkTrafficAnnotationTag() {
return traffic_annotation_;
}
} // namespace quick_pair
} // namespace ash