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

Side by Side 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: Add const and fix braces Created 9 years, 11 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/login/login_prompt.h" 5 #include "chrome/browser/ui/login/login_prompt.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "app/l10n_util.h" 9 #include "app/l10n_util.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 109
110 TabContents* LoginHandler::GetTabContentsForLogin() const { 110 TabContents* LoginHandler::GetTabContentsForLogin() const {
111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
112 112
113 return tab_util::GetTabContentsByID(render_process_host_id_, 113 return tab_util::GetTabContentsByID(render_process_host_id_,
114 tab_contents_id_); 114 tab_contents_id_);
115 } 115 }
116 116
117 void LoginHandler::SetAuth(const std::wstring& username, 117 void LoginHandler::SetAuth(const std::wstring& username,
118 const std::wstring& password) { 118 const std::wstring& password) {
119 if (WasAuthHandled(true)) 119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
120
121 if (TestAndSetAuthHandled())
120 return; 122 return;
121 123
122 // Tell the password manager the credentials were submitted / accepted. 124 // Tell the password manager the credentials were submitted / accepted.
123 if (password_manager_) { 125 if (password_manager_) {
124 password_form_.username_value = WideToUTF16Hack(username); 126 password_form_.username_value = WideToUTF16Hack(username);
125 password_form_.password_value = WideToUTF16Hack(password); 127 password_form_.password_value = WideToUTF16Hack(password);
126 password_manager_->ProvisionallySavePassword(password_form_); 128 password_manager_->ProvisionallySavePassword(password_form_);
127 } 129 }
128 130
131 // Calling NotifyAuthSupplied() directly instead of posting a task
132 // allows other LoginHandler instances to queue their
133 // CloseContentsDeferred() before ours. Closing dialogs in the
134 // opposite order as they were created avoids races where remaining
135 // dialogs in the same tab may be briefly displayed to the user
136 // before they are removed.
137 NotifyAuthSupplied(username, password);
138
129 BrowserThread::PostTask( 139 BrowserThread::PostTask(
130 BrowserThread::UI, FROM_HERE, 140 BrowserThread::UI, FROM_HERE,
131 NewRunnableMethod(this, &LoginHandler::CloseContentsDeferred)); 141 NewRunnableMethod(this, &LoginHandler::CloseContentsDeferred));
132 BrowserThread::PostTask( 142 BrowserThread::PostTask(
133 BrowserThread::UI, FROM_HERE,
134 NewRunnableMethod(
135 this, &LoginHandler::NotifyAuthSupplied, username, password));
136 BrowserThread::PostTask(
137 BrowserThread::IO, FROM_HERE, 143 BrowserThread::IO, FROM_HERE,
138 NewRunnableMethod( 144 NewRunnableMethod(
139 this, &LoginHandler::SetAuthDeferred, username, password)); 145 this, &LoginHandler::SetAuthDeferred, username, password));
140 } 146 }
141 147
142 void LoginHandler::CancelAuth() { 148 void LoginHandler::CancelAuth() {
143 if (WasAuthHandled(true)) 149 if (TestAndSetAuthHandled())
144 return; 150 return;
145 151
152 // Similar to how we deal with notifications above in SetAuth()
153 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
154 NotifyAuthCancelled();
155 } else {
156 BrowserThread::PostTask(
157 BrowserThread::UI, FROM_HERE,
158 NewRunnableMethod(this, &LoginHandler::NotifyAuthCancelled));
159 }
160
146 BrowserThread::PostTask( 161 BrowserThread::PostTask(
147 BrowserThread::UI, FROM_HERE, 162 BrowserThread::UI, FROM_HERE,
148 NewRunnableMethod(this, &LoginHandler::CloseContentsDeferred)); 163 NewRunnableMethod(this, &LoginHandler::CloseContentsDeferred));
149 BrowserThread::PostTask( 164 BrowserThread::PostTask(
150 BrowserThread::UI, FROM_HERE,
151 NewRunnableMethod(this, &LoginHandler::NotifyAuthCancelled));
152 BrowserThread::PostTask(
153 BrowserThread::IO, FROM_HERE, 165 BrowserThread::IO, FROM_HERE,
154 NewRunnableMethod(this, &LoginHandler::CancelAuthDeferred)); 166 NewRunnableMethod(this, &LoginHandler::CancelAuthDeferred));
155 } 167 }
156 168
157 void LoginHandler::OnRequestCancelled() { 169 void LoginHandler::OnRequestCancelled() {
158 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)) << 170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)) <<
159 "Why is OnRequestCancelled called from the UI thread?"; 171 "Why is OnRequestCancelled called from the UI thread?";
160 172
161 // Reference is no longer valid. 173 // Reference is no longer valid.
162 request_ = NULL; 174 request_ = NULL;
(...skipping 26 matching lines...) Expand all
189 const NotificationSource& source, 201 const NotificationSource& source,
190 const NotificationDetails& details) { 202 const NotificationDetails& details) {
191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 203 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
192 DCHECK(type == NotificationType::AUTH_SUPPLIED || 204 DCHECK(type == NotificationType::AUTH_SUPPLIED ||
193 type == NotificationType::AUTH_CANCELLED); 205 type == NotificationType::AUTH_CANCELLED);
194 206
195 TabContents* requesting_contents = GetTabContentsForLogin(); 207 TabContents* requesting_contents = GetTabContentsForLogin();
196 if (!requesting_contents) 208 if (!requesting_contents)
197 return; 209 return;
198 210
199 NavigationController* this_controller = &requesting_contents->controller(); 211 // Break out early if we aren't interested in the notification.
200 NavigationController* that_controller = 212 if (WasAuthHandled())
201 Source<NavigationController>(source).ptr();
202
203 // Only handle notifications from other handlers.
204 if (this_controller == that_controller)
205 return; 213 return;
206 214
207 LoginNotificationDetails* login_details = 215 LoginNotificationDetails* login_details =
208 Details<LoginNotificationDetails>(details).ptr(); 216 Details<LoginNotificationDetails>(details).ptr();
209 217
218 // WasAuthHandled() should always test positive before we publish
219 // AUTH_SUPPLIED or AUTH_CANCELLED notifications.
220 DCHECK(login_details->handler() != this);
221
210 // Only handle notification for the identical auth info. 222 // Only handle notification for the identical auth info.
211 if (*login_details->handler()->auth_info() != *auth_info()) 223 if (*login_details->handler()->auth_info() != *auth_info())
212 return; 224 return;
213 225
214 // Set or cancel the auth in this handler. 226 // Set or cancel the auth in this handler.
215 if (type == NotificationType::AUTH_SUPPLIED) { 227 if (type == NotificationType::AUTH_SUPPLIED) {
216 AuthSuppliedLoginNotificationDetails* supplied_details = 228 AuthSuppliedLoginNotificationDetails* supplied_details =
217 Details<AuthSuppliedLoginNotificationDetails>(details).ptr(); 229 Details<AuthSuppliedLoginNotificationDetails>(details).ptr();
218 SetAuth(supplied_details->username(), supplied_details->password()); 230 SetAuth(supplied_details->username(), supplied_details->password());
219 } else { 231 } else {
220 DCHECK(type == NotificationType::AUTH_CANCELLED); 232 DCHECK(type == NotificationType::AUTH_CANCELLED);
221 CancelAuth(); 233 CancelAuth();
222 } 234 }
223 } 235 }
224 236
225 void LoginHandler::SetModel(LoginModel* model) { 237 void LoginHandler::SetModel(LoginModel* model) {
226 if (login_model_) 238 if (login_model_)
227 login_model_->SetObserver(NULL); 239 login_model_->SetObserver(NULL);
228 login_model_ = model; 240 login_model_ = model;
229 if (login_model_) 241 if (login_model_)
230 login_model_->SetObserver(this); 242 login_model_->SetObserver(this);
231 } 243 }
232 244
233 void LoginHandler::SetDialog(ConstrainedWindow* dialog) { 245 void LoginHandler::SetDialog(ConstrainedWindow* dialog) {
234 dialog_ = dialog; 246 dialog_ = dialog;
235 } 247 }
236 248
237 void LoginHandler::NotifyAuthNeeded() { 249 void LoginHandler::NotifyAuthNeeded() {
238 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 250 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
239 if (WasAuthHandled(false)) 251 if (WasAuthHandled())
240 return; 252 return;
241 253
242 TabContents* requesting_contents = GetTabContentsForLogin(); 254 TabContents* requesting_contents = GetTabContentsForLogin();
243 if (!requesting_contents) 255 if (!requesting_contents)
244 return; 256 return;
245 257
246 NotificationService* service = NotificationService::current(); 258 NotificationService* service = NotificationService::current();
247 NavigationController* controller = &requesting_contents->controller(); 259 NavigationController* controller = &requesting_contents->controller();
248 LoginNotificationDetails details(this); 260 LoginNotificationDetails details(this);
249 261
250 service->Notify(NotificationType::AUTH_NEEDED, 262 service->Notify(NotificationType::AUTH_NEEDED,
251 Source<NavigationController>(controller), 263 Source<NavigationController>(controller),
252 Details<LoginNotificationDetails>(&details)); 264 Details<LoginNotificationDetails>(&details));
253 } 265 }
254 266
255 void LoginHandler::NotifyAuthCancelled() { 267 void LoginHandler::NotifyAuthCancelled() {
256 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 268 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
257 DCHECK(WasAuthHandled(false)); 269 DCHECK(WasAuthHandled());
258 270
259 TabContents* requesting_contents = GetTabContentsForLogin(); 271 TabContents* requesting_contents = GetTabContentsForLogin();
260 if (!requesting_contents) 272 if (!requesting_contents)
261 return; 273 return;
262 274
263 NotificationService* service = NotificationService::current(); 275 NotificationService* service = NotificationService::current();
264 NavigationController* controller = &requesting_contents->controller(); 276 NavigationController* controller = &requesting_contents->controller();
265 LoginNotificationDetails details(this); 277 LoginNotificationDetails details(this);
266 278
267 service->Notify(NotificationType::AUTH_CANCELLED, 279 service->Notify(NotificationType::AUTH_CANCELLED,
268 Source<NavigationController>(controller), 280 Source<NavigationController>(controller),
269 Details<LoginNotificationDetails>(&details)); 281 Details<LoginNotificationDetails>(&details));
270 } 282 }
271 283
272 void LoginHandler::NotifyAuthSupplied(const std::wstring& username, 284 void LoginHandler::NotifyAuthSupplied(const std::wstring& username,
273 const std::wstring& password) { 285 const std::wstring& password) {
274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 286 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
275 DCHECK(WasAuthHandled(false)); 287 DCHECK(WasAuthHandled());
276 288
277 TabContents* requesting_contents = GetTabContentsForLogin(); 289 TabContents* requesting_contents = GetTabContentsForLogin();
278 if (!requesting_contents) 290 if (!requesting_contents)
279 return; 291 return;
280 292
281 NotificationService* service = NotificationService::current(); 293 NotificationService* service = NotificationService::current();
282 NavigationController* controller = &requesting_contents->controller(); 294 NavigationController* controller = &requesting_contents->controller();
283 AuthSuppliedLoginNotificationDetails details(this, username, password); 295 AuthSuppliedLoginNotificationDetails details(this, username, password);
284 296
285 service->Notify(NotificationType::AUTH_SUPPLIED, 297 service->Notify(NotificationType::AUTH_SUPPLIED,
286 Source<NavigationController>(controller), 298 Source<NavigationController>(controller),
287 Details<AuthSuppliedLoginNotificationDetails>(&details)); 299 Details<AuthSuppliedLoginNotificationDetails>(&details));
288 } 300 }
289 301
290 void LoginHandler::ReleaseSoon() { 302 void LoginHandler::ReleaseSoon() {
291 if (!WasAuthHandled(true)) { 303 if (!TestAndSetAuthHandled()) {
292 BrowserThread::PostTask( 304 BrowserThread::PostTask(
293 BrowserThread::IO, FROM_HERE, 305 BrowserThread::IO, FROM_HERE,
294 NewRunnableMethod(this, &LoginHandler::CancelAuthDeferred)); 306 NewRunnableMethod(this, &LoginHandler::CancelAuthDeferred));
295 BrowserThread::PostTask( 307 BrowserThread::PostTask(
296 BrowserThread::UI, FROM_HERE, 308 BrowserThread::UI, FROM_HERE,
297 NewRunnableMethod(this, &LoginHandler::NotifyAuthCancelled)); 309 NewRunnableMethod(this, &LoginHandler::NotifyAuthCancelled));
298 } 310 }
299 311
300 BrowserThread::PostTask( 312 BrowserThread::PostTask(
301 BrowserThread::UI, FROM_HERE, 313 BrowserThread::UI, FROM_HERE,
302 NewRunnableMethod(this, &LoginHandler::RemoveObservers)); 314 NewRunnableMethod(this, &LoginHandler::RemoveObservers));
303 315
304 // Delete this object once all InvokeLaters have been called. 316 // Delete this object once all InvokeLaters have been called.
305 BrowserThread::ReleaseSoon(BrowserThread::IO, FROM_HERE, this); 317 BrowserThread::ReleaseSoon(BrowserThread::IO, FROM_HERE, this);
306 } 318 }
307 319
308 // Returns whether authentication had been handled (SetAuth or CancelAuth). 320 // Returns whether authentication had been handled (SetAuth or CancelAuth).
309 // If |set_handled| is true, it will mark authentication as handled. 321 bool LoginHandler::WasAuthHandled() const {
310 bool LoginHandler::WasAuthHandled(bool set_handled) {
311 AutoLock lock(handled_auth_lock_); 322 AutoLock lock(handled_auth_lock_);
312 bool was_handled = handled_auth_; 323 bool was_handled = handled_auth_;
313 if (set_handled)
314 handled_auth_ = true;
315 return was_handled; 324 return was_handled;
316 } 325 }
317 326
327 // Marks authentication as handled and returns the previous handled state.
328 bool LoginHandler::TestAndSetAuthHandled() {
329 AutoLock lock(handled_auth_lock_);
330 bool was_handled = handled_auth_;
331 handled_auth_ = true;
332 return was_handled;
333 }
334
318 // Calls SetAuth from the IO loop. 335 // Calls SetAuth from the IO loop.
319 void LoginHandler::SetAuthDeferred(const std::wstring& username, 336 void LoginHandler::SetAuthDeferred(const std::wstring& username,
320 const std::wstring& password) { 337 const std::wstring& password) {
321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 338 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
322 339
323 if (request_) { 340 if (request_) {
324 request_->SetAuth(WideToUTF16Hack(username), WideToUTF16Hack(password)); 341 request_->SetAuth(WideToUTF16Hack(username), WideToUTF16Hack(password));
325 ResetLoginHandlerForRequest(request_); 342 ResetLoginHandlerForRequest(request_);
326 } 343 }
327 } 344 }
(...skipping 30 matching lines...) Expand all
358 LoginDialogTask(const GURL& request_url, 375 LoginDialogTask(const GURL& request_url,
359 net::AuthChallengeInfo* auth_info, 376 net::AuthChallengeInfo* auth_info,
360 LoginHandler* handler) 377 LoginHandler* handler)
361 : request_url_(request_url), auth_info_(auth_info), handler_(handler) { 378 : request_url_(request_url), auth_info_(auth_info), handler_(handler) {
362 } 379 }
363 virtual ~LoginDialogTask() { 380 virtual ~LoginDialogTask() {
364 } 381 }
365 382
366 void Run() { 383 void Run() {
367 TabContents* parent_contents = handler_->GetTabContentsForLogin(); 384 TabContents* parent_contents = handler_->GetTabContentsForLogin();
368 if (!parent_contents) { 385 if (!parent_contents || handler_->WasAuthHandled()) {
369 // The request may have been cancelled, or it may be for a renderer 386 // The request may have been cancelled, or it may be for a renderer
370 // not hosted by a tab (e.g. an extension). Cancel just in case 387 // not hosted by a tab (e.g. an extension). Cancel just in case
371 // (cancelling twice is a no-op). 388 // (cancelling twice is a no-op).
372 handler_->CancelAuth(); 389 handler_->CancelAuth();
373 return; 390 return;
374 } 391 }
375 392
376 // Tell the password manager to look for saved passwords. 393 // Tell the password manager to look for saved passwords.
377 TabContentsWrapper** wrapper = 394 TabContentsWrapper** wrapper =
378 TabContentsWrapper::property_accessor()->GetProperty( 395 TabContentsWrapper::property_accessor()->GetProperty(
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 // Public API 463 // Public API
447 464
448 LoginHandler* CreateLoginPrompt(net::AuthChallengeInfo* auth_info, 465 LoginHandler* CreateLoginPrompt(net::AuthChallengeInfo* auth_info,
449 net::URLRequest* request) { 466 net::URLRequest* request) {
450 LoginHandler* handler = LoginHandler::Create(auth_info, request); 467 LoginHandler* handler = LoginHandler::Create(auth_info, request);
451 BrowserThread::PostTask( 468 BrowserThread::PostTask(
452 BrowserThread::UI, FROM_HERE, new LoginDialogTask( 469 BrowserThread::UI, FROM_HERE, new LoginDialogTask(
453 request->url(), auth_info, handler)); 470 request->url(), auth_info, handler));
454 return handler; 471 return handler;
455 } 472 }
OLDNEW
« 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