Index: chrome/browser/login_prompt.cc |
=================================================================== |
--- chrome/browser/login_prompt.cc (revision 43269) |
+++ chrome/browser/login_prompt.cc (working copy) |
@@ -67,18 +67,26 @@ |
// ---------------------------------------------------------------------------- |
// LoginHandler |
-LoginHandler::LoginHandler(URLRequest* request) |
+LoginHandler::LoginHandler(net::AuthChallengeInfo* auth_info, |
+ URLRequest* request) |
: handled_auth_(false), |
dialog_(NULL), |
+ auth_info_(auth_info), |
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"; |
+ DCHECK(request_) << "LoginHandler constructed with NULL request"; |
+ DCHECK(auth_info_) << "LoginHandler constructed with NULL auth info"; |
AddRef(); // matched by ReleaseSoon::ReleaseSoon(). |
+ |
+ ChromeThread::PostTask( |
+ ChromeThread::UI, FROM_HERE, |
+ NewRunnableMethod(this, &LoginHandler::AddObservers)); |
+ |
if (!ResourceDispatcherHost::RenderViewForRequest( |
request_, &render_process_host_id_, &tab_contents_id_)) { |
NOTREACHED(); |
@@ -121,11 +129,12 @@ |
NewRunnableMethod(this, &LoginHandler::CloseContentsDeferred)); |
ChromeThread::PostTask( |
ChromeThread::UI, FROM_HERE, |
- NewRunnableMethod(this, &LoginHandler::SendNotifications)); |
+ NewRunnableMethod( |
+ this, &LoginHandler::NotifyAuthSupplied, username, password)); |
ChromeThread::PostTask( |
ChromeThread::IO, FROM_HERE, |
- NewRunnableMethod(this, &LoginHandler::SetAuthDeferred, |
- username, password)); |
+ NewRunnableMethod( |
+ this, &LoginHandler::SetAuthDeferred, username, password)); |
} |
void LoginHandler::CancelAuth() { |
@@ -137,7 +146,7 @@ |
NewRunnableMethod(this, &LoginHandler::CloseContentsDeferred)); |
ChromeThread::PostTask( |
ChromeThread::UI, FROM_HERE, |
- NewRunnableMethod(this, &LoginHandler::SendNotifications)); |
+ NewRunnableMethod(this, &LoginHandler::NotifyAuthCancelled)); |
ChromeThread::PostTask( |
ChromeThread::IO, FROM_HERE, |
NewRunnableMethod(this, &LoginHandler::CancelAuthDeferred)); |
@@ -154,6 +163,63 @@ |
CancelAuth(); |
} |
+void LoginHandler::AddObservers() { |
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
+ |
+ registrar_.Add(this, NotificationType::AUTH_SUPPLIED, |
+ NotificationService::AllSources()); |
+ registrar_.Add(this, NotificationType::AUTH_CANCELLED, |
+ NotificationService::AllSources()); |
+} |
+ |
+void LoginHandler::RemoveObservers() { |
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
+ |
+ registrar_.Remove(this, NotificationType::AUTH_SUPPLIED, |
+ NotificationService::AllSources()); |
+ registrar_.Remove(this, NotificationType::AUTH_CANCELLED, |
+ NotificationService::AllSources()); |
+ |
+ DCHECK(registrar_.IsEmpty()); |
+} |
+ |
+void LoginHandler::Observe(NotificationType type, |
+ const NotificationSource& source, |
+ const NotificationDetails& details) { |
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
+ DCHECK(type == NotificationType::AUTH_SUPPLIED || |
+ type == NotificationType::AUTH_CANCELLED); |
+ |
+ TabContents* requesting_contents = GetTabContentsForLogin(); |
+ if (!requesting_contents) |
+ return; |
+ |
+ NavigationController* this_controller = &requesting_contents->controller(); |
+ NavigationController* that_controller = |
+ Source<NavigationController>(source).ptr(); |
+ |
+ // Only handle notifications from other handlers. |
+ if (this_controller == that_controller) |
+ return; |
+ |
+ LoginNotificationDetails* login_details = |
+ Details<LoginNotificationDetails>(details).ptr(); |
+ |
+ // Only handle notification for the identical auth info. |
+ if (*login_details->handler()->auth_info() != *auth_info()) |
+ return; |
+ |
+ // Set or cancel the auth in this handler. |
+ if (type == NotificationType::AUTH_SUPPLIED) { |
+ AuthSuppliedLoginNotificationDetails* supplied_details = |
+ Details<AuthSuppliedLoginNotificationDetails>(details).ptr(); |
+ SetAuth(supplied_details->username(), supplied_details->password()); |
+ } else { |
+ DCHECK(type == NotificationType::AUTH_CANCELLED); |
+ CancelAuth(); |
+ } |
+} |
+ |
void LoginHandler::SetModel(LoginModel* model) { |
if (login_model_) |
login_model_->SetObserver(NULL); |
@@ -166,30 +232,59 @@ |
dialog_ = dialog; |
} |
-// Notify observers that authentication is needed or received. The automation |
-// proxy uses this for testing. |
-void LoginHandler::SendNotifications() { |
+void LoginHandler::NotifyAuthNeeded() { |
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
+ if (WasAuthHandled(false)) |
+ return; |
+ TabContents* requesting_contents = GetTabContentsForLogin(); |
+ if (!requesting_contents) |
+ return; |
+ |
NotificationService* service = NotificationService::current(); |
+ NavigationController* controller = &requesting_contents->controller(); |
+ LoginNotificationDetails details(this); |
+ |
+ service->Notify(NotificationType::AUTH_NEEDED, |
+ Source<NavigationController>(controller), |
+ Details<LoginNotificationDetails>(&details)); |
+} |
+ |
+void LoginHandler::NotifyAuthCancelled() { |
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
+ DCHECK(WasAuthHandled(false)); |
+ |
TabContents* requesting_contents = GetTabContentsForLogin(); |
if (!requesting_contents) |
return; |
+ NotificationService* service = NotificationService::current(); |
NavigationController* controller = &requesting_contents->controller(); |
+ LoginNotificationDetails details(this); |
- 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()); |
- } |
+ service->Notify(NotificationType::AUTH_CANCELLED, |
+ Source<NavigationController>(controller), |
+ Details<LoginNotificationDetails>(&details)); |
} |
+void LoginHandler::NotifyAuthSupplied(const std::wstring& username, |
+ const std::wstring& password) { |
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
+ DCHECK(WasAuthHandled(false)); |
+ |
+ TabContents* requesting_contents = GetTabContentsForLogin(); |
+ if (!requesting_contents) |
+ return; |
+ |
+ NotificationService* service = NotificationService::current(); |
+ NavigationController* controller = &requesting_contents->controller(); |
+ AuthSuppliedLoginNotificationDetails details(this, username, password); |
+ |
+ service->Notify(NotificationType::AUTH_SUPPLIED, |
+ Source<NavigationController>(controller), |
+ Details<AuthSuppliedLoginNotificationDetails>(&details)); |
+} |
+ |
void LoginHandler::ReleaseSoon() { |
if (!WasAuthHandled(true)) { |
ChromeThread::PostTask( |
@@ -197,9 +292,13 @@ |
NewRunnableMethod(this, &LoginHandler::CancelAuthDeferred)); |
ChromeThread::PostTask( |
ChromeThread::UI, FROM_HERE, |
- NewRunnableMethod(this, &LoginHandler::SendNotifications)); |
+ NewRunnableMethod(this, &LoginHandler::NotifyAuthCancelled)); |
} |
+ ChromeThread::PostTask( |
+ ChromeThread::UI, FROM_HERE, |
+ NewRunnableMethod(this, &LoginHandler::RemoveObservers)); |
+ |
// Delete this object once all InvokeLaters have been called. |
ChromeThread::ReleaseSoon(ChromeThread::IO, FROM_HERE, this); |
} |
@@ -231,7 +330,7 @@ |
if (request_) { |
request_->CancelAuth(); |
- // Verify that CancelAuth does destroy the request via our delegate. |
+ // Verify that CancelAuth doesn't destroy the request via our delegate. |
DCHECK(request_ != NULL); |
ResetLoginHandlerForRequest(request_); |
} |
@@ -303,7 +402,7 @@ |
std::string host_and_port(WideToASCII(auth_info_->host_and_port)); |
if (net::GetHostAndPort(request_url_) != host_and_port) { |
dialog_form.origin = GURL(); |
- NOTREACHED(); |
+ NOTREACHED(); // crbug.com/32718 |
} else if (auth_info_->is_proxy) { |
std::string origin = host_and_port; |
// We don't expect this to already start with http:// or https://. |
@@ -329,7 +428,7 @@ |
// This is owned by the ResourceDispatcherHost that invoked us. |
LoginHandler* handler_; |
- DISALLOW_EVIL_CONSTRUCTORS(LoginDialogTask); |
+ DISALLOW_COPY_AND_ASSIGN(LoginDialogTask); |
}; |
// ---------------------------------------------------------------------------- |
@@ -337,7 +436,7 @@ |
LoginHandler* CreateLoginPrompt(net::AuthChallengeInfo* auth_info, |
URLRequest* request) { |
- LoginHandler* handler = LoginHandler::Create(request); |
+ LoginHandler* handler = LoginHandler::Create(auth_info, request); |
ChromeThread::PostTask( |
ChromeThread::UI, FROM_HERE, new LoginDialogTask( |
request->url(), auth_info, handler)); |