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

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

Issue 2582573002: Signin/OAuth: Create an AccessTokenFetcher helper class (Closed)
Patch Set: AuthInProgress test Created 3 years, 11 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 "base/threading/thread_task_runner_handle.h"
11 #include "components/signin/core/browser/signin_manager_base.h"
12 #include "google_apis/gaia/google_service_auth_error.h"
13
14 AccessTokenFetcher::AccessTokenFetcher(
15 const std::string& oauth_consumer_name,
16 const SigninManagerBase* signin_manager,
17 OAuth2TokenService* token_service,
18 const OAuth2TokenService::ScopeSet& scopes,
19 const TokenCallback& callback)
20 : OAuth2TokenService::Consumer(oauth_consumer_name),
21 signin_manager_(signin_manager),
22 token_service_(token_service),
23 scopes_(scopes),
24 callback_(callback),
25 weak_ptr_factory_(this) {
26 Start();
27 }
28
29 AccessTokenFetcher::~AccessTokenFetcher() {
30 if (waiting_for_refresh_token_) {
31 token_service_->RemoveObserver(this);
32 }
33 }
34
35 void AccessTokenFetcher::Start() {
36 if (signin_manager_->IsAuthenticated() &&
37 token_service_->RefreshTokenIsAvailable(
38 signin_manager_->GetAuthenticatedAccountId())) {
39 // Already have refresh token: Get the access token directly.
40 StartAccessTokenRequest();
41 } else if (signin_manager_->IsAuthenticated() ||
42 signin_manager_->AuthInProgress()) {
43 // Currently signing in, or signed in but refresh token isn't there yet:
44 // Wait for auth to finish (to get the refresh token), then get the access
45 // token.
46 // TODO(treib): In the AuthInProgress case, should we wait for
47 // GoogleSigninSucceeded/Failed (from SigninManagerBase::Observer) first?
msarda 2017/01/18 21:55:19 I agree this is a tricky question: currently the r
Marc Treib 2017/01/19 15:03:55 Done. However, I'm still not super confident that
msarda 2017/01/23 17:08:09 I think using a timeout is not a good API. This c
Marc Treib 2017/01/24 10:17:32 Not calling the callback after we're destroyed is
48 DCHECK(!waiting_for_refresh_token_);
49 waiting_for_refresh_token_ = true;
50 token_service_->AddObserver(this);
51 } else {
52 // Not signed in, no access token. Make sure not to run the callback
53 // synchronously, and not to run it if we get deleted in the meantime.
54 base::ThreadTaskRunnerHandle::Get()->PostTask(
msarda 2017/01/18 21:55:19 It is not clear to me how you would use this API:
Marc Treib 2017/01/19 15:03:55 There are some (future) clients of this class that
55 FROM_HERE, base::Bind(&AccessTokenFetcher::NotSignedInCallback,
56 weak_ptr_factory_.GetWeakPtr()));
57 }
58 }
59
60 void AccessTokenFetcher::NotSignedInCallback() {
61 callback_.Run(std::string());
msarda 2017/01/18 21:55:19 We should to pass an error to the callback here a
msarda 2017/01/18 21:55:19 We should use a callback that may be called only o
Marc Treib 2017/01/19 15:03:55 I actually did use OnceCallback in a previous iter
Marc Treib 2017/01/19 15:03:55 So far, none of the callers I'm aware of care abou
msarda 2017/01/23 17:08:09 I think the current API is fine for discussion, bu
62 }
63
64 void AccessTokenFetcher::OnRefreshTokenAvailable(
65 const std::string& account_id) {
66 DCHECK(waiting_for_refresh_token_);
msarda 2017/01/18 21:55:19 Just to make sure what I said in my previous comme
Marc Treib 2017/01/19 15:03:55 Done.
67
68 // Only react on tokens for the account the user has signed in with.
69 if (account_id != signin_manager_->GetAuthenticatedAccountId()) {
70 return;
71 }
72
msarda 2017/01/18 21:55:18 Nit: I would set waiting_for_refresh_token_ before
Marc Treib 2017/01/19 15:03:55 Done.
73 token_service_->RemoveObserver(this);
74 waiting_for_refresh_token_ = false;
75 StartAccessTokenRequest();
76 }
77
78 void AccessTokenFetcher::OnRefreshTokensLoaded() {
79 DCHECK(waiting_for_refresh_token_);
80
81 // All refresh tokens were loaded, but we didn't get one for the account we
82 // care about. We probably won't get one any time soon.
83 token_service_->RemoveObserver(this);
84 waiting_for_refresh_token_ = false;
85 callback_.Run(std::string());
86 }
87
88 void AccessTokenFetcher::StartAccessTokenRequest() {
89 access_token_request_ = token_service_->StartRequest(
90 signin_manager_->GetAuthenticatedAccountId(), scopes_, this);
91 }
92
93 void AccessTokenFetcher::OnGetTokenSuccess(
94 const OAuth2TokenService::Request* request,
95 const std::string& access_token,
96 const base::Time& expiration_time) {
97 DCHECK_EQ(request, access_token_request_.get());
98 std::unique_ptr<OAuth2TokenService::Request> request_deleter(
99 std::move(access_token_request_));
100
101 callback_.Run(access_token);
102 }
103
104 void AccessTokenFetcher::OnGetTokenFailure(
105 const OAuth2TokenService::Request* request,
106 const GoogleServiceAuthError& error) {
107 DCHECK_EQ(request, access_token_request_.get());
108 std::unique_ptr<OAuth2TokenService::Request> request_deleter(
109 std::move(access_token_request_));
110
111 if (!access_token_retried_ &&
112 error.state() == GoogleServiceAuthError::State::REQUEST_CANCELED) {
113 // The request can get reset by loading the refresh token (happens during
114 // startup) - try one more time.
115 access_token_retried_ = true;
116 StartAccessTokenRequest();
msarda 2017/01/18 21:55:19 It is not clear to me yet why we need to retry. I
Marc Treib 2017/01/19 15:03:55 We had a case on Android where sometimes during st
jkrcal 2017/01/19 15:48:45 I agree it is ugly. Reasoning for the retry: https
msarda 2017/01/23 17:08:09 Thank you for the pointer. I think we should not d
Marc Treib 2017/01/24 10:17:32 The thread is not public unfortunately, so we can'
117 return;
118 }
119
120 DLOG(WARNING) << "Unable to get token: " << error.ToString();
121 callback_.Run(std::string());
msarda 2017/01/18 21:55:18 We need an API that would allow us to pass the err
Marc Treib 2017/01/24 10:17:32 I'd actually prefer if any retrying were handled w
msarda 2017/01/25 09:54:28 I agree with this - we should hide the nasty thing
122 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698