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

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: Fix race condition on Mac Created 10 years 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
« no previous file with comments | « chrome/browser/ui/login/login_prompt.h ('k') | chrome/browser/ui/login/login_prompt_browsertest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 d653457de8ed16f517d42939b3146bac51be62ce..f8b00eb9fb31a3347cc5a882ae384d02778ec33e 100644
--- a/chrome/browser/ui/login/login_prompt.cc
+++ b/chrome/browser/ui/login/login_prompt.cc
@@ -116,7 +116,7 @@ TabContents* LoginHandler::GetTabContentsForLogin() const {
void LoginHandler::SetAuth(const std::wstring& username,
const std::wstring& password) {
- if (WasAuthHandled(true))
+ if (TestAndSetAuthHandled())
return;
// Tell the password manager the credentials were submitted / accepted.
@@ -126,30 +126,45 @@ void LoginHandler::SetAuth(const std::wstring& username,
password_manager_->ProvisionallySavePassword(password_form_);
}
+ // If we are on the UI thread, then calling NotifyAuthSupplied()
+ // directly 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 may be briefly displayed to the user before they are
+ // removed.
+ 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
+ NotifyAuthSupplied(username, password);
+ else
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ this, &LoginHandler::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
+ 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 +211,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 +251,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 +269,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 +287,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 +303,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 +321,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 +385,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).
« no previous file with comments | « chrome/browser/ui/login/login_prompt.h ('k') | chrome/browser/ui/login/login_prompt_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698