Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(607)

Unified Diff: chrome/browser/ui/login/login_prompt.cc

Issue 5814005: Minimize login prompts (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: LoginHandler::SetAuth() expects to be called on the UI thread Created 9 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/login/login_prompt.cc
diff --git a/chrome/browser/ui/login/login_prompt.cc b/chrome/browser/ui/login/login_prompt.cc
index 40cc66a1475a651e98c76d1b5241f0f4abbc7f3a..dd875d262a3cf34dc8c222d94c8d89f279794b95 100644
--- a/chrome/browser/ui/login/login_prompt.cc
+++ b/chrome/browser/ui/login/login_prompt.cc
@@ -116,7 +116,9 @@ TabContents* LoginHandler::GetTabContentsForLogin() const {
void LoginHandler::SetAuth(const std::wstring& username,
const std::wstring& password) {
- if (WasAuthHandled(true))
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (TestAndSetAuthHandled())
return;
// Tell the password manager the credentials were submitted / accepted.
@@ -126,30 +128,39 @@ void LoginHandler::SetAuth(const std::wstring& username,
password_manager_->ProvisionallySavePassword(password_form_);
}
+ // Calling NotifyAuthSupplied() directly instead of posting a task
+ // allows other LoginHandler instances to queue their
+ // CloseContentsDeferred() before ours. Closing dialogs in the
+ // opposite order as they were created avoids races where remaining
+ // dialogs in the same tab may be briefly displayed to the user
+ // before they are removed.
+ NotifyAuthSupplied(username, password);
+
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
NewRunnableMethod(this, &LoginHandler::CloseContentsDeferred));
BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(
- this, &LoginHandler::NotifyAuthSupplied, username, password));
- BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
NewRunnableMethod(
this, &LoginHandler::SetAuthDeferred, username, password));
}
void LoginHandler::CancelAuth() {
- if (WasAuthHandled(true))
+ if (TestAndSetAuthHandled())
return;
+ // Similar to how we deal with notifications above in SetAuth()
+ if (BrowserThread::CurrentlyOn(BrowserThread::UI))
+ NotifyAuthCancelled();
+ 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.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &LoginHandler::NotifyAuthCancelled));
+
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
NewRunnableMethod(this, &LoginHandler::CloseContentsDeferred));
BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(this, &LoginHandler::NotifyAuthCancelled));
- BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
NewRunnableMethod(this, &LoginHandler::CancelAuthDeferred));
}
@@ -196,17 +207,17 @@ void LoginHandler::Observe(NotificationType type,
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)
+ // Break out early if we aren't interested in the notification.
+ if (WasAuthHandled())
return;
LoginNotificationDetails* login_details =
Details<LoginNotificationDetails>(details).ptr();
+ // WasAuthHandled() should always test positive before we publish
+ // AUTH_SUPPLIED or AUTH_CANCELLED notifications.
+ DCHECK(login_details->handler() != this);
+
// Only handle notification for the identical auth info.
if (*login_details->handler()->auth_info() != *auth_info())
return;
@@ -236,7 +247,7 @@ void LoginHandler::SetDialog(ConstrainedWindow* dialog) {
void LoginHandler::NotifyAuthNeeded() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (WasAuthHandled(false))
+ if (WasAuthHandled())
return;
TabContents* requesting_contents = GetTabContentsForLogin();
@@ -254,7 +265,7 @@ void LoginHandler::NotifyAuthNeeded() {
void LoginHandler::NotifyAuthCancelled() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(WasAuthHandled(false));
+ DCHECK(WasAuthHandled());
TabContents* requesting_contents = GetTabContentsForLogin();
if (!requesting_contents)
@@ -272,7 +283,7 @@ void LoginHandler::NotifyAuthCancelled() {
void LoginHandler::NotifyAuthSupplied(const std::wstring& username,
const std::wstring& password) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(WasAuthHandled(false));
+ DCHECK(WasAuthHandled());
TabContents* requesting_contents = GetTabContentsForLogin();
if (!requesting_contents)
@@ -288,7 +299,7 @@ void LoginHandler::NotifyAuthSupplied(const std::wstring& username,
}
void LoginHandler::ReleaseSoon() {
- if (!WasAuthHandled(true)) {
+ if (!TestAndSetAuthHandled()) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
NewRunnableMethod(this, &LoginHandler::CancelAuthDeferred));
@@ -306,12 +317,17 @@ void LoginHandler::ReleaseSoon() {
}
// 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) {
+bool LoginHandler::WasAuthHandled() {
+ AutoLock lock(handled_auth_lock_);
+ bool was_handled = handled_auth_;
+ return was_handled;
+}
+
+// Marks authentication as handled and returns the previous handled state.
+bool LoginHandler::TestAndSetAuthHandled() {
AutoLock lock(handled_auth_lock_);
bool was_handled = handled_auth_;
- if (set_handled)
- handled_auth_ = true;
+ handled_auth_ = true;
return was_handled;
}
@@ -365,7 +381,7 @@ class LoginDialogTask : public Task {
void Run() {
TabContents* parent_contents = handler_->GetTabContentsForLogin();
- if (!parent_contents) {
+ if (!parent_contents || handler_->WasAuthHandled()) {
// The request may have been cancelled, or it may be for a renderer
// not hosted by a tab (e.g. an extension). Cancel just in case
// (cancelling twice is a no-op).

Powered by Google App Engine
This is Rietveld 408576698