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

Side by Side Diff: chrome/browser/google_apis/auth_service.cc

Issue 96413002: Move c/b/google_apis to google_apis/drive. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 7 years 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 "chrome/browser/google_apis/auth_service.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/location.h"
12 #include "base/message_loop/message_loop_proxy.h"
13 #include "base/metrics/histogram.h"
14 #include "chrome/browser/google_apis/auth_service_observer.h"
15 #include "google_apis/gaia/google_service_auth_error.h"
16 #include "net/url_request/url_request_context_getter.h"
17
18 namespace google_apis {
19
20 namespace {
21
22 // Used for success ratio histograms. 0 for failure, 1 for success,
23 // 2 for no connection (likely offline).
24 const int kSuccessRatioHistogramFailure = 0;
25 const int kSuccessRatioHistogramSuccess = 1;
26 const int kSuccessRatioHistogramNoConnection = 2;
27 const int kSuccessRatioHistogramTemporaryFailure = 3;
28 const int kSuccessRatioHistogramMaxValue = 4; // The max value is exclusive.
29
30 // OAuth2 authorization token retrieval request.
31 class AuthRequest : public OAuth2TokenService::Consumer {
32 public:
33 AuthRequest(OAuth2TokenService* oauth2_token_service,
34 const std::string& account_id,
35 net::URLRequestContextGetter* url_request_context_getter,
36 const AuthStatusCallback& callback,
37 const std::vector<std::string>& scopes);
38 virtual ~AuthRequest();
39
40 private:
41 // Overridden from OAuth2TokenService::Consumer:
42 virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
43 const std::string& access_token,
44 const base::Time& expiration_time) OVERRIDE;
45 virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
46 const GoogleServiceAuthError& error) OVERRIDE;
47
48 AuthStatusCallback callback_;
49 scoped_ptr<OAuth2TokenService::Request> request_;
50 base::ThreadChecker thread_checker_;
51
52 DISALLOW_COPY_AND_ASSIGN(AuthRequest);
53 };
54
55 AuthRequest::AuthRequest(
56 OAuth2TokenService* oauth2_token_service,
57 const std::string& account_id,
58 net::URLRequestContextGetter* url_request_context_getter,
59 const AuthStatusCallback& callback,
60 const std::vector<std::string>& scopes)
61 : callback_(callback) {
62 DCHECK(!callback_.is_null());
63 request_ = oauth2_token_service->
64 StartRequestWithContext(
65 account_id,
66 url_request_context_getter,
67 OAuth2TokenService::ScopeSet(scopes.begin(), scopes.end()),
68 this);
69 }
70
71 AuthRequest::~AuthRequest() {}
72
73 // Callback for OAuth2AccessTokenFetcher on success. |access_token| is the token
74 // used to start fetching user data.
75 void AuthRequest::OnGetTokenSuccess(const OAuth2TokenService::Request* request,
76 const std::string& access_token,
77 const base::Time& expiration_time) {
78 DCHECK(thread_checker_.CalledOnValidThread());
79
80 UMA_HISTOGRAM_ENUMERATION("GData.AuthSuccess",
81 kSuccessRatioHistogramSuccess,
82 kSuccessRatioHistogramMaxValue);
83
84 callback_.Run(HTTP_SUCCESS, access_token);
85 delete this;
86 }
87
88 // Callback for OAuth2AccessTokenFetcher on failure.
89 void AuthRequest::OnGetTokenFailure(const OAuth2TokenService::Request* request,
90 const GoogleServiceAuthError& error) {
91 DCHECK(thread_checker_.CalledOnValidThread());
92
93 LOG(WARNING) << "AuthRequest: token request using refresh token failed: "
94 << error.ToString();
95
96 // There are many ways to fail, but if the failure is due to connection,
97 // it's likely that the device is off-line. We treat the error differently
98 // so that the file manager works while off-line.
99 if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED) {
100 UMA_HISTOGRAM_ENUMERATION("GData.AuthSuccess",
101 kSuccessRatioHistogramNoConnection,
102 kSuccessRatioHistogramMaxValue);
103 callback_.Run(GDATA_NO_CONNECTION, std::string());
104 } else if (error.state() == GoogleServiceAuthError::SERVICE_UNAVAILABLE) {
105 // Temporary auth error.
106 UMA_HISTOGRAM_ENUMERATION("GData.AuthSuccess",
107 kSuccessRatioHistogramTemporaryFailure,
108 kSuccessRatioHistogramMaxValue);
109 callback_.Run(HTTP_FORBIDDEN, std::string());
110 } else {
111 // Permanent auth error.
112 UMA_HISTOGRAM_ENUMERATION("GData.AuthSuccess",
113 kSuccessRatioHistogramFailure,
114 kSuccessRatioHistogramMaxValue);
115 callback_.Run(HTTP_UNAUTHORIZED, std::string());
116 }
117 delete this;
118 }
119
120 } // namespace
121
122 AuthService::AuthService(
123 OAuth2TokenService* oauth2_token_service,
124 const std::string& account_id,
125 net::URLRequestContextGetter* url_request_context_getter,
126 const std::vector<std::string>& scopes)
127 : oauth2_token_service_(oauth2_token_service),
128 account_id_(account_id),
129 url_request_context_getter_(url_request_context_getter),
130 scopes_(scopes),
131 weak_ptr_factory_(this) {
132 DCHECK(oauth2_token_service);
133
134 // Get OAuth2 refresh token (if we have any) and register for its updates.
135 oauth2_token_service_->AddObserver(this);
136 has_refresh_token_ = oauth2_token_service_->RefreshTokenIsAvailable(
137 account_id_);
138 }
139
140 AuthService::~AuthService() {
141 oauth2_token_service_->RemoveObserver(this);
142 }
143
144 void AuthService::StartAuthentication(const AuthStatusCallback& callback) {
145 DCHECK(thread_checker_.CalledOnValidThread());
146 scoped_refptr<base::MessageLoopProxy> relay_proxy(
147 base::MessageLoopProxy::current());
148
149 if (HasAccessToken()) {
150 // We already have access token. Give it back to the caller asynchronously.
151 relay_proxy->PostTask(FROM_HERE,
152 base::Bind(callback, HTTP_SUCCESS, access_token_));
153 } else if (HasRefreshToken()) {
154 // We have refresh token, let's get an access token.
155 new AuthRequest(oauth2_token_service_,
156 account_id_,
157 url_request_context_getter_,
158 base::Bind(&AuthService::OnAuthCompleted,
159 weak_ptr_factory_.GetWeakPtr(),
160 callback),
161 scopes_);
162 } else {
163 relay_proxy->PostTask(FROM_HERE,
164 base::Bind(callback, GDATA_NOT_READY, std::string()));
165 }
166 }
167
168 bool AuthService::HasAccessToken() const {
169 return !access_token_.empty();
170 }
171
172 bool AuthService::HasRefreshToken() const {
173 return has_refresh_token_;
174 }
175
176 const std::string& AuthService::access_token() const {
177 return access_token_;
178 }
179
180 void AuthService::ClearAccessToken() {
181 access_token_.clear();
182 }
183
184 void AuthService::ClearRefreshToken() {
185 has_refresh_token_ = false;
186
187 FOR_EACH_OBSERVER(AuthServiceObserver,
188 observers_,
189 OnOAuth2RefreshTokenChanged());
190 }
191
192 void AuthService::OnAuthCompleted(const AuthStatusCallback& callback,
193 GDataErrorCode error,
194 const std::string& access_token) {
195 DCHECK(thread_checker_.CalledOnValidThread());
196 DCHECK(!callback.is_null());
197
198 if (error == HTTP_SUCCESS) {
199 access_token_ = access_token;
200 } else if (error == HTTP_UNAUTHORIZED) {
201 // Refreshing access token using the refresh token is failed with 401 error
202 // (HTTP_UNAUTHORIZED). This means the current refresh token is invalid for
203 // Drive, hence we clear the refresh token here to make HasRefreshToken()
204 // false, thus the invalidness is clearly observable.
205 // This is not for triggering refetch of the refresh token. UI should
206 // show some message to encourage user to log-off and log-in again in order
207 // to fetch new valid refresh token.
208 ClearRefreshToken();
209 }
210
211 callback.Run(error, access_token);
212 }
213
214 void AuthService::AddObserver(AuthServiceObserver* observer) {
215 observers_.AddObserver(observer);
216 }
217
218 void AuthService::RemoveObserver(AuthServiceObserver* observer) {
219 observers_.RemoveObserver(observer);
220 }
221
222 void AuthService::OnRefreshTokenAvailable(const std::string& account_id) {
223 OnHandleRefreshToken(true);
224 }
225
226 void AuthService::OnRefreshTokenRevoked(const std::string& account_id) {
227 OnHandleRefreshToken(false);
228 }
229
230 void AuthService::OnHandleRefreshToken(bool has_refresh_token) {
231 access_token_.clear();
232 has_refresh_token_ = has_refresh_token;
233
234 FOR_EACH_OBSERVER(AuthServiceObserver,
235 observers_,
236 OnOAuth2RefreshTokenChanged());
237 }
238
239 } // namespace google_apis
OLDNEW
« no previous file with comments | « chrome/browser/google_apis/auth_service.h ('k') | chrome/browser/google_apis/auth_service_interface.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698