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

Side by Side Diff: chrome/browser/login_prompt.cc

Issue 1528012: Notify all active login prompts when one login prompt is submitted. This allo... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 10 years, 8 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
« no previous file with comments | « chrome/browser/login_prompt.h ('k') | chrome/browser/login_prompt_gtk.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/login_prompt.h" 5 #include "chrome/browser/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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 signon_realm = url.GetOrigin().spec(); 60 signon_realm = url.GetOrigin().spec();
61 // This ends with a "/". 61 // This ends with a "/".
62 } 62 }
63 signon_realm.append(WideToUTF8(auth_info.realm)); 63 signon_realm.append(WideToUTF8(auth_info.realm));
64 return signon_realm; 64 return signon_realm;
65 } 65 }
66 66
67 // ---------------------------------------------------------------------------- 67 // ----------------------------------------------------------------------------
68 // LoginHandler 68 // LoginHandler
69 69
70 LoginHandler::LoginHandler(URLRequest* request) 70 LoginHandler::LoginHandler(net::AuthChallengeInfo* auth_info,
71 URLRequest* request)
71 : handled_auth_(false), 72 : handled_auth_(false),
72 dialog_(NULL), 73 dialog_(NULL),
74 auth_info_(auth_info),
73 request_(request), 75 request_(request),
74 password_manager_(NULL), 76 password_manager_(NULL),
75 login_model_(NULL) { 77 login_model_(NULL) {
76 // This constructor is called on the I/O thread, so we cannot load the nib 78 // This constructor is called on the I/O thread, so we cannot load the nib
77 // here. BuildViewForPasswordManager() will be invoked on the UI thread 79 // here. BuildViewForPasswordManager() will be invoked on the UI thread
78 // later, so wait with loading the nib until then. 80 // later, so wait with loading the nib until then.
79 DCHECK(request_) << "LoginHandlerMac constructed with NULL request"; 81 DCHECK(request_) << "LoginHandler constructed with NULL request";
82 DCHECK(auth_info_) << "LoginHandler constructed with NULL auth info";
80 83
81 AddRef(); // matched by ReleaseSoon::ReleaseSoon(). 84 AddRef(); // matched by ReleaseSoon::ReleaseSoon().
85
86 ChromeThread::PostTask(
87 ChromeThread::UI, FROM_HERE,
88 NewRunnableMethod(this, &LoginHandler::AddObservers));
89
82 if (!ResourceDispatcherHost::RenderViewForRequest( 90 if (!ResourceDispatcherHost::RenderViewForRequest(
83 request_, &render_process_host_id_, &tab_contents_id_)) { 91 request_, &render_process_host_id_, &tab_contents_id_)) {
84 NOTREACHED(); 92 NOTREACHED();
85 } 93 }
86 } 94 }
87 95
88 LoginHandler::~LoginHandler() { 96 LoginHandler::~LoginHandler() {
89 SetModel(NULL); 97 SetModel(NULL);
90 } 98 }
91 99
(...skipping 22 matching lines...) Expand all
114 password_form_.username_value = WideToUTF16Hack(username); 122 password_form_.username_value = WideToUTF16Hack(username);
115 password_form_.password_value = WideToUTF16Hack(password); 123 password_form_.password_value = WideToUTF16Hack(password);
116 password_manager_->ProvisionallySavePassword(password_form_); 124 password_manager_->ProvisionallySavePassword(password_form_);
117 } 125 }
118 126
119 ChromeThread::PostTask( 127 ChromeThread::PostTask(
120 ChromeThread::UI, FROM_HERE, 128 ChromeThread::UI, FROM_HERE,
121 NewRunnableMethod(this, &LoginHandler::CloseContentsDeferred)); 129 NewRunnableMethod(this, &LoginHandler::CloseContentsDeferred));
122 ChromeThread::PostTask( 130 ChromeThread::PostTask(
123 ChromeThread::UI, FROM_HERE, 131 ChromeThread::UI, FROM_HERE,
124 NewRunnableMethod(this, &LoginHandler::SendNotifications)); 132 NewRunnableMethod(
133 this, &LoginHandler::NotifyAuthSupplied, username, password));
125 ChromeThread::PostTask( 134 ChromeThread::PostTask(
126 ChromeThread::IO, FROM_HERE, 135 ChromeThread::IO, FROM_HERE,
127 NewRunnableMethod(this, &LoginHandler::SetAuthDeferred, 136 NewRunnableMethod(
128 username, password)); 137 this, &LoginHandler::SetAuthDeferred, username, password));
129 } 138 }
130 139
131 void LoginHandler::CancelAuth() { 140 void LoginHandler::CancelAuth() {
132 if (WasAuthHandled(true)) 141 if (WasAuthHandled(true))
133 return; 142 return;
134 143
135 ChromeThread::PostTask( 144 ChromeThread::PostTask(
136 ChromeThread::UI, FROM_HERE, 145 ChromeThread::UI, FROM_HERE,
137 NewRunnableMethod(this, &LoginHandler::CloseContentsDeferred)); 146 NewRunnableMethod(this, &LoginHandler::CloseContentsDeferred));
138 ChromeThread::PostTask( 147 ChromeThread::PostTask(
139 ChromeThread::UI, FROM_HERE, 148 ChromeThread::UI, FROM_HERE,
140 NewRunnableMethod(this, &LoginHandler::SendNotifications)); 149 NewRunnableMethod(this, &LoginHandler::NotifyAuthCancelled));
141 ChromeThread::PostTask( 150 ChromeThread::PostTask(
142 ChromeThread::IO, FROM_HERE, 151 ChromeThread::IO, FROM_HERE,
143 NewRunnableMethod(this, &LoginHandler::CancelAuthDeferred)); 152 NewRunnableMethod(this, &LoginHandler::CancelAuthDeferred));
144 } 153 }
145 154
146 void LoginHandler::OnRequestCancelled() { 155 void LoginHandler::OnRequestCancelled() {
147 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)) << 156 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)) <<
148 "Why is OnRequestCancelled called from the UI thread?"; 157 "Why is OnRequestCancelled called from the UI thread?";
149 158
150 // Reference is no longer valid. 159 // Reference is no longer valid.
151 request_ = NULL; 160 request_ = NULL;
152 161
153 // Give up on auth if the request was cancelled. 162 // Give up on auth if the request was cancelled.
154 CancelAuth(); 163 CancelAuth();
155 } 164 }
156 165
166 void LoginHandler::AddObservers() {
167 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
168
169 registrar_.Add(this, NotificationType::AUTH_SUPPLIED,
170 NotificationService::AllSources());
171 registrar_.Add(this, NotificationType::AUTH_CANCELLED,
172 NotificationService::AllSources());
173 }
174
175 void LoginHandler::RemoveObservers() {
176 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
177
178 registrar_.Remove(this, NotificationType::AUTH_SUPPLIED,
179 NotificationService::AllSources());
180 registrar_.Remove(this, NotificationType::AUTH_CANCELLED,
181 NotificationService::AllSources());
182
183 DCHECK(registrar_.IsEmpty());
184 }
185
186 void LoginHandler::Observe(NotificationType type,
187 const NotificationSource& source,
188 const NotificationDetails& details) {
189 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
190 DCHECK(type == NotificationType::AUTH_SUPPLIED ||
191 type == NotificationType::AUTH_CANCELLED);
192
193 TabContents* requesting_contents = GetTabContentsForLogin();
194 if (!requesting_contents)
195 return;
196
197 NavigationController* this_controller = &requesting_contents->controller();
198 NavigationController* that_controller =
199 Source<NavigationController>(source).ptr();
200
201 // Only handle notifications from other handlers.
202 if (this_controller == that_controller)
203 return;
204
205 LoginNotificationDetails* login_details =
206 Details<LoginNotificationDetails>(details).ptr();
207
208 // Only handle notification for the identical auth info.
209 if (*login_details->handler()->auth_info() != *auth_info())
210 return;
211
212 // Set or cancel the auth in this handler.
213 if (type == NotificationType::AUTH_SUPPLIED) {
214 AuthSuppliedLoginNotificationDetails* supplied_details =
215 Details<AuthSuppliedLoginNotificationDetails>(details).ptr();
216 SetAuth(supplied_details->username(), supplied_details->password());
217 } else {
218 DCHECK(type == NotificationType::AUTH_CANCELLED);
219 CancelAuth();
220 }
221 }
222
157 void LoginHandler::SetModel(LoginModel* model) { 223 void LoginHandler::SetModel(LoginModel* model) {
158 if (login_model_) 224 if (login_model_)
159 login_model_->SetObserver(NULL); 225 login_model_->SetObserver(NULL);
160 login_model_ = model; 226 login_model_ = model;
161 if (login_model_) 227 if (login_model_)
162 login_model_->SetObserver(this); 228 login_model_->SetObserver(this);
163 } 229 }
164 230
165 void LoginHandler::SetDialog(ConstrainedWindow* dialog) { 231 void LoginHandler::SetDialog(ConstrainedWindow* dialog) {
166 dialog_ = dialog; 232 dialog_ = dialog;
167 } 233 }
168 234
169 // Notify observers that authentication is needed or received. The automation 235 void LoginHandler::NotifyAuthNeeded() {
170 // proxy uses this for testing.
171 void LoginHandler::SendNotifications() {
172 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 236 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
237 if (WasAuthHandled(false))
238 return;
173 239
174 NotificationService* service = NotificationService::current();
175 TabContents* requesting_contents = GetTabContentsForLogin(); 240 TabContents* requesting_contents = GetTabContentsForLogin();
176 if (!requesting_contents) 241 if (!requesting_contents)
177 return; 242 return;
178 243
244 NotificationService* service = NotificationService::current();
179 NavigationController* controller = &requesting_contents->controller(); 245 NavigationController* controller = &requesting_contents->controller();
246 LoginNotificationDetails details(this);
180 247
181 if (!WasAuthHandled(false)) { 248 service->Notify(NotificationType::AUTH_NEEDED,
182 LoginNotificationDetails details(this); 249 Source<NavigationController>(controller),
183 service->Notify(NotificationType::AUTH_NEEDED, 250 Details<LoginNotificationDetails>(&details));
184 Source<NavigationController>(controller), 251 }
185 Details<LoginNotificationDetails>(&details)); 252
186 } else { 253 void LoginHandler::NotifyAuthCancelled() {
187 service->Notify(NotificationType::AUTH_SUPPLIED, 254 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
188 Source<NavigationController>(controller), 255 DCHECK(WasAuthHandled(false));
189 NotificationService::NoDetails()); 256
190 } 257 TabContents* requesting_contents = GetTabContentsForLogin();
258 if (!requesting_contents)
259 return;
260
261 NotificationService* service = NotificationService::current();
262 NavigationController* controller = &requesting_contents->controller();
263 LoginNotificationDetails details(this);
264
265 service->Notify(NotificationType::AUTH_CANCELLED,
266 Source<NavigationController>(controller),
267 Details<LoginNotificationDetails>(&details));
268 }
269
270 void LoginHandler::NotifyAuthSupplied(const std::wstring& username,
271 const std::wstring& password) {
272 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
273 DCHECK(WasAuthHandled(false));
274
275 TabContents* requesting_contents = GetTabContentsForLogin();
276 if (!requesting_contents)
277 return;
278
279 NotificationService* service = NotificationService::current();
280 NavigationController* controller = &requesting_contents->controller();
281 AuthSuppliedLoginNotificationDetails details(this, username, password);
282
283 service->Notify(NotificationType::AUTH_SUPPLIED,
284 Source<NavigationController>(controller),
285 Details<AuthSuppliedLoginNotificationDetails>(&details));
191 } 286 }
192 287
193 void LoginHandler::ReleaseSoon() { 288 void LoginHandler::ReleaseSoon() {
194 if (!WasAuthHandled(true)) { 289 if (!WasAuthHandled(true)) {
195 ChromeThread::PostTask( 290 ChromeThread::PostTask(
196 ChromeThread::IO, FROM_HERE, 291 ChromeThread::IO, FROM_HERE,
197 NewRunnableMethod(this, &LoginHandler::CancelAuthDeferred)); 292 NewRunnableMethod(this, &LoginHandler::CancelAuthDeferred));
198 ChromeThread::PostTask( 293 ChromeThread::PostTask(
199 ChromeThread::UI, FROM_HERE, 294 ChromeThread::UI, FROM_HERE,
200 NewRunnableMethod(this, &LoginHandler::SendNotifications)); 295 NewRunnableMethod(this, &LoginHandler::NotifyAuthCancelled));
201 } 296 }
202 297
298 ChromeThread::PostTask(
299 ChromeThread::UI, FROM_HERE,
300 NewRunnableMethod(this, &LoginHandler::RemoveObservers));
301
203 // Delete this object once all InvokeLaters have been called. 302 // Delete this object once all InvokeLaters have been called.
204 ChromeThread::ReleaseSoon(ChromeThread::IO, FROM_HERE, this); 303 ChromeThread::ReleaseSoon(ChromeThread::IO, FROM_HERE, this);
205 } 304 }
206 305
207 // Returns whether authentication had been handled (SetAuth or CancelAuth). 306 // Returns whether authentication had been handled (SetAuth or CancelAuth).
208 // If |set_handled| is true, it will mark authentication as handled. 307 // If |set_handled| is true, it will mark authentication as handled.
209 bool LoginHandler::WasAuthHandled(bool set_handled) { 308 bool LoginHandler::WasAuthHandled(bool set_handled) {
210 AutoLock lock(handled_auth_lock_); 309 AutoLock lock(handled_auth_lock_);
211 bool was_handled = handled_auth_; 310 bool was_handled = handled_auth_;
212 if (set_handled) 311 if (set_handled)
(...skipping 11 matching lines...) Expand all
224 ResetLoginHandlerForRequest(request_); 323 ResetLoginHandlerForRequest(request_);
225 } 324 }
226 } 325 }
227 326
228 // Calls CancelAuth from the IO loop. 327 // Calls CancelAuth from the IO loop.
229 void LoginHandler::CancelAuthDeferred() { 328 void LoginHandler::CancelAuthDeferred() {
230 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); 329 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
231 330
232 if (request_) { 331 if (request_) {
233 request_->CancelAuth(); 332 request_->CancelAuth();
234 // Verify that CancelAuth does destroy the request via our delegate. 333 // Verify that CancelAuth doesn't destroy the request via our delegate.
235 DCHECK(request_ != NULL); 334 DCHECK(request_ != NULL);
236 ResetLoginHandlerForRequest(request_); 335 ResetLoginHandlerForRequest(request_);
237 } 336 }
238 } 337 }
239 338
240 // Closes the view_contents from the UI loop. 339 // Closes the view_contents from the UI loop.
241 void LoginHandler::CloseContentsDeferred() { 340 void LoginHandler::CloseContentsDeferred() {
242 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 341 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
243 342
244 // The hosting ConstrainedWindow may have been freed. 343 // The hosting ConstrainedWindow may have been freed.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 if (LowerCaseEqualsASCII(auth_info_->scheme, "basic")) { 395 if (LowerCaseEqualsASCII(auth_info_->scheme, "basic")) {
297 dialog_form.scheme = PasswordForm::SCHEME_BASIC; 396 dialog_form.scheme = PasswordForm::SCHEME_BASIC;
298 } else if (LowerCaseEqualsASCII(auth_info_->scheme, "digest")) { 397 } else if (LowerCaseEqualsASCII(auth_info_->scheme, "digest")) {
299 dialog_form.scheme = PasswordForm::SCHEME_DIGEST; 398 dialog_form.scheme = PasswordForm::SCHEME_DIGEST;
300 } else { 399 } else {
301 dialog_form.scheme = PasswordForm::SCHEME_OTHER; 400 dialog_form.scheme = PasswordForm::SCHEME_OTHER;
302 } 401 }
303 std::string host_and_port(WideToASCII(auth_info_->host_and_port)); 402 std::string host_and_port(WideToASCII(auth_info_->host_and_port));
304 if (net::GetHostAndPort(request_url_) != host_and_port) { 403 if (net::GetHostAndPort(request_url_) != host_and_port) {
305 dialog_form.origin = GURL(); 404 dialog_form.origin = GURL();
306 NOTREACHED(); 405 NOTREACHED(); // crbug.com/32718
307 } else if (auth_info_->is_proxy) { 406 } else if (auth_info_->is_proxy) {
308 std::string origin = host_and_port; 407 std::string origin = host_and_port;
309 // We don't expect this to already start with http:// or https://. 408 // We don't expect this to already start with http:// or https://.
310 DCHECK(origin.find("http://") != 0 && origin.find("https://") != 0); 409 DCHECK(origin.find("http://") != 0 && origin.find("https://") != 0);
311 origin = std::string("http://") + origin; 410 origin = std::string("http://") + origin;
312 dialog_form.origin = GURL(origin); 411 dialog_form.origin = GURL(origin);
313 } else { 412 } else {
314 dialog_form.origin = GURL(request_url_.scheme() + "://" + host_and_port); 413 dialog_form.origin = GURL(request_url_.scheme() + "://" + host_and_port);
315 } 414 }
316 dialog_form.signon_realm = GetSignonRealm(dialog_form.origin, *auth_info_); 415 dialog_form.signon_realm = GetSignonRealm(dialog_form.origin, *auth_info_);
317 password_manager_input->push_back(dialog_form); 416 password_manager_input->push_back(dialog_form);
318 // Set the password form for the handler (by copy). 417 // Set the password form for the handler (by copy).
319 handler_->SetPasswordForm(dialog_form); 418 handler_->SetPasswordForm(dialog_form);
320 } 419 }
321 420
322 // The url from the URLRequest initiating the auth challenge. 421 // The url from the URLRequest initiating the auth challenge.
323 GURL request_url_; 422 GURL request_url_;
324 423
325 // Info about who/where/what is asking for authentication. 424 // Info about who/where/what is asking for authentication.
326 scoped_refptr<net::AuthChallengeInfo> auth_info_; 425 scoped_refptr<net::AuthChallengeInfo> auth_info_;
327 426
328 // Where to send the authentication when obtained. 427 // Where to send the authentication when obtained.
329 // This is owned by the ResourceDispatcherHost that invoked us. 428 // This is owned by the ResourceDispatcherHost that invoked us.
330 LoginHandler* handler_; 429 LoginHandler* handler_;
331 430
332 DISALLOW_EVIL_CONSTRUCTORS(LoginDialogTask); 431 DISALLOW_COPY_AND_ASSIGN(LoginDialogTask);
333 }; 432 };
334 433
335 // ---------------------------------------------------------------------------- 434 // ----------------------------------------------------------------------------
336 // Public API 435 // Public API
337 436
338 LoginHandler* CreateLoginPrompt(net::AuthChallengeInfo* auth_info, 437 LoginHandler* CreateLoginPrompt(net::AuthChallengeInfo* auth_info,
339 URLRequest* request) { 438 URLRequest* request) {
340 LoginHandler* handler = LoginHandler::Create(request); 439 LoginHandler* handler = LoginHandler::Create(auth_info, request);
341 ChromeThread::PostTask( 440 ChromeThread::PostTask(
342 ChromeThread::UI, FROM_HERE, new LoginDialogTask( 441 ChromeThread::UI, FROM_HERE, new LoginDialogTask(
343 request->url(), auth_info, handler)); 442 request->url(), auth_info, handler));
344 return handler; 443 return handler;
345 } 444 }
OLDNEW
« no previous file with comments | « chrome/browser/login_prompt.h ('k') | chrome/browser/login_prompt_gtk.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698