Index: chrome/browser/login_prompt.cc |
=================================================================== |
--- chrome/browser/login_prompt.cc (revision 42281) |
+++ chrome/browser/login_prompt.cc (working copy) |
@@ -17,7 +17,9 @@ |
#include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h" |
#include "chrome/browser/tab_contents/constrained_window.h" |
#include "chrome/browser/tab_contents/tab_contents.h" |
+#include "chrome/browser/tab_contents/tab_util.h" |
#include "chrome/common/chrome_switches.h" |
+#include "chrome/common/notification_service.h" |
#include "grit/generated_resources.h" |
#include "net/base/auth.h" |
#include "net/base/net_util.h" |
@@ -63,6 +65,188 @@ |
} |
// ---------------------------------------------------------------------------- |
+// LoginHandler |
+ |
+LoginHandler::LoginHandler(URLRequest* request) |
+ : handled_auth_(false), |
+ dialog_(NULL), |
+ request_(request), |
+ password_manager_(NULL), |
+ login_model_(NULL) { |
+ // This constructor is called on the I/O thread, so we cannot load the nib |
+ // here. BuildViewForPasswordManager() will be invoked on the UI thread |
+ // later, so wait with loading the nib until then. |
+ DCHECK(request_) << "LoginHandlerMac constructed with NULL request"; |
+ |
+ AddRef(); // matched by ReleaseSoon::ReleaseSoon(). |
+ if (!ResourceDispatcherHost::RenderViewForRequest( |
+ request_, &render_process_host_id_, &tab_contents_id_)) { |
+ NOTREACHED(); |
+ } |
+} |
+ |
+LoginHandler::~LoginHandler() { |
+ SetModel(NULL); |
+} |
+ |
+void LoginHandler::SetPasswordForm(const webkit_glue::PasswordForm& form) { |
+ password_form_ = form; |
+} |
+ |
+void LoginHandler::SetPasswordManager(PasswordManager* password_manager) { |
+ password_manager_ = password_manager; |
+} |
+ |
+TabContents* LoginHandler::GetTabContentsForLogin() const { |
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
+ |
+ return tab_util::GetTabContentsByID(render_process_host_id_, |
+ tab_contents_id_); |
+} |
+ |
+void LoginHandler::SetAuth(const std::wstring& username, |
+ const std::wstring& password) { |
+ if (WasAuthHandled(true)) |
+ return; |
+ |
+ // Tell the password manager the credentials were submitted / accepted. |
+ if (password_manager_) { |
+ password_form_.username_value = WideToUTF16Hack(username); |
+ password_form_.password_value = WideToUTF16Hack(password); |
+ password_manager_->ProvisionallySavePassword(password_form_); |
+ } |
+ |
+ ChromeThread::PostTask( |
+ ChromeThread::UI, FROM_HERE, |
+ NewRunnableMethod(this, &LoginHandler::CloseContentsDeferred)); |
+ ChromeThread::PostTask( |
+ ChromeThread::UI, FROM_HERE, |
+ NewRunnableMethod(this, &LoginHandler::SendNotifications)); |
+ ChromeThread::PostTask( |
+ ChromeThread::IO, FROM_HERE, |
+ NewRunnableMethod(this, &LoginHandler::SetAuthDeferred, |
+ username, password)); |
+} |
+ |
+void LoginHandler::CancelAuth() { |
+ if (WasAuthHandled(true)) |
+ return; |
+ |
+ ChromeThread::PostTask( |
+ ChromeThread::UI, FROM_HERE, |
+ NewRunnableMethod(this, &LoginHandler::CloseContentsDeferred)); |
+ ChromeThread::PostTask( |
+ ChromeThread::UI, FROM_HERE, |
+ NewRunnableMethod(this, &LoginHandler::SendNotifications)); |
+ ChromeThread::PostTask( |
+ ChromeThread::IO, FROM_HERE, |
+ NewRunnableMethod(this, &LoginHandler::CancelAuthDeferred)); |
+} |
+ |
+void LoginHandler::OnRequestCancelled() { |
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)) << |
+ "Why is OnRequestCancelled called from the UI thread?"; |
+ |
+ // Reference is no longer valid. |
+ request_ = NULL; |
+ |
+ // Give up on auth if the request was cancelled. |
+ CancelAuth(); |
+} |
+ |
+void LoginHandler::SetModel(LoginModel* model) { |
+ if (login_model_) |
+ login_model_->SetObserver(NULL); |
+ login_model_ = model; |
+ if (login_model_) |
+ login_model_->SetObserver(this); |
+} |
+ |
+void LoginHandler::SetDialog(ConstrainedWindow* dialog) { |
+ dialog_ = dialog; |
+} |
+ |
+// Notify observers that authentication is needed or received. The automation |
+// proxy uses this for testing. |
+void LoginHandler::SendNotifications() { |
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
+ |
+ NotificationService* service = NotificationService::current(); |
+ TabContents* requesting_contents = GetTabContentsForLogin(); |
+ if (!requesting_contents) |
+ return; |
+ |
+ NavigationController* controller = &requesting_contents->controller(); |
+ |
+ if (!WasAuthHandled(false)) { |
+ LoginNotificationDetails details(this); |
+ service->Notify(NotificationType::AUTH_NEEDED, |
+ Source<NavigationController>(controller), |
+ Details<LoginNotificationDetails>(&details)); |
+ } else { |
+ service->Notify(NotificationType::AUTH_SUPPLIED, |
+ Source<NavigationController>(controller), |
+ NotificationService::NoDetails()); |
+ } |
+} |
+ |
+void LoginHandler::ReleaseSoon() { |
+ if (!WasAuthHandled(true)) { |
+ ChromeThread::PostTask( |
+ ChromeThread::IO, FROM_HERE, |
+ NewRunnableMethod(this, &LoginHandler::CancelAuthDeferred)); |
+ ChromeThread::PostTask( |
+ ChromeThread::UI, FROM_HERE, |
+ NewRunnableMethod(this, &LoginHandler::SendNotifications)); |
+ } |
+ |
+ // Delete this object once all InvokeLaters have been called. |
+ ChromeThread::ReleaseSoon(ChromeThread::IO, FROM_HERE, this); |
+} |
+ |
+// Returns whether authentication had been handled (SetAuth or CancelAuth). |
+// If |set_handled| is true, it will mark authentication as handled. |
+bool LoginHandler::WasAuthHandled(bool set_handled) { |
+ AutoLock lock(handled_auth_lock_); |
+ bool was_handled = handled_auth_; |
+ if (set_handled) |
+ handled_auth_ = true; |
+ return was_handled; |
+} |
+ |
+// Calls SetAuth from the IO loop. |
+void LoginHandler::SetAuthDeferred(const std::wstring& username, |
+ const std::wstring& password) { |
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
+ |
+ if (request_) { |
+ request_->SetAuth(username, password); |
+ ResetLoginHandlerForRequest(request_); |
+ } |
+} |
+ |
+// Calls CancelAuth from the IO loop. |
+void LoginHandler::CancelAuthDeferred() { |
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
+ |
+ if (request_) { |
+ request_->CancelAuth(); |
+ // Verify that CancelAuth does destroy the request via our delegate. |
+ DCHECK(request_ != NULL); |
+ ResetLoginHandlerForRequest(request_); |
+ } |
+} |
+ |
+// Closes the view_contents from the UI loop. |
+void LoginHandler::CloseContentsDeferred() { |
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
+ |
+ // The hosting ConstrainedWindow may have been freed. |
+ if (dialog_) |
+ dialog_->CloseConstrainedWindow(); |
+} |
+ |
+// ---------------------------------------------------------------------------- |
// LoginDialogTask |
// This task is run on the UI thread and creates a constrained window with |