OLD | NEW |
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/values.h" | 7 #include "base/values.h" |
8 #include "chrome/common/extensions/api/experimental_identity.h" | 8 #include "chrome/common/extensions/api/experimental_identity.h" |
9 #include "chrome/browser/extensions/extension_install_prompt.h" | 9 #include "chrome/browser/extensions/extension_install_prompt.h" |
10 #include "chrome/browser/extensions/extension_function_dispatcher.h" | 10 #include "chrome/browser/extensions/extension_function_dispatcher.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/signin/token_service.h" | 13 #include "chrome/browser/signin/token_service.h" |
14 #include "chrome/browser/signin/token_service_factory.h" | 14 #include "chrome/browser/signin/token_service_factory.h" |
15 #include "chrome/browser/ui/browser.h" | 15 #include "chrome/browser/ui/browser.h" |
16 #include "chrome/browser/ui/tab_contents/tab_contents.h" | 16 #include "chrome/browser/ui/browser_navigator.h" |
| 17 #include "chrome/browser/ui/webui/signin/login_ui_service.h" |
| 18 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" |
17 #include "chrome/common/extensions/extension.h" | 19 #include "chrome/common/extensions/extension.h" |
| 20 #include "chrome/common/url_constants.h" |
| 21 #include "content/public/common/page_transition_types.h" |
18 #include "googleurl/src/gurl.h" | 22 #include "googleurl/src/gurl.h" |
| 23 #include "webkit/glue/window_open_disposition.h" |
19 | 24 |
20 namespace extensions { | 25 namespace extensions { |
21 | 26 |
22 namespace { | 27 const char IdentityGetAuthTokenFunction::kInvalidClientId[] = |
23 | 28 "Invalid OAuth2 Client ID."; |
24 const char kInvalidClientId[] = "Invalid OAuth2 Client ID."; | 29 const char IdentityGetAuthTokenFunction::kInvalidScopes[] = |
25 const char kInvalidScopes[] = "Invalid OAuth2 scopes."; | 30 "Invalid OAuth2 scopes."; |
26 const char kInvalidRedirect[] = "Did not redirect to the right URL."; | 31 const char IdentityGetAuthTokenFunction::kAuthFailure[] = |
27 const char kAuthFailure[] = "OAuth2 request failed: "; | 32 "OAuth2 request failed: "; |
28 const char kNoGrant[] = "OAuth2 not granted or revoked."; | 33 const char IdentityGetAuthTokenFunction::kNoGrant[] = |
29 const char kUserRejected[] = "The user did not approve access."; | 34 "OAuth2 not granted or revoked."; |
30 | 35 const char IdentityGetAuthTokenFunction::kUserRejected[] = |
31 } // namespace | 36 "The user did not approve access."; |
| 37 const char IdentityGetAuthTokenFunction::kUserNotSignedIn[] = |
| 38 "The user is not signed in."; |
32 | 39 |
33 namespace GetAuthToken = extensions::api::experimental_identity::GetAuthToken; | 40 namespace GetAuthToken = extensions::api::experimental_identity::GetAuthToken; |
34 namespace LaunchWebAuthFlow = | 41 namespace LaunchWebAuthFlow = |
35 extensions::api::experimental_identity::LaunchWebAuthFlow; | 42 extensions::api::experimental_identity::LaunchWebAuthFlow; |
36 | 43 |
37 IdentityGetAuthTokenFunction::IdentityGetAuthTokenFunction() | 44 IdentityGetAuthTokenFunction::IdentityGetAuthTokenFunction() |
38 : interactive_(false) {} | 45 : interactive_(false) {} |
39 IdentityGetAuthTokenFunction::~IdentityGetAuthTokenFunction() {} | 46 IdentityGetAuthTokenFunction::~IdentityGetAuthTokenFunction() {} |
40 | 47 |
41 bool IdentityGetAuthTokenFunction::RunImpl() { | 48 bool IdentityGetAuthTokenFunction::RunImpl() { |
42 scoped_ptr<GetAuthToken::Params> params(GetAuthToken::Params::Create(*args_)); | 49 scoped_ptr<GetAuthToken::Params> params(GetAuthToken::Params::Create(*args_)); |
43 EXTENSION_FUNCTION_VALIDATE(params.get()); | 50 EXTENSION_FUNCTION_VALIDATE(params.get()); |
44 if (params->details.get() && params->details->interactive.get()) | 51 if (params->details.get() && params->details->interactive.get()) |
45 interactive_ = *params->details->interactive; | 52 interactive_ = *params->details->interactive; |
46 | 53 |
| 54 const Extension::OAuth2Info& oauth2_info = GetExtension()->oauth2_info(); |
| 55 |
| 56 // Check that the necessary information is present in the manfist. |
| 57 if (oauth2_info.client_id.empty()) { |
| 58 error_ = kInvalidClientId; |
| 59 return false; |
| 60 } |
| 61 |
| 62 if (oauth2_info.scopes.size() == 0) { |
| 63 error_ = kInvalidScopes; |
| 64 return false; |
| 65 } |
| 66 |
47 // Balanced in OnIssueAdviceSuccess|OnMintTokenSuccess|OnMintTokenFailure| | 67 // Balanced in OnIssueAdviceSuccess|OnMintTokenSuccess|OnMintTokenFailure| |
48 // InstallUIAbort. | 68 // InstallUIAbort|OnLoginUIClosed. |
49 AddRef(); | 69 AddRef(); |
50 | 70 |
51 if (StartFlow(ExtensionInstallPrompt::ShouldAutomaticallyApproveScopes() ? | 71 if (!HasLoginToken()) { |
52 OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE : | 72 if (StartLogin()) { |
53 OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE)) { | 73 return true; |
| 74 } else { |
| 75 Release(); |
| 76 return false; |
| 77 } |
| 78 } |
| 79 |
| 80 if (StartFlow(GetTokenFlowMode())) { |
54 return true; | 81 return true; |
55 } else { | 82 } else { |
56 Release(); | 83 Release(); |
57 return false; | 84 return false; |
58 } | 85 } |
59 } | 86 } |
60 | 87 |
61 void IdentityGetAuthTokenFunction::OnMintTokenSuccess( | 88 void IdentityGetAuthTokenFunction::OnMintTokenSuccess( |
62 const std::string& access_token) { | 89 const std::string& access_token) { |
63 SetResult(Value::CreateStringValue(access_token)); | 90 SetResult(Value::CreateStringValue(access_token)); |
64 SendResponse(true); | 91 SendResponse(true); |
65 Release(); // Balanced in RunImpl. | 92 Release(); // Balanced in RunImpl. |
66 } | 93 } |
67 | 94 |
68 void IdentityGetAuthTokenFunction::OnMintTokenFailure( | 95 void IdentityGetAuthTokenFunction::OnMintTokenFailure( |
69 const GoogleServiceAuthError& error) { | 96 const GoogleServiceAuthError& error) { |
70 error_ = std::string(kAuthFailure) + error.ToString(); | 97 error_ = std::string(kAuthFailure) + error.ToString(); |
71 SendResponse(false); | 98 SendResponse(false); |
72 Release(); // Balanced in RunImpl. | 99 Release(); // Balanced in RunImpl. |
73 } | 100 } |
74 | 101 |
75 void IdentityGetAuthTokenFunction::OnIssueAdviceSuccess( | 102 void IdentityGetAuthTokenFunction::OnIssueAdviceSuccess( |
76 const IssueAdviceInfo& issue_advice) { | 103 const IssueAdviceInfo& issue_advice) { |
77 // Existing grant was revoked and we used NO_FORCE, so we got info back | 104 // Existing grant was revoked and we used NO_FORCE, so we got info back |
78 // instead. | 105 // instead. |
79 if (interactive_) { | 106 if (interactive_) { |
80 install_ui_.reset( | 107 install_ui_.reset( |
81 chrome::CreateExtensionInstallPromptWithBrowser(GetCurrentBrowser())); | 108 chrome::CreateExtensionInstallPromptWithBrowser(GetCurrentBrowser())); |
82 install_ui_->ConfirmIssueAdvice(this, GetExtension(), issue_advice); | 109 ShowOAuthApprovalDialog(issue_advice); |
83 } else { | 110 } else { |
84 error_ = kNoGrant; | 111 error_ = kNoGrant; |
85 SendResponse(false); | 112 SendResponse(false); |
86 Release(); // Balanced in RunImpl. | 113 Release(); // Balanced in RunImpl. |
87 } | 114 } |
88 } | 115 } |
89 | 116 |
| 117 void IdentityGetAuthTokenFunction::OnLoginUIClosed( |
| 118 LoginUIService::LoginUI* ui) { |
| 119 StopObservingLoginService(); |
| 120 if (!StartFlow(GetTokenFlowMode())) { |
| 121 SendResponse(false); |
| 122 Release(); |
| 123 } |
| 124 } |
| 125 |
90 void IdentityGetAuthTokenFunction::InstallUIProceed() { | 126 void IdentityGetAuthTokenFunction::InstallUIProceed() { |
91 DCHECK(install_ui_->record_oauth2_grant()); | 127 DCHECK(install_ui_->record_oauth2_grant()); |
92 // The user has accepted the scopes, so we may now force (recording a grant | 128 // The user has accepted the scopes, so we may now force (recording a grant |
93 // and receiving a token). | 129 // and receiving a token). |
94 bool success = StartFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE); | 130 bool success = StartFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE); |
95 DCHECK(success); | 131 DCHECK(success); |
96 } | 132 } |
97 | 133 |
98 void IdentityGetAuthTokenFunction::InstallUIAbort(bool user_initiated) { | 134 void IdentityGetAuthTokenFunction::InstallUIAbort(bool user_initiated) { |
99 error_ = kUserRejected; | 135 error_ = kUserRejected; |
100 SendResponse(false); | 136 SendResponse(false); |
101 Release(); // Balanced in RunImpl. | 137 Release(); // Balanced in RunImpl. |
102 } | 138 } |
103 | 139 |
104 bool IdentityGetAuthTokenFunction::StartFlow(OAuth2MintTokenFlow::Mode mode) { | 140 bool IdentityGetAuthTokenFunction::StartFlow(OAuth2MintTokenFlow::Mode mode) { |
105 const Extension* extension = GetExtension(); | 141 if (!HasLoginToken()) { |
106 Extension::OAuth2Info oauth2_info = extension->oauth2_info(); | 142 error_ = kUserNotSignedIn; |
107 | |
108 if (oauth2_info.client_id.empty()) { | |
109 error_ = kInvalidClientId; | |
110 return false; | 143 return false; |
111 } | 144 } |
112 | 145 |
113 if (oauth2_info.scopes.size() == 0) { | 146 flow_.reset(CreateMintTokenFlow(mode)); |
114 error_ = kInvalidScopes; | 147 flow_->Start(); |
| 148 return true; |
| 149 } |
| 150 |
| 151 bool IdentityGetAuthTokenFunction::StartLogin() { |
| 152 if (!interactive_) { |
| 153 error_ = kUserNotSignedIn; |
115 return false; | 154 return false; |
116 } | 155 } |
117 | 156 |
| 157 ShowLoginPopup(); |
| 158 return true; |
| 159 } |
| 160 |
| 161 void IdentityGetAuthTokenFunction::StartObservingLoginService() { |
| 162 LoginUIService* login_ui_service = |
| 163 LoginUIServiceFactory::GetForProfile(profile()); |
| 164 login_ui_service->AddObserver(this); |
| 165 } |
| 166 |
| 167 void IdentityGetAuthTokenFunction::StopObservingLoginService() { |
| 168 LoginUIService* login_ui_service = |
| 169 LoginUIServiceFactory::GetForProfile(profile()); |
| 170 login_ui_service->RemoveObserver(this); |
| 171 } |
| 172 |
| 173 void IdentityGetAuthTokenFunction::ShowLoginPopup() { |
| 174 StartObservingLoginService(); |
| 175 |
| 176 LoginUIService* login_ui_service = |
| 177 LoginUIServiceFactory::GetForProfile(profile()); |
| 178 LoginUIService::LoginUI* login_ui = login_ui_service->current_login_ui(); |
| 179 if (login_ui) { |
| 180 login_ui->FocusUI(); |
| 181 } else { |
| 182 Browser* browser = Browser::CreateWithParams(Browser::CreateParams( |
| 183 Browser::TYPE_POPUP, profile())); |
| 184 chrome::NavigateParams params(browser, |
| 185 GURL(chrome::kChromeUISyncPromoURL), |
| 186 content::PAGE_TRANSITION_START_PAGE); |
| 187 params.disposition = CURRENT_TAB; |
| 188 chrome::Navigate(¶ms); |
| 189 } |
| 190 } |
| 191 |
| 192 void IdentityGetAuthTokenFunction::ShowOAuthApprovalDialog( |
| 193 const IssueAdviceInfo& issue_advice) { |
| 194 install_ui_->ConfirmIssueAdvice(this, GetExtension(), issue_advice); |
| 195 } |
| 196 |
| 197 OAuth2MintTokenFlow* IdentityGetAuthTokenFunction::CreateMintTokenFlow( |
| 198 OAuth2MintTokenFlow::Mode mode) { |
| 199 const Extension::OAuth2Info& oauth2_info = GetExtension()->oauth2_info(); |
118 TokenService* token_service = TokenServiceFactory::GetForProfile(profile()); | 200 TokenService* token_service = TokenServiceFactory::GetForProfile(profile()); |
119 flow_.reset(new OAuth2MintTokenFlow( | 201 return new OAuth2MintTokenFlow( |
120 profile()->GetRequestContext(), | 202 profile()->GetRequestContext(), |
121 this, | 203 this, |
122 OAuth2MintTokenFlow::Parameters( | 204 OAuth2MintTokenFlow::Parameters( |
123 token_service->GetOAuth2LoginRefreshToken(), | 205 token_service->GetOAuth2LoginRefreshToken(), |
124 extension->id(), | 206 GetExtension()->id(), |
125 oauth2_info.client_id, | 207 oauth2_info.client_id, |
126 oauth2_info.scopes, | 208 oauth2_info.scopes, |
127 mode))); | 209 mode)); |
128 flow_->Start(); | |
129 return true; | |
130 } | 210 } |
131 | 211 |
| 212 bool IdentityGetAuthTokenFunction::HasLoginToken() const { |
| 213 TokenService* token_service = TokenServiceFactory::GetForProfile(profile()); |
| 214 return token_service->HasOAuthLoginToken(); |
| 215 } |
| 216 |
| 217 OAuth2MintTokenFlow::Mode IdentityGetAuthTokenFunction::GetTokenFlowMode() |
| 218 const { |
| 219 return ExtensionInstallPrompt::ShouldAutomaticallyApproveScopes() ? |
| 220 OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE : |
| 221 OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE; |
| 222 } |
| 223 |
| 224 const char IdentityLaunchWebAuthFlowFunction::kInvalidRedirect[] = |
| 225 "Did not redirect to the right URL."; |
| 226 |
132 IdentityLaunchWebAuthFlowFunction::IdentityLaunchWebAuthFlowFunction() {} | 227 IdentityLaunchWebAuthFlowFunction::IdentityLaunchWebAuthFlowFunction() {} |
133 IdentityLaunchWebAuthFlowFunction::~IdentityLaunchWebAuthFlowFunction() {} | 228 IdentityLaunchWebAuthFlowFunction::~IdentityLaunchWebAuthFlowFunction() {} |
134 | 229 |
135 bool IdentityLaunchWebAuthFlowFunction::RunImpl() { | 230 bool IdentityLaunchWebAuthFlowFunction::RunImpl() { |
136 scoped_ptr<LaunchWebAuthFlow::Params> params( | 231 scoped_ptr<LaunchWebAuthFlow::Params> params( |
137 LaunchWebAuthFlow::Params::Create(*args_)); | 232 LaunchWebAuthFlow::Params::Create(*args_)); |
138 EXTENSION_FUNCTION_VALIDATE(params.get()); | 233 EXTENSION_FUNCTION_VALIDATE(params.get()); |
139 | 234 |
140 GURL auth_url(params->details.url); | 235 GURL auth_url(params->details.url); |
141 WebAuthFlow::Mode mode = | 236 WebAuthFlow::Mode mode = |
(...skipping 14 matching lines...) Expand all Loading... |
156 Release(); // Balanced in RunImpl. | 251 Release(); // Balanced in RunImpl. |
157 } | 252 } |
158 | 253 |
159 void IdentityLaunchWebAuthFlowFunction::OnAuthFlowFailure() { | 254 void IdentityLaunchWebAuthFlowFunction::OnAuthFlowFailure() { |
160 error_ = kInvalidRedirect; | 255 error_ = kInvalidRedirect; |
161 SendResponse(false); | 256 SendResponse(false); |
162 Release(); // Balanced in RunImpl. | 257 Release(); // Balanced in RunImpl. |
163 } | 258 } |
164 | 259 |
165 } // namespace extensions | 260 } // namespace extensions |
OLD | NEW |