| 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
|
|
|