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

Side by Side Diff: chrome/browser/net/gaia/token_service.cc

Issue 7574009: Added OAuth support to TokenService (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 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 (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/net/gaia/token_service.h" 5 #include "chrome/browser/net/gaia/token_service.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/string_util.h" 8 #include "base/string_util.h"
9 #include "chrome/browser/profiles/profile.h" 9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/common/chrome_notification_types.h" 10 #include "chrome/common/chrome_notification_types.h"
11 #include "chrome/common/chrome_switches.h" 11 #include "chrome/common/chrome_switches.h"
12 #include "chrome/common/net/gaia/gaia_auth_fetcher.h" 12 #include "chrome/common/net/gaia/gaia_auth_fetcher.h"
13 #include "chrome/common/net/gaia/gaia_constants.h" 13 #include "chrome/common/net/gaia/gaia_constants.h"
14 #include "content/browser/browser_thread.h" 14 #include "content/browser/browser_thread.h"
15 #include "content/common/notification_service.h" 15 #include "content/common/notification_service.h"
16 #include "content/common/notification_source.h" 16 #include "content/common/notification_source.h"
17 #include "net/url_request/url_request_context_getter.h" 17 #include "net/url_request/url_request_context_getter.h"
18 18
19 // Unfortunately kNumServices must be defined in the .h. 19 // Unfortunately kNumServices must be defined in the .h.
20 // TODO(chron): Sync doesn't use the TalkToken anymore so we can stop 20 // TODO(chron): Sync doesn't use the TalkToken anymore so we can stop
21 // requesting it. 21 // requesting it.
22 const char* TokenService::kServices[] = { 22 const char* TokenService::kServices[] = {
23 GaiaConstants::kGaiaService, 23 GaiaConstants::kGaiaService,
24 GaiaConstants::kSyncService, 24 GaiaConstants::kSyncService,
25 GaiaConstants::kTalkService, 25 GaiaConstants::kTalkService,
26 GaiaConstants::kDeviceManagementService 26 GaiaConstants::kDeviceManagementService
27 }; 27 };
28 28
29 const char* kUnusedServiceScope = "unused-service-scope";
30
31 // Unfortunately kNumOAuthServices must be defined in the .h.
32 // For OAuth, Chrome uses the OAuth2 service scope as the service name.
33 const char* TokenService::kOAuthServices[] = {
34 GaiaConstants::kSyncServiceOAuth,
35 };
36
29 TokenService::TokenService() 37 TokenService::TokenService()
30 : token_loading_query_(0) { 38 : profile_(NULL),
39 token_loading_query_(0) {
31 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 40 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
32 } 41 }
33 42
34 TokenService::~TokenService() { 43 TokenService::~TokenService() {
35 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 44 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
36 ResetCredentialsInMemory(); 45 ResetCredentialsInMemory();
37 } 46 }
38 47
39 void TokenService::Initialize(const char* const source, 48 void TokenService::Initialize(const char* const source,
40 Profile* profile) { 49 Profile* profile) {
41 50
42 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
43 if (!source_.empty()) { 52 if (!source_.empty()) {
44 // Already initialized. 53 // Already initialized.
45 return; 54 return;
46 } 55 }
56 DCHECK(!profile_);
57 profile_ = profile;
47 getter_ = profile->GetRequestContext(); 58 getter_ = profile->GetRequestContext();
Mattias Nissler (ping if slow) 2011/08/04 13:39:57 It doesn't make much sense to keep around both the
Rick Campbell 2011/08/04 17:24:42 I might be misunderstanding here. The current dep
48 // Since the user can create a bookmark in incognito, sync may be running. 59 // Since the user can create a bookmark in incognito, sync may be running.
49 // Thus we have to go for explicit access. 60 // Thus we have to go for explicit access.
50 web_data_service_ = profile->GetWebDataService(Profile::EXPLICIT_ACCESS); 61 web_data_service_ = profile->GetWebDataService(Profile::EXPLICIT_ACCESS);
51 source_ = std::string(source); 62 source_ = std::string(source);
52 63
53 #ifndef NDEBUG 64 #ifndef NDEBUG
54 CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 65 CommandLine* cmd_line = CommandLine::ForCurrentProcess();
55 // Allow the token service to be cleared from the command line. 66 // Allow the token service to be cleared from the command line.
56 if (cmd_line->HasSwitch(switches::kClearTokenService)) 67 if (cmd_line->HasSwitch(switches::kClearTokenService))
57 EraseTokensFromDB(); 68 EraseTokensFromDB();
(...skipping 11 matching lines...) Expand all
69 80
70 registrar_.Add(this, 81 registrar_.Add(this,
71 chrome::NOTIFICATION_TOKEN_UPDATED, 82 chrome::NOTIFICATION_TOKEN_UPDATED,
72 Source<Profile>(profile)); 83 Source<Profile>(profile));
73 } 84 }
74 85
75 void TokenService::ResetCredentialsInMemory() { 86 void TokenService::ResetCredentialsInMemory() {
76 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 87 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
77 88
78 // Terminate any running fetchers. Callbacks will not return. 89 // Terminate any running fetchers. Callbacks will not return.
79 for (int i = 0; i < kNumServices; i++) { 90 for (int i = 0; i < kNumServices; ++i) {
80 fetchers_[i].reset(); 91 fetchers_[i].reset();
81 } 92 }
93 for (int i = 0; i < kNumOAuthServices; ++i) {
94 oauth_fetchers_[i].reset();
95 }
82 96
83 // Cancel pending loads. Callbacks will not return. 97 // Cancel pending loads. Callbacks will not return.
84 if (token_loading_query_) { 98 if (token_loading_query_) {
85 web_data_service_->CancelRequest(token_loading_query_); 99 web_data_service_->CancelRequest(token_loading_query_);
86 token_loading_query_ = 0; 100 token_loading_query_ = 0;
87 } 101 }
88 102
89 token_map_.clear(); 103 token_map_.clear();
90 credentials_ = GaiaAuthConsumer::ClientLoginResult(); 104 credentials_ = GaiaAuthConsumer::ClientLoginResult();
105 oauth_token_.clear();
106 oauth_secret_.clear();
91 } 107 }
92 108
93 void TokenService::UpdateCredentials( 109 void TokenService::UpdateCredentials(
94 const GaiaAuthConsumer::ClientLoginResult& credentials) { 110 const GaiaAuthConsumer::ClientLoginResult& credentials) {
95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
96 credentials_ = credentials; 112 credentials_ = credentials;
97 113
98 SaveAuthTokenToDB(GaiaConstants::kGaiaLsid, credentials.lsid); 114 SaveAuthTokenToDB(GaiaConstants::kGaiaLsid, credentials.lsid);
99 SaveAuthTokenToDB(GaiaConstants::kGaiaSid, credentials.sid); 115 SaveAuthTokenToDB(GaiaConstants::kGaiaSid, credentials.sid);
100 116
101 // Cancels any currently running requests. 117 // Cancels any currently running requests.
102 for (int i = 0; i < kNumServices; i++) { 118 for (int i = 0; i < kNumServices; i++) {
103 fetchers_[i].reset(new GaiaAuthFetcher(this, source_, getter_)); 119 fetchers_[i].reset(new GaiaAuthFetcher(this, source_, getter_));
104 } 120 }
105 } 121 }
106 122
123 void TokenService::UpdateOAuthCredentials(
124 const std::string& oauth_token,
125 const std::string& oauth_secret) {
126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
127 oauth_token_ = oauth_token;
128 oauth_secret_ = oauth_secret;
129
130 SaveAuthTokenToDB(GaiaConstants::kGaiaOAuthToken, oauth_token);
131 SaveAuthTokenToDB(GaiaConstants::kGaiaOAuthSecret, oauth_secret);
132
133 // Cancels any currently running requests.
134 for (int i = 0; i < kNumOAuthServices; i++) {
135 oauth_fetchers_[i].reset(
136 new GaiaOAuthFetcher(this, getter_, profile_, kUnusedServiceScope));
137 }
138 }
139
107 void TokenService::LoadTokensFromDB() { 140 void TokenService::LoadTokensFromDB() {
108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 141 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
109 if (web_data_service_.get()) 142 if (web_data_service_.get())
110 token_loading_query_ = web_data_service_->GetAllTokens(this); 143 token_loading_query_ = web_data_service_->GetAllTokens(this);
111 } 144 }
112 145
113 void TokenService::SaveAuthTokenToDB(const std::string& service, 146 void TokenService::SaveAuthTokenToDB(const std::string& service,
114 const std::string& auth_token) { 147 const std::string& auth_token) {
115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 148 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
116 if (web_data_service_.get()) 149 if (web_data_service_.get())
117 web_data_service_->SetTokenForService(service, auth_token); 150 web_data_service_->SetTokenForService(service, auth_token);
118 } 151 }
119 152
120 void TokenService::EraseTokensFromDB() { 153 void TokenService::EraseTokensFromDB() {
121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 154 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
122 if (web_data_service_.get()) 155 if (web_data_service_.get())
123 web_data_service_->RemoveAllTokens(); 156 web_data_service_->RemoveAllTokens();
124 } 157 }
125 158
126 bool TokenService::AreCredentialsValid() const { 159 bool TokenService::AreCredentialsValid() const {
127 return !credentials_.lsid.empty() && !credentials_.sid.empty(); 160 return !credentials_.lsid.empty() && !credentials_.sid.empty();
128 } 161 }
129 162
163 bool TokenService::AreOAuthCredentialsValid() const {
164 return !oauth_token_.empty() && !oauth_secret_.empty();
165 }
166
130 bool TokenService::HasLsid() const { 167 bool TokenService::HasLsid() const {
131 return !credentials_.lsid.empty(); 168 return !credentials_.lsid.empty();
132 } 169 }
133 170
134 const std::string& TokenService::GetLsid() const { 171 const std::string& TokenService::GetLsid() const {
135 return credentials_.lsid; 172 return credentials_.lsid;
136 } 173 }
137 174
138 void TokenService::StartFetchingTokens() { 175 void TokenService::StartFetchingTokens() {
139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
140 DCHECK(AreCredentialsValid()); 177 DCHECK(AreCredentialsValid());
141 for (int i = 0; i < kNumServices; i++) { 178 for (int i = 0; i < kNumServices; i++) {
142 fetchers_[i]->StartIssueAuthToken(credentials_.sid, 179 fetchers_[i]->StartIssueAuthToken(credentials_.sid,
143 credentials_.lsid, 180 credentials_.lsid,
144 kServices[i]); 181 kServices[i]);
145 } 182 }
146 } 183 }
147 184
185 void TokenService::StartFetchingOAuthTokens() {
186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
187 DCHECK(AreOAuthCredentialsValid());
188 for (int i = 0; i < kNumOAuthServices; i++) {
189 oauth_fetchers_[i]->StartOAuthWrapBridge(oauth_token_,
190 oauth_secret_,
191 GaiaConstants::kGaiaOAuthDuration,
192 kOAuthServices[i]);
193 }
194 }
195
148 // Services dependent on a token will check if a token is available. 196 // Services dependent on a token will check if a token is available.
149 // If it isn't, they'll go to sleep until they get a token event. 197 // If it isn't, they'll go to sleep until they get a token event.
150 bool TokenService::HasTokenForService(const char* const service) const { 198 bool TokenService::HasTokenForService(const char* const service) const {
151 return token_map_.count(service) > 0; 199 return token_map_.count(service) > 0;
152 } 200 }
153 201
154 const std::string& TokenService::GetTokenForService( 202 const std::string& TokenService::GetTokenForService(
155 const char* const service) const { 203 const char* const service) const {
156 204
157 if (token_map_.count(service) > 0) { 205 if (token_map_.count(service) > 0) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 SaveAuthTokenToDB(service, auth_token); 251 SaveAuthTokenToDB(service, auth_token);
204 } 252 }
205 253
206 void TokenService::OnIssueAuthTokenFailure(const std::string& service, 254 void TokenService::OnIssueAuthTokenFailure(const std::string& service,
207 const GoogleServiceAuthError& error) { 255 const GoogleServiceAuthError& error) {
208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 256 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
209 LOG(WARNING) << "Auth token issuing failed for service:" << service; 257 LOG(WARNING) << "Auth token issuing failed for service:" << service;
210 FireTokenRequestFailedNotification(service, error); 258 FireTokenRequestFailedNotification(service, error);
211 } 259 }
212 260
261 void TokenService::OnOAuthGetAccessTokenSuccess(const std::string& token,
262 const std::string& secret) {
263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
264 VLOG(1) << "TokenService::OnOAuthGetAccessTokenSuccess";
265 SaveAuthTokenToDB(GaiaConstants::kGaiaOAuthToken, token);
266 SaveAuthTokenToDB(GaiaConstants::kGaiaOAuthSecret, secret);
267 UpdateOAuthCredentials(token, secret);
268 }
269
270 void TokenService::OnOAuthGetAccessTokenFailure(
271 const GoogleServiceAuthError& error) {
272 VLOG(1) << "TokenService::OnOAuthGetAccessTokenFailure";
273 }
274
275 void TokenService::OnOAuthWrapBridgeSuccess(const std::string& service_scope,
276 const std::string& token,
277 const std::string& expires_in) {
278 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
279 VLOG(1) << "Got an access token for " << service_scope;
280 token_map_[service_scope] = token;
281 FireTokenAvailableNotification(service_scope, token);
282 SaveAuthTokenToDB(service_scope, token);
283 }
284
285 void TokenService::OnOAuthWrapBridgeFailure(
286 const std::string& service_scope,
287 const GoogleServiceAuthError& error) {
288 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
289 LOG(WARNING) << "Auth token issuing failed for service:" << service_scope;
290 FireTokenRequestFailedNotification(service_scope, error);
291
Mattias Nissler (ping if slow) 2011/08/04 13:39:57 remove blank line
Rick Campbell 2011/08/04 17:24:42 Done.
292 }
293
213 void TokenService::OnWebDataServiceRequestDone(WebDataService::Handle h, 294 void TokenService::OnWebDataServiceRequestDone(WebDataService::Handle h,
214 const WDTypedResult* result) { 295 const WDTypedResult* result) {
215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 296 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
216 DCHECK(token_loading_query_); 297 DCHECK(token_loading_query_);
217 token_loading_query_ = 0; 298 token_loading_query_ = 0;
218 299
219 // If the fetch failed, there will be no result. In that case, we just don't 300 // If the fetch failed, there will be no result. In that case, we just don't
220 // load any tokens at all from the DB. 301 // load any tokens at all from the DB.
221 if (result) { 302 if (result) {
222 DCHECK(result->GetType() == TOKEN_RESULT); 303 DCHECK(result->GetType() == TOKEN_RESULT);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 if (db_tokens.count(GaiaConstants::kGaiaSid) > 0) 351 if (db_tokens.count(GaiaConstants::kGaiaSid) > 0)
271 sid = db_tokens.find(GaiaConstants::kGaiaSid)->second; 352 sid = db_tokens.find(GaiaConstants::kGaiaSid)->second;
272 353
273 if (!lsid.empty() && !sid.empty()) { 354 if (!lsid.empty() && !sid.empty()) {
274 UpdateCredentials(GaiaAuthConsumer::ClientLoginResult(sid, 355 UpdateCredentials(GaiaAuthConsumer::ClientLoginResult(sid,
275 lsid, 356 lsid,
276 std::string(), 357 std::string(),
277 std::string())); 358 std::string()));
278 } 359 }
279 } 360 }
361
362 for (int i = 0; i < kNumOAuthServices; i++) {
363 // OnIssueAuthTokenSuccess should come from the same thread.
364 // If a token is already present in the map, it could only have
365 // come from a DB read or from IssueAuthToken. Since we should never
366 // fetch from the DB twice in a browser session, it must be from
367 // OnIssueAuthTokenSuccess, which is a live fetcher.
368 //
369 // Network fetched tokens take priority over DB tokens, so exclude tokens
370 // which have already been loaded by the fetcher.
371 if (!in_memory_tokens->count(kOAuthServices[i]) &&
372 db_tokens.count(kOAuthServices[i])) {
373 std::string db_token = db_tokens.find(kOAuthServices[i])->second;
374 if (!db_token.empty()) {
375 VLOG(1) << "Loading " << kOAuthServices[i] << "token from DB: "
376 << db_token;
377 (*in_memory_tokens)[kOAuthServices[i]] = db_token;
378 FireTokenAvailableNotification(kOAuthServices[i], db_token);
379 // Failures are only for network errors.
380 }
381 }
382 }
383
384 if (oauth_token_.empty() && oauth_secret_.empty()) {
385 // Look for GAIA OAuth1 access token and secret. If we have both, and the
386 // current crendentials are empty, update the credentials.
387 std::string oauth_token;
388 std::string oauth_secret;
389
390 if (db_tokens.count(GaiaConstants::kGaiaOAuthToken) > 0)
391 oauth_token = db_tokens.find(GaiaConstants::kGaiaOAuthToken)->second;
392
393 if (db_tokens.count(GaiaConstants::kGaiaOAuthSecret) > 0)
394 oauth_secret = db_tokens.find(GaiaConstants::kGaiaOAuthSecret)->second;
395
396 if (!oauth_token.empty() && !oauth_secret.empty()) {
397 UpdateOAuthCredentials(oauth_token, oauth_secret);
398 }
399 }
280 } 400 }
281 401
282 void TokenService::Observe(int type, 402 void TokenService::Observe(int type,
283 const NotificationSource& source, 403 const NotificationSource& source,
284 const NotificationDetails& details) { 404 const NotificationDetails& details) {
285 DCHECK_EQ(type, chrome::NOTIFICATION_TOKEN_UPDATED); 405 DCHECK_EQ(type, chrome::NOTIFICATION_TOKEN_UPDATED);
286 TokenAvailableDetails* tok_details = 406 TokenAvailableDetails* tok_details =
287 Details<TokenAvailableDetails>(details).ptr(); 407 Details<TokenAvailableDetails>(details).ptr();
288 OnIssueAuthTokenSuccess(tok_details->service(), tok_details->token()); 408 OnIssueAuthTokenSuccess(tok_details->service(), tok_details->token());
289 } 409 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698