OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/prefs/pref_service.h" | 12 #include "base/prefs/pref_service.h" |
13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
15 #include "base/synchronization/lock.h" | 15 #include "base/synchronization/lock.h" |
16 #include "chrome/browser/chrome_notification_types.h" | 16 #include "chrome/browser/chrome_notification_types.h" |
17 #include "chrome/browser/password_manager/chrome_password_manager_client.h" | 17 #include "chrome/browser/password_manager/chrome_password_manager_client.h" |
18 #include "chrome/browser/prerender/prerender_contents.h" | 18 #include "chrome/browser/prerender/prerender_contents.h" |
19 #include "chrome/browser/profiles/profile.h" | 19 #include "chrome/browser/profiles/profile.h" |
20 #include "chrome/browser/tab_contents/tab_util.h" | 20 #include "chrome/browser/tab_contents/tab_util.h" |
21 #include "chrome/browser/ui/login/login_interstitial_delegate.h" | 21 #include "chrome/browser/ui/login/login_interstitial_delegate.h" |
22 #include "chrome/common/pref_names.h" | 22 #include "chrome/common/pref_names.h" |
23 #include "chrome/grit/generated_resources.h" | 23 #include "chrome/grit/generated_resources.h" |
24 #include "components/password_manager/content/browser/content_password_manager_d river.h" | |
25 #include "components/password_manager/core/browser/browser_save_password_progres s_logger.h" | 24 #include "components/password_manager/core/browser/browser_save_password_progres s_logger.h" |
26 #include "components/password_manager/core/browser/password_manager.h" | 25 #include "components/password_manager/core/browser/password_manager.h" |
27 #include "components/url_formatter/elide_url.h" | 26 #include "components/url_formatter/elide_url.h" |
28 #include "content/public/browser/browser_thread.h" | 27 #include "content/public/browser/browser_thread.h" |
29 #include "content/public/browser/notification_registrar.h" | 28 #include "content/public/browser/notification_registrar.h" |
30 #include "content/public/browser/notification_service.h" | 29 #include "content/public/browser/notification_service.h" |
31 #include "content/public/browser/render_frame_host.h" | 30 #include "content/public/browser/render_frame_host.h" |
32 #include "content/public/browser/resource_dispatcher_host.h" | 31 #include "content/public/browser/resource_dispatcher_host.h" |
33 #include "content/public/browser/resource_request_info.h" | 32 #include "content/public/browser/resource_request_info.h" |
34 #include "content/public/browser/web_contents.h" | 33 #include "content/public/browser/web_contents.h" |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
83 signon_realm = url.GetOrigin().spec(); | 82 signon_realm = url.GetOrigin().spec(); |
84 // This ends with a "/". | 83 // This ends with a "/". |
85 } | 84 } |
86 signon_realm.append(auth_info.realm); | 85 signon_realm.append(auth_info.realm); |
87 return signon_realm; | 86 return signon_realm; |
88 } | 87 } |
89 | 88 |
90 // ---------------------------------------------------------------------------- | 89 // ---------------------------------------------------------------------------- |
91 // LoginHandler | 90 // LoginHandler |
92 | 91 |
92 LoginHandler::LoginModelData::LoginModelData( | |
93 password_manager::LoginModel* login_model, | |
94 const autofill::PasswordForm& observed_form) | |
95 : model(login_model), form(observed_form) { | |
96 DCHECK(model); | |
97 } | |
98 | |
93 LoginHandler::LoginHandler(net::AuthChallengeInfo* auth_info, | 99 LoginHandler::LoginHandler(net::AuthChallengeInfo* auth_info, |
94 net::URLRequest* request) | 100 net::URLRequest* request) |
95 : handled_auth_(false), | 101 : handled_auth_(false), |
96 auth_info_(auth_info), | 102 auth_info_(auth_info), |
97 request_(request), | 103 request_(request), |
98 http_network_session_( | 104 http_network_session_( |
99 request_->context()->http_transaction_factory()->GetSession()), | 105 request_->context()->http_transaction_factory()->GetSession()), |
100 password_manager_(NULL), | 106 password_manager_(NULL), |
101 login_model_(NULL) { | 107 login_model_(NULL) { |
102 // This constructor is called on the I/O thread, so we cannot load the nib | 108 // This constructor is called on the I/O thread, so we cannot load the nib |
103 // here. BuildViewForPasswordManager() will be invoked on the UI thread | 109 // here. BuildView() will be invoked on the UI thread later, so wait with |
104 // later, so wait with loading the nib until then. | 110 // loading the nib until then. |
105 DCHECK(request_) << "LoginHandler constructed with NULL request"; | 111 DCHECK(request_) << "LoginHandler constructed with NULL request"; |
106 DCHECK(auth_info_.get()) << "LoginHandler constructed with NULL auth info"; | 112 DCHECK(auth_info_.get()) << "LoginHandler constructed with NULL auth info"; |
107 | 113 |
108 AddRef(); // matched by LoginHandler::ReleaseSoon(). | 114 AddRef(); // matched by LoginHandler::ReleaseSoon(). |
109 | 115 |
110 BrowserThread::PostTask( | 116 BrowserThread::PostTask( |
111 BrowserThread::UI, FROM_HERE, | 117 BrowserThread::UI, FROM_HERE, |
112 base::Bind(&LoginHandler::AddObservers, this)); | 118 base::Bind(&LoginHandler::AddObservers, this)); |
113 | 119 |
114 if (!ResourceRequestInfo::ForRequest(request_)->GetAssociatedRenderFrame( | 120 if (!ResourceRequestInfo::ForRequest(request_)->GetAssociatedRenderFrame( |
(...skipping 23 matching lines...) Expand all Loading... | |
138 } | 144 } |
139 | 145 |
140 WebContents* LoginHandler::GetWebContentsForLogin() const { | 146 WebContents* LoginHandler::GetWebContentsForLogin() const { |
141 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 147 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
142 | 148 |
143 content::RenderFrameHost* rfh = content::RenderFrameHost::FromID( | 149 content::RenderFrameHost* rfh = content::RenderFrameHost::FromID( |
144 render_process_host_id_, render_frame_id_); | 150 render_process_host_id_, render_frame_id_); |
145 return WebContents::FromRenderFrameHost(rfh); | 151 return WebContents::FromRenderFrameHost(rfh); |
146 } | 152 } |
147 | 153 |
148 password_manager::ContentPasswordManagerDriver* | 154 password_manager::PasswordManager* LoginHandler::GetPasswordManagerForLogin() { |
149 LoginHandler::GetPasswordManagerDriverForLogin() { | 155 ChromePasswordManagerClient* client = |
150 content::RenderFrameHost* rfh = content::RenderFrameHost::FromID( | 156 ChromePasswordManagerClient::FromWebContents(GetWebContentsForLogin()); |
151 render_process_host_id_, render_frame_id_); | 157 return client ? client->GetPasswordManager() : nullptr; |
152 return password_manager::ContentPasswordManagerDriver::GetForRenderFrameHost( | |
153 rfh); | |
154 } | 158 } |
155 | 159 |
156 void LoginHandler::SetAuth(const base::string16& username, | 160 void LoginHandler::SetAuth(const base::string16& username, |
157 const base::string16& password) { | 161 const base::string16& password) { |
158 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 162 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
159 | 163 |
160 scoped_ptr<password_manager::BrowserSavePasswordProgressLogger> logger; | 164 scoped_ptr<password_manager::BrowserSavePasswordProgressLogger> logger; |
161 if (password_manager_ && password_manager_->client()->IsLoggingActive()) { | 165 if (password_manager_ && password_manager_->client()->IsLoggingActive()) { |
162 logger.reset(new password_manager::BrowserSavePasswordProgressLogger( | 166 logger.reset(new password_manager::BrowserSavePasswordProgressLogger( |
163 password_manager_->client())); | 167 password_manager_->client())); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
267 } | 271 } |
268 | 272 |
269 // Returns whether authentication had been handled (SetAuth or CancelAuth). | 273 // Returns whether authentication had been handled (SetAuth or CancelAuth). |
270 bool LoginHandler::WasAuthHandled() const { | 274 bool LoginHandler::WasAuthHandled() const { |
271 base::AutoLock lock(handled_auth_lock_); | 275 base::AutoLock lock(handled_auth_lock_); |
272 bool was_handled = handled_auth_; | 276 bool was_handled = handled_auth_; |
273 return was_handled; | 277 return was_handled; |
274 } | 278 } |
275 | 279 |
276 LoginHandler::~LoginHandler() { | 280 LoginHandler::~LoginHandler() { |
277 SetModel(NULL); | 281 ResetModel(); |
278 } | 282 } |
279 | 283 |
280 void LoginHandler::SetModel(password_manager::LoginModel* model) { | 284 void LoginHandler::SetModel(LoginModelData model_data) { |
281 if (login_model_) | 285 if (login_model_) |
282 login_model_->RemoveObserver(this); | 286 login_model_->RemoveObserver(this); |
Peter Kasting
2015/10/07 22:27:07
Nit: I wonder if this should be a call to ResetMod
vabr (Chromium)
2015/10/08 10:24:12
I was considering this, and did not find compellin
| |
283 login_model_ = model; | 287 login_model_ = model_data.model; |
288 login_model_->AddObserverAndDeliverCredentials(this, model_data.form); | |
289 } | |
290 | |
291 void LoginHandler::ResetModel() { | |
284 if (login_model_) | 292 if (login_model_) |
285 login_model_->AddObserver(this); | 293 login_model_->RemoveObserver(this); |
294 login_model_ = nullptr; | |
286 } | 295 } |
287 | 296 |
288 void LoginHandler::NotifyAuthNeeded() { | 297 void LoginHandler::NotifyAuthNeeded() { |
289 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 298 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
290 if (WasAuthHandled()) | 299 if (WasAuthHandled()) |
291 return; | 300 return; |
292 | 301 |
293 content::NotificationService* service = | 302 content::NotificationService* service = |
294 content::NotificationService::current(); | 303 content::NotificationService::current(); |
295 NavigationController* controller = NULL; | 304 NavigationController* controller = NULL; |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
422 if (!requesting_contents) | 431 if (!requesting_contents) |
423 return; | 432 return; |
424 // If a (blank) login interstitial was displayed, proceed so that the | 433 // If a (blank) login interstitial was displayed, proceed so that the |
425 // navigation is committed. | 434 // navigation is committed. |
426 content::InterstitialPage* interstitial_page = | 435 content::InterstitialPage* interstitial_page = |
427 requesting_contents->GetInterstitialPage(); | 436 requesting_contents->GetInterstitialPage(); |
428 if (interstitial_page) | 437 if (interstitial_page) |
429 interstitial_page->Proceed(); | 438 interstitial_page->Proceed(); |
430 } | 439 } |
431 | 440 |
432 // Helper to create a PasswordForm and stuff it into a vector as input | 441 // Helper to create a PasswordForm for PasswordManager to start looking for |
433 // for PasswordManager::PasswordFormsParsed, the hook into PasswordManager. | 442 // saved credentials. |
434 void MakeInputForPasswordManager( | 443 PasswordForm MakeInputForPasswordManager(const GURL& request_url, |
435 const GURL& request_url, | 444 net::AuthChallengeInfo* auth_info, |
436 net::AuthChallengeInfo* auth_info, | 445 LoginHandler* handler) { |
davidben
2015/10/07 23:13:54
(Existing unrelated issue, but this and the two fu
vabr (Chromium)
2015/10/08 10:24:12
Done.
| |
437 LoginHandler* handler, | |
438 std::vector<PasswordForm>* password_manager_input) { | |
439 PasswordForm dialog_form; | 446 PasswordForm dialog_form; |
440 if (base::LowerCaseEqualsASCII(auth_info->scheme, "basic")) { | 447 if (base::LowerCaseEqualsASCII(auth_info->scheme, "basic")) { |
441 dialog_form.scheme = PasswordForm::SCHEME_BASIC; | 448 dialog_form.scheme = PasswordForm::SCHEME_BASIC; |
442 } else if (base::LowerCaseEqualsASCII(auth_info->scheme, "digest")) { | 449 } else if (base::LowerCaseEqualsASCII(auth_info->scheme, "digest")) { |
443 dialog_form.scheme = PasswordForm::SCHEME_DIGEST; | 450 dialog_form.scheme = PasswordForm::SCHEME_DIGEST; |
444 } else { | 451 } else { |
445 dialog_form.scheme = PasswordForm::SCHEME_OTHER; | 452 dialog_form.scheme = PasswordForm::SCHEME_OTHER; |
446 } | 453 } |
447 std::string host_and_port(auth_info->challenger.ToString()); | 454 std::string host_and_port(auth_info->challenger.ToString()); |
448 if (auth_info->is_proxy) { | 455 if (auth_info->is_proxy) { |
449 std::string origin = host_and_port; | 456 std::string origin = host_and_port; |
450 // We don't expect this to already start with http:// or https://. | 457 // We don't expect this to already start with http:// or https://. |
451 DCHECK(origin.find("http://") != 0 && origin.find("https://") != 0); | 458 DCHECK(origin.find("http://") != 0 && origin.find("https://") != 0); |
452 origin = std::string("http://") + origin; | 459 origin = std::string("http://") + origin; |
453 dialog_form.origin = GURL(origin); | 460 dialog_form.origin = GURL(origin); |
454 } else if (!auth_info->challenger.Equals( | 461 } else if (!auth_info->challenger.Equals( |
455 net::HostPortPair::FromURL(request_url))) { | 462 net::HostPortPair::FromURL(request_url))) { |
456 dialog_form.origin = GURL(); | 463 dialog_form.origin = GURL(); |
457 NOTREACHED(); // crbug.com/32718 | 464 NOTREACHED(); // crbug.com/32718 |
458 } else { | 465 } else { |
459 dialog_form.origin = GURL(request_url.scheme() + "://" + host_and_port); | 466 dialog_form.origin = GURL(request_url.scheme() + "://" + host_and_port); |
460 } | 467 } |
461 dialog_form.signon_realm = GetSignonRealm(dialog_form.origin, *auth_info); | 468 dialog_form.signon_realm = GetSignonRealm(dialog_form.origin, *auth_info); |
462 password_manager_input->push_back(dialog_form); | |
463 // Set the password form for the handler (by copy). | 469 // Set the password form for the handler (by copy). |
464 handler->SetPasswordForm(dialog_form); | 470 handler->SetPasswordForm(dialog_form); |
davidben
2015/10/07 23:13:54
(Existing unrelated issue, but it's pretty weird t
vabr (Chromium)
2015/10/08 10:24:12
Done.
| |
471 return dialog_form; | |
465 } | 472 } |
466 | 473 |
467 void ShowLoginPrompt(const GURL& request_url, | 474 void ShowLoginPrompt(const GURL& request_url, |
468 net::AuthChallengeInfo* auth_info, | 475 net::AuthChallengeInfo* auth_info, |
469 LoginHandler* handler) { | 476 LoginHandler* handler) { |
470 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 477 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
471 WebContents* parent_contents = handler->GetWebContentsForLogin(); | 478 WebContents* parent_contents = handler->GetWebContentsForLogin(); |
472 if (!parent_contents) | 479 if (!parent_contents) |
473 return; | 480 return; |
474 prerender::PrerenderContents* prerender_contents = | 481 prerender::PrerenderContents* prerender_contents = |
475 prerender::PrerenderContents::FromWebContents(parent_contents); | 482 prerender::PrerenderContents::FromWebContents(parent_contents); |
476 if (prerender_contents) { | 483 if (prerender_contents) { |
477 prerender_contents->Destroy(prerender::FINAL_STATUS_AUTH_NEEDED); | 484 prerender_contents->Destroy(prerender::FINAL_STATUS_AUTH_NEEDED); |
478 return; | 485 return; |
479 } | 486 } |
480 | 487 |
481 password_manager::ContentPasswordManagerDriver* driver = | |
482 handler->GetPasswordManagerDriverForLogin(); | |
483 | |
484 // The realm is controlled by the remote server, so there is no reason | 488 // The realm is controlled by the remote server, so there is no reason |
485 // to believe it is of a reasonable length. | 489 // to believe it is of a reasonable length. |
486 base::string16 elided_realm; | 490 base::string16 elided_realm; |
487 gfx::ElideString(base::UTF8ToUTF16(auth_info->realm), 120, &elided_realm); | 491 gfx::ElideString(base::UTF8ToUTF16(auth_info->realm), 120, &elided_realm); |
488 | 492 |
489 std::string languages; | 493 std::string languages; |
490 content::WebContents* web_contents = handler->GetWebContentsForLogin(); | 494 content::WebContents* web_contents = handler->GetWebContentsForLogin(); |
491 if (web_contents) { | 495 if (web_contents) { |
492 Profile* profile = | 496 Profile* profile = |
493 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 497 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
494 if (profile) | 498 if (profile) |
495 languages = profile->GetPrefs()->GetString(prefs::kAcceptLanguages); | 499 languages = profile->GetPrefs()->GetString(prefs::kAcceptLanguages); |
496 } | 500 } |
497 | 501 |
498 base::string16 authority = | 502 base::string16 authority = |
499 url_formatter::FormatUrlForSecurityDisplay(request_url, languages); | 503 url_formatter::FormatUrlForSecurityDisplay(request_url, languages); |
500 base::string16 explanation = | 504 base::string16 explanation = |
501 elided_realm.empty() | 505 elided_realm.empty() |
502 ? l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION_NO_REALM, | 506 ? l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION_NO_REALM, |
503 authority) | 507 authority) |
504 : l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION, authority, | 508 : l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION, authority, |
505 elided_realm); | 509 elided_realm); |
506 | 510 |
507 if (!driver) { | 511 password_manager::PasswordManager* password_manager = |
512 handler->GetPasswordManagerForLogin(); | |
513 | |
514 if (!password_manager) { | |
508 #if defined(ENABLE_EXTENSIONS) | 515 #if defined(ENABLE_EXTENSIONS) |
509 // A WebContents in a <webview> (a GuestView type) does not have a password | 516 // A WebContents in a <webview> (a GuestView type) does not have a password |
510 // manager, but still needs to be able to show login prompts. | 517 // manager, but still needs to be able to show login prompts. |
511 if (guest_view::GuestViewBase::FromWebContents(parent_contents)) { | 518 if (guest_view::GuestViewBase::FromWebContents(parent_contents)) { |
512 handler->BuildViewForPasswordManager(nullptr, explanation); | 519 handler->BuildView(explanation, nullptr); |
513 return; | 520 return; |
514 } | 521 } |
515 #endif | 522 #endif |
516 handler->CancelAuth(); | 523 handler->CancelAuth(); |
517 return; | 524 return; |
518 } | 525 } |
519 | 526 |
520 password_manager::PasswordManager* password_manager = | |
521 driver->GetPasswordManager(); | |
522 if (password_manager && password_manager->client()->IsLoggingActive()) { | 527 if (password_manager && password_manager->client()->IsLoggingActive()) { |
523 password_manager::BrowserSavePasswordProgressLogger logger( | 528 password_manager::BrowserSavePasswordProgressLogger logger( |
524 password_manager->client()); | 529 password_manager->client()); |
525 logger.LogMessage( | 530 logger.LogMessage( |
526 autofill::SavePasswordProgressLogger::STRING_SHOW_LOGIN_PROMPT_METHOD); | 531 autofill::SavePasswordProgressLogger::STRING_SHOW_LOGIN_PROMPT_METHOD); |
527 } | 532 } |
528 | 533 |
529 // Tell the password manager to look for saved passwords. | 534 handler->SetPasswordManager(password_manager); |
530 std::vector<PasswordForm> v; | |
531 MakeInputForPasswordManager(request_url, auth_info, handler, &v); | |
532 driver->OnPasswordFormsParsedNoRenderCheck(v); | |
533 handler->SetPasswordManager(driver->GetPasswordManager()); | |
534 | 535 |
535 handler->BuildViewForPasswordManager(driver->GetPasswordManager(), | 536 PasswordForm observed_form( |
536 explanation); | 537 MakeInputForPasswordManager(request_url, auth_info, handler)); |
538 LoginHandler::LoginModelData model_data(password_manager, observed_form); | |
539 handler->BuildView(explanation, &model_data); | |
davidben
2015/10/07 23:13:54
(Existing tangentially-related issue, but it's pre
vabr (Chromium)
2015/10/08 10:24:12
Done.
| |
537 } | 540 } |
538 | 541 |
539 // This callback is run on the UI thread and creates a constrained window with | 542 // This callback is run on the UI thread and creates a constrained window with |
540 // a LoginView to prompt the user. If the prompt is triggered because of | 543 // a LoginView to prompt the user. If the prompt is triggered because of |
541 // a cross origin navigation in the main frame, a blank interstitial is first | 544 // a cross origin navigation in the main frame, a blank interstitial is first |
542 // created which in turn creates the LoginView. Otherwise, a LoginView is | 545 // created which in turn creates the LoginView. Otherwise, a LoginView is |
543 // directly in this callback. In both cases, the response will be sent to | 546 // directly in this callback. In both cases, the response will be sent to |
544 // LoginHandler, which then routes it to the net::URLRequest on the I/O thread. | 547 // LoginHandler, which then routes it to the net::URLRequest on the I/O thread. |
545 void LoginDialogCallback(const GURL& request_url, | 548 void LoginDialogCallback(const GURL& request_url, |
546 net::AuthChallengeInfo* auth_info, | 549 net::AuthChallengeInfo* auth_info, |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
600 net::URLRequest* request) { | 603 net::URLRequest* request) { |
601 bool is_main_frame = (request->load_flags() & net::LOAD_MAIN_FRAME) != 0; | 604 bool is_main_frame = (request->load_flags() & net::LOAD_MAIN_FRAME) != 0; |
602 LoginHandler* handler = LoginHandler::Create(auth_info, request); | 605 LoginHandler* handler = LoginHandler::Create(auth_info, request); |
603 BrowserThread::PostTask( | 606 BrowserThread::PostTask( |
604 BrowserThread::UI, FROM_HERE, | 607 BrowserThread::UI, FROM_HERE, |
605 base::Bind(&LoginDialogCallback, request->url(), | 608 base::Bind(&LoginDialogCallback, request->url(), |
606 make_scoped_refptr(auth_info), make_scoped_refptr(handler), | 609 make_scoped_refptr(auth_info), make_scoped_refptr(handler), |
607 is_main_frame)); | 610 is_main_frame)); |
608 return handler; | 611 return handler; |
609 } | 612 } |
OLD | NEW |