| 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 |