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

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

Issue 12647008: Refactor OAuth2TokenService to have profile- and device-based implementations. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: rebase again Created 7 years, 8 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
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.h" 11 #include "base/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.h" 14 #include "base/time.h"
15 #include "base/timer.h" 15 #include "base/timer.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/signin/oauth2_token_service_factory.h"
18 #include "chrome/browser/signin/signin_manager.h"
19 #include "chrome/browser/signin/signin_manager_factory.h"
20 #include "chrome/browser/signin/token_service.h"
21 #include "chrome/browser/signin/token_service_factory.h"
22 #include "chrome/common/chrome_notification_types.h"
23 #include "content/public/browser/browser_thread.h" 16 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/notification_details.h"
25 #include "content/public/browser/notification_source.h"
26 #include "google_apis/gaia/gaia_constants.h"
27 #include "google_apis/gaia/gaia_urls.h" 17 #include "google_apis/gaia/gaia_urls.h"
28 #include "google_apis/gaia/google_service_auth_error.h" 18 #include "google_apis/gaia/google_service_auth_error.h"
29 #include "google_apis/gaia/oauth2_access_token_consumer.h" 19 #include "google_apis/gaia/oauth2_access_token_consumer.h"
30 #include "google_apis/gaia/oauth2_access_token_fetcher.h" 20 #include "google_apis/gaia/oauth2_access_token_fetcher.h"
31 21 #include "net/url_request/url_request_context_getter.h"
32 #if defined(OS_ANDROID)
33 #include "chrome/browser/sync/profile_sync_service_android.h"
34 #endif
35 22
36 namespace { 23 namespace {
37 24
38 // Maximum number of retries in fetching an OAuth2 access token. 25 // Maximum number of retries in fetching an OAuth2 access token.
39 const int kMaxFetchRetryNum = 5; 26 const int kMaxFetchRetryNum = 5;
40 27
41 // Returns an exponential backoff in milliseconds including randomness less than 28 // Returns an exponential backoff in milliseconds including randomness less than
42 // 1000 ms when retrying fetching an OAuth2 access token. 29 // 1000 ms when retrying fetching an OAuth2 access token.
43 int64 ComputeExponentialBackOffMilliseconds(int retry_num) { 30 int64 ComputeExponentialBackOffMilliseconds(int retry_num) {
44 DCHECK(retry_num < kMaxFetchRetryNum); 31 DCHECK(retry_num < kMaxFetchRetryNum);
45 int64 exponential_backoff_in_seconds = 1 << retry_num; 32 int64 exponential_backoff_in_seconds = 1 << retry_num;
46 // Returns a backoff with randomness < 1000ms 33 // Returns a backoff with randomness < 1000ms
47 return (exponential_backoff_in_seconds + base::RandDouble()) * 1000; 34 return (exponential_backoff_in_seconds + base::RandDouble()) * 1000;
48 } 35 }
49 36
50 } // namespace 37 } // namespace
51 38
52 // Implements a cancelable |OAuth2TokenService::Request|, which should be
53 // operated on the UI thread.
54 class OAuth2TokenService::RequestImpl
55 : public base::SupportsWeakPtr<RequestImpl>,
56 public OAuth2TokenService::Request {
57 public:
58 // |consumer| is required to outlive this.
59 explicit RequestImpl(OAuth2TokenService::Consumer* consumer);
60 virtual ~RequestImpl();
61
62 // Informs |consumer_| that this request is completed.
63 void InformConsumer(const GoogleServiceAuthError& error,
64 const std::string& access_token,
65 const base::Time& expiration_date);
66
67 private:
68 // |consumer_| to call back when this request completes.
69 OAuth2TokenService::Consumer* const consumer_;
70 };
71
72 OAuth2TokenService::RequestImpl::RequestImpl( 39 OAuth2TokenService::RequestImpl::RequestImpl(
73 OAuth2TokenService::Consumer* consumer) 40 OAuth2TokenService::Consumer* consumer)
74 : consumer_(consumer) { 41 : consumer_(consumer) {
75 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 42 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
76 } 43 }
77 44
78 OAuth2TokenService::RequestImpl::~RequestImpl() { 45 OAuth2TokenService::RequestImpl::~RequestImpl() {
79 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 46 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
80 } 47 }
81 48
82 void OAuth2TokenService::RequestImpl::InformConsumer( 49 void OAuth2TokenService::RequestImpl::InformConsumer(
83 const GoogleServiceAuthError& error, 50 const GoogleServiceAuthError& error,
84 const std::string& access_token, 51 const std::string& access_token,
85 const base::Time& expiration_date) { 52 const base::Time& expiration_date) {
86 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 53 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
87 if (error.state() == GoogleServiceAuthError::NONE) 54 if (error.state() == GoogleServiceAuthError::NONE)
88 consumer_-> OnGetTokenSuccess(this, access_token, expiration_date); 55 consumer_->OnGetTokenSuccess(this, access_token, expiration_date);
89 else 56 else
90 consumer_-> OnGetTokenFailure(this, error); 57 consumer_->OnGetTokenFailure(this, error);
91 } 58 }
92 59
93 // Class that fetches OAuth2 access tokens for given scopes and refresh token. 60 // Class that fetches OAuth2 access tokens for given scopes and refresh token.
94 // 61 //
95 // It aims to meet OAuth2TokenService's requirements on token fetching. Retry 62 // It aims to meet OAuth2TokenService's requirements on token fetching. Retry
96 // mechanism is used to handle failures. 63 // mechanism is used to handle failures.
97 // 64 //
98 // To use this class, call CreateAndStart() to create and start a Fetcher. 65 // To use this class, call CreateAndStart() to create and start a Fetcher.
99 // 66 //
100 // The Fetcher will call back the service by calling 67 // The Fetcher will call back the service by calling
(...skipping 13 matching lines...) Expand all
114 // deleted 81 // deleted
115 // - when the Fetcher completes fetching, if the Fetcher is not destructed 82 // - when the Fetcher completes fetching, if the Fetcher is not destructed
116 // before it completes fetching, or 83 // before it completes fetching, or
117 // - when the Fetcher is destructed if the Fetcher is destructed before it 84 // - when the Fetcher is destructed if the Fetcher is destructed before it
118 // completes fetching (in this case, the waiting requests will be called back 85 // completes fetching (in this case, the waiting requests will be called back
119 // with error). 86 // with error).
120 class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer { 87 class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer {
121 public: 88 public:
122 // Creates a Fetcher and starts fetching an OAuth2 access token for 89 // Creates a Fetcher and starts fetching an OAuth2 access token for
123 // |refresh_token| and |scopes| in the request context obtained by |getter|. 90 // |refresh_token| and |scopes| in the request context obtained by |getter|.
124 // |profile|'s OAuth2TokenService will be informed when fetching is done. 91 // The given |oauth2_token_service| will be informed when fetching is done.
125 static Fetcher* CreateAndStart(Profile* profile, 92 static Fetcher* CreateAndStart(OAuth2TokenService* oauth2_token_service,
126 net::URLRequestContextGetter* getter, 93 net::URLRequestContextGetter* getter,
127 const std::string& refresh_token, 94 const std::string& refresh_token,
128 const OAuth2TokenService::ScopeSet& scopes, 95 const OAuth2TokenService::ScopeSet& scopes,
129 base::WeakPtr<RequestImpl> waiting_request); 96 base::WeakPtr<RequestImpl> waiting_request);
130 virtual ~Fetcher(); 97 virtual ~Fetcher();
131 98
132 // Add a request that is waiting for the result of this Fetcher. 99 // Add a request that is waiting for the result of this Fetcher.
133 void AddWaitingRequest(base::WeakPtr<RequestImpl> waiting_request); 100 void AddWaitingRequest(base::WeakPtr<RequestImpl> waiting_request);
134 101
135 const OAuth2TokenService::ScopeSet& GetScopeSet() const; 102 const OAuth2TokenService::ScopeSet& GetScopeSet() const;
136 const std::string& GetRefreshToken() const; 103 const std::string& GetRefreshToken() const;
137 104
138 // The error result from this fetcher. 105 // The error result from this fetcher.
139 const GoogleServiceAuthError& error() const { return error_; } 106 const GoogleServiceAuthError& error() const { return error_; }
140 107
141 protected: 108 protected:
142 // OAuth2AccessTokenConsumer 109 // OAuth2AccessTokenConsumer
143 virtual void OnGetTokenSuccess(const std::string& access_token, 110 virtual void OnGetTokenSuccess(const std::string& access_token,
144 const base::Time& expiration_date) OVERRIDE; 111 const base::Time& expiration_date) OVERRIDE;
145 virtual void OnGetTokenFailure(const GoogleServiceAuthError& error) OVERRIDE; 112 virtual void OnGetTokenFailure(const GoogleServiceAuthError& error) OVERRIDE;
146 113
147 private: 114 private:
148 Fetcher(Profile* profile, 115 Fetcher(OAuth2TokenService* oauth2_token_service,
149 net::URLRequestContextGetter* getter, 116 net::URLRequestContextGetter* getter,
150 const std::string& refresh_token, 117 const std::string& refresh_token,
151 const OAuth2TokenService::ScopeSet& scopes, 118 const OAuth2TokenService::ScopeSet& scopes,
152 base::WeakPtr<RequestImpl> waiting_request); 119 base::WeakPtr<RequestImpl> waiting_request);
153 void Start(); 120 void Start();
154 void InformWaitingRequests(); 121 void InformWaitingRequests();
155 static bool ShouldRetry(const GoogleServiceAuthError& error); 122 static bool ShouldRetry(const GoogleServiceAuthError& error);
156 123
157 Profile* const profile_; 124 // |oauth2_token_service_| remains valid for the life of this Fetcher, since
125 // this Fetcher is destructed in the dtor of the OAuth2TokenService or is
126 // scheduled for deletion at the end of OnGetTokenFailure/OnGetTokenSuccess
127 // (whichever comes first).
128 OAuth2TokenService* const oauth2_token_service_;
158 scoped_refptr<net::URLRequestContextGetter> getter_; 129 scoped_refptr<net::URLRequestContextGetter> getter_;
159 const std::string refresh_token_; 130 const std::string refresh_token_;
160 const OAuth2TokenService::ScopeSet scopes_; 131 const OAuth2TokenService::ScopeSet scopes_;
161 std::vector<base::WeakPtr<RequestImpl> > waiting_requests_; 132 std::vector<base::WeakPtr<RequestImpl> > waiting_requests_;
162 133
163 int retry_number_; 134 int retry_number_;
164 base::OneShotTimer<OAuth2TokenService::Fetcher> retry_timer_; 135 base::OneShotTimer<OAuth2TokenService::Fetcher> retry_timer_;
165 scoped_ptr<OAuth2AccessTokenFetcher> fetcher_; 136 scoped_ptr<OAuth2AccessTokenFetcher> fetcher_;
166 137
167 // Variables that store fetch results. 138 // Variables that store fetch results.
168 // Initialized to be GoogleServiceAuthError::SERVICE_UNAVAILABLE to handle 139 // Initialized to be GoogleServiceAuthError::SERVICE_UNAVAILABLE to handle
169 // destruction. 140 // destruction.
170 GoogleServiceAuthError error_; 141 GoogleServiceAuthError error_;
171 std::string access_token_; 142 std::string access_token_;
172 base::Time expiration_date_; 143 base::Time expiration_date_;
173 144
174 DISALLOW_COPY_AND_ASSIGN(Fetcher); 145 DISALLOW_COPY_AND_ASSIGN(Fetcher);
175 }; 146 };
176 147
177 // static 148 // static
178 OAuth2TokenService::Fetcher* OAuth2TokenService::Fetcher::CreateAndStart( 149 OAuth2TokenService::Fetcher* OAuth2TokenService::Fetcher::CreateAndStart(
179 Profile* profile, 150 OAuth2TokenService* oauth2_token_service,
180 net::URLRequestContextGetter* getter, 151 net::URLRequestContextGetter* getter,
181 const std::string& refresh_token, 152 const std::string& refresh_token,
182 const OAuth2TokenService::ScopeSet& scopes, 153 const OAuth2TokenService::ScopeSet& scopes,
183 base::WeakPtr<RequestImpl> waiting_request) { 154 base::WeakPtr<RequestImpl> waiting_request) {
184 OAuth2TokenService::Fetcher* fetcher = new Fetcher( 155 OAuth2TokenService::Fetcher* fetcher = new Fetcher(
185 profile, getter, refresh_token, scopes, waiting_request); 156 oauth2_token_service, getter, refresh_token, scopes, waiting_request);
186 fetcher->Start(); 157 fetcher->Start();
187 return fetcher; 158 return fetcher;
188 } 159 }
189 160
190 OAuth2TokenService::Fetcher::Fetcher( 161 OAuth2TokenService::Fetcher::Fetcher(
191 Profile* profile, 162 OAuth2TokenService* oauth2_token_service,
192 net::URLRequestContextGetter* getter, 163 net::URLRequestContextGetter* getter,
193 const std::string& refresh_token, 164 const std::string& refresh_token,
194 const OAuth2TokenService::ScopeSet& scopes, 165 const OAuth2TokenService::ScopeSet& scopes,
195 base::WeakPtr<RequestImpl> waiting_request) 166 base::WeakPtr<RequestImpl> waiting_request)
196 : profile_(profile), 167 : oauth2_token_service_(oauth2_token_service),
197 getter_(getter), 168 getter_(getter),
198 refresh_token_(refresh_token), 169 refresh_token_(refresh_token),
199 scopes_(scopes), 170 scopes_(scopes),
200 retry_number_(0), 171 retry_number_(0),
201 error_(GoogleServiceAuthError::SERVICE_UNAVAILABLE) { 172 error_(GoogleServiceAuthError::SERVICE_UNAVAILABLE) {
202 DCHECK(profile_); 173 DCHECK(oauth2_token_service_);
203 DCHECK(getter_); 174 DCHECK(getter_);
204 DCHECK(refresh_token_.length()); 175 DCHECK(refresh_token_.length());
205 waiting_requests_.push_back(waiting_request); 176 waiting_requests_.push_back(waiting_request);
206 } 177 }
207 178
208 OAuth2TokenService::Fetcher::~Fetcher() { 179 OAuth2TokenService::Fetcher::~Fetcher() {
209 // Inform the waiting requests if it has not done so. 180 // Inform the waiting requests if it has not done so.
210 if (waiting_requests_.size()) 181 if (waiting_requests_.size())
211 InformWaitingRequests(); 182 InformWaitingRequests();
212 } 183 }
213 184
214 void OAuth2TokenService::Fetcher::Start() { 185 void OAuth2TokenService::Fetcher::Start() {
215 fetcher_.reset(new OAuth2AccessTokenFetcher(this, getter_)); 186 fetcher_.reset(new OAuth2AccessTokenFetcher(this, getter_));
216 fetcher_->Start(GaiaUrls::GetInstance()->oauth2_chrome_client_id(), 187 fetcher_->Start(GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
217 GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), 188 GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
218 refresh_token_, 189 refresh_token_,
219 std::vector<std::string>(scopes_.begin(), scopes_.end())); 190 std::vector<std::string>(scopes_.begin(), scopes_.end()));
220 retry_timer_.Stop(); 191 retry_timer_.Stop();
221 } 192 }
222 193
223 void OAuth2TokenService::Fetcher::OnGetTokenSuccess( 194 void OAuth2TokenService::Fetcher::OnGetTokenSuccess(
224 const std::string& access_token, 195 const std::string& access_token,
225 const base::Time& expiration_date) { 196 const base::Time& expiration_date) {
226 fetcher_.reset(); 197 fetcher_.reset();
227 198
228 // Fetch completes. 199 // Fetch completes.
229 error_ = GoogleServiceAuthError(GoogleServiceAuthError::NONE); 200 error_ = GoogleServiceAuthError::AuthErrorNone();
230 access_token_ = access_token; 201 access_token_ = access_token;
231 expiration_date_ = expiration_date; 202 expiration_date_ = expiration_date;
232 203
233 // |oauth2_token_service| should not be NULL as this Fetcher is destructed in 204 // Subclasses may override this method to skip caching in some cases, but
234 // the dtor of the OAuth2TokenService that creates it if it is not scheduled 205 // we still inform all waiting Consumers of a successful token fetch below.
235 // to be destructed here and in OnGetTokenFailure(). 206 // This is intentional -- some consumers may need the token for cleanup
236 OAuth2TokenService* oauth2_token_service = 207 // tasks. https://chromiumcodereview.appspot.com/11312124/
237 OAuth2TokenServiceFactory::GetForProfile(profile_); 208 oauth2_token_service_->RegisterCacheEntry(refresh_token_,
238 DCHECK(oauth2_token_service); 209 scopes_,
239 210 access_token_,
240 oauth2_token_service->RegisterCacheEntry(refresh_token_, 211 expiration_date_);
241 scopes_,
242 access_token_,
243 expiration_date_);
244 // Deregisters itself from the service to prevent more waiting requests to 212 // Deregisters itself from the service to prevent more waiting requests to
245 // be added when it calls back the waiting requests. 213 // be added when it calls back the waiting requests.
246 oauth2_token_service->OnFetchComplete(this); 214 oauth2_token_service_->OnFetchComplete(this);
247 InformWaitingRequests(); 215 InformWaitingRequests();
248 MessageLoop::current()->DeleteSoon(FROM_HERE, this); 216 MessageLoop::current()->DeleteSoon(FROM_HERE, this);
249 } 217 }
250 218
251 void OAuth2TokenService::Fetcher::OnGetTokenFailure( 219 void OAuth2TokenService::Fetcher::OnGetTokenFailure(
252 const GoogleServiceAuthError& error) { 220 const GoogleServiceAuthError& error) {
253 fetcher_.reset(); 221 fetcher_.reset();
254 222
255 if (ShouldRetry(error) && retry_number_ < kMaxFetchRetryNum) { 223 if (ShouldRetry(error) && retry_number_ < kMaxFetchRetryNum) {
256 int64 backoff = ComputeExponentialBackOffMilliseconds(retry_number_); 224 int64 backoff = ComputeExponentialBackOffMilliseconds(retry_number_);
257 ++retry_number_; 225 ++retry_number_;
258 retry_timer_.Stop(); 226 retry_timer_.Stop();
259 retry_timer_.Start(FROM_HERE, 227 retry_timer_.Start(FROM_HERE,
260 base::TimeDelta::FromMilliseconds(backoff), 228 base::TimeDelta::FromMilliseconds(backoff),
261 this, 229 this,
262 &OAuth2TokenService::Fetcher::Start); 230 &OAuth2TokenService::Fetcher::Start);
263 return; 231 return;
264 } 232 }
265 233
266 // Fetch completes. 234 // Fetch completes.
267 error_ = error; 235 error_ = error;
268 236
269 // |oauth2_token_service| should not be NULL as this Fetcher is destructed in
270 // the dtor of the OAuth2TokenService that creates it if it is not scheduled
271 // to be destructed here and in OnGetTokenSuccess().
272 OAuth2TokenService* oauth2_token_service =
273 OAuth2TokenServiceFactory::GetForProfile(profile_);
274 DCHECK(oauth2_token_service);
275 // Deregisters itself from the service to prevent more waiting requests to be 237 // Deregisters itself from the service to prevent more waiting requests to be
276 // added when it calls back the waiting requests. 238 // added when it calls back the waiting requests.
277 oauth2_token_service->OnFetchComplete(this); 239 oauth2_token_service_->OnFetchComplete(this);
278 InformWaitingRequests(); 240 InformWaitingRequests();
279 MessageLoop::current()->DeleteSoon(FROM_HERE, this); 241 MessageLoop::current()->DeleteSoon(FROM_HERE, this);
280 } 242 }
281 243
282 // static 244 // static
283 bool OAuth2TokenService::Fetcher::ShouldRetry( 245 bool OAuth2TokenService::Fetcher::ShouldRetry(
284 const GoogleServiceAuthError& error) { 246 const GoogleServiceAuthError& error) {
285 GoogleServiceAuthError::State error_state = error.state(); 247 GoogleServiceAuthError::State error_state = error.state();
286 return error_state == GoogleServiceAuthError::CONNECTION_FAILED || 248 return error_state == GoogleServiceAuthError::CONNECTION_FAILED ||
287 error_state == GoogleServiceAuthError::REQUEST_CANCELED || 249 error_state == GoogleServiceAuthError::REQUEST_CANCELED ||
(...skipping 30 matching lines...) Expand all
318 280
319 OAuth2TokenService::Request::~Request() { 281 OAuth2TokenService::Request::~Request() {
320 } 282 }
321 283
322 OAuth2TokenService::Consumer::Consumer() { 284 OAuth2TokenService::Consumer::Consumer() {
323 } 285 }
324 286
325 OAuth2TokenService::Consumer::~Consumer() { 287 OAuth2TokenService::Consumer::~Consumer() {
326 } 288 }
327 289
328 OAuth2TokenService::OAuth2TokenService() 290 OAuth2TokenService::OAuth2TokenService(net::URLRequestContextGetter* getter)
329 : profile_(NULL), 291 : request_context_getter_(getter) {
330 last_auth_error_(GoogleServiceAuthError::NONE) {
331 } 292 }
332 293
333 OAuth2TokenService::~OAuth2TokenService() { 294 OAuth2TokenService::~OAuth2TokenService() {
295 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
334 // Release all the pending fetchers. 296 // Release all the pending fetchers.
335 STLDeleteContainerPairSecondPointers( 297 STLDeleteContainerPairSecondPointers(
336 pending_fetchers_.begin(), pending_fetchers_.end()); 298 pending_fetchers_.begin(), pending_fetchers_.end());
337 } 299 }
338 300
339 void OAuth2TokenService::Initialize(Profile* profile) { 301 bool OAuth2TokenService::RefreshTokenIsAvailable() {
340 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 302 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
341 303 return !GetRefreshToken().empty();
342 DCHECK(profile);
343 DCHECK(!profile_);
344 profile_ = profile;
345 getter_ = profile->GetRequestContext();
346 content::Source<TokenService> token_service_source(
347 TokenServiceFactory::GetForProfile(profile));
348 registrar_.Add(this,
349 chrome::NOTIFICATION_TOKENS_CLEARED,
350 token_service_source);
351 registrar_.Add(this,
352 chrome::NOTIFICATION_TOKEN_AVAILABLE,
353 token_service_source);
354 SigninManagerFactory::GetForProfile(profile_)->signin_global_error()->
355 AddProvider(this);
356 } 304 }
357 305
358 void OAuth2TokenService::Shutdown() {
359 if (profile_) {
360 SigninManagerFactory::GetForProfile(profile_)->signin_global_error()->
361 RemoveProvider(this);
362 }
363 }
364
365
366 // static 306 // static
367 void OAuth2TokenService::InformConsumer( 307 void OAuth2TokenService::InformConsumer(
368 base::WeakPtr<OAuth2TokenService::RequestImpl> request, 308 base::WeakPtr<OAuth2TokenService::RequestImpl> request,
369 const GoogleServiceAuthError& error, 309 const GoogleServiceAuthError& error,
370 const std::string& access_token, 310 const std::string& access_token,
371 const base::Time& expiration_date) { 311 const base::Time& expiration_date) {
372 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 312 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
373 313
374 if (request) 314 if (request)
375 request->InformConsumer(error, access_token, expiration_date); 315 request->InformConsumer(error, access_token, expiration_date);
376 } 316 }
377 317
378 scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest( 318 scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest(
379 const OAuth2TokenService::ScopeSet& scopes, 319 const OAuth2TokenService::ScopeSet& scopes,
380 OAuth2TokenService::Consumer* consumer) { 320 OAuth2TokenService::Consumer* consumer) {
381 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 321 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
382 322
383 scoped_ptr<RequestImpl> request(new RequestImpl(consumer)); 323 scoped_ptr<RequestImpl> request(new RequestImpl(consumer));
384 324
385 #if !defined(OS_ANDROID) 325 std::string refresh_token = GetRefreshToken();
386 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); 326 if (refresh_token.empty()) {
387 if (!token_service || !token_service->HasOAuthLoginToken()) {
388 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
389 &OAuth2TokenService::InformConsumer,
390 request->AsWeakPtr(),
391 GoogleServiceAuthError(GoogleServiceAuthError::USER_NOT_SIGNED_UP),
392 std::string(),
393 base::Time()));
394 return request.PassAs<Request>();
395 }
396 #endif
397
398 const CacheEntry* cache_entry = GetCacheEntry(scopes);
399 if (cache_entry && cache_entry->access_token.length()) {
400 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
401 &OAuth2TokenService::InformConsumer,
402 request->AsWeakPtr(),
403 GoogleServiceAuthError(GoogleServiceAuthError::NONE),
404 cache_entry->access_token,
405 cache_entry->expiration_date));
406 return request.PassAs<Request>();
407 }
408
409 #if defined(OS_ANDROID)
410 DCHECK_EQ(scopes.size(), 1U);
411 std::vector<std::string> scope_list(scopes.begin(), scopes.end());
412 ProfileSyncServiceAndroid* sync_service =
413 ProfileSyncServiceAndroid::GetProfileSyncServiceAndroid();
414 sync_service->FetchOAuth2Token(
415 scope_list.front(),
416 base::Bind(&OAuth2TokenService::InformConsumer,
417 request->AsWeakPtr()));
418 return request.PassAs<Request>();
419 #else
420 std::string refresh_token = token_service->GetOAuth2LoginRefreshToken();
421 if (!refresh_token.length()) {
422 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( 327 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
423 &OAuth2TokenService::InformConsumer, 328 &OAuth2TokenService::InformConsumer,
424 request->AsWeakPtr(), 329 request->AsWeakPtr(),
425 GoogleServiceAuthError( 330 GoogleServiceAuthError(
426 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS), 331 GoogleServiceAuthError::USER_NOT_SIGNED_UP),
427 std::string(), 332 std::string(),
428 base::Time())); 333 base::Time()));
429 return request.PassAs<Request>(); 334 return request.PassAs<Request>();
430 } 335 }
431 336
337 if (HasCacheEntry(scopes))
338 return StartCacheLookupRequest(scopes, consumer);
339
432 // Makes sure there is a pending fetcher for |scopes| and |refresh_token|. 340 // Makes sure there is a pending fetcher for |scopes| and |refresh_token|.
433 // Adds |request| to the waiting request list of this fetcher so |request| 341 // Adds |request| to the waiting request list of this fetcher so |request|
434 // will be called back when this fetcher finishes fetching. 342 // will be called back when this fetcher finishes fetching.
435 FetchParameters fetch_parameters = std::make_pair(refresh_token, scopes); 343 FetchParameters fetch_parameters = std::make_pair(refresh_token, scopes);
436 std::map<FetchParameters, Fetcher*>::iterator iter = 344 std::map<FetchParameters, Fetcher*>::iterator iter =
437 pending_fetchers_.find(fetch_parameters); 345 pending_fetchers_.find(fetch_parameters);
438 if (iter != pending_fetchers_.end()) { 346 if (iter != pending_fetchers_.end()) {
439 iter->second->AddWaitingRequest(request->AsWeakPtr()); 347 iter->second->AddWaitingRequest(request->AsWeakPtr());
440 return request.PassAs<Request>(); 348 return request.PassAs<Request>();
441 } 349 }
442 pending_fetchers_[fetch_parameters] = Fetcher::CreateAndStart( 350 pending_fetchers_[fetch_parameters] = Fetcher::CreateAndStart(
443 profile_, getter_, refresh_token, scopes, request->AsWeakPtr()); 351 this, request_context_getter_, refresh_token, scopes,
352 request->AsWeakPtr());
444 return request.PassAs<Request>(); 353 return request.PassAs<Request>();
445 #endif // defined(OS_ANDROID) 354 }
355
356 scoped_ptr<OAuth2TokenService::Request>
357 OAuth2TokenService::StartCacheLookupRequest(
358 const OAuth2TokenService::ScopeSet& scopes,
359 OAuth2TokenService::Consumer* consumer) {
360 CHECK(HasCacheEntry(scopes));
361 const CacheEntry* cache_entry = GetCacheEntry(scopes);
362 scoped_ptr<RequestImpl> request(new RequestImpl(consumer));
363 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
364 &OAuth2TokenService::InformConsumer,
365 request->AsWeakPtr(),
366 GoogleServiceAuthError(GoogleServiceAuthError::NONE),
367 cache_entry->access_token,
368 cache_entry->expiration_date));
369 return request.PassAs<Request>();
446 } 370 }
447 371
448 void OAuth2TokenService::InvalidateToken(const ScopeSet& scopes, 372 void OAuth2TokenService::InvalidateToken(const ScopeSet& scopes,
449 const std::string& invalid_token) { 373 const std::string& invalid_token) {
374 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
450 RemoveCacheEntry(scopes, invalid_token); 375 RemoveCacheEntry(scopes, invalid_token);
451
452 #if defined(OS_ANDROID)
453 DCHECK_EQ(scopes.size(), 1U);
454 std::vector<std::string> scope_list(scopes.begin(), scopes.end());
455 ProfileSyncServiceAndroid* sync_service =
456 ProfileSyncServiceAndroid::GetProfileSyncServiceAndroid();
457 sync_service->InvalidateOAuth2Token(
458 scope_list.front(),
459 invalid_token);
460 #endif
461 } 376 }
462 377
463 void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) { 378 void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) {
464 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 379 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
465 380
466 // Update the auth error state so auth errors are appropriately communicated 381 // Update the auth error state so auth errors are appropriately communicated
467 // to the user. 382 // to the user.
468 UpdateAuthError(fetcher->error()); 383 UpdateAuthError(fetcher->error());
469 384
470 // Note |fetcher| is recorded in |pending_fetcher_| mapped to its refresh 385 // Note |fetcher| is recorded in |pending_fetcher_| mapped to its refresh
471 // token and scope set. This is guaranteed as follows; here a Fetcher is said 386 // token and scope set. This is guaranteed as follows; here a Fetcher is said
472 // to be uncompleted if it has not finished calling back 387 // to be uncompleted if it has not finished calling back
473 // OAuth2TokenService::OnFetchComplete(). 388 // OAuth2TokenService::OnFetchComplete().
474 // 389 //
475 // (1) All the live Fetchers are created by this service. 390 // (1) All the live Fetchers are created by this service.
476 // This is because (1) all the live Fetchers are created by a live 391 // This is because (1) all the live Fetchers are created by a live
477 // service, as all the fetchers created by a service are destructed in the 392 // service, as all the fetchers created by a service are destructed in the
478 // service's dtor, and (2) there is at most one live OAuth2TokenSevice for 393 // service's dtor.
479 // a given profile at a time.
480 // 394 //
481 // (2) All the uncompleted Fetchers created by this service are recorded in 395 // (2) All the uncompleted Fetchers created by this service are recorded in
482 // |pending_fetchers_|. 396 // |pending_fetchers_|.
483 // This is because (1) all the created Fetchers are added to 397 // This is because (1) all the created Fetchers are added to
484 // |pending_fetchers_| (in method StartRequest()) and (2) method 398 // |pending_fetchers_| (in method StartRequest()) and (2) method
485 // OnFetchComplete() is the only place where a Fetcher is erased from 399 // OnFetchComplete() is the only place where a Fetcher is erased from
486 // |pending_fetchers_|. Note no Fetcher is erased in method 400 // |pending_fetchers_|. Note no Fetcher is erased in method
487 // StartRequest(). 401 // StartRequest().
488 // 402 //
489 // (3) Each of the Fetchers recorded in |pending_fetchers_| is mapped to its 403 // (3) Each of the Fetchers recorded in |pending_fetchers_| is mapped to its
490 // refresh token and ScopeSet. This is guaranteed by Fetcher creation in 404 // refresh token and ScopeSet. This is guaranteed by Fetcher creation in
491 // method StartReuest(). 405 // method StartRequest().
492 // 406 //
493 // When this method is called, |fetcher| is alive and uncompleted. 407 // When this method is called, |fetcher| is alive and uncompleted.
494 // By (1), |fetcher| is created by this service. 408 // By (1), |fetcher| is created by this service.
495 // Then by (2), |fetcher| is recorded in |pending_fetchers_|. 409 // Then by (2), |fetcher| is recorded in |pending_fetchers_|.
496 // Then by (3), |fetcher_| is mapped to its refresh token and ScopeSet. 410 // Then by (3), |fetcher_| is mapped to its refresh token and ScopeSet.
497 std::map<FetchParameters, Fetcher*>::iterator iter = 411 std::map<FetchParameters, Fetcher*>::iterator iter =
498 pending_fetchers_.find(std::make_pair( 412 pending_fetchers_.find(std::make_pair(
499 fetcher->GetRefreshToken(), fetcher->GetScopeSet())); 413 fetcher->GetRefreshToken(), fetcher->GetScopeSet()));
500 DCHECK(iter != pending_fetchers_.end()); 414 DCHECK(iter != pending_fetchers_.end());
501 DCHECK_EQ(fetcher, iter->second); 415 DCHECK_EQ(fetcher, iter->second);
502 pending_fetchers_.erase(iter); 416 pending_fetchers_.erase(iter);
503 } 417 }
504 418
419 bool OAuth2TokenService::HasCacheEntry(
420 const OAuth2TokenService::ScopeSet& scopes) {
421 const CacheEntry* cache_entry = GetCacheEntry(scopes);
422 return cache_entry && cache_entry->access_token.length();
423 }
424
505 const OAuth2TokenService::CacheEntry* OAuth2TokenService::GetCacheEntry( 425 const OAuth2TokenService::CacheEntry* OAuth2TokenService::GetCacheEntry(
506 const OAuth2TokenService::ScopeSet& scopes) { 426 const OAuth2TokenService::ScopeSet& scopes) {
507 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 427 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
508 TokenCache::iterator token_iterator = token_cache_.find(scopes); 428 TokenCache::iterator token_iterator = token_cache_.find(scopes);
509 if (token_iterator == token_cache_.end()) 429 if (token_iterator == token_cache_.end())
510 return NULL; 430 return NULL;
511 if (token_iterator->second.expiration_date <= base::Time::Now()) { 431 if (token_iterator->second.expiration_date <= base::Time::Now()) {
512 token_cache_.erase(token_iterator); 432 token_cache_.erase(token_iterator);
513 return NULL; 433 return NULL;
514 } 434 }
(...skipping 13 matching lines...) Expand all
528 return false; 448 return false;
529 } 449 }
530 450
531 void OAuth2TokenService::RegisterCacheEntry( 451 void OAuth2TokenService::RegisterCacheEntry(
532 const std::string& refresh_token, 452 const std::string& refresh_token,
533 const OAuth2TokenService::ScopeSet& scopes, 453 const OAuth2TokenService::ScopeSet& scopes,
534 const std::string& access_token, 454 const std::string& access_token,
535 const base::Time& expiration_date) { 455 const base::Time& expiration_date) {
536 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 456 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
537 457
538 #if !defined(OS_ANDROID)
539 // Only register OAuth2 access tokens for the refresh token held by
540 // TokenService.
541 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
542 if (!token_service ||
543 !token_service->HasOAuthLoginToken() ||
544 token_service->GetOAuth2LoginRefreshToken().compare(refresh_token) != 0) {
545 DLOG(INFO) <<
546 "Received a token with a refresh token not maintained by TokenService.";
547 return;
548 }
549 #endif
550
551 CacheEntry& token = token_cache_[scopes]; 458 CacheEntry& token = token_cache_[scopes];
552 token.access_token = access_token; 459 token.access_token = access_token;
553 token.expiration_date = expiration_date; 460 token.expiration_date = expiration_date;
554 } 461 }
555 462
556 void OAuth2TokenService::Observe(int type, 463 void OAuth2TokenService::UpdateAuthError(const GoogleServiceAuthError& error) {
557 const content::NotificationSource& source, 464 // Default implementation does nothing.
558 const content::NotificationDetails& details) {
559 DCHECK(type == chrome::NOTIFICATION_TOKENS_CLEARED ||
560 type == chrome::NOTIFICATION_TOKEN_AVAILABLE);
561 if (type == chrome::NOTIFICATION_TOKEN_AVAILABLE) {
562 TokenService::TokenAvailableDetails* tok_details =
563 content::Details<TokenService::TokenAvailableDetails>(details).ptr();
564 if (tok_details->service() != GaiaConstants::kGaiaOAuth2LoginRefreshToken)
565 return;
566 }
567 // The GaiaConstants::kGaiaOAuth2LoginRefreshToken token is used to create
568 // OAuth2 access tokens. If this token either changes or is cleared, any
569 // available tokens must be invalidated.
570 token_cache_.clear();
571 UpdateAuthError(GoogleServiceAuthError::AuthErrorNone());
572 } 465 }
573 466
574 void OAuth2TokenService::UpdateAuthError(const GoogleServiceAuthError& error) { 467 void OAuth2TokenService::ClearCache() {
575 // Do not report connection errors as these are not actually auth errors. 468 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
576 // We also want to avoid masking a "real" auth error just because we 469 token_cache_.clear();
577 // subsequently get a transient network error.
578 if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED)
579 return;
580
581 if (error.state() != last_auth_error_.state()) {
582 last_auth_error_ = error;
583 SigninManagerFactory::GetForProfile(profile_)->signin_global_error()->
584 AuthStatusChanged();
585 }
586 } 470 }
587 471
588 GoogleServiceAuthError OAuth2TokenService::GetAuthStatus() const { 472 int OAuth2TokenService::cache_size_for_testing() const {
589 return last_auth_error_; 473 return token_cache_.size();
590 } 474 }
OLDNEW
« no previous file with comments | « chrome/browser/signin/oauth2_token_service.h ('k') | chrome/browser/signin/oauth2_token_service_factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698