Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(630)

Side by Side Diff: components/signin/core/browser/access_token_fetcher.cc

Issue 2582573002: Signin/OAuth: Create an AccessTokenFetcher helper class (Closed)
Patch Set: review4 Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/signin/core/browser/access_token_fetcher.h"
6
7 #include <utility>
8
9 #include "base/logging.h"
10
11 AccessTokenFetcher::AccessTokenFetcher(
12 const std::string& oauth_consumer_name,
13 SigninManagerBase* signin_manager,
14 OAuth2TokenService* token_service,
15 const OAuth2TokenService::ScopeSet& scopes,
16 TokenCallback callback)
17 : OAuth2TokenService::Consumer(oauth_consumer_name),
18 signin_manager_(signin_manager),
19 token_service_(token_service),
20 scopes_(scopes),
21 callback_(std::move(callback)),
22 waiting_for_sign_in_(false),
23 waiting_for_refresh_token_(false),
24 access_token_retried_(false) {
25 Start();
26 }
27
28 AccessTokenFetcher::~AccessTokenFetcher() {
29 if (waiting_for_sign_in_) {
30 signin_manager_->RemoveObserver(this);
31 }
32 if (waiting_for_refresh_token_) {
33 token_service_->RemoveObserver(this);
34 }
35 }
36
37 void AccessTokenFetcher::Start() {
38 if (signin_manager_->IsAuthenticated()) {
39 // Already signed in: Make sure we have a refresh token, then get the access
40 // token.
41 WaitForRefreshToken();
42 return;
43 }
44
45 // Not signed in: Wait for a sign-in to complete (to get the refresh token),
46 // then get the access token.
47 DCHECK(!waiting_for_sign_in_);
48 waiting_for_sign_in_ = true;
49 signin_manager_->AddObserver(this);
50 }
51
52 void AccessTokenFetcher::WaitForRefreshToken() {
53 DCHECK(signin_manager_->IsAuthenticated());
54 DCHECK(!waiting_for_refresh_token_);
55
56 if (token_service_->RefreshTokenIsAvailable(
57 signin_manager_->GetAuthenticatedAccountId())) {
58 // Already have refresh token: Get the access token directly.
59 StartAccessTokenRequest();
60 return;
61 }
62
63 // Signed in, but refresh token isn't there yet: Wait for the refresh
64 // token to be loaded, then get the access token.
65 waiting_for_refresh_token_ = true;
66 token_service_->AddObserver(this);
67 }
68
69 void AccessTokenFetcher::StartAccessTokenRequest() {
70 DCHECK(token_service_->RefreshTokenIsAvailable(
71 signin_manager_->GetAuthenticatedAccountId()));
72 DCHECK(!access_token_request_);
73 access_token_request_ = token_service_->StartRequest(
74 signin_manager_->GetAuthenticatedAccountId(), scopes_, this);
75 }
76
77 void AccessTokenFetcher::GoogleSigninSucceeded(const std::string& account_id,
78 const std::string& username,
79 const std::string& password) {
80 DCHECK(waiting_for_sign_in_);
81 DCHECK(!waiting_for_refresh_token_);
82 DCHECK(signin_manager_->IsAuthenticated());
83 waiting_for_sign_in_ = false;
84 signin_manager_->RemoveObserver(this);
85
86 WaitForRefreshToken();
87 }
88
89 void AccessTokenFetcher::GoogleSigninFailed(
90 const GoogleServiceAuthError& error) {
91 DCHECK(waiting_for_sign_in_);
92 DCHECK(!waiting_for_refresh_token_);
93 waiting_for_sign_in_ = false;
94 signin_manager_->RemoveObserver(this);
95
96 std::move(callback_).Run(error, std::string());
97 }
98
99 void AccessTokenFetcher::OnRefreshTokenAvailable(
100 const std::string& account_id) {
101 DCHECK(waiting_for_refresh_token_);
102 DCHECK(!waiting_for_sign_in_);
103
104 // Only react on tokens for the account the user has signed in with.
105 if (account_id != signin_manager_->GetAuthenticatedAccountId()) {
106 return;
107 }
108
109 waiting_for_refresh_token_ = false;
110 token_service_->RemoveObserver(this);
111 StartAccessTokenRequest();
112 }
113
114 void AccessTokenFetcher::OnRefreshTokensLoaded() {
115 DCHECK(waiting_for_refresh_token_);
116 DCHECK(!waiting_for_sign_in_);
117 DCHECK(!access_token_request_);
118
119 // All refresh tokens were loaded, but we didn't get one for the account we
120 // care about. We probably won't get one any time soon.
121 waiting_for_refresh_token_ = false;
122 token_service_->RemoveObserver(this);
123 std::move(callback_).Run(
msarda 2017/01/27 12:35:37 I am a bit afraid of generating our own auth error
Marc Treib 2017/01/27 13:16:39 I wasn't happy about generating our own auth error
124 GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS),
125 std::string());
126 }
127
128 void AccessTokenFetcher::OnGetTokenSuccess(
129 const OAuth2TokenService::Request* request,
130 const std::string& access_token,
131 const base::Time& expiration_time) {
132 DCHECK_EQ(request, access_token_request_.get());
133 std::unique_ptr<OAuth2TokenService::Request> request_deleter(
134 std::move(access_token_request_));
135
136 std::move(callback_).Run(GoogleServiceAuthError::AuthErrorNone(),
137 access_token);
138 }
139
140 void AccessTokenFetcher::OnGetTokenFailure(
141 const OAuth2TokenService::Request* request,
142 const GoogleServiceAuthError& error) {
143 DCHECK_EQ(request, access_token_request_.get());
144 std::unique_ptr<OAuth2TokenService::Request> request_deleter(
145 std::move(access_token_request_));
146
147 // There is a special case for Android that RefreshTokenIsAvailable and
148 // StartRequest are called to pre-fetch the account image and name before
149 // sign-in. In that case, our ongoing access token request gets cancelled.
150 // Moreover, OnRefreshTokenAvailable might happen after startup when the
151 // credentials are changed/updated.
152 // To handle these cases, we retry a canceled request once.
153 // However, a request may also get cancelled for legitimate reasons, e.g.
154 // because the user signed out. In those cases, there's no point in retrying,
155 // so only retry if there (still) is a valid refresh token.
156 // TODO(treib): Should we check error.IsTransientError() instead of explicit
157 // checking for REQUEST_CANCELED?
158 if (!access_token_retried_ &&
159 error.state() == GoogleServiceAuthError::State::REQUEST_CANCELED &&
160 token_service_->RefreshTokenIsAvailable(
161 signin_manager_->GetAuthenticatedAccountId())) {
162 access_token_retried_ = true;
163 StartAccessTokenRequest();
164 return;
165 }
166
167 std::move(callback_).Run(error, std::string());
168 }
OLDNEW
« no previous file with comments | « components/signin/core/browser/access_token_fetcher.h ('k') | components/signin/core/browser/access_token_fetcher_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698