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

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

Issue 2582573002: Signin/OAuth: Create an AccessTokenFetcher helper class (Closed)
Patch Set: review2 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 #include "google_apis/gaia/google_service_auth_error.h"
11
12 AccessTokenFetcher::AccessTokenFetcher(
13 const std::string& oauth_consumer_name,
14 SigninManagerBase* signin_manager,
15 OAuth2TokenService* token_service,
16 const OAuth2TokenService::ScopeSet& scopes,
17 TokenCallback callback)
18 : OAuth2TokenService::Consumer(oauth_consumer_name),
19 signin_manager_(signin_manager),
20 token_service_(token_service),
21 scopes_(scopes),
22 callback_(std::move(callback)),
23 waiting_for_sign_in_(false),
24 waiting_for_refresh_token_(false),
25 access_token_retried_(false) {
26 Start();
27 }
28
29 AccessTokenFetcher::~AccessTokenFetcher() {
30 if (waiting_for_sign_in_) {
31 signin_manager_->RemoveObserver(this);
32 }
33 if (waiting_for_refresh_token_) {
34 token_service_->RemoveObserver(this);
35 }
36 }
37
38 void AccessTokenFetcher::Start() {
39 if (signin_manager_->IsAuthenticated()) {
40 // Already signed in: Make sure we have a refresh token, then get the access
41 // token.
42 WaitForRefreshToken();
43 } else {
44 // Not signed in: Wait for a sign-in to complete (to get the refresh token),
45 // then get the access token.
46 DCHECK(!waiting_for_sign_in_);
47 waiting_for_sign_in_ = true;
48 signin_manager_->AddObserver(this);
49 }
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();
msarda 2017/01/25 09:54:29 Optional nit: Let's use an early return here and r
Marc Treib 2017/01/25 11:37:04 Done. Also done similarly in Start() above.
60 } else {
61 // Signed in, but refresh token isn't there yet: Wait for the refresh
62 // token to be loaded, then get the access token.
63 waiting_for_refresh_token_ = true;
64 token_service_->AddObserver(this);
65 }
66 }
67
68 void AccessTokenFetcher::StartAccessTokenRequest() {
msarda 2017/01/25 09:54:29 Let's add a DCHECK that this method is called only
Marc Treib 2017/01/25 11:37:04 Yup, sounds reasonable. Done.
69 access_token_request_ = token_service_->StartRequest(
70 signin_manager_->GetAuthenticatedAccountId(), scopes_, this);
71 }
72
73 void AccessTokenFetcher::GoogleSigninSucceeded(const std::string& account_id,
74 const std::string& username,
75 const std::string& password) {
76 DCHECK(waiting_for_sign_in_);
77 DCHECK(!waiting_for_refresh_token_);
78 waiting_for_sign_in_ = false;
79 signin_manager_->RemoveObserver(this);
80
81 DCHECK(signin_manager_->IsAuthenticated());
msarda 2017/01/25 09:54:29 Nit: Move this DCHECK in the group of DCHECKs abov
Marc Treib 2017/01/25 11:37:04 Done.
82
83 WaitForRefreshToken();
84 }
85
86 void AccessTokenFetcher::GoogleSigninFailed(
87 const GoogleServiceAuthError& error) {
88 DCHECK(waiting_for_sign_in_);
89 DCHECK(!waiting_for_refresh_token_);
90 waiting_for_sign_in_ = false;
91 signin_manager_->RemoveObserver(this);
92
93 std::move(callback_).Run(std::string());
94 }
95
96 void AccessTokenFetcher::OnRefreshTokenAvailable(
97 const std::string& account_id) {
98 DCHECK(waiting_for_refresh_token_);
99 DCHECK(!waiting_for_sign_in_);
100
101 // Only react on tokens for the account the user has signed in with.
102 if (account_id != signin_manager_->GetAuthenticatedAccountId()) {
103 return;
104 }
105
106 waiting_for_refresh_token_ = false;
107 token_service_->RemoveObserver(this);
108 StartAccessTokenRequest();
109 }
110
111 void AccessTokenFetcher::OnRefreshTokensLoaded() {
112 DCHECK(waiting_for_refresh_token_);
113 DCHECK(!waiting_for_sign_in_);
114
115 // All refresh tokens were loaded, but we didn't get one for the account we
116 // care about. We probably won't get one any time soon.
117 waiting_for_refresh_token_ = false;
118 token_service_->RemoveObserver(this);
119 std::move(callback_).Run(std::string());
120 }
121
122 void AccessTokenFetcher::OnGetTokenSuccess(
123 const OAuth2TokenService::Request* request,
124 const std::string& access_token,
125 const base::Time& expiration_time) {
126 DCHECK_EQ(request, access_token_request_.get());
127 std::unique_ptr<OAuth2TokenService::Request> request_deleter(
128 std::move(access_token_request_));
129
130 std::move(callback_).Run(access_token);
131 }
132
133 void AccessTokenFetcher::OnGetTokenFailure(
134 const OAuth2TokenService::Request* request,
135 const GoogleServiceAuthError& error) {
136 DCHECK_EQ(request, access_token_request_.get());
137 std::unique_ptr<OAuth2TokenService::Request> request_deleter(
138 std::move(access_token_request_));
139
140 if (!access_token_retried_ &&
141 error.state() == GoogleServiceAuthError::State::REQUEST_CANCELED) {
msarda 2017/01/25 09:54:29 I think this case is a bit more tricky: 1. If the
Marc Treib 2017/01/25 11:37:04 Yup, that sounds very reasonable! I guess it doesn
142 // There is a special case for Android that RefreshTokenIsAvailable and
143 // StartRequest are called to pre-fetch the account image and name before
144 // sign-in. In that case, our ongoing access token request gets cancelled.
145 // Moreover, OnRefreshTokenAvailable might happen after startup when the
146 // credentials are changed/updated.
147 // To handle these cases, we retry a canceled request once.
148 access_token_retried_ = true;
149 StartAccessTokenRequest();
150 return;
151 }
152
153 DLOG(WARNING) << "Unable to get token: " << error.ToString();
154 std::move(callback_).Run(std::string());
155 }
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