Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/ui/login/login_prompt.h" | 5 #include "chrome/browser/ui/login/login_prompt.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "app/l10n_util.h" | 9 #include "app/l10n_util.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 109 | 109 |
| 110 TabContents* LoginHandler::GetTabContentsForLogin() const { | 110 TabContents* LoginHandler::GetTabContentsForLogin() const { |
| 111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 112 | 112 |
| 113 return tab_util::GetTabContentsByID(render_process_host_id_, | 113 return tab_util::GetTabContentsByID(render_process_host_id_, |
| 114 tab_contents_id_); | 114 tab_contents_id_); |
| 115 } | 115 } |
| 116 | 116 |
| 117 void LoginHandler::SetAuth(const std::wstring& username, | 117 void LoginHandler::SetAuth(const std::wstring& username, |
| 118 const std::wstring& password) { | 118 const std::wstring& password) { |
| 119 if (WasAuthHandled(true)) | 119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 120 | |
| 121 if (TestAndSetAuthHandled()) | |
| 120 return; | 122 return; |
| 121 | 123 |
| 122 // Tell the password manager the credentials were submitted / accepted. | 124 // Tell the password manager the credentials were submitted / accepted. |
| 123 if (password_manager_) { | 125 if (password_manager_) { |
| 124 password_form_.username_value = WideToUTF16Hack(username); | 126 password_form_.username_value = WideToUTF16Hack(username); |
| 125 password_form_.password_value = WideToUTF16Hack(password); | 127 password_form_.password_value = WideToUTF16Hack(password); |
| 126 password_manager_->ProvisionallySavePassword(password_form_); | 128 password_manager_->ProvisionallySavePassword(password_form_); |
| 127 } | 129 } |
| 128 | 130 |
| 131 // Calling NotifyAuthSupplied() directly instead of posting a task | |
| 132 // allows other LoginHandler instances to queue their | |
| 133 // CloseContentsDeferred() before ours. Closing dialogs in the | |
| 134 // opposite order as they were created avoids races where remaining | |
| 135 // dialogs in the same tab may be briefly displayed to the user | |
| 136 // before they are removed. | |
| 137 NotifyAuthSupplied(username, password); | |
| 138 | |
| 129 BrowserThread::PostTask( | 139 BrowserThread::PostTask( |
| 130 BrowserThread::UI, FROM_HERE, | 140 BrowserThread::UI, FROM_HERE, |
| 131 NewRunnableMethod(this, &LoginHandler::CloseContentsDeferred)); | 141 NewRunnableMethod(this, &LoginHandler::CloseContentsDeferred)); |
| 132 BrowserThread::PostTask( | 142 BrowserThread::PostTask( |
| 133 BrowserThread::UI, FROM_HERE, | |
| 134 NewRunnableMethod( | |
| 135 this, &LoginHandler::NotifyAuthSupplied, username, password)); | |
| 136 BrowserThread::PostTask( | |
| 137 BrowserThread::IO, FROM_HERE, | 143 BrowserThread::IO, FROM_HERE, |
| 138 NewRunnableMethod( | 144 NewRunnableMethod( |
| 139 this, &LoginHandler::SetAuthDeferred, username, password)); | 145 this, &LoginHandler::SetAuthDeferred, username, password)); |
| 140 } | 146 } |
| 141 | 147 |
| 142 void LoginHandler::CancelAuth() { | 148 void LoginHandler::CancelAuth() { |
| 143 if (WasAuthHandled(true)) | 149 if (TestAndSetAuthHandled()) |
| 144 return; | 150 return; |
| 145 | 151 |
| 152 // Similar to how we deal with notifications above in SetAuth() | |
| 153 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) | |
| 154 NotifyAuthCancelled(); | |
| 155 else | |
|
cbentzel
2011/01/05 13:13:52
Nit: use braces {} for multi-line else clauses [an
asanka (google)
2011/01/05 14:29:11
Done.
| |
| 156 BrowserThread::PostTask( | |
| 157 BrowserThread::UI, FROM_HERE, | |
| 158 NewRunnableMethod(this, &LoginHandler::NotifyAuthCancelled)); | |
| 159 | |
| 146 BrowserThread::PostTask( | 160 BrowserThread::PostTask( |
| 147 BrowserThread::UI, FROM_HERE, | 161 BrowserThread::UI, FROM_HERE, |
| 148 NewRunnableMethod(this, &LoginHandler::CloseContentsDeferred)); | 162 NewRunnableMethod(this, &LoginHandler::CloseContentsDeferred)); |
| 149 BrowserThread::PostTask( | 163 BrowserThread::PostTask( |
| 150 BrowserThread::UI, FROM_HERE, | |
| 151 NewRunnableMethod(this, &LoginHandler::NotifyAuthCancelled)); | |
| 152 BrowserThread::PostTask( | |
| 153 BrowserThread::IO, FROM_HERE, | 164 BrowserThread::IO, FROM_HERE, |
| 154 NewRunnableMethod(this, &LoginHandler::CancelAuthDeferred)); | 165 NewRunnableMethod(this, &LoginHandler::CancelAuthDeferred)); |
| 155 } | 166 } |
| 156 | 167 |
| 157 void LoginHandler::OnRequestCancelled() { | 168 void LoginHandler::OnRequestCancelled() { |
| 158 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)) << | 169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)) << |
| 159 "Why is OnRequestCancelled called from the UI thread?"; | 170 "Why is OnRequestCancelled called from the UI thread?"; |
| 160 | 171 |
| 161 // Reference is no longer valid. | 172 // Reference is no longer valid. |
| 162 request_ = NULL; | 173 request_ = NULL; |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 189 const NotificationSource& source, | 200 const NotificationSource& source, |
| 190 const NotificationDetails& details) { | 201 const NotificationDetails& details) { |
| 191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 192 DCHECK(type == NotificationType::AUTH_SUPPLIED || | 203 DCHECK(type == NotificationType::AUTH_SUPPLIED || |
| 193 type == NotificationType::AUTH_CANCELLED); | 204 type == NotificationType::AUTH_CANCELLED); |
| 194 | 205 |
| 195 TabContents* requesting_contents = GetTabContentsForLogin(); | 206 TabContents* requesting_contents = GetTabContentsForLogin(); |
| 196 if (!requesting_contents) | 207 if (!requesting_contents) |
| 197 return; | 208 return; |
| 198 | 209 |
| 199 NavigationController* this_controller = &requesting_contents->controller(); | 210 // Break out early if we aren't interested in the notification. |
| 200 NavigationController* that_controller = | 211 if (WasAuthHandled()) |
| 201 Source<NavigationController>(source).ptr(); | |
| 202 | |
| 203 // Only handle notifications from other handlers. | |
| 204 if (this_controller == that_controller) | |
| 205 return; | 212 return; |
| 206 | 213 |
| 207 LoginNotificationDetails* login_details = | 214 LoginNotificationDetails* login_details = |
| 208 Details<LoginNotificationDetails>(details).ptr(); | 215 Details<LoginNotificationDetails>(details).ptr(); |
| 209 | 216 |
| 217 // WasAuthHandled() should always test positive before we publish | |
| 218 // AUTH_SUPPLIED or AUTH_CANCELLED notifications. | |
| 219 DCHECK(login_details->handler() != this); | |
| 220 | |
| 210 // Only handle notification for the identical auth info. | 221 // Only handle notification for the identical auth info. |
| 211 if (*login_details->handler()->auth_info() != *auth_info()) | 222 if (*login_details->handler()->auth_info() != *auth_info()) |
| 212 return; | 223 return; |
| 213 | 224 |
| 214 // Set or cancel the auth in this handler. | 225 // Set or cancel the auth in this handler. |
| 215 if (type == NotificationType::AUTH_SUPPLIED) { | 226 if (type == NotificationType::AUTH_SUPPLIED) { |
| 216 AuthSuppliedLoginNotificationDetails* supplied_details = | 227 AuthSuppliedLoginNotificationDetails* supplied_details = |
| 217 Details<AuthSuppliedLoginNotificationDetails>(details).ptr(); | 228 Details<AuthSuppliedLoginNotificationDetails>(details).ptr(); |
| 218 SetAuth(supplied_details->username(), supplied_details->password()); | 229 SetAuth(supplied_details->username(), supplied_details->password()); |
| 219 } else { | 230 } else { |
| 220 DCHECK(type == NotificationType::AUTH_CANCELLED); | 231 DCHECK(type == NotificationType::AUTH_CANCELLED); |
| 221 CancelAuth(); | 232 CancelAuth(); |
| 222 } | 233 } |
| 223 } | 234 } |
| 224 | 235 |
| 225 void LoginHandler::SetModel(LoginModel* model) { | 236 void LoginHandler::SetModel(LoginModel* model) { |
| 226 if (login_model_) | 237 if (login_model_) |
| 227 login_model_->SetObserver(NULL); | 238 login_model_->SetObserver(NULL); |
| 228 login_model_ = model; | 239 login_model_ = model; |
| 229 if (login_model_) | 240 if (login_model_) |
| 230 login_model_->SetObserver(this); | 241 login_model_->SetObserver(this); |
| 231 } | 242 } |
| 232 | 243 |
| 233 void LoginHandler::SetDialog(ConstrainedWindow* dialog) { | 244 void LoginHandler::SetDialog(ConstrainedWindow* dialog) { |
| 234 dialog_ = dialog; | 245 dialog_ = dialog; |
| 235 } | 246 } |
| 236 | 247 |
| 237 void LoginHandler::NotifyAuthNeeded() { | 248 void LoginHandler::NotifyAuthNeeded() { |
| 238 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 249 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 239 if (WasAuthHandled(false)) | 250 if (WasAuthHandled()) |
| 240 return; | 251 return; |
| 241 | 252 |
| 242 TabContents* requesting_contents = GetTabContentsForLogin(); | 253 TabContents* requesting_contents = GetTabContentsForLogin(); |
| 243 if (!requesting_contents) | 254 if (!requesting_contents) |
| 244 return; | 255 return; |
| 245 | 256 |
| 246 NotificationService* service = NotificationService::current(); | 257 NotificationService* service = NotificationService::current(); |
| 247 NavigationController* controller = &requesting_contents->controller(); | 258 NavigationController* controller = &requesting_contents->controller(); |
| 248 LoginNotificationDetails details(this); | 259 LoginNotificationDetails details(this); |
| 249 | 260 |
| 250 service->Notify(NotificationType::AUTH_NEEDED, | 261 service->Notify(NotificationType::AUTH_NEEDED, |
| 251 Source<NavigationController>(controller), | 262 Source<NavigationController>(controller), |
| 252 Details<LoginNotificationDetails>(&details)); | 263 Details<LoginNotificationDetails>(&details)); |
| 253 } | 264 } |
| 254 | 265 |
| 255 void LoginHandler::NotifyAuthCancelled() { | 266 void LoginHandler::NotifyAuthCancelled() { |
| 256 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 257 DCHECK(WasAuthHandled(false)); | 268 DCHECK(WasAuthHandled()); |
| 258 | 269 |
| 259 TabContents* requesting_contents = GetTabContentsForLogin(); | 270 TabContents* requesting_contents = GetTabContentsForLogin(); |
| 260 if (!requesting_contents) | 271 if (!requesting_contents) |
| 261 return; | 272 return; |
| 262 | 273 |
| 263 NotificationService* service = NotificationService::current(); | 274 NotificationService* service = NotificationService::current(); |
| 264 NavigationController* controller = &requesting_contents->controller(); | 275 NavigationController* controller = &requesting_contents->controller(); |
| 265 LoginNotificationDetails details(this); | 276 LoginNotificationDetails details(this); |
| 266 | 277 |
| 267 service->Notify(NotificationType::AUTH_CANCELLED, | 278 service->Notify(NotificationType::AUTH_CANCELLED, |
| 268 Source<NavigationController>(controller), | 279 Source<NavigationController>(controller), |
| 269 Details<LoginNotificationDetails>(&details)); | 280 Details<LoginNotificationDetails>(&details)); |
| 270 } | 281 } |
| 271 | 282 |
| 272 void LoginHandler::NotifyAuthSupplied(const std::wstring& username, | 283 void LoginHandler::NotifyAuthSupplied(const std::wstring& username, |
| 273 const std::wstring& password) { | 284 const std::wstring& password) { |
| 274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 285 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 275 DCHECK(WasAuthHandled(false)); | 286 DCHECK(WasAuthHandled()); |
| 276 | 287 |
| 277 TabContents* requesting_contents = GetTabContentsForLogin(); | 288 TabContents* requesting_contents = GetTabContentsForLogin(); |
| 278 if (!requesting_contents) | 289 if (!requesting_contents) |
| 279 return; | 290 return; |
| 280 | 291 |
| 281 NotificationService* service = NotificationService::current(); | 292 NotificationService* service = NotificationService::current(); |
| 282 NavigationController* controller = &requesting_contents->controller(); | 293 NavigationController* controller = &requesting_contents->controller(); |
| 283 AuthSuppliedLoginNotificationDetails details(this, username, password); | 294 AuthSuppliedLoginNotificationDetails details(this, username, password); |
| 284 | 295 |
| 285 service->Notify(NotificationType::AUTH_SUPPLIED, | 296 service->Notify(NotificationType::AUTH_SUPPLIED, |
| 286 Source<NavigationController>(controller), | 297 Source<NavigationController>(controller), |
| 287 Details<AuthSuppliedLoginNotificationDetails>(&details)); | 298 Details<AuthSuppliedLoginNotificationDetails>(&details)); |
| 288 } | 299 } |
| 289 | 300 |
| 290 void LoginHandler::ReleaseSoon() { | 301 void LoginHandler::ReleaseSoon() { |
| 291 if (!WasAuthHandled(true)) { | 302 if (!TestAndSetAuthHandled()) { |
| 292 BrowserThread::PostTask( | 303 BrowserThread::PostTask( |
| 293 BrowserThread::IO, FROM_HERE, | 304 BrowserThread::IO, FROM_HERE, |
| 294 NewRunnableMethod(this, &LoginHandler::CancelAuthDeferred)); | 305 NewRunnableMethod(this, &LoginHandler::CancelAuthDeferred)); |
| 295 BrowserThread::PostTask( | 306 BrowserThread::PostTask( |
| 296 BrowserThread::UI, FROM_HERE, | 307 BrowserThread::UI, FROM_HERE, |
| 297 NewRunnableMethod(this, &LoginHandler::NotifyAuthCancelled)); | 308 NewRunnableMethod(this, &LoginHandler::NotifyAuthCancelled)); |
| 298 } | 309 } |
| 299 | 310 |
| 300 BrowserThread::PostTask( | 311 BrowserThread::PostTask( |
| 301 BrowserThread::UI, FROM_HERE, | 312 BrowserThread::UI, FROM_HERE, |
| 302 NewRunnableMethod(this, &LoginHandler::RemoveObservers)); | 313 NewRunnableMethod(this, &LoginHandler::RemoveObservers)); |
| 303 | 314 |
| 304 // Delete this object once all InvokeLaters have been called. | 315 // Delete this object once all InvokeLaters have been called. |
| 305 BrowserThread::ReleaseSoon(BrowserThread::IO, FROM_HERE, this); | 316 BrowserThread::ReleaseSoon(BrowserThread::IO, FROM_HERE, this); |
| 306 } | 317 } |
| 307 | 318 |
| 308 // Returns whether authentication had been handled (SetAuth or CancelAuth). | 319 // Returns whether authentication had been handled (SetAuth or CancelAuth). |
| 309 // If |set_handled| is true, it will mark authentication as handled. | 320 bool LoginHandler::WasAuthHandled() { |
| 310 bool LoginHandler::WasAuthHandled(bool set_handled) { | |
| 311 AutoLock lock(handled_auth_lock_); | 321 AutoLock lock(handled_auth_lock_); |
| 312 bool was_handled = handled_auth_; | 322 bool was_handled = handled_auth_; |
| 313 if (set_handled) | |
| 314 handled_auth_ = true; | |
| 315 return was_handled; | 323 return was_handled; |
| 316 } | 324 } |
| 317 | 325 |
| 326 // Marks authentication as handled and returns the previous handled state. | |
| 327 bool LoginHandler::TestAndSetAuthHandled() { | |
| 328 AutoLock lock(handled_auth_lock_); | |
| 329 bool was_handled = handled_auth_; | |
| 330 handled_auth_ = true; | |
| 331 return was_handled; | |
| 332 } | |
| 333 | |
| 318 // Calls SetAuth from the IO loop. | 334 // Calls SetAuth from the IO loop. |
| 319 void LoginHandler::SetAuthDeferred(const std::wstring& username, | 335 void LoginHandler::SetAuthDeferred(const std::wstring& username, |
| 320 const std::wstring& password) { | 336 const std::wstring& password) { |
| 321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 337 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 322 | 338 |
| 323 if (request_) { | 339 if (request_) { |
| 324 request_->SetAuth(WideToUTF16Hack(username), WideToUTF16Hack(password)); | 340 request_->SetAuth(WideToUTF16Hack(username), WideToUTF16Hack(password)); |
| 325 ResetLoginHandlerForRequest(request_); | 341 ResetLoginHandlerForRequest(request_); |
| 326 } | 342 } |
| 327 } | 343 } |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 358 LoginDialogTask(const GURL& request_url, | 374 LoginDialogTask(const GURL& request_url, |
| 359 net::AuthChallengeInfo* auth_info, | 375 net::AuthChallengeInfo* auth_info, |
| 360 LoginHandler* handler) | 376 LoginHandler* handler) |
| 361 : request_url_(request_url), auth_info_(auth_info), handler_(handler) { | 377 : request_url_(request_url), auth_info_(auth_info), handler_(handler) { |
| 362 } | 378 } |
| 363 virtual ~LoginDialogTask() { | 379 virtual ~LoginDialogTask() { |
| 364 } | 380 } |
| 365 | 381 |
| 366 void Run() { | 382 void Run() { |
| 367 TabContents* parent_contents = handler_->GetTabContentsForLogin(); | 383 TabContents* parent_contents = handler_->GetTabContentsForLogin(); |
| 368 if (!parent_contents) { | 384 if (!parent_contents || handler_->WasAuthHandled()) { |
| 369 // The request may have been cancelled, or it may be for a renderer | 385 // The request may have been cancelled, or it may be for a renderer |
| 370 // not hosted by a tab (e.g. an extension). Cancel just in case | 386 // not hosted by a tab (e.g. an extension). Cancel just in case |
| 371 // (cancelling twice is a no-op). | 387 // (cancelling twice is a no-op). |
| 372 handler_->CancelAuth(); | 388 handler_->CancelAuth(); |
| 373 return; | 389 return; |
| 374 } | 390 } |
| 375 | 391 |
| 376 // Tell the password manager to look for saved passwords. | 392 // Tell the password manager to look for saved passwords. |
| 377 TabContentsWrapper** wrapper = | 393 TabContentsWrapper** wrapper = |
| 378 TabContentsWrapper::property_accessor()->GetProperty( | 394 TabContentsWrapper::property_accessor()->GetProperty( |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 446 // Public API | 462 // Public API |
| 447 | 463 |
| 448 LoginHandler* CreateLoginPrompt(net::AuthChallengeInfo* auth_info, | 464 LoginHandler* CreateLoginPrompt(net::AuthChallengeInfo* auth_info, |
| 449 net::URLRequest* request) { | 465 net::URLRequest* request) { |
| 450 LoginHandler* handler = LoginHandler::Create(auth_info, request); | 466 LoginHandler* handler = LoginHandler::Create(auth_info, request); |
| 451 BrowserThread::PostTask( | 467 BrowserThread::PostTask( |
| 452 BrowserThread::UI, FROM_HERE, new LoginDialogTask( | 468 BrowserThread::UI, FROM_HERE, new LoginDialogTask( |
| 453 request->url(), auth_info, handler)); | 469 request->url(), auth_info, handler)); |
| 454 return handler; | 470 return handler; |
| 455 } | 471 } |
| OLD | NEW |