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

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

Issue 12929014: Identity API: Pop-up a sign-in dialog if gaia credentials are bad (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@lkgr
Patch Set: launch sign-in through LoginUIService 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 "base/lazy_instance.h" 7 #include "base/lazy_instance.h"
8 #include "base/values.h" 8 #include "base/values.h"
9 #include "chrome/browser/extensions/extension_function_dispatcher.h" 9 #include "chrome/browser/extensions/extension_function_dispatcher.h"
10 #include "chrome/browser/extensions/extension_install_prompt.h" 10 #include "chrome/browser/extensions/extension_install_prompt.h"
11 #include "chrome/browser/extensions/extension_service.h" 11 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/extensions/permissions_updater.h" 12 #include "chrome/browser/extensions/permissions_updater.h"
13 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/signin/signin_manager.h"
15 #include "chrome/browser/signin/signin_manager_factory.h"
14 #include "chrome/browser/signin/token_service.h" 16 #include "chrome/browser/signin/token_service.h"
15 #include "chrome/browser/signin/token_service_factory.h" 17 #include "chrome/browser/signin/token_service_factory.h"
16 #include "chrome/browser/ui/browser.h" 18 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/browser_navigator.h"
18 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
19 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
20 #include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
21 #include "chrome/common/extensions/api/experimental_identity.h" 19 #include "chrome/common/extensions/api/experimental_identity.h"
22 #include "chrome/common/extensions/api/identity/oauth2_manifest_handler.h" 20 #include "chrome/common/extensions/api/identity/oauth2_manifest_handler.h"
23 #include "chrome/common/extensions/extension.h" 21 #include "chrome/common/extensions/extension.h"
24 #include "chrome/common/extensions/extension_manifest_constants.h" 22 #include "chrome/common/extensions/extension_manifest_constants.h"
25 #include "chrome/common/extensions/manifest_handler.h" 23 #include "chrome/common/extensions/manifest_handler.h"
26 #include "chrome/common/url_constants.h" 24 #include "chrome/common/url_constants.h"
27 #include "content/public/common/page_transition_types.h" 25 #include "content/public/common/page_transition_types.h"
26 #include "google_apis/gaia/gaia_constants.h"
28 #include "googleurl/src/gurl.h" 27 #include "googleurl/src/gurl.h"
29 #include "ui/base/window_open_disposition.h" 28 #include "ui/base/window_open_disposition.h"
30 29
31 namespace extensions { 30 namespace extensions {
32 31
33 namespace identity_constants { 32 namespace identity_constants {
34 const char kInvalidClientId[] = "Invalid OAuth2 Client ID."; 33 const char kInvalidClientId[] = "Invalid OAuth2 Client ID.";
35 const char kInvalidScopes[] = "Invalid OAuth2 scopes."; 34 const char kInvalidScopes[] = "Invalid OAuth2 scopes.";
36 const char kAuthFailure[] = "OAuth2 request failed: "; 35 const char kAuthFailure[] = "OAuth2 request failed: ";
37 const char kNoGrant[] = "OAuth2 not granted or revoked."; 36 const char kNoGrant[] = "OAuth2 not granted or revoked.";
38 const char kUserRejected[] = "The user did not approve access."; 37 const char kUserRejected[] = "The user did not approve access.";
39 const char kUserNotSignedIn[] = "The user is not signed in."; 38 const char kUserNotSignedIn[] = "The user is not signed in.";
40 const char kInvalidRedirect[] = "Did not redirect to the right URL."; 39 const char kInvalidRedirect[] = "Did not redirect to the right URL.";
41 } // namespace identity_constants 40 } // namespace identity_constants
42 41
43 namespace GetAuthToken = api::experimental_identity::GetAuthToken; 42 namespace GetAuthToken = api::experimental_identity::GetAuthToken;
44 namespace LaunchWebAuthFlow = api::experimental_identity::LaunchWebAuthFlow; 43 namespace LaunchWebAuthFlow = api::experimental_identity::LaunchWebAuthFlow;
45 namespace identity = api::experimental_identity; 44 namespace identity = api::experimental_identity;
46 45
47 IdentityGetAuthTokenFunction::IdentityGetAuthTokenFunction() 46 IdentityGetAuthTokenFunction::IdentityGetAuthTokenFunction()
48 : interactive_(false) {} 47 : interactive_(false),
48 should_retry_with_signin_(false) {}
49 IdentityGetAuthTokenFunction::~IdentityGetAuthTokenFunction() {} 49 IdentityGetAuthTokenFunction::~IdentityGetAuthTokenFunction() {}
50 50
51 bool IdentityGetAuthTokenFunction::RunImpl() { 51 bool IdentityGetAuthTokenFunction::RunImpl() {
52 scoped_ptr<GetAuthToken::Params> params(GetAuthToken::Params::Create(*args_)); 52 scoped_ptr<GetAuthToken::Params> params(GetAuthToken::Params::Create(*args_));
53 EXTENSION_FUNCTION_VALIDATE(params.get()); 53 EXTENSION_FUNCTION_VALIDATE(params.get());
54 if (params->details.get() && params->details->interactive.get()) 54 if (params->details.get() && params->details->interactive.get())
55 interactive_ = *params->details->interactive; 55 interactive_ = *params->details->interactive;
56 56
57 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension()); 57 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
58 58
59 // Check that the necessary information is present in the manfist. 59 // Check that the necessary information is present in the manfist.
60 if (oauth2_info.client_id.empty()) { 60 if (oauth2_info.client_id.empty()) {
61 error_ = identity_constants::kInvalidClientId; 61 error_ = identity_constants::kInvalidClientId;
62 return false; 62 return false;
63 } 63 }
64 64
65 if (oauth2_info.scopes.size() == 0) { 65 if (oauth2_info.scopes.size() == 0) {
66 error_ = identity_constants::kInvalidScopes; 66 error_ = identity_constants::kInvalidScopes;
67 return false; 67 return false;
68 } 68 }
69 69
70 // Balanced in OnIssueAdviceSuccess|OnMintTokenSuccess|OnMintTokenFailure| 70 // Balanced in OnIssueAdviceSuccess|OnMintTokenSuccess|OnMintTokenFailure|
71 // InstallUIAbort|OnLoginUIClosed. 71 // InstallUIAbort|SigninFailed.
72 AddRef(); 72 AddRef();
73 73
74 if (!HasLoginToken()) { 74 if (!HasLoginToken()) {
75 if (StartLogin()) { 75 if (!interactive_) {
76 return true; 76 error_ = identity_constants::kUserNotSignedIn;
77 } else {
78 Release(); 77 Release();
79 return false; 78 return false;
80 } 79 }
80 ShowLoginPopup();
81 } else {
82 TokenService* token_service = TokenServiceFactory::GetForProfile(profile());
83 refresh_token_ = token_service->GetOAuth2LoginRefreshToken();
84 should_retry_with_signin_ = interactive_;
85 StartFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE);
81 } 86 }
82 87
83 if (StartFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE)) { 88 return true;
84 return true;
85 } else {
86 Release();
87 return false;
88 }
89 } 89 }
90 90
91 void IdentityGetAuthTokenFunction::OnMintTokenSuccess( 91 void IdentityGetAuthTokenFunction::OnMintTokenSuccess(
92 const std::string& access_token) { 92 const std::string& access_token) {
93 SetResult(Value::CreateStringValue(access_token)); 93 SetResult(Value::CreateStringValue(access_token));
94 SendResponse(true); 94 SendResponse(true);
95 Release(); // Balanced in RunImpl. 95 Release(); // Balanced in RunImpl.
96 } 96 }
97 97
98 void IdentityGetAuthTokenFunction::OnMintTokenFailure( 98 void IdentityGetAuthTokenFunction::OnMintTokenFailure(
99 const GoogleServiceAuthError& error) { 99 const GoogleServiceAuthError& error) {
100 switch (error.state()) {
101 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
102 case GoogleServiceAuthError::ACCOUNT_DELETED:
103 case GoogleServiceAuthError::ACCOUNT_DISABLED:
104 extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(
105 profile())->ReportAuthError(error);
106 if (should_retry_with_signin_) {
107 should_retry_with_signin_ = false;
108 ShowLoginPopup();
109 return;
110 }
111 break;
112 default:
113 // Return error to caller.
114 break;
115 }
116
100 error_ = std::string(identity_constants::kAuthFailure) + error.ToString(); 117 error_ = std::string(identity_constants::kAuthFailure) + error.ToString();
101 SendResponse(false); 118 SendResponse(false);
102 Release(); // Balanced in RunImpl. 119 Release(); // Balanced in RunImpl.
103 } 120 }
104 121
105 void IdentityGetAuthTokenFunction::OnIssueAdviceSuccess( 122 void IdentityGetAuthTokenFunction::OnIssueAdviceSuccess(
106 const IssueAdviceInfo& issue_advice) { 123 const IssueAdviceInfo& issue_advice) {
124 should_retry_with_signin_ = false;
107 // Existing grant was revoked and we used NO_FORCE, so we got info back 125 // Existing grant was revoked and we used NO_FORCE, so we got info back
108 // instead. 126 // instead.
109 if (interactive_) { 127 if (interactive_) {
110 install_ui_.reset(new ExtensionInstallPrompt(GetAssociatedWebContents())); 128 install_ui_.reset(new ExtensionInstallPrompt(GetAssociatedWebContents()));
111 ShowOAuthApprovalDialog(issue_advice); 129 ShowOAuthApprovalDialog(issue_advice);
112 } else { 130 } else {
113 error_ = identity_constants::kNoGrant; 131 error_ = identity_constants::kNoGrant;
114 SendResponse(false); 132 SendResponse(false);
115 Release(); // Balanced in RunImpl. 133 Release(); // Balanced in RunImpl.
116 } 134 }
117 } 135 }
118 136
119 void IdentityGetAuthTokenFunction::OnLoginUIClosed( 137 void IdentityGetAuthTokenFunction::SigninSuccess(const std::string& token) {
120 LoginUIService::LoginUI* ui) { 138 refresh_token_ = token;
121 StopObservingLoginService(); 139 StartFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE);
122 if (!StartFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE)) { 140 }
123 SendResponse(false); 141
124 Release(); 142 void IdentityGetAuthTokenFunction::SigninFailed() {
125 } 143 error_ = identity_constants::kUserNotSignedIn;
144 SendResponse(false);
145 Release();
126 } 146 }
127 147
128 void IdentityGetAuthTokenFunction::InstallUIProceed() { 148 void IdentityGetAuthTokenFunction::InstallUIProceed() {
129 DCHECK(install_ui_->record_oauth2_grant()); 149 DCHECK(install_ui_->record_oauth2_grant());
130 // The user has accepted the scopes, so we may now force (recording a grant 150 // The user has accepted the scopes, so we may now force (recording a grant
131 // and receiving a token). 151 // and receiving a token).
132 bool success = StartFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE); 152 StartFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE);
133 DCHECK(success);
134 } 153 }
135 154
136 void IdentityGetAuthTokenFunction::InstallUIAbort(bool user_initiated) { 155 void IdentityGetAuthTokenFunction::InstallUIAbort(bool user_initiated) {
137 error_ = identity_constants::kUserRejected; 156 error_ = identity_constants::kUserRejected;
138 SendResponse(false); 157 SendResponse(false);
139 Release(); // Balanced in RunImpl. 158 Release(); // Balanced in RunImpl.
140 } 159 }
141 160
142 bool IdentityGetAuthTokenFunction::StartFlow(OAuth2MintTokenFlow::Mode mode) { 161 void IdentityGetAuthTokenFunction::StartFlow(OAuth2MintTokenFlow::Mode mode) {
143 if (!HasLoginToken()) { 162 signin_flow_.reset(NULL);
144 error_ = identity_constants::kUserNotSignedIn;
145 return false;
146 }
147
148 flow_.reset(CreateMintTokenFlow(mode)); 163 flow_.reset(CreateMintTokenFlow(mode));
149 flow_->Start(); 164 flow_->Start();
150 return true;
151 }
152
153 bool IdentityGetAuthTokenFunction::StartLogin() {
154 if (!interactive_) {
155 error_ = identity_constants::kUserNotSignedIn;
156 return false;
157 }
158
159 ShowLoginPopup();
160 return true;
161 }
162
163 void IdentityGetAuthTokenFunction::StartObservingLoginService() {
164 LoginUIService* login_ui_service =
165 LoginUIServiceFactory::GetForProfile(profile());
166 login_ui_service->AddObserver(this);
167 }
168
169 void IdentityGetAuthTokenFunction::StopObservingLoginService() {
170 LoginUIService* login_ui_service =
171 LoginUIServiceFactory::GetForProfile(profile());
172 login_ui_service->RemoveObserver(this);
173 } 165 }
174 166
175 void IdentityGetAuthTokenFunction::ShowLoginPopup() { 167 void IdentityGetAuthTokenFunction::ShowLoginPopup() {
176 StartObservingLoginService(); 168 signin_flow_.reset(new IdentitySigninFlow(this, profile()));
177 169 signin_flow_->Start();
178 LoginUIService* login_ui_service =
179 LoginUIServiceFactory::GetForProfile(profile());
180 login_ui_service->ShowLoginPopup();
181 } 170 }
182 171
183 void IdentityGetAuthTokenFunction::ShowOAuthApprovalDialog( 172 void IdentityGetAuthTokenFunction::ShowOAuthApprovalDialog(
184 const IssueAdviceInfo& issue_advice) { 173 const IssueAdviceInfo& issue_advice) {
185 install_ui_->ConfirmIssueAdvice(this, GetExtension(), issue_advice); 174 install_ui_->ConfirmIssueAdvice(this, GetExtension(), issue_advice);
186 } 175 }
187 176
188 OAuth2MintTokenFlow* IdentityGetAuthTokenFunction::CreateMintTokenFlow( 177 OAuth2MintTokenFlow* IdentityGetAuthTokenFunction::CreateMintTokenFlow(
189 OAuth2MintTokenFlow::Mode mode) { 178 OAuth2MintTokenFlow::Mode mode) {
190 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension()); 179 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
191 TokenService* token_service = TokenServiceFactory::GetForProfile(profile());
192 return new OAuth2MintTokenFlow( 180 return new OAuth2MintTokenFlow(
193 profile()->GetRequestContext(), 181 profile()->GetRequestContext(),
194 this, 182 this,
195 OAuth2MintTokenFlow::Parameters( 183 OAuth2MintTokenFlow::Parameters(
196 token_service->GetOAuth2LoginRefreshToken(), 184 refresh_token_,
197 GetExtension()->id(), 185 GetExtension()->id(),
198 oauth2_info.client_id, 186 oauth2_info.client_id,
199 oauth2_info.scopes, 187 oauth2_info.scopes,
200 mode)); 188 mode));
201 } 189 }
202 190
203 bool IdentityGetAuthTokenFunction::HasLoginToken() const { 191 bool IdentityGetAuthTokenFunction::HasLoginToken() const {
204 TokenService* token_service = TokenServiceFactory::GetForProfile(profile()); 192 TokenService* token_service = TokenServiceFactory::GetForProfile(profile());
205 return token_service->HasOAuthLoginToken(); 193 return token_service->HasOAuthLoginToken();
206 } 194 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 SendResponse(true); 237 SendResponse(true);
250 Release(); // Balanced in RunImpl. 238 Release(); // Balanced in RunImpl.
251 } 239 }
252 240
253 void IdentityLaunchWebAuthFlowFunction::OnAuthFlowFailure() { 241 void IdentityLaunchWebAuthFlowFunction::OnAuthFlowFailure() {
254 error_ = identity_constants::kInvalidRedirect; 242 error_ = identity_constants::kInvalidRedirect;
255 SendResponse(false); 243 SendResponse(false);
256 Release(); // Balanced in RunImpl. 244 Release(); // Balanced in RunImpl.
257 } 245 }
258 246
259 IdentityAPI::IdentityAPI(Profile* profile) { 247 IdentityAPI::IdentityAPI(Profile* profile)
248 : profile_(profile),
249 signin_manager_(NULL),
250 error_(GoogleServiceAuthError::NONE) {
260 (new OAuth2ManifestHandler)->Register(); 251 (new OAuth2ManifestHandler)->Register();
261 } 252 }
262 253
263 IdentityAPI::~IdentityAPI() { 254 IdentityAPI::~IdentityAPI() {
264 } 255 }
265 256
257 void IdentityAPI::Initialize() {
258 signin_manager_ = SigninManagerFactory::GetForProfile(profile_);
259 signin_manager_->signin_global_error()->AddProvider(this);
260
261 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
262 registrar_.Add(this,
263 chrome::NOTIFICATION_TOKEN_AVAILABLE,
264 content::Source<TokenService>(token_service));
265 }
266
267 void IdentityAPI::ReportAuthError(const GoogleServiceAuthError& error) {
268 if (!signin_manager_)
269 Initialize();
270
271 error_ = error;
272 signin_manager_->signin_global_error()->AuthStatusChanged();
273 }
274
275 void IdentityAPI::Shutdown() {
276 if (signin_manager_)
277 signin_manager_->signin_global_error()->RemoveProvider(this);
278 }
279
266 static base::LazyInstance<ProfileKeyedAPIFactory<IdentityAPI> > 280 static base::LazyInstance<ProfileKeyedAPIFactory<IdentityAPI> >
267 g_factory = LAZY_INSTANCE_INITIALIZER; 281 g_factory = LAZY_INSTANCE_INITIALIZER;
268 282
269 // static 283 // static
270 ProfileKeyedAPIFactory<IdentityAPI>* IdentityAPI::GetFactoryInstance() { 284 ProfileKeyedAPIFactory<IdentityAPI>* IdentityAPI::GetFactoryInstance() {
271 return &g_factory.Get(); 285 return &g_factory.Get();
272 } 286 }
273 287
288 GoogleServiceAuthError IdentityAPI::GetAuthStatus() const {
289 return error_;
290 }
291
292 void IdentityAPI::Observe(int type,
293 const content::NotificationSource& source,
294 const content::NotificationDetails& details) {
295 if (type == chrome::NOTIFICATION_TOKEN_AVAILABLE) {
296 TokenService::TokenAvailableDetails* token_details =
297 content::Details<TokenService::TokenAvailableDetails>(details).ptr();
Pete Williamson 2013/03/27 18:03:55 It seems odd that we aren't doing much with the to
Michael Courage 2013/03/27 18:40:11 This class has an interest in the token independen
298 if (token_details->service() ==
299 GaiaConstants::kGaiaOAuth2LoginRefreshToken) {
300 error_ = GoogleServiceAuthError::AuthErrorNone();
301 signin_manager_->signin_global_error()->AuthStatusChanged();
302 }
303 } else {
304 NOTREACHED();
305 }
306 }
307
308 template <>
309 void ProfileKeyedAPIFactory<IdentityAPI>::DeclareFactoryDependencies() {
310 DependsOn(ExtensionSystemFactory::GetInstance());
311 DependsOn(TokenServiceFactory::GetInstance());
312 DependsOn(SigninManagerFactory::GetInstance());
313 }
314
274 } // namespace extensions 315 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698