forked from Pissandshittium/pissandshittium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathambient_access_token_controller.cc
117 lines (88 loc) · 3.28 KB
/
ambient_access_token_controller.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// 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 <algorithm>
#include <utility>
#include "ash/public/cpp/ambient/ambient_client.h"
#include "base/rand_util.h"
#include "base/time/time.h"
namespace ash {
namespace {
constexpr base::TimeDelta kMinTokenRefreshDelay =
base::TimeDelta::FromMilliseconds(1000);
constexpr base::TimeDelta kMaxTokenRefreshDelay =
base::TimeDelta::FromMilliseconds(60 * 1000);
// The buffer time to use the access token.
constexpr base::TimeDelta kTokenExpirationTimeBuffer =
base::TimeDelta::FromMinutes(10);
} // namespace
AmbientAccessTokenController::AmbientAccessTokenController() = default;
AmbientAccessTokenController::~AmbientAccessTokenController() = default;
void AmbientAccessTokenController::RequestAccessToken(
AccessTokenCallback callback) {
// |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() > kTokenExpirationTimeBuffer) {
RunCallback(std::move(callback));
return;
}
access_token_ = std::string();
expiration_time_ = base::Time::Now();
}
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()) {
RetryRefreshAccessToken();
return;
}
VLOG(1) << "Access token fetched.";
gaia_id_ = gaia_id;
access_token_ = access_token;
expiration_time_ = expiration_time;
NotifyAccessTokenRefreshed();
}
void AmbientAccessTokenController::RetryRefreshAccessToken() {
base::TimeDelta backoff_delay =
std::min(kMinTokenRefreshDelay *
(1 << (token_refresh_error_backoff_factor - 1)),
kMaxTokenRefreshDelay) +
base::RandDouble() * kMinTokenRefreshDelay;
if (backoff_delay < kMaxTokenRefreshDelay)
++token_refresh_error_backoff_factor;
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) {
DCHECK(!gaia_id_.empty());
DCHECK(!access_token_.empty());
std::move(callback).Run(gaia_id_, access_token_);
}
} // namespace ash