Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 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 "chrome/browser/signin/oauth2_token_service.h" | 5 #include "chrome/browser/signin/oauth2_token_service.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/memory/weak_ptr.h" | 10 #include "base/memory/weak_ptr.h" |
| 11 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
| 12 #include "base/rand_util.h" | 12 #include "base/rand_util.h" |
| 13 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
| 14 #include "base/time/time.h" | 14 #include "base/time/time.h" |
| 15 #include "base/timer/timer.h" | |
| 16 #include "content/public/browser/browser_thread.h" | 15 #include "content/public/browser/browser_thread.h" |
| 17 #include "google_apis/gaia/gaia_urls.h" | 16 #include "google_apis/gaia/gaia_urls.h" |
| 18 #include "google_apis/gaia/google_service_auth_error.h" | 17 #include "google_apis/gaia/google_service_auth_error.h" |
| 19 #include "google_apis/gaia/oauth2_access_token_consumer.h" | |
| 20 #include "google_apis/gaia/oauth2_access_token_fetcher.h" | |
| 21 #include "net/url_request/url_request_context_getter.h" | 18 #include "net/url_request/url_request_context_getter.h" |
| 22 | 19 |
| 23 int OAuth2TokenService::max_fetch_retry_num_ = 5; | 20 int OAuth2TokenService::max_fetch_retry_num_ = 5; |
| 24 | 21 |
| 22 OAuth2TokenService::ClientScopeSet::ClientScopeSet( | |
| 23 const std::string& request_origin, | |
| 24 const std::string& client_id, | |
| 25 const ScopeSet& scopes) | |
| 26 : request_origin(request_origin), | |
| 27 client_id(client_id), | |
| 28 scopes(scopes) { | |
| 29 } | |
| 30 | |
| 31 bool OAuth2TokenService::ClientScopeSet::operator<( | |
| 32 const ClientScopeSet& s) const { | |
| 33 return ((request_origin < s.request_origin) || | |
| 34 (!(s.request_origin < request_origin) && (client_id < s.client_id))) || | |
|
Andrew T Wilson (Slow)
2013/08/19 14:04:19
I wonder if this would be more legible as if state
zel
2013/08/19 16:03:17
I've also got deceived believing that what you pro
fgorski
2013/08/19 16:16:06
There is a way to rewrite the conditions in a long
zel
2013/08/19 16:25:48
Right. Done. PTAL.
| |
| 35 (!(s.request_origin < request_origin) && | |
| 36 !(s.client_id < client_id) && | |
| 37 (scopes < s.scopes)); | |
| 38 } | |
| 39 | |
| 40 OAuth2TokenService::FetchParameters::FetchParameters( | |
| 41 const std::string& request_origin, | |
| 42 const std::string& client_id, | |
| 43 const std::string& refresh_token, | |
| 44 const ScopeSet& scopes) | |
| 45 : request_origin(request_origin), | |
| 46 client_id(client_id), | |
| 47 refresh_token(refresh_token), | |
| 48 scopes(scopes) { | |
| 49 } | |
| 50 | |
| 51 bool OAuth2TokenService::FetchParameters::operator<( | |
| 52 const FetchParameters& p) const { | |
| 53 return ((request_origin < p.request_origin) || | |
| 54 (!(p.request_origin < request_origin) && (client_id < p.client_id))) || | |
| 55 (!(p.request_origin < request_origin) && | |
|
Andrew T Wilson (Slow)
2013/08/19 14:04:19
See my previous comment. This nested logic just se
zel
2013/08/19 16:03:17
See my comments above. There aren't many obvious w
| |
| 56 !(p.client_id < client_id) && | |
| 57 (refresh_token < p.refresh_token)) || | |
| 58 (!(p.request_origin < request_origin) && | |
| 59 !(p.client_id < client_id) && | |
| 60 !(p.refresh_token < refresh_token) && | |
| 61 (scopes < p.scopes)); | |
| 62 } | |
| 63 | |
| 25 OAuth2TokenService::RequestImpl::RequestImpl( | 64 OAuth2TokenService::RequestImpl::RequestImpl( |
| 26 OAuth2TokenService::Consumer* consumer) | 65 OAuth2TokenService::Consumer* consumer) |
| 27 : consumer_(consumer) { | 66 : consumer_(consumer) { |
| 28 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 67 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 29 } | 68 } |
| 30 | 69 |
| 31 OAuth2TokenService::RequestImpl::~RequestImpl() { | 70 OAuth2TokenService::RequestImpl::~RequestImpl() { |
| 32 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 71 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 33 } | 72 } |
| 34 | 73 |
| 35 void OAuth2TokenService::RequestImpl::InformConsumer( | 74 void OAuth2TokenService::RequestImpl::InformConsumer( |
| 36 const GoogleServiceAuthError& error, | 75 const GoogleServiceAuthError& error, |
| 37 const std::string& access_token, | 76 const std::string& access_token, |
| 38 const base::Time& expiration_date) { | 77 const base::Time& expiration_date) { |
| 39 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 78 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 40 if (error.state() == GoogleServiceAuthError::NONE) | 79 if (error.state() == GoogleServiceAuthError::NONE) |
| 41 consumer_->OnGetTokenSuccess(this, access_token, expiration_date); | 80 consumer_->OnGetTokenSuccess(this, access_token, expiration_date); |
| 42 else | 81 else |
| 43 consumer_->OnGetTokenFailure(this, error); | 82 consumer_->OnGetTokenFailure(this, error); |
| 44 } | 83 } |
| 45 | 84 |
| 46 // Class that fetches OAuth2 access tokens for given scopes and refresh token. | |
| 47 // | |
| 48 // It aims to meet OAuth2TokenService's requirements on token fetching. Retry | |
| 49 // mechanism is used to handle failures. | |
| 50 // | |
| 51 // To use this class, call CreateAndStart() to create and start a Fetcher. | |
| 52 // | |
| 53 // The Fetcher will call back the service by calling | |
| 54 // OAuth2TokenService::OnFetchComplete() when it completes fetching, if it is | |
| 55 // not destructed before it completes fetching; if the Fetcher is destructed | |
| 56 // before it completes fetching, the service will never be called back. The | |
| 57 // Fetcher destructs itself after calling back the service when finishes | |
| 58 // fetching. | |
| 59 // | |
| 60 // Requests that are waiting for the fetching results of this Fetcher can be | |
| 61 // added to the Fetcher by calling | |
| 62 // OAuth2TokenService::Fetcher::AddWaitingRequest() before the Fetcher completes | |
| 63 // fetching. | |
| 64 // | |
| 65 // The waiting requests are taken as weak pointers and they can be deleted. The | |
| 66 // waiting requests will be called back with fetching results if they are not | |
| 67 // deleted | |
| 68 // - when the Fetcher completes fetching, if the Fetcher is not destructed | |
| 69 // before it completes fetching, or | |
| 70 // - when the Fetcher is destructed if the Fetcher is destructed before it | |
| 71 // completes fetching (in this case, the waiting requests will be called back | |
| 72 // with error). | |
| 73 class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer { | |
| 74 public: | |
| 75 // Creates a Fetcher and starts fetching an OAuth2 access token for | |
| 76 // |refresh_token| and |scopes| in the request context obtained by |getter|. | |
| 77 // The given |oauth2_token_service| will be informed when fetching is done. | |
| 78 static Fetcher* CreateAndStart(OAuth2TokenService* oauth2_token_service, | |
| 79 net::URLRequestContextGetter* getter, | |
| 80 const std::string& chrome_client_id, | |
| 81 const std::string& chrome_client_secret, | |
| 82 const std::string& refresh_token, | |
| 83 const OAuth2TokenService::ScopeSet& scopes, | |
| 84 base::WeakPtr<RequestImpl> waiting_request); | |
| 85 virtual ~Fetcher(); | |
| 86 | |
| 87 // Add a request that is waiting for the result of this Fetcher. | |
| 88 void AddWaitingRequest(base::WeakPtr<RequestImpl> waiting_request); | |
| 89 | |
| 90 void Cancel(); | |
| 91 | |
| 92 const OAuth2TokenService::ScopeSet& GetScopeSet() const; | |
| 93 const std::string& GetRefreshToken() const; | |
| 94 | |
| 95 // The error result from this fetcher. | |
| 96 const GoogleServiceAuthError& error() const { return error_; } | |
| 97 | |
| 98 protected: | |
| 99 // OAuth2AccessTokenConsumer | |
| 100 virtual void OnGetTokenSuccess(const std::string& access_token, | |
| 101 const base::Time& expiration_date) OVERRIDE; | |
| 102 virtual void OnGetTokenFailure(const GoogleServiceAuthError& error) OVERRIDE; | |
| 103 | |
| 104 private: | |
| 105 Fetcher(OAuth2TokenService* oauth2_token_service, | |
| 106 net::URLRequestContextGetter* getter, | |
| 107 const std::string& chrome_client_id, | |
| 108 const std::string& chrome_client_secret, | |
| 109 const std::string& refresh_token, | |
| 110 const OAuth2TokenService::ScopeSet& scopes, | |
| 111 base::WeakPtr<RequestImpl> waiting_request); | |
| 112 void Start(); | |
| 113 void InformWaitingRequests(); | |
| 114 void InformWaitingRequestsAndDelete(); | |
| 115 static bool ShouldRetry(const GoogleServiceAuthError& error); | |
| 116 int64 ComputeExponentialBackOffMilliseconds(int retry_num); | |
| 117 | |
| 118 // |oauth2_token_service_| remains valid for the life of this Fetcher, since | |
| 119 // this Fetcher is destructed in the dtor of the OAuth2TokenService or is | |
| 120 // scheduled for deletion at the end of OnGetTokenFailure/OnGetTokenSuccess | |
| 121 // (whichever comes first). | |
| 122 OAuth2TokenService* const oauth2_token_service_; | |
| 123 scoped_refptr<net::URLRequestContextGetter> getter_; | |
| 124 const std::string refresh_token_; | |
| 125 const OAuth2TokenService::ScopeSet scopes_; | |
| 126 std::vector<base::WeakPtr<RequestImpl> > waiting_requests_; | |
| 127 | |
| 128 int retry_number_; | |
| 129 base::OneShotTimer<OAuth2TokenService::Fetcher> retry_timer_; | |
| 130 scoped_ptr<OAuth2AccessTokenFetcher> fetcher_; | |
| 131 | |
| 132 // Variables that store fetch results. | |
| 133 // Initialized to be GoogleServiceAuthError::SERVICE_UNAVAILABLE to handle | |
| 134 // destruction. | |
| 135 GoogleServiceAuthError error_; | |
| 136 std::string access_token_; | |
| 137 base::Time expiration_date_; | |
| 138 // OAuth2 client id and secret. | |
| 139 std::string chrome_client_id_; | |
| 140 std::string chrome_client_secret_; | |
| 141 | |
| 142 DISALLOW_COPY_AND_ASSIGN(Fetcher); | |
| 143 }; | |
| 144 | |
| 145 // static | 85 // static |
| 146 OAuth2TokenService::Fetcher* OAuth2TokenService::Fetcher::CreateAndStart( | 86 OAuth2TokenService::Fetcher* OAuth2TokenService::Fetcher::CreateAndStart( |
| 147 OAuth2TokenService* oauth2_token_service, | 87 OAuth2TokenService* oauth2_token_service, |
| 148 net::URLRequestContextGetter* getter, | 88 net::URLRequestContextGetter* getter, |
| 149 const std::string& chrome_client_id, | 89 const std::string& request_origin, |
| 150 const std::string& chrome_client_secret, | 90 const std::string& client_id, |
| 91 const std::string& client_secret, | |
| 151 const std::string& refresh_token, | 92 const std::string& refresh_token, |
| 152 const OAuth2TokenService::ScopeSet& scopes, | 93 const OAuth2TokenService::ScopeSet& scopes, |
| 153 base::WeakPtr<RequestImpl> waiting_request) { | 94 base::WeakPtr<RequestImpl> waiting_request) { |
| 154 OAuth2TokenService::Fetcher* fetcher = new Fetcher( | 95 OAuth2TokenService::Fetcher* fetcher = new Fetcher( |
| 155 oauth2_token_service, | 96 oauth2_token_service, |
| 156 getter, | 97 getter, |
| 157 chrome_client_id, | 98 request_origin, |
| 158 chrome_client_secret, | 99 client_id, |
| 100 client_secret, | |
| 159 refresh_token, | 101 refresh_token, |
| 160 scopes, | 102 scopes, |
| 161 waiting_request); | 103 waiting_request); |
| 162 fetcher->Start(); | 104 fetcher->Start(); |
| 163 return fetcher; | 105 return fetcher; |
| 164 } | 106 } |
| 165 | 107 |
| 166 OAuth2TokenService::Fetcher::Fetcher( | 108 OAuth2TokenService::Fetcher::Fetcher( |
| 167 OAuth2TokenService* oauth2_token_service, | 109 OAuth2TokenService* oauth2_token_service, |
| 168 net::URLRequestContextGetter* getter, | 110 net::URLRequestContextGetter* getter, |
| 169 const std::string& chrome_client_id, | 111 const std::string& request_origin, |
| 170 const std::string& chrome_client_secret, | 112 const std::string& client_id, |
| 113 const std::string& client_secret, | |
| 171 const std::string& refresh_token, | 114 const std::string& refresh_token, |
| 172 const OAuth2TokenService::ScopeSet& scopes, | 115 const OAuth2TokenService::ScopeSet& scopes, |
| 173 base::WeakPtr<RequestImpl> waiting_request) | 116 base::WeakPtr<RequestImpl> waiting_request) |
| 174 : oauth2_token_service_(oauth2_token_service), | 117 : oauth2_token_service_(oauth2_token_service), |
| 175 getter_(getter), | 118 getter_(getter), |
| 176 refresh_token_(refresh_token), | 119 refresh_token_(refresh_token), |
| 177 scopes_(scopes), | 120 scopes_(scopes), |
| 178 retry_number_(0), | 121 retry_number_(0), |
| 179 error_(GoogleServiceAuthError::SERVICE_UNAVAILABLE), | 122 error_(GoogleServiceAuthError::SERVICE_UNAVAILABLE), |
| 180 chrome_client_id_(chrome_client_id), | 123 request_origin_(request_origin), |
| 181 chrome_client_secret_(chrome_client_secret) { | 124 client_id_(client_id), |
| 125 client_secret_(client_secret) { | |
| 182 DCHECK(oauth2_token_service_); | 126 DCHECK(oauth2_token_service_); |
| 183 DCHECK(getter_.get()); | 127 DCHECK(getter_.get()); |
| 184 DCHECK(refresh_token_.length()); | 128 DCHECK(refresh_token_.length()); |
| 185 waiting_requests_.push_back(waiting_request); | 129 waiting_requests_.push_back(waiting_request); |
| 186 } | 130 } |
| 187 | 131 |
| 188 OAuth2TokenService::Fetcher::~Fetcher() { | 132 OAuth2TokenService::Fetcher::~Fetcher() { |
| 189 // Inform the waiting requests if it has not done so. | 133 // Inform the waiting requests if it has not done so. |
| 190 if (waiting_requests_.size()) | 134 if (waiting_requests_.size()) |
| 191 InformWaitingRequests(); | 135 InformWaitingRequests(); |
| 192 } | 136 } |
| 193 | 137 |
| 194 void OAuth2TokenService::Fetcher::Start() { | 138 void OAuth2TokenService::Fetcher::Start() { |
| 195 fetcher_.reset(new OAuth2AccessTokenFetcher(this, getter_.get())); | 139 fetcher_.reset(new OAuth2AccessTokenFetcher(this, getter_.get())); |
| 196 fetcher_->Start(chrome_client_id_, | 140 fetcher_->Start(client_id_, |
| 197 chrome_client_secret_, | 141 client_secret_, |
| 198 refresh_token_, | 142 refresh_token_, |
| 199 std::vector<std::string>(scopes_.begin(), scopes_.end())); | 143 std::vector<std::string>(scopes_.begin(), scopes_.end())); |
| 200 retry_timer_.Stop(); | 144 retry_timer_.Stop(); |
| 201 } | 145 } |
| 202 | 146 |
| 203 void OAuth2TokenService::Fetcher::OnGetTokenSuccess( | 147 void OAuth2TokenService::Fetcher::OnGetTokenSuccess( |
| 204 const std::string& access_token, | 148 const std::string& access_token, |
| 205 const base::Time& expiration_date) { | 149 const base::Time& expiration_date) { |
| 206 fetcher_.reset(); | 150 fetcher_.reset(); |
| 207 | 151 |
| 208 // Fetch completes. | 152 // Fetch completes. |
| 209 error_ = GoogleServiceAuthError::AuthErrorNone(); | 153 error_ = GoogleServiceAuthError::AuthErrorNone(); |
| 210 access_token_ = access_token; | 154 access_token_ = access_token; |
| 211 expiration_date_ = expiration_date; | 155 expiration_date_ = expiration_date; |
| 212 | 156 |
| 213 // Subclasses may override this method to skip caching in some cases, but | 157 // Subclasses may override this method to skip caching in some cases, but |
| 214 // we still inform all waiting Consumers of a successful token fetch below. | 158 // we still inform all waiting Consumers of a successful token fetch below. |
| 215 // This is intentional -- some consumers may need the token for cleanup | 159 // This is intentional -- some consumers may need the token for cleanup |
| 216 // tasks. https://chromiumcodereview.appspot.com/11312124/ | 160 // tasks. https://chromiumcodereview.appspot.com/11312124/ |
| 217 oauth2_token_service_->RegisterCacheEntry(refresh_token_, | 161 oauth2_token_service_->RegisterCacheEntry(request_origin_, |
| 162 client_id_, | |
| 163 refresh_token_, | |
| 218 scopes_, | 164 scopes_, |
| 219 access_token_, | 165 access_token_, |
| 220 expiration_date_); | 166 expiration_date_); |
| 221 InformWaitingRequestsAndDelete(); | 167 InformWaitingRequestsAndDelete(); |
| 222 } | 168 } |
| 223 | 169 |
| 224 void OAuth2TokenService::Fetcher::OnGetTokenFailure( | 170 void OAuth2TokenService::Fetcher::OnGetTokenFailure( |
| 225 const GoogleServiceAuthError& error) { | 171 const GoogleServiceAuthError& error) { |
| 226 fetcher_.reset(); | 172 fetcher_.reset(); |
| 227 | 173 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 276 oauth2_token_service_->OnFetchComplete(this); | 222 oauth2_token_service_->OnFetchComplete(this); |
| 277 InformWaitingRequests(); | 223 InformWaitingRequests(); |
| 278 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); | 224 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| 279 } | 225 } |
| 280 | 226 |
| 281 void OAuth2TokenService::Fetcher::AddWaitingRequest( | 227 void OAuth2TokenService::Fetcher::AddWaitingRequest( |
| 282 base::WeakPtr<OAuth2TokenService::RequestImpl> waiting_request) { | 228 base::WeakPtr<OAuth2TokenService::RequestImpl> waiting_request) { |
| 283 waiting_requests_.push_back(waiting_request); | 229 waiting_requests_.push_back(waiting_request); |
| 284 } | 230 } |
| 285 | 231 |
| 232 size_t OAuth2TokenService::Fetcher::GetWaitingRequestCount() const { | |
| 233 return waiting_requests_.size(); | |
| 234 } | |
| 235 | |
| 286 void OAuth2TokenService::Fetcher::Cancel() { | 236 void OAuth2TokenService::Fetcher::Cancel() { |
| 287 fetcher_.reset(); | 237 fetcher_.reset(); |
| 288 retry_timer_.Stop(); | 238 retry_timer_.Stop(); |
| 289 error_ = GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED); | 239 error_ = GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED); |
| 290 InformWaitingRequestsAndDelete(); | 240 InformWaitingRequestsAndDelete(); |
| 291 } | 241 } |
| 292 | 242 |
| 293 const OAuth2TokenService::ScopeSet& OAuth2TokenService::Fetcher::GetScopeSet() | 243 const OAuth2TokenService::ScopeSet& OAuth2TokenService::Fetcher::GetScopeSet() |
| 294 const { | 244 const { |
| 295 return scopes_; | 245 return scopes_; |
| 296 } | 246 } |
| 297 | 247 |
| 298 const std::string& OAuth2TokenService::Fetcher::GetRefreshToken() const { | 248 const std::string& OAuth2TokenService::Fetcher::GetRefreshToken() const { |
| 299 return refresh_token_; | 249 return refresh_token_; |
| 300 } | 250 } |
| 301 | 251 |
| 252 const std::string& OAuth2TokenService::Fetcher::GetClientId() const { | |
| 253 return client_id_; | |
| 254 } | |
| 255 | |
| 256 const std::string& OAuth2TokenService::Fetcher::GetRequestOrigin() const { | |
| 257 return request_origin_; | |
| 258 } | |
| 259 | |
| 302 OAuth2TokenService::Request::Request() { | 260 OAuth2TokenService::Request::Request() { |
| 303 } | 261 } |
| 304 | 262 |
| 305 OAuth2TokenService::Request::~Request() { | 263 OAuth2TokenService::Request::~Request() { |
| 306 } | 264 } |
| 307 | 265 |
| 308 OAuth2TokenService::Consumer::Consumer() { | 266 OAuth2TokenService::Consumer::Consumer() { |
| 309 } | 267 } |
| 310 | 268 |
| 311 OAuth2TokenService::Consumer::~Consumer() { | 269 OAuth2TokenService::Consumer::~Consumer() { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 332 bool OAuth2TokenService::RefreshTokenIsAvailable() { | 290 bool OAuth2TokenService::RefreshTokenIsAvailable() { |
| 333 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 291 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 334 return !GetRefreshToken().empty(); | 292 return !GetRefreshToken().empty(); |
| 335 } | 293 } |
| 336 | 294 |
| 337 scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest( | 295 scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest( |
| 338 const OAuth2TokenService::ScopeSet& scopes, | 296 const OAuth2TokenService::ScopeSet& scopes, |
| 339 OAuth2TokenService::Consumer* consumer) { | 297 OAuth2TokenService::Consumer* consumer) { |
| 340 return StartRequestForClientWithContext( | 298 return StartRequestForClientWithContext( |
| 341 GetRequestContext(), | 299 GetRequestContext(), |
| 300 std::string(), | |
| 342 GaiaUrls::GetInstance()->oauth2_chrome_client_id(), | 301 GaiaUrls::GetInstance()->oauth2_chrome_client_id(), |
| 343 GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), | 302 GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), |
| 344 scopes, | 303 scopes, |
| 345 consumer); | 304 consumer); |
| 346 } | 305 } |
| 347 | 306 |
| 348 scoped_ptr<OAuth2TokenService::Request> | 307 scoped_ptr<OAuth2TokenService::Request> |
| 349 OAuth2TokenService::StartRequestForClient( | 308 OAuth2TokenService::StartRequestForClient( |
| 309 const std::string& request_origin, | |
| 350 const std::string& client_id, | 310 const std::string& client_id, |
| 351 const std::string& client_secret, | 311 const std::string& client_secret, |
| 352 const OAuth2TokenService::ScopeSet& scopes, | 312 const OAuth2TokenService::ScopeSet& scopes, |
| 353 OAuth2TokenService::Consumer* consumer) { | 313 OAuth2TokenService::Consumer* consumer) { |
| 354 return StartRequestForClientWithContext( | 314 return StartRequestForClientWithContext( |
| 355 GetRequestContext(), | 315 GetRequestContext(), |
| 316 request_origin, | |
| 356 client_id, | 317 client_id, |
| 357 client_secret, | 318 client_secret, |
| 358 scopes, | 319 scopes, |
| 359 consumer); | 320 consumer); |
| 360 } | 321 } |
| 361 | 322 |
| 362 scoped_ptr<OAuth2TokenService::Request> | 323 scoped_ptr<OAuth2TokenService::Request> |
| 363 OAuth2TokenService::StartRequestWithContext( | 324 OAuth2TokenService::StartRequestWithContext( |
| 364 net::URLRequestContextGetter* getter, | 325 net::URLRequestContextGetter* getter, |
| 365 const ScopeSet& scopes, | 326 const ScopeSet& scopes, |
| 366 Consumer* consumer) { | 327 Consumer* consumer) { |
| 367 return StartRequestForClientWithContext( | 328 return StartRequestForClientWithContext( |
| 368 getter, | 329 getter, |
| 330 std::string(), | |
| 369 GaiaUrls::GetInstance()->oauth2_chrome_client_id(), | 331 GaiaUrls::GetInstance()->oauth2_chrome_client_id(), |
| 370 GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), | 332 GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), |
| 371 scopes, | 333 scopes, |
| 372 consumer); | 334 consumer); |
| 373 } | 335 } |
| 374 | 336 |
| 375 scoped_ptr<OAuth2TokenService::Request> | 337 scoped_ptr<OAuth2TokenService::Request> |
| 376 OAuth2TokenService::StartRequestForClientWithContext( | 338 OAuth2TokenService::StartRequestForClientWithContext( |
| 377 net::URLRequestContextGetter* getter, | 339 net::URLRequestContextGetter* getter, |
| 340 const std::string& request_origin, | |
| 378 const std::string& client_id, | 341 const std::string& client_id, |
| 379 const std::string& client_secret, | 342 const std::string& client_secret, |
| 380 const ScopeSet& scopes, | 343 const ScopeSet& scopes, |
| 381 Consumer* consumer) { | 344 Consumer* consumer) { |
| 382 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 345 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 383 | 346 |
| 384 scoped_ptr<RequestImpl> request(new RequestImpl(consumer)); | 347 scoped_ptr<RequestImpl> request(new RequestImpl(consumer)); |
| 385 | 348 |
| 386 std::string refresh_token = GetRefreshToken(); | 349 std::string refresh_token = GetRefreshToken(); |
| 387 if (refresh_token.empty()) { | 350 if (refresh_token.empty()) { |
| 388 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 351 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
| 389 &RequestImpl::InformConsumer, | 352 &RequestImpl::InformConsumer, |
| 390 request->AsWeakPtr(), | 353 request->AsWeakPtr(), |
| 391 GoogleServiceAuthError( | 354 GoogleServiceAuthError( |
| 392 GoogleServiceAuthError::USER_NOT_SIGNED_UP), | 355 GoogleServiceAuthError::USER_NOT_SIGNED_UP), |
| 393 std::string(), | 356 std::string(), |
| 394 base::Time())); | 357 base::Time())); |
| 395 return request.PassAs<Request>(); | 358 return request.PassAs<Request>(); |
| 396 } | 359 } |
| 397 | 360 |
| 398 if (HasCacheEntry(scopes)) | 361 ClientScopeSet client_scopes(request_origin, |
| 399 return StartCacheLookupRequest(scopes, consumer); | 362 client_id, |
| 363 scopes); | |
| 364 if (HasCacheEntry(client_scopes)) | |
| 365 return StartCacheLookupRequest(client_scopes, consumer); | |
| 400 | 366 |
| 401 // If there is already a pending fetcher for |scopes| and |refresh_token|, | 367 // If there is already a pending fetcher for |scopes| and |refresh_token|, |
| 402 // simply register this |request| for those results rather than starting | 368 // simply register this |request| for those results rather than starting |
| 403 // a new fetcher. | 369 // a new fetcher. |
| 404 FetchParameters fetch_parameters = std::make_pair(refresh_token, scopes); | 370 FetchParameters fetch_parameters = FetchParameters(request_origin, |
| 371 client_id, | |
| 372 refresh_token, | |
| 373 scopes); | |
| 405 std::map<FetchParameters, Fetcher*>::iterator iter = | 374 std::map<FetchParameters, Fetcher*>::iterator iter = |
| 406 pending_fetchers_.find(fetch_parameters); | 375 pending_fetchers_.find(fetch_parameters); |
| 407 if (iter != pending_fetchers_.end()) { | 376 if (iter != pending_fetchers_.end()) { |
| 408 iter->second->AddWaitingRequest(request->AsWeakPtr()); | 377 iter->second->AddWaitingRequest(request->AsWeakPtr()); |
| 409 return request.PassAs<Request>(); | 378 return request.PassAs<Request>(); |
| 410 } | 379 } |
| 411 | 380 |
| 412 pending_fetchers_[fetch_parameters] = | 381 pending_fetchers_[fetch_parameters] = |
| 413 Fetcher::CreateAndStart(this, | 382 Fetcher::CreateAndStart(this, |
| 414 getter, | 383 getter, |
| 384 request_origin, | |
| 415 client_id, | 385 client_id, |
| 416 client_secret, | 386 client_secret, |
| 417 refresh_token, | 387 refresh_token, |
| 418 scopes, | 388 scopes, |
| 419 request->AsWeakPtr()); | 389 request->AsWeakPtr()); |
| 420 return request.PassAs<Request>(); | 390 return request.PassAs<Request>(); |
| 421 } | 391 } |
| 422 | 392 |
| 423 scoped_ptr<OAuth2TokenService::Request> | 393 scoped_ptr<OAuth2TokenService::Request> |
| 424 OAuth2TokenService::StartCacheLookupRequest( | 394 OAuth2TokenService::StartCacheLookupRequest( |
| 425 const OAuth2TokenService::ScopeSet& scopes, | 395 const OAuth2TokenService::ClientScopeSet& client_scopes, |
| 426 OAuth2TokenService::Consumer* consumer) { | 396 OAuth2TokenService::Consumer* consumer) { |
| 427 CHECK(HasCacheEntry(scopes)); | 397 CHECK(HasCacheEntry(client_scopes)); |
| 428 const CacheEntry* cache_entry = GetCacheEntry(scopes); | 398 const CacheEntry* cache_entry = GetCacheEntry(client_scopes); |
| 429 scoped_ptr<RequestImpl> request(new RequestImpl(consumer)); | 399 scoped_ptr<RequestImpl> request(new RequestImpl(consumer)); |
| 430 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 400 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
| 431 &RequestImpl::InformConsumer, | 401 &RequestImpl::InformConsumer, |
| 432 request->AsWeakPtr(), | 402 request->AsWeakPtr(), |
| 433 GoogleServiceAuthError(GoogleServiceAuthError::NONE), | 403 GoogleServiceAuthError(GoogleServiceAuthError::NONE), |
| 434 cache_entry->access_token, | 404 cache_entry->access_token, |
| 435 cache_entry->expiration_date)); | 405 cache_entry->expiration_date)); |
| 436 return request.PassAs<Request>(); | 406 return request.PassAs<Request>(); |
| 437 } | 407 } |
| 438 | 408 |
| 439 void OAuth2TokenService::InvalidateToken(const ScopeSet& scopes, | 409 void OAuth2TokenService::InvalidateToken(const ScopeSet& scopes, |
| 440 const std::string& invalid_token) { | 410 const std::string& invalid_token) { |
| 441 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 411 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 442 RemoveCacheEntry(scopes, invalid_token); | 412 RemoveCacheEntry( |
| 413 ClientScopeSet(std::string(), | |
| 414 GaiaUrls::GetInstance()->oauth2_chrome_client_id(), | |
| 415 scopes), | |
| 416 invalid_token); | |
| 443 } | 417 } |
| 444 | 418 |
| 445 void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) { | 419 void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) { |
| 446 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 420 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 447 | 421 |
| 448 // Update the auth error state so auth errors are appropriately communicated | 422 // Update the auth error state so auth errors are appropriately communicated |
| 449 // to the user. | 423 // to the user. |
| 450 UpdateAuthError(fetcher->error()); | 424 UpdateAuthError(fetcher->error()); |
| 451 | 425 |
| 452 // Note |fetcher| is recorded in |pending_fetcher_| mapped to its refresh | 426 // Note |fetcher| is recorded in |pending_fetcher_| mapped to its refresh |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 469 // | 443 // |
| 470 // (3) Each of the Fetchers recorded in |pending_fetchers_| is mapped to its | 444 // (3) Each of the Fetchers recorded in |pending_fetchers_| is mapped to its |
| 471 // refresh token and ScopeSet. This is guaranteed by Fetcher creation in | 445 // refresh token and ScopeSet. This is guaranteed by Fetcher creation in |
| 472 // method StartRequest(). | 446 // method StartRequest(). |
| 473 // | 447 // |
| 474 // When this method is called, |fetcher| is alive and uncompleted. | 448 // When this method is called, |fetcher| is alive and uncompleted. |
| 475 // By (1), |fetcher| is created by this service. | 449 // By (1), |fetcher| is created by this service. |
| 476 // Then by (2), |fetcher| is recorded in |pending_fetchers_|. | 450 // Then by (2), |fetcher| is recorded in |pending_fetchers_|. |
| 477 // Then by (3), |fetcher_| is mapped to its refresh token and ScopeSet. | 451 // Then by (3), |fetcher_| is mapped to its refresh token and ScopeSet. |
| 478 std::map<FetchParameters, Fetcher*>::iterator iter = | 452 std::map<FetchParameters, Fetcher*>::iterator iter = |
| 479 pending_fetchers_.find(std::make_pair( | 453 pending_fetchers_.find(FetchParameters( |
| 480 fetcher->GetRefreshToken(), fetcher->GetScopeSet())); | 454 fetcher->GetRequestOrigin(), |
| 455 fetcher->GetClientId(), | |
| 456 fetcher->GetRefreshToken(), | |
| 457 fetcher->GetScopeSet())); | |
| 481 DCHECK(iter != pending_fetchers_.end()); | 458 DCHECK(iter != pending_fetchers_.end()); |
| 482 DCHECK_EQ(fetcher, iter->second); | 459 DCHECK_EQ(fetcher, iter->second); |
| 483 pending_fetchers_.erase(iter); | 460 pending_fetchers_.erase(iter); |
| 484 } | 461 } |
| 485 | 462 |
| 486 bool OAuth2TokenService::HasCacheEntry( | 463 bool OAuth2TokenService::HasCacheEntry( |
| 487 const OAuth2TokenService::ScopeSet& scopes) { | 464 const ClientScopeSet& client_scopes) { |
| 488 const CacheEntry* cache_entry = GetCacheEntry(scopes); | 465 const CacheEntry* cache_entry = GetCacheEntry(client_scopes); |
| 489 return cache_entry && cache_entry->access_token.length(); | 466 return cache_entry && cache_entry->access_token.length(); |
| 490 } | 467 } |
| 491 | 468 |
| 492 const OAuth2TokenService::CacheEntry* OAuth2TokenService::GetCacheEntry( | 469 const OAuth2TokenService::CacheEntry* OAuth2TokenService::GetCacheEntry( |
| 493 const OAuth2TokenService::ScopeSet& scopes) { | 470 const ClientScopeSet& client_scopes) { |
| 494 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 471 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 495 TokenCache::iterator token_iterator = token_cache_.find(scopes); | 472 TokenCache::iterator token_iterator = token_cache_.find(client_scopes); |
| 496 if (token_iterator == token_cache_.end()) | 473 if (token_iterator == token_cache_.end()) |
| 497 return NULL; | 474 return NULL; |
| 498 if (token_iterator->second.expiration_date <= base::Time::Now()) { | 475 if (token_iterator->second.expiration_date <= base::Time::Now()) { |
| 499 token_cache_.erase(token_iterator); | 476 token_cache_.erase(token_iterator); |
| 500 return NULL; | 477 return NULL; |
| 501 } | 478 } |
| 502 return &token_iterator->second; | 479 return &token_iterator->second; |
| 503 } | 480 } |
| 504 | 481 |
| 505 bool OAuth2TokenService::RemoveCacheEntry( | 482 bool OAuth2TokenService::RemoveCacheEntry( |
| 506 const OAuth2TokenService::ScopeSet& scopes, | 483 const ClientScopeSet& client_scopes, |
| 507 const std::string& token_to_remove) { | 484 const std::string& token_to_remove) { |
| 508 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 485 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 509 TokenCache::iterator token_iterator = token_cache_.find(scopes); | 486 TokenCache::iterator token_iterator = token_cache_.find(client_scopes); |
| 510 if (token_iterator != token_cache_.end() && | 487 if (token_iterator != token_cache_.end() && |
| 511 token_iterator->second.access_token == token_to_remove) { | 488 token_iterator->second.access_token == token_to_remove) { |
| 512 token_cache_.erase(token_iterator); | 489 token_cache_.erase(token_iterator); |
| 513 return true; | 490 return true; |
| 514 } | 491 } |
| 515 return false; | 492 return false; |
| 516 } | 493 } |
| 517 | 494 |
| 518 void OAuth2TokenService::RegisterCacheEntry( | 495 void OAuth2TokenService::RegisterCacheEntry( |
| 496 const std::string& request_origin, | |
| 497 const std::string& client_id, | |
| 519 const std::string& refresh_token, | 498 const std::string& refresh_token, |
| 520 const OAuth2TokenService::ScopeSet& scopes, | 499 const OAuth2TokenService::ScopeSet& scopes, |
| 521 const std::string& access_token, | 500 const std::string& access_token, |
| 522 const base::Time& expiration_date) { | 501 const base::Time& expiration_date) { |
| 523 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 502 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 524 | 503 |
| 525 CacheEntry& token = token_cache_[scopes]; | 504 CacheEntry& token = token_cache_[ClientScopeSet(request_origin, |
| 505 client_id, | |
| 506 scopes)]; | |
| 526 token.access_token = access_token; | 507 token.access_token = access_token; |
| 527 token.expiration_date = expiration_date; | 508 token.expiration_date = expiration_date; |
| 528 } | 509 } |
| 529 | 510 |
| 530 void OAuth2TokenService::UpdateAuthError(const GoogleServiceAuthError& error) { | 511 void OAuth2TokenService::UpdateAuthError(const GoogleServiceAuthError& error) { |
| 531 // Default implementation does nothing. | 512 // Default implementation does nothing. |
| 532 } | 513 } |
| 533 | 514 |
| 534 void OAuth2TokenService::ClearCache() { | 515 void OAuth2TokenService::ClearCache() { |
| 535 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 516 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 547 CancelFetchers(fetchers_to_cancel); | 528 CancelFetchers(fetchers_to_cancel); |
| 548 } | 529 } |
| 549 | 530 |
| 550 void OAuth2TokenService::CancelRequestsForToken( | 531 void OAuth2TokenService::CancelRequestsForToken( |
| 551 const std::string& refresh_token) { | 532 const std::string& refresh_token) { |
| 552 std::vector<Fetcher*> fetchers_to_cancel; | 533 std::vector<Fetcher*> fetchers_to_cancel; |
| 553 for (std::map<FetchParameters, Fetcher*>::iterator iter = | 534 for (std::map<FetchParameters, Fetcher*>::iterator iter = |
| 554 pending_fetchers_.begin(); | 535 pending_fetchers_.begin(); |
| 555 iter != pending_fetchers_.end(); | 536 iter != pending_fetchers_.end(); |
| 556 ++iter) { | 537 ++iter) { |
| 557 if (iter->first.first == refresh_token) | 538 if (iter->first.refresh_token == refresh_token) |
| 558 fetchers_to_cancel.push_back(iter->second); | 539 fetchers_to_cancel.push_back(iter->second); |
| 559 } | 540 } |
| 560 CancelFetchers(fetchers_to_cancel); | 541 CancelFetchers(fetchers_to_cancel); |
| 561 } | 542 } |
| 562 | 543 |
| 563 void OAuth2TokenService::CancelFetchers( | 544 void OAuth2TokenService::CancelFetchers( |
| 564 std::vector<Fetcher*> fetchers_to_cancel) { | 545 std::vector<Fetcher*> fetchers_to_cancel) { |
| 565 for (std::vector<OAuth2TokenService::Fetcher*>::iterator iter = | 546 for (std::vector<OAuth2TokenService::Fetcher*>::iterator iter = |
| 566 fetchers_to_cancel.begin(); | 547 fetchers_to_cancel.begin(); |
| 567 iter != fetchers_to_cancel.end(); | 548 iter != fetchers_to_cancel.end(); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 593 | 574 |
| 594 int OAuth2TokenService::cache_size_for_testing() const { | 575 int OAuth2TokenService::cache_size_for_testing() const { |
| 595 return token_cache_.size(); | 576 return token_cache_.size(); |
| 596 } | 577 } |
| 597 | 578 |
| 598 void OAuth2TokenService::set_max_authorization_token_fetch_retries_for_testing( | 579 void OAuth2TokenService::set_max_authorization_token_fetch_retries_for_testing( |
| 599 int max_retries) { | 580 int max_retries) { |
| 600 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 581 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 601 max_fetch_retry_num_ = max_retries; | 582 max_fetch_retry_num_ = max_retries; |
| 602 } | 583 } |
| OLD | NEW |