123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- // Copyright 2020 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 "ash/ambient/ambient_access_token_controller.h"
- #include "ash/login/ui/lock_screen.h"
- #include "ash/public/cpp/ambient/ambient_client.h"
- #include "base/bind.h"
- #include "base/logging.h"
- #include "base/rand_util.h"
- #include "base/time/time.h"
- namespace ash {
- namespace {
- constexpr int kMaxRetries = 3;
- constexpr net::BackoffEntry::Policy kRetryBackoffPolicy = {
- 0, // Number of initial errors to ignore.
- 1000, // Initial delay in ms.
- 2.0, // Factor by which the waiting time will be multiplied.
- 0.2, // Fuzzing percentage.
- 60 * 1000, // Maximum delay in ms.
- -1, // Never discard the entry.
- true, // Use initial delay.
- };
- } // namespace
- AmbientAccessTokenController::AmbientAccessTokenController()
- : refresh_token_retry_backoff_(&kRetryBackoffPolicy) {}
- AmbientAccessTokenController::~AmbientAccessTokenController() = default;
- void AmbientAccessTokenController::RequestAccessToken(
- AccessTokenCallback callback,
- bool may_refresh_token_on_lock) {
- // |token_refresh_timer_| may become stale during sleeping.
- if (token_refresh_timer_.IsRunning())
- token_refresh_timer_.AbandonAndStop();
- if (!access_token_.empty()) {
- DCHECK(!has_pending_request_);
- // Return the token if there is enough time to use the access token when
- // requested.
- if (expiration_time_ - base::Time::Now() > token_usage_time_buffer_) {
- RunCallback(std::move(callback));
- return;
- }
- access_token_ = std::string();
- expiration_time_ = base::Time::Now();
- }
- if (!may_refresh_token_on_lock && LockScreen::HasInstance()) {
- RunCallback(std::move(callback));
- return;
- }
- callbacks_.emplace_back(std::move(callback));
- if (has_pending_request_)
- return;
- RefreshAccessToken();
- }
- void AmbientAccessTokenController::RefreshAccessToken() {
- DCHECK(!token_refresh_timer_.IsRunning());
- has_pending_request_ = true;
- AmbientClient::Get()->RequestAccessToken(
- base::BindOnce(&AmbientAccessTokenController::AccessTokenRefreshed,
- weak_factory_.GetWeakPtr()));
- }
- void AmbientAccessTokenController::AccessTokenRefreshed(
- const std::string& gaia_id,
- const std::string& access_token,
- const base::Time& expiration_time) {
- has_pending_request_ = false;
- if (gaia_id.empty() || access_token.empty()) {
- refresh_token_retry_backoff_.InformOfRequest(/*succeeded=*/false);
- if (refresh_token_retry_backoff_.failure_count() <= kMaxRetries) {
- LOG(WARNING) << "Unable to refresh access token. Retrying..";
- RetryRefreshAccessToken();
- } else {
- LOG(ERROR) << "Unable to refresh access token. All retries attempted.";
- NotifyAccessTokenRefreshed();
- }
- return;
- }
- DVLOG(1) << "Access token fetched.";
- DCHECK(gaia_id_.empty() || gaia_id_ == gaia_id);
- refresh_token_retry_backoff_.Reset();
- gaia_id_ = gaia_id;
- access_token_ = access_token;
- expiration_time_ = expiration_time;
- NotifyAccessTokenRefreshed();
- }
- void AmbientAccessTokenController::RetryRefreshAccessToken() {
- base::TimeDelta backoff_delay =
- refresh_token_retry_backoff_.GetTimeUntilRelease();
- token_refresh_timer_.Start(
- FROM_HERE, backoff_delay,
- base::BindOnce(&AmbientAccessTokenController::RefreshAccessToken,
- base::Unretained(this)));
- }
- void AmbientAccessTokenController::NotifyAccessTokenRefreshed() {
- for (auto& callback : callbacks_)
- RunCallback(std::move(callback));
- callbacks_.clear();
- }
- void AmbientAccessTokenController::RunCallback(AccessTokenCallback callback) {
- std::move(callback).Run(gaia_id_, access_token_);
- }
- void AmbientAccessTokenController::SetTokenUsageBufferForTesting(
- base::TimeDelta time) {
- token_usage_time_buffer_ = time;
- }
- base::TimeDelta AmbientAccessTokenController::GetTimeUntilReleaseForTesting() {
- return refresh_token_retry_backoff_.GetTimeUntilRelease();
- }
- } // namespace ash
|