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

Side by Side Diff: chrome/browser/signin/oauth2_token_service.cc

Issue 22581003: Handling of multiple concurrent requests from different clients in OAuth2TokenService (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 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 | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698