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