OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "google_apis/drive/auth_service.h" | 5 #include "google_apis/drive/auth_service.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/location.h" | 11 #include "base/location.h" |
12 #include "base/message_loop/message_loop_proxy.h" | 12 #include "base/message_loop/message_loop.h" |
13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
14 #include "google_apis/drive/auth_service_observer.h" | 14 #include "google_apis/drive/auth_service_observer.h" |
15 #include "google_apis/gaia/google_service_auth_error.h" | 15 #include "google_apis/gaia/google_service_auth_error.h" |
16 #include "net/url_request/url_request_context_getter.h" | 16 #include "net/url_request/url_request_context_getter.h" |
17 | 17 |
18 namespace google_apis { | 18 namespace google_apis { |
19 | 19 |
20 namespace { | 20 namespace { |
21 | 21 |
22 // Used for success ratio histograms. 0 for failure, 1 for success, | 22 // Used for success ratio histograms. 0 for failure, 1 for success, |
23 // 2 for no connection (likely offline). | 23 // 2 for no connection (likely offline). |
24 const int kSuccessRatioHistogramFailure = 0; | 24 const int kSuccessRatioHistogramFailure = 0; |
25 const int kSuccessRatioHistogramSuccess = 1; | 25 const int kSuccessRatioHistogramSuccess = 1; |
26 const int kSuccessRatioHistogramNoConnection = 2; | 26 const int kSuccessRatioHistogramNoConnection = 2; |
27 const int kSuccessRatioHistogramTemporaryFailure = 3; | 27 const int kSuccessRatioHistogramTemporaryFailure = 3; |
28 const int kSuccessRatioHistogramMaxValue = 4; // The max value is exclusive. | 28 const int kSuccessRatioHistogramMaxValue = 4; // The max value is exclusive. |
29 | 29 |
| 30 void RecordAuthResultHistogram(int value) { |
| 31 UMA_HISTOGRAM_ENUMERATION("GData.AuthSuccess", |
| 32 value, |
| 33 kSuccessRatioHistogramMaxValue); |
| 34 } |
| 35 |
30 // OAuth2 authorization token retrieval request. | 36 // OAuth2 authorization token retrieval request. |
31 class AuthRequest : public OAuth2TokenService::Consumer { | 37 class AuthRequest : public OAuth2TokenService::Consumer { |
32 public: | 38 public: |
33 AuthRequest(OAuth2TokenService* oauth2_token_service, | 39 AuthRequest(OAuth2TokenService* oauth2_token_service, |
34 const std::string& account_id, | 40 const std::string& account_id, |
35 net::URLRequestContextGetter* url_request_context_getter, | 41 net::URLRequestContextGetter* url_request_context_getter, |
36 const AuthStatusCallback& callback, | 42 const AuthStatusCallback& callback, |
37 const std::vector<std::string>& scopes); | 43 const std::vector<std::string>& scopes); |
38 virtual ~AuthRequest(); | 44 virtual ~AuthRequest(); |
39 | 45 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 | 77 |
72 AuthRequest::~AuthRequest() {} | 78 AuthRequest::~AuthRequest() {} |
73 | 79 |
74 // Callback for OAuth2AccessTokenFetcher on success. |access_token| is the token | 80 // Callback for OAuth2AccessTokenFetcher on success. |access_token| is the token |
75 // used to start fetching user data. | 81 // used to start fetching user data. |
76 void AuthRequest::OnGetTokenSuccess(const OAuth2TokenService::Request* request, | 82 void AuthRequest::OnGetTokenSuccess(const OAuth2TokenService::Request* request, |
77 const std::string& access_token, | 83 const std::string& access_token, |
78 const base::Time& expiration_time) { | 84 const base::Time& expiration_time) { |
79 DCHECK(thread_checker_.CalledOnValidThread()); | 85 DCHECK(thread_checker_.CalledOnValidThread()); |
80 | 86 |
81 UMA_HISTOGRAM_ENUMERATION("GData.AuthSuccess", | 87 RecordAuthResultHistogram(kSuccessRatioHistogramSuccess); |
82 kSuccessRatioHistogramSuccess, | |
83 kSuccessRatioHistogramMaxValue); | |
84 | |
85 callback_.Run(HTTP_SUCCESS, access_token); | 88 callback_.Run(HTTP_SUCCESS, access_token); |
86 delete this; | 89 delete this; |
87 } | 90 } |
88 | 91 |
89 // Callback for OAuth2AccessTokenFetcher on failure. | 92 // Callback for OAuth2AccessTokenFetcher on failure. |
90 void AuthRequest::OnGetTokenFailure(const OAuth2TokenService::Request* request, | 93 void AuthRequest::OnGetTokenFailure(const OAuth2TokenService::Request* request, |
91 const GoogleServiceAuthError& error) { | 94 const GoogleServiceAuthError& error) { |
92 DCHECK(thread_checker_.CalledOnValidThread()); | 95 DCHECK(thread_checker_.CalledOnValidThread()); |
93 | 96 |
94 LOG(WARNING) << "AuthRequest: token request using refresh token failed: " | 97 LOG(WARNING) << "AuthRequest: token request using refresh token failed: " |
95 << error.ToString(); | 98 << error.ToString(); |
96 | 99 |
97 // There are many ways to fail, but if the failure is due to connection, | 100 // There are many ways to fail, but if the failure is due to connection, |
98 // it's likely that the device is off-line. We treat the error differently | 101 // it's likely that the device is off-line. We treat the error differently |
99 // so that the file manager works while off-line. | 102 // so that the file manager works while off-line. |
100 if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED) { | 103 if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED) { |
101 UMA_HISTOGRAM_ENUMERATION("GData.AuthSuccess", | 104 RecordAuthResultHistogram(kSuccessRatioHistogramNoConnection); |
102 kSuccessRatioHistogramNoConnection, | |
103 kSuccessRatioHistogramMaxValue); | |
104 callback_.Run(GDATA_NO_CONNECTION, std::string()); | 105 callback_.Run(GDATA_NO_CONNECTION, std::string()); |
105 } else if (error.state() == GoogleServiceAuthError::SERVICE_UNAVAILABLE) { | 106 } else if (error.state() == GoogleServiceAuthError::SERVICE_UNAVAILABLE) { |
106 // Temporary auth error. | 107 RecordAuthResultHistogram(kSuccessRatioHistogramTemporaryFailure); |
107 UMA_HISTOGRAM_ENUMERATION("GData.AuthSuccess", | |
108 kSuccessRatioHistogramTemporaryFailure, | |
109 kSuccessRatioHistogramMaxValue); | |
110 callback_.Run(HTTP_FORBIDDEN, std::string()); | 108 callback_.Run(HTTP_FORBIDDEN, std::string()); |
111 } else { | 109 } else { |
112 // Permanent auth error. | 110 // Permanent auth error. |
113 UMA_HISTOGRAM_ENUMERATION("GData.AuthSuccess", | 111 RecordAuthResultHistogram(kSuccessRatioHistogramFailure); |
114 kSuccessRatioHistogramFailure, | |
115 kSuccessRatioHistogramMaxValue); | |
116 callback_.Run(HTTP_UNAUTHORIZED, std::string()); | 112 callback_.Run(HTTP_UNAUTHORIZED, std::string()); |
117 } | 113 } |
118 delete this; | 114 delete this; |
119 } | 115 } |
120 | 116 |
121 } // namespace | 117 } // namespace |
122 | 118 |
123 AuthService::AuthService( | 119 AuthService::AuthService( |
124 OAuth2TokenService* oauth2_token_service, | 120 OAuth2TokenService* oauth2_token_service, |
125 const std::string& account_id, | 121 const std::string& account_id, |
(...skipping 11 matching lines...) Expand all Loading... |
137 has_refresh_token_ = oauth2_token_service_->RefreshTokenIsAvailable( | 133 has_refresh_token_ = oauth2_token_service_->RefreshTokenIsAvailable( |
138 account_id_); | 134 account_id_); |
139 } | 135 } |
140 | 136 |
141 AuthService::~AuthService() { | 137 AuthService::~AuthService() { |
142 oauth2_token_service_->RemoveObserver(this); | 138 oauth2_token_service_->RemoveObserver(this); |
143 } | 139 } |
144 | 140 |
145 void AuthService::StartAuthentication(const AuthStatusCallback& callback) { | 141 void AuthService::StartAuthentication(const AuthStatusCallback& callback) { |
146 DCHECK(thread_checker_.CalledOnValidThread()); | 142 DCHECK(thread_checker_.CalledOnValidThread()); |
147 scoped_refptr<base::MessageLoopProxy> relay_proxy( | |
148 base::MessageLoopProxy::current()); | |
149 | 143 |
150 if (HasAccessToken()) { | 144 if (HasAccessToken()) { |
151 // We already have access token. Give it back to the caller asynchronously. | 145 // We already have access token. Give it back to the caller asynchronously. |
152 relay_proxy->PostTask(FROM_HERE, | 146 base::MessageLoop::current()->PostTask( |
153 base::Bind(callback, HTTP_SUCCESS, access_token_)); | 147 FROM_HERE, base::Bind(callback, HTTP_SUCCESS, access_token_)); |
154 } else if (HasRefreshToken()) { | 148 } else if (HasRefreshToken()) { |
155 // We have refresh token, let's get an access token. | 149 // We have refresh token, let's get an access token. |
156 new AuthRequest(oauth2_token_service_, | 150 new AuthRequest(oauth2_token_service_, |
157 account_id_, | 151 account_id_, |
158 url_request_context_getter_, | 152 url_request_context_getter_, |
159 base::Bind(&AuthService::OnAuthCompleted, | 153 base::Bind(&AuthService::OnAuthCompleted, |
160 weak_ptr_factory_.GetWeakPtr(), | 154 weak_ptr_factory_.GetWeakPtr(), |
161 callback), | 155 callback), |
162 scopes_); | 156 scopes_); |
163 } else { | 157 } else { |
164 relay_proxy->PostTask(FROM_HERE, | 158 base::MessageLoop::current()->PostTask( |
165 base::Bind(callback, GDATA_NOT_READY, std::string())); | 159 FROM_HERE, base::Bind(callback, GDATA_NOT_READY, std::string())); |
166 } | 160 } |
167 } | 161 } |
168 | 162 |
169 bool AuthService::HasAccessToken() const { | 163 bool AuthService::HasAccessToken() const { |
170 return !access_token_.empty(); | 164 return !access_token_.empty(); |
171 } | 165 } |
172 | 166 |
173 bool AuthService::HasRefreshToken() const { | 167 bool AuthService::HasRefreshToken() const { |
174 return has_refresh_token_; | 168 return has_refresh_token_; |
175 } | 169 } |
176 | 170 |
177 const std::string& AuthService::access_token() const { | 171 const std::string& AuthService::access_token() const { |
178 return access_token_; | 172 return access_token_; |
179 } | 173 } |
180 | 174 |
181 void AuthService::ClearAccessToken() { | 175 void AuthService::ClearAccessToken() { |
182 access_token_.clear(); | 176 access_token_.clear(); |
183 } | 177 } |
184 | 178 |
185 void AuthService::ClearRefreshToken() { | 179 void AuthService::ClearRefreshToken() { |
186 has_refresh_token_ = false; | 180 OnHandleRefreshToken(false); |
187 | |
188 FOR_EACH_OBSERVER(AuthServiceObserver, | |
189 observers_, | |
190 OnOAuth2RefreshTokenChanged()); | |
191 } | 181 } |
192 | 182 |
193 void AuthService::OnAuthCompleted(const AuthStatusCallback& callback, | 183 void AuthService::OnAuthCompleted(const AuthStatusCallback& callback, |
194 GDataErrorCode error, | 184 GDataErrorCode error, |
195 const std::string& access_token) { | 185 const std::string& access_token) { |
196 DCHECK(thread_checker_.CalledOnValidThread()); | 186 DCHECK(thread_checker_.CalledOnValidThread()); |
197 DCHECK(!callback.is_null()); | 187 DCHECK(!callback.is_null()); |
198 | 188 |
199 if (error == HTTP_SUCCESS) { | 189 if (error == HTTP_SUCCESS) { |
200 access_token_ = access_token; | 190 access_token_ = access_token; |
(...skipping 13 matching lines...) Expand all Loading... |
214 | 204 |
215 void AuthService::AddObserver(AuthServiceObserver* observer) { | 205 void AuthService::AddObserver(AuthServiceObserver* observer) { |
216 observers_.AddObserver(observer); | 206 observers_.AddObserver(observer); |
217 } | 207 } |
218 | 208 |
219 void AuthService::RemoveObserver(AuthServiceObserver* observer) { | 209 void AuthService::RemoveObserver(AuthServiceObserver* observer) { |
220 observers_.RemoveObserver(observer); | 210 observers_.RemoveObserver(observer); |
221 } | 211 } |
222 | 212 |
223 void AuthService::OnRefreshTokenAvailable(const std::string& account_id) { | 213 void AuthService::OnRefreshTokenAvailable(const std::string& account_id) { |
224 OnHandleRefreshToken(true); | 214 if (account_id == account_id_) |
| 215 OnHandleRefreshToken(true); |
225 } | 216 } |
226 | 217 |
227 void AuthService::OnRefreshTokenRevoked(const std::string& account_id) { | 218 void AuthService::OnRefreshTokenRevoked(const std::string& account_id) { |
228 OnHandleRefreshToken(false); | 219 if (account_id == account_id_) |
| 220 OnHandleRefreshToken(false); |
229 } | 221 } |
230 | 222 |
231 void AuthService::OnHandleRefreshToken(bool has_refresh_token) { | 223 void AuthService::OnHandleRefreshToken(bool has_refresh_token) { |
232 access_token_.clear(); | 224 access_token_.clear(); |
233 has_refresh_token_ = has_refresh_token; | 225 has_refresh_token_ = has_refresh_token; |
234 | 226 |
235 FOR_EACH_OBSERVER(AuthServiceObserver, | 227 FOR_EACH_OBSERVER(AuthServiceObserver, |
236 observers_, | 228 observers_, |
237 OnOAuth2RefreshTokenChanged()); | 229 OnOAuth2RefreshTokenChanged()); |
238 } | 230 } |
239 | 231 |
240 } // namespace google_apis | 232 } // namespace google_apis |
OLD | NEW |