blob: 46be6f06b147a04d674284db59838fb794ee8e56 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/signin/bound_session_credentials/bound_session_refresh_cookie_fetcher_impl.h"
#include <memory>
#include "components/signin/public/base/signin_client.h"
#include "google_apis/gaia/gaia_urls.h"
#include "net/traffic_annotation/network_traffic_annotation.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"
#include "third_party/abseil-cpp/absl/types/optional.h"
BoundSessionRefreshCookieFetcherImpl::BoundSessionRefreshCookieFetcherImpl(
SigninClient* client)
: client_(client), url_loader_factory_(client->GetURLLoaderFactory()) {}
BoundSessionRefreshCookieFetcherImpl::~BoundSessionRefreshCookieFetcherImpl() =
default;
void BoundSessionRefreshCookieFetcherImpl::Start(
RefreshCookieCompleteCallback callback) {
CHECK(!callback_);
CHECK(callback);
callback_ = std::move(callback);
client_->DelayNetworkCall(
base::BindOnce(&BoundSessionRefreshCookieFetcherImpl::StartRefreshRequest,
weak_ptr_factory_.GetWeakPtr()));
}
void BoundSessionRefreshCookieFetcherImpl::StartRefreshRequest() {
// TODO(b/273920907): Update the `traffic_annotation` setting once a mechanism
// allowing the user to disable the feature is implemented.
net::NetworkTrafficAnnotationTag traffic_annotation =
net::DefineNetworkTrafficAnnotation("gaia_auth_rotate_bound_cookies",
R"(
semantics {
sender: "Chrome - Google authentication API"
description:
"This request is used to rotate bound Google authentication "
"cookies."
trigger:
"This request is triggered in a bound session when the bound Google"
" authentication cookies are soon to expire."
user_data {
type: ACCESS_TOKEN
}
data: "Request includes cookies and a signed token proving that a"
" request comes from the same device as was registered before."
destination: GOOGLE_OWNED_SERVICE
internal {
contacts {
email: "chrome-signin-team@google.com"
}
}
last_reviewed: "2023-05-09"
}
policy {
cookies_allowed: YES
cookies_store: "user"
setting:
"This feature is under development and must be enabled by user"
" action."
policy_exception_justification:
"Not implemented. "
"If the feature is on, this request must be made to ensure the user"
" maintains their signed in status on the web for Google owned"
" domains."
})");
auto request = std::make_unique<network::ResourceRequest>();
request->url = GaiaUrls::GetInstance()->rotate_bound_cookies_url();
request->method = "GET";
url::Origin origin = GaiaUrls::GetInstance()->gaia_origin();
request->site_for_cookies = net::SiteForCookies::FromOrigin(origin);
request->trusted_params = network::ResourceRequest::TrustedParams();
request->trusted_params->isolation_info =
net::IsolationInfo::CreateForInternalRequest(origin);
// TODO(b/273920907): Figure out how to handle redirects. Currently
// `network::SimpleURLLoader::SetOnRedirectCallback()` doesn't support
// modifying the headers nor asynchronously resuming the reguest.
url_loader_ =
network::SimpleURLLoader::Create(std::move(request), traffic_annotation);
url_loader_->SetRetryOptions(
3, network::SimpleURLLoader::RETRY_ON_NETWORK_CHANGE);
// TODO(b/273920907): Download the response body to support in refresh DBSC
// instructions update.
// `base::Unretained(this)` is safe as `this` owns `url_loader_`.
url_loader_->DownloadHeadersOnly(
url_loader_factory_.get(),
base::BindOnce(&BoundSessionRefreshCookieFetcherImpl::OnURLLoaderComplete,
base::Unretained(this)));
}
void BoundSessionRefreshCookieFetcherImpl::OnURLLoaderComplete(
scoped_refptr<net::HttpResponseHeaders> headers) {
net::Error net_error = static_cast<net::Error>(url_loader_->NetError());
std::move(callback_).Run(
Result(net_error, headers ? absl::optional<int>(headers->response_code())
: absl::nullopt));
}