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

Side by Side Diff: chrome/browser/extensions/api/identity/identity_api.cc

Issue 14270007: Identity API: getAuthToken request queues (token cache prelude) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@lkgr
Patch Set: fix test fixture init + address code review feedback 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/identity/identity_api.h" 5 #include "chrome/browser/extensions/api/identity/identity_api.h"
6 6
7 #include <set>
8 #include <string>
9 #include <vector>
10
7 #include "base/lazy_instance.h" 11 #include "base/lazy_instance.h"
8 #include "base/stringprintf.h" 12 #include "base/stringprintf.h"
9 #include "base/values.h" 13 #include "base/values.h"
10 #include "chrome/browser/app_mode/app_mode_utils.h" 14 #include "chrome/browser/app_mode/app_mode_utils.h"
11 #include "chrome/browser/extensions/extension_function_dispatcher.h" 15 #include "chrome/browser/extensions/extension_function_dispatcher.h"
12 #include "chrome/browser/extensions/extension_install_prompt.h" 16 #include "chrome/browser/extensions/extension_install_prompt.h"
13 #include "chrome/browser/extensions/extension_service.h" 17 #include "chrome/browser/extensions/extension_service.h"
14 #include "chrome/browser/extensions/permissions_updater.h" 18 #include "chrome/browser/extensions/permissions_updater.h"
15 #include "chrome/browser/profiles/profile.h" 19 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/signin/signin_manager.h" 20 #include "chrome/browser/signin/signin_manager.h"
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 57
54 } // namespace 58 } // namespace
55 59
56 namespace GetAuthToken = api::experimental_identity::GetAuthToken; 60 namespace GetAuthToken = api::experimental_identity::GetAuthToken;
57 namespace LaunchWebAuthFlow = api::experimental_identity::LaunchWebAuthFlow; 61 namespace LaunchWebAuthFlow = api::experimental_identity::LaunchWebAuthFlow;
58 namespace identity = api::experimental_identity; 62 namespace identity = api::experimental_identity;
59 63
60 IdentityGetAuthTokenFunction::IdentityGetAuthTokenFunction() 64 IdentityGetAuthTokenFunction::IdentityGetAuthTokenFunction()
61 : should_prompt_for_scopes_(false), 65 : should_prompt_for_scopes_(false),
62 should_prompt_for_signin_(false) {} 66 should_prompt_for_signin_(false) {}
67
63 IdentityGetAuthTokenFunction::~IdentityGetAuthTokenFunction() {} 68 IdentityGetAuthTokenFunction::~IdentityGetAuthTokenFunction() {}
64 69
65 bool IdentityGetAuthTokenFunction::RunImpl() { 70 bool IdentityGetAuthTokenFunction::RunImpl() {
66 scoped_ptr<GetAuthToken::Params> params(GetAuthToken::Params::Create(*args_)); 71 scoped_ptr<GetAuthToken::Params> params(GetAuthToken::Params::Create(*args_));
67 EXTENSION_FUNCTION_VALIDATE(params.get()); 72 EXTENSION_FUNCTION_VALIDATE(params.get());
68 bool interactive = params->details.get() && 73 bool interactive = params->details.get() &&
69 params->details->interactive.get() && 74 params->details->interactive.get() &&
70 *params->details->interactive; 75 *params->details->interactive;
71 76
72 should_prompt_for_scopes_ = interactive; 77 should_prompt_for_scopes_ = interactive;
73 should_prompt_for_signin_ = interactive; 78 should_prompt_for_signin_ = interactive;
74 79
75 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension()); 80 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
76 81
77 // Check that the necessary information is present in the manifest. 82 // Check that the necessary information is present in the manifest.
78 if (oauth2_info.client_id.empty()) { 83 if (oauth2_info.client_id.empty()) {
79 error_ = identity_constants::kInvalidClientId; 84 error_ = identity_constants::kInvalidClientId;
80 return false; 85 return false;
81 } 86 }
82 87
83 if (oauth2_info.scopes.size() == 0) { 88 if (oauth2_info.scopes.size() == 0) {
84 error_ = identity_constants::kInvalidScopes; 89 error_ = identity_constants::kInvalidScopes;
85 return false; 90 return false;
86 } 91 }
87 92
88 // Balanced in OnIssueAdviceSuccess|OnMintTokenSuccess|OnMintTokenFailure| 93 // Balanced in CompleteFunctionWithResult|CompleteFunctionWithError
89 // InstallUIAbort|SigninFailed.
90 AddRef(); 94 AddRef();
91 95
92 if (!HasLoginToken()) { 96 if (!HasLoginToken()) {
93 if (!should_prompt_for_signin_) { 97 if (!should_prompt_for_signin_) {
94 error_ = identity_constants::kUserNotSignedIn; 98 error_ = identity_constants::kUserNotSignedIn;
95 Release(); 99 Release();
96 return false; 100 return false;
97 } 101 }
98 // Display a login prompt. If the subsequent mint fails, don't display the 102 // Display a login prompt.
99 // prompt again. 103 StartSigninFlow();
100 should_prompt_for_signin_ = false;
101 ShowLoginPopup();
102 } else { 104 } else {
103 TokenService* token_service = TokenServiceFactory::GetForProfile(profile()); 105 TokenService* token_service = TokenServiceFactory::GetForProfile(profile());
104 refresh_token_ = token_service->GetOAuth2LoginRefreshToken(); 106 refresh_token_ = token_service->GetOAuth2LoginRefreshToken();
105 StartFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE); 107 StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE);
106 } 108 }
107 109
108 return true; 110 return true;
109 } 111 }
110 112
111 void IdentityGetAuthTokenFunction::OnMintTokenSuccess( 113 void IdentityGetAuthTokenFunction::CompleteFunctionWithResult(
112 const std::string& access_token) { 114 const std::string& access_token) {
113 SetResult(Value::CreateStringValue(access_token)); 115 SetResult(Value::CreateStringValue(access_token));
114 SendResponse(true); 116 SendResponse(true);
115 Release(); // Balanced in RunImpl. 117 Release(); // Balanced in RunImpl.
116 } 118 }
117 119
120 void IdentityGetAuthTokenFunction::CompleteFunctionWithError(
121 const std::string& error) {
122 error_ = error;
123 SendResponse(false);
124 Release(); // Balanced in RunImpl.
125 }
126
127 void IdentityGetAuthTokenFunction::StartSigninFlow() {
128 // Display a login prompt. If the subsequent mint fails, don't display the
129 // login prompt again.
130 should_prompt_for_signin_ = false;
131 ShowLoginPopup();
132 }
133
134 void IdentityGetAuthTokenFunction::StartMintTokenFlow(
135 IdentityMintRequestQueue::MintType type) {
136 mint_token_flow_type_ = type;
137
138 // Flows are serialized to prevent excessive traffic to GAIA, and
139 // to consolidate UI pop-ups.
140 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
141 std::set<std::string> scopes(oauth2_info.scopes.begin(),
142 oauth2_info.scopes.end());
143 IdentityAPI* id_api =
144 extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(profile_);
145
146 // If there is an interactive flow in progress, non-interactive
147 // requests should complete immediately since a consent UI is
148 // known to be required.
149 if (!should_prompt_for_scopes_ && !id_api->mint_queue()->empty(
150 IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE,
151 GetExtension()->id(), scopes)) {
152 CompleteFunctionWithError(identity_constants::kNoGrant);
153 return;
154 }
155 id_api->mint_queue()->RequestStart(type,
156 GetExtension()->id(),
157 scopes,
158 this);
159 }
160
161 void IdentityGetAuthTokenFunction::CompleteMintTokenFlow() {
162 IdentityMintRequestQueue::MintType type = mint_token_flow_type_;
163
164 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
165 std::set<std::string> scopes(oauth2_info.scopes.begin(),
166 oauth2_info.scopes.end());
167
168 extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(
169 profile_)->mint_queue()->RequestComplete(type,
170 GetExtension()->id(),
171 scopes,
172 this);
173 }
174
175 void IdentityGetAuthTokenFunction::StartMintToken(
176 IdentityMintRequestQueue::MintType type) {
177 switch (type) {
178 case IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE:
179 StartGaiaRequest(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE);
180 break;
181
182 case IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE:
183 install_ui_.reset(new ExtensionInstallPrompt(GetAssociatedWebContents()));
184 ShowOAuthApprovalDialog(issue_advice_);
185 break;
186
187 default:
188 NOTREACHED() << "Unexepected mint type in StartMintToken: " << type;
189 break;
190 };
191 }
192
193 void IdentityGetAuthTokenFunction::OnMintTokenSuccess(
194 const std::string& access_token) {
195 CompleteMintTokenFlow();
196 CompleteFunctionWithResult(access_token);
197 }
198
118 void IdentityGetAuthTokenFunction::OnMintTokenFailure( 199 void IdentityGetAuthTokenFunction::OnMintTokenFailure(
119 const GoogleServiceAuthError& error) { 200 const GoogleServiceAuthError& error) {
201 CompleteMintTokenFlow();
202
120 switch (error.state()) { 203 switch (error.state()) {
121 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: 204 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
122 case GoogleServiceAuthError::ACCOUNT_DELETED: 205 case GoogleServiceAuthError::ACCOUNT_DELETED:
123 case GoogleServiceAuthError::ACCOUNT_DISABLED: 206 case GoogleServiceAuthError::ACCOUNT_DISABLED:
124 extensions::IdentityAPI::GetFactoryInstance()->GetForProfile( 207 extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(
125 profile())->ReportAuthError(error); 208 profile())->ReportAuthError(error);
126 if (should_prompt_for_signin_) { 209 if (should_prompt_for_signin_) {
127 // Display a login prompt and try again (once). 210 // Display a login prompt and try again (once).
128 should_prompt_for_signin_ = false; 211 StartSigninFlow();
129 ShowLoginPopup();
130 return; 212 return;
131 } 213 }
132 break; 214 break;
133 default: 215 default:
134 // Return error to caller. 216 // Return error to caller.
135 break; 217 break;
136 } 218 }
137 219
138 error_ = std::string(identity_constants::kAuthFailure) + error.ToString(); 220 CompleteFunctionWithError(
139 SendResponse(false); 221 std::string(identity_constants::kAuthFailure) + error.ToString());
140 Release(); // Balanced in RunImpl.
141 } 222 }
142 223
143 void IdentityGetAuthTokenFunction::OnIssueAdviceSuccess( 224 void IdentityGetAuthTokenFunction::OnIssueAdviceSuccess(
144 const IssueAdviceInfo& issue_advice) { 225 const IssueAdviceInfo& issue_advice) {
226 CompleteMintTokenFlow();
227
145 should_prompt_for_signin_ = false; 228 should_prompt_for_signin_ = false;
146 // Existing grant was revoked and we used NO_FORCE, so we got info back 229 // Existing grant was revoked and we used NO_FORCE, so we got info back
147 // instead. 230 // instead.
148 if (should_prompt_for_scopes_) { 231 if (should_prompt_for_scopes_) {
149 install_ui_.reset(new ExtensionInstallPrompt(GetAssociatedWebContents())); 232 issue_advice_ = issue_advice;
150 ShowOAuthApprovalDialog(issue_advice); 233 StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
151 } else { 234 } else {
152 error_ = identity_constants::kNoGrant; 235 CompleteFunctionWithError(identity_constants::kNoGrant);
153 SendResponse(false);
154 Release(); // Balanced in RunImpl.
155 } 236 }
156 } 237 }
157 238
158 void IdentityGetAuthTokenFunction::SigninSuccess(const std::string& token) { 239 void IdentityGetAuthTokenFunction::SigninSuccess(const std::string& token) {
159 refresh_token_ = token; 240 refresh_token_ = token;
160 StartFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE); 241 StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE);
161 } 242 }
162 243
163 void IdentityGetAuthTokenFunction::SigninFailed() { 244 void IdentityGetAuthTokenFunction::SigninFailed() {
164 error_ = identity_constants::kUserNotSignedIn; 245 CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
165 SendResponse(false);
166 Release();
167 } 246 }
168 247
169 void IdentityGetAuthTokenFunction::InstallUIProceed() { 248 void IdentityGetAuthTokenFunction::InstallUIProceed() {
170 DCHECK(install_ui_->record_oauth2_grant()); 249 DCHECK(install_ui_->record_oauth2_grant());
171 // The user has accepted the scopes, so we may now force (recording a grant 250 // The user has accepted the scopes, so we may now force (recording a grant
172 // and receiving a token). 251 // and receiving a token).
173 StartFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE); 252 StartGaiaRequest(OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE);
174 } 253 }
175 254
176 void IdentityGetAuthTokenFunction::InstallUIAbort(bool user_initiated) { 255 void IdentityGetAuthTokenFunction::InstallUIAbort(bool user_initiated) {
177 error_ = identity_constants::kUserRejected; 256 CompleteMintTokenFlow();
178 SendResponse(false); 257 CompleteFunctionWithError(identity_constants::kUserRejected);
179 Release(); // Balanced in RunImpl.
180 } 258 }
181 259
182 void IdentityGetAuthTokenFunction::StartFlow(OAuth2MintTokenFlow::Mode mode) { 260 void IdentityGetAuthTokenFunction::StartGaiaRequest(
183 signin_flow_.reset(NULL); 261 OAuth2MintTokenFlow::Mode mode) {
184 mint_token_flow_.reset(CreateMintTokenFlow(mode)); 262 mint_token_flow_.reset(CreateMintTokenFlow(mode));
185 mint_token_flow_->Start(); 263 mint_token_flow_->Start();
186 } 264 }
187 265
188 void IdentityGetAuthTokenFunction::ShowLoginPopup() { 266 void IdentityGetAuthTokenFunction::ShowLoginPopup() {
189 signin_flow_.reset(new IdentitySigninFlow(this, profile())); 267 signin_flow_.reset(new IdentitySigninFlow(this, profile()));
190 signin_flow_->Start(); 268 signin_flow_->Start();
191 } 269 }
192 270
193 void IdentityGetAuthTokenFunction::ShowOAuthApprovalDialog( 271 void IdentityGetAuthTokenFunction::ShowOAuthApprovalDialog(
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 void IdentityAPI::Initialize() { 410 void IdentityAPI::Initialize() {
333 signin_manager_ = SigninManagerFactory::GetForProfile(profile_); 411 signin_manager_ = SigninManagerFactory::GetForProfile(profile_);
334 signin_manager_->signin_global_error()->AddProvider(this); 412 signin_manager_->signin_global_error()->AddProvider(this);
335 413
336 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); 414 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
337 registrar_.Add(this, 415 registrar_.Add(this,
338 chrome::NOTIFICATION_TOKEN_AVAILABLE, 416 chrome::NOTIFICATION_TOKEN_AVAILABLE,
339 content::Source<TokenService>(token_service)); 417 content::Source<TokenService>(token_service));
340 } 418 }
341 419
420 IdentityMintRequestQueue* IdentityAPI::mint_queue() {
421 return &mint_queue_;
422 }
423
342 void IdentityAPI::ReportAuthError(const GoogleServiceAuthError& error) { 424 void IdentityAPI::ReportAuthError(const GoogleServiceAuthError& error) {
343 if (!signin_manager_) 425 if (!signin_manager_)
344 Initialize(); 426 Initialize();
345 427
346 error_ = error; 428 error_ = error;
347 signin_manager_->signin_global_error()->AuthStatusChanged(); 429 signin_manager_->signin_global_error()->AuthStatusChanged();
348 } 430 }
349 431
350 void IdentityAPI::Shutdown() { 432 void IdentityAPI::Shutdown() {
351 if (signin_manager_) 433 if (signin_manager_)
(...skipping 26 matching lines...) Expand all
378 } 460 }
379 461
380 template <> 462 template <>
381 void ProfileKeyedAPIFactory<IdentityAPI>::DeclareFactoryDependencies() { 463 void ProfileKeyedAPIFactory<IdentityAPI>::DeclareFactoryDependencies() {
382 DependsOn(ExtensionSystemFactory::GetInstance()); 464 DependsOn(ExtensionSystemFactory::GetInstance());
383 DependsOn(TokenServiceFactory::GetInstance()); 465 DependsOn(TokenServiceFactory::GetInstance());
384 DependsOn(SigninManagerFactory::GetInstance()); 466 DependsOn(SigninManagerFactory::GetInstance());
385 } 467 }
386 468
387 } // namespace extensions 469 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/api/identity/identity_api.h ('k') | chrome/browser/extensions/api/identity/identity_apitest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698