Chromium Code Reviews| 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 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 138 } | 137 } |
| 139 | 138 |
| 140 WebContents* LoginHandler::GetWebContentsForLogin() const { | 139 WebContents* LoginHandler::GetWebContentsForLogin() const { |
| 141 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 140 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 142 | 141 |
| 143 content::RenderFrameHost* rfh = content::RenderFrameHost::FromID( | 142 content::RenderFrameHost* rfh = content::RenderFrameHost::FromID( |
| 144 render_process_host_id_, render_frame_id_); | 143 render_process_host_id_, render_frame_id_); |
| 145 return WebContents::FromRenderFrameHost(rfh); | 144 return WebContents::FromRenderFrameHost(rfh); |
| 146 } | 145 } |
| 147 | 146 |
| 148 password_manager::ContentPasswordManagerDriver* | 147 password_manager::PasswordManager* LoginHandler::GetPasswordManagerForLogin() { |
| 149 LoginHandler::GetPasswordManagerDriverForLogin() { | 148 ChromePasswordManagerClient* client = |
| 150 content::RenderFrameHost* rfh = content::RenderFrameHost::FromID( | 149 ChromePasswordManagerClient::FromWebContents(GetWebContentsForLogin()); |
| 151 render_process_host_id_, render_frame_id_); | 150 if (!client) |
| 152 return password_manager::ContentPasswordManagerDriver::GetForRenderFrameHost( | 151 return nullptr; |
| 153 rfh); | 152 return client->GetPasswordManager(); |
|
Peter Kasting
2015/10/06 22:14:49
Nit: Shorter:
return client ? client->GetPasswo
vabr (Chromium)
2015/10/07 10:29:22
Done.
| |
| 154 } | 153 } |
| 155 | 154 |
| 156 void LoginHandler::SetAuth(const base::string16& username, | 155 void LoginHandler::SetAuth(const base::string16& username, |
| 157 const base::string16& password) { | 156 const base::string16& password) { |
| 158 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 157 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 159 | 158 |
| 160 scoped_ptr<password_manager::BrowserSavePasswordProgressLogger> logger; | 159 scoped_ptr<password_manager::BrowserSavePasswordProgressLogger> logger; |
| 161 if (password_manager_ && password_manager_->client()->IsLoggingActive()) { | 160 if (password_manager_ && password_manager_->client()->IsLoggingActive()) { |
| 162 logger.reset(new password_manager::BrowserSavePasswordProgressLogger( | 161 logger.reset(new password_manager::BrowserSavePasswordProgressLogger( |
| 163 password_manager_->client())); | 162 password_manager_->client())); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 267 } | 266 } |
| 268 | 267 |
| 269 // Returns whether authentication had been handled (SetAuth or CancelAuth). | 268 // Returns whether authentication had been handled (SetAuth or CancelAuth). |
| 270 bool LoginHandler::WasAuthHandled() const { | 269 bool LoginHandler::WasAuthHandled() const { |
| 271 base::AutoLock lock(handled_auth_lock_); | 270 base::AutoLock lock(handled_auth_lock_); |
| 272 bool was_handled = handled_auth_; | 271 bool was_handled = handled_auth_; |
| 273 return was_handled; | 272 return was_handled; |
| 274 } | 273 } |
| 275 | 274 |
| 276 LoginHandler::~LoginHandler() { | 275 LoginHandler::~LoginHandler() { |
| 277 SetModel(NULL); | 276 SetModel(nullptr, nullptr); |
| 278 } | 277 } |
| 279 | 278 |
| 280 void LoginHandler::SetModel(password_manager::LoginModel* model) { | 279 void LoginHandler::SetModel(password_manager::LoginModel* model, |
| 280 const autofill::PasswordForm* observed_form) { | |
| 281 DCHECK_EQ(model == nullptr, observed_form == nullptr); | |
| 281 if (login_model_) | 282 if (login_model_) |
| 282 login_model_->RemoveObserver(this); | 283 login_model_->RemoveObserver(this); |
| 283 login_model_ = model; | 284 login_model_ = model; |
| 284 if (login_model_) | 285 if (login_model_) |
| 285 login_model_->AddObserver(this); | 286 login_model_->AddObserverAndDeliverCredentials(this, *observed_form); |
| 286 } | 287 } |
| 287 | 288 |
| 288 void LoginHandler::NotifyAuthNeeded() { | 289 void LoginHandler::NotifyAuthNeeded() { |
| 289 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 290 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 290 if (WasAuthHandled()) | 291 if (WasAuthHandled()) |
| 291 return; | 292 return; |
| 292 | 293 |
| 293 content::NotificationService* service = | 294 content::NotificationService* service = |
| 294 content::NotificationService::current(); | 295 content::NotificationService::current(); |
| 295 NavigationController* controller = NULL; | 296 NavigationController* controller = NULL; |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 422 if (!requesting_contents) | 423 if (!requesting_contents) |
| 423 return; | 424 return; |
| 424 // If a (blank) login interstitial was displayed, proceed so that the | 425 // If a (blank) login interstitial was displayed, proceed so that the |
| 425 // navigation is committed. | 426 // navigation is committed. |
| 426 content::InterstitialPage* interstitial_page = | 427 content::InterstitialPage* interstitial_page = |
| 427 requesting_contents->GetInterstitialPage(); | 428 requesting_contents->GetInterstitialPage(); |
| 428 if (interstitial_page) | 429 if (interstitial_page) |
| 429 interstitial_page->Proceed(); | 430 interstitial_page->Proceed(); |
| 430 } | 431 } |
| 431 | 432 |
| 432 // Helper to create a PasswordForm and stuff it into a vector as input | 433 // Helper to create a PasswordForm for PasswordManager to start looking for |
| 433 // for PasswordManager::PasswordFormsParsed, the hook into PasswordManager. | 434 // saved credentials. |
| 434 void MakeInputForPasswordManager( | 435 PasswordForm MakeInputForPasswordManager(const GURL& request_url, |
| 435 const GURL& request_url, | 436 net::AuthChallengeInfo* auth_info, |
| 436 net::AuthChallengeInfo* auth_info, | 437 LoginHandler* handler) { |
| 437 LoginHandler* handler, | |
| 438 std::vector<PasswordForm>* password_manager_input) { | |
| 439 PasswordForm dialog_form; | 438 PasswordForm dialog_form; |
| 440 if (base::LowerCaseEqualsASCII(auth_info->scheme, "basic")) { | 439 if (base::LowerCaseEqualsASCII(auth_info->scheme, "basic")) { |
| 441 dialog_form.scheme = PasswordForm::SCHEME_BASIC; | 440 dialog_form.scheme = PasswordForm::SCHEME_BASIC; |
| 442 } else if (base::LowerCaseEqualsASCII(auth_info->scheme, "digest")) { | 441 } else if (base::LowerCaseEqualsASCII(auth_info->scheme, "digest")) { |
| 443 dialog_form.scheme = PasswordForm::SCHEME_DIGEST; | 442 dialog_form.scheme = PasswordForm::SCHEME_DIGEST; |
| 444 } else { | 443 } else { |
| 445 dialog_form.scheme = PasswordForm::SCHEME_OTHER; | 444 dialog_form.scheme = PasswordForm::SCHEME_OTHER; |
| 446 } | 445 } |
| 447 std::string host_and_port(auth_info->challenger.ToString()); | 446 std::string host_and_port(auth_info->challenger.ToString()); |
| 448 if (auth_info->is_proxy) { | 447 if (auth_info->is_proxy) { |
| 449 std::string origin = host_and_port; | 448 std::string origin = host_and_port; |
| 450 // We don't expect this to already start with http:// or https://. | 449 // We don't expect this to already start with http:// or https://. |
| 451 DCHECK(origin.find("http://") != 0 && origin.find("https://") != 0); | 450 DCHECK(origin.find("http://") != 0 && origin.find("https://") != 0); |
| 452 origin = std::string("http://") + origin; | 451 origin = std::string("http://") + origin; |
| 453 dialog_form.origin = GURL(origin); | 452 dialog_form.origin = GURL(origin); |
| 454 } else if (!auth_info->challenger.Equals( | 453 } else if (!auth_info->challenger.Equals( |
| 455 net::HostPortPair::FromURL(request_url))) { | 454 net::HostPortPair::FromURL(request_url))) { |
| 456 dialog_form.origin = GURL(); | 455 dialog_form.origin = GURL(); |
| 457 NOTREACHED(); // crbug.com/32718 | 456 NOTREACHED(); // crbug.com/32718 |
| 458 } else { | 457 } else { |
| 459 dialog_form.origin = GURL(request_url.scheme() + "://" + host_and_port); | 458 dialog_form.origin = GURL(request_url.scheme() + "://" + host_and_port); |
| 460 } | 459 } |
| 461 dialog_form.signon_realm = GetSignonRealm(dialog_form.origin, *auth_info); | 460 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). | 461 // Set the password form for the handler (by copy). |
| 464 handler->SetPasswordForm(dialog_form); | 462 handler->SetPasswordForm(dialog_form); |
| 463 return dialog_form; | |
| 465 } | 464 } |
| 466 | 465 |
| 467 void ShowLoginPrompt(const GURL& request_url, | 466 void ShowLoginPrompt(const GURL& request_url, |
| 468 net::AuthChallengeInfo* auth_info, | 467 net::AuthChallengeInfo* auth_info, |
| 469 LoginHandler* handler) { | 468 LoginHandler* handler) { |
| 470 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 469 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 471 WebContents* parent_contents = handler->GetWebContentsForLogin(); | 470 WebContents* parent_contents = handler->GetWebContentsForLogin(); |
| 472 if (!parent_contents) | 471 if (!parent_contents) |
| 473 return; | 472 return; |
| 474 prerender::PrerenderContents* prerender_contents = | 473 prerender::PrerenderContents* prerender_contents = |
| 475 prerender::PrerenderContents::FromWebContents(parent_contents); | 474 prerender::PrerenderContents::FromWebContents(parent_contents); |
| 476 if (prerender_contents) { | 475 if (prerender_contents) { |
| 477 prerender_contents->Destroy(prerender::FINAL_STATUS_AUTH_NEEDED); | 476 prerender_contents->Destroy(prerender::FINAL_STATUS_AUTH_NEEDED); |
| 478 return; | 477 return; |
| 479 } | 478 } |
| 480 | 479 |
| 481 password_manager::ContentPasswordManagerDriver* driver = | |
| 482 handler->GetPasswordManagerDriverForLogin(); | |
| 483 | |
| 484 // The realm is controlled by the remote server, so there is no reason | 480 // The realm is controlled by the remote server, so there is no reason |
| 485 // to believe it is of a reasonable length. | 481 // to believe it is of a reasonable length. |
| 486 base::string16 elided_realm; | 482 base::string16 elided_realm; |
| 487 gfx::ElideString(base::UTF8ToUTF16(auth_info->realm), 120, &elided_realm); | 483 gfx::ElideString(base::UTF8ToUTF16(auth_info->realm), 120, &elided_realm); |
| 488 | 484 |
| 489 std::string languages; | 485 std::string languages; |
| 490 content::WebContents* web_contents = handler->GetWebContentsForLogin(); | 486 content::WebContents* web_contents = handler->GetWebContentsForLogin(); |
| 491 if (web_contents) { | 487 if (web_contents) { |
| 492 Profile* profile = | 488 Profile* profile = |
| 493 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 489 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
| 494 if (profile) | 490 if (profile) |
| 495 languages = profile->GetPrefs()->GetString(prefs::kAcceptLanguages); | 491 languages = profile->GetPrefs()->GetString(prefs::kAcceptLanguages); |
| 496 } | 492 } |
| 497 | 493 |
| 498 base::string16 authority = | 494 base::string16 authority = |
| 499 url_formatter::FormatUrlForSecurityDisplay(request_url, languages); | 495 url_formatter::FormatUrlForSecurityDisplay(request_url, languages); |
| 500 base::string16 explanation = | 496 base::string16 explanation = |
| 501 elided_realm.empty() | 497 elided_realm.empty() |
| 502 ? l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION_NO_REALM, | 498 ? l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION_NO_REALM, |
| 503 authority) | 499 authority) |
| 504 : l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION, authority, | 500 : l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION, authority, |
| 505 elided_realm); | 501 elided_realm); |
| 506 | 502 |
| 507 if (!driver) { | 503 password_manager::PasswordManager* password_manager = |
| 504 handler->GetPasswordManagerForLogin(); | |
| 505 | |
| 506 if (!password_manager) { | |
| 508 #if defined(ENABLE_EXTENSIONS) | 507 #if defined(ENABLE_EXTENSIONS) |
| 509 // A WebContents in a <webview> (a GuestView type) does not have a password | 508 // 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. | 509 // manager, but still needs to be able to show login prompts. |
| 511 if (guest_view::GuestViewBase::FromWebContents(parent_contents)) { | 510 if (guest_view::GuestViewBase::FromWebContents(parent_contents)) { |
| 512 handler->BuildViewForPasswordManager(nullptr, explanation); | 511 handler->BuildViewForPasswordManager(nullptr, explanation, nullptr); |
| 513 return; | 512 return; |
| 514 } | 513 } |
| 515 #endif | 514 #endif |
| 516 handler->CancelAuth(); | 515 handler->CancelAuth(); |
| 517 return; | 516 return; |
| 518 } | 517 } |
| 519 | 518 |
| 520 password_manager::PasswordManager* password_manager = | |
| 521 driver->GetPasswordManager(); | |
| 522 if (password_manager && password_manager->client()->IsLoggingActive()) { | 519 if (password_manager && password_manager->client()->IsLoggingActive()) { |
| 523 password_manager::BrowserSavePasswordProgressLogger logger( | 520 password_manager::BrowserSavePasswordProgressLogger logger( |
| 524 password_manager->client()); | 521 password_manager->client()); |
| 525 logger.LogMessage( | 522 logger.LogMessage( |
| 526 autofill::SavePasswordProgressLogger::STRING_SHOW_LOGIN_PROMPT_METHOD); | 523 autofill::SavePasswordProgressLogger::STRING_SHOW_LOGIN_PROMPT_METHOD); |
| 527 } | 524 } |
| 528 | 525 |
| 529 // Tell the password manager to look for saved passwords. | 526 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 | 527 |
| 535 handler->BuildViewForPasswordManager(driver->GetPasswordManager(), | 528 PasswordForm observed_form( |
| 536 explanation); | 529 MakeInputForPasswordManager(request_url, auth_info, handler)); |
| 530 handler->BuildViewForPasswordManager(password_manager, explanation, | |
| 531 &observed_form); | |
| 537 } | 532 } |
| 538 | 533 |
| 539 // This callback is run on the UI thread and creates a constrained window with | 534 // 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 | 535 // 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 | 536 // 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 | 537 // 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 | 538 // 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. | 539 // LoginHandler, which then routes it to the net::URLRequest on the I/O thread. |
| 545 void LoginDialogCallback(const GURL& request_url, | 540 void LoginDialogCallback(const GURL& request_url, |
| 546 net::AuthChallengeInfo* auth_info, | 541 net::AuthChallengeInfo* auth_info, |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 600 net::URLRequest* request) { | 595 net::URLRequest* request) { |
| 601 bool is_main_frame = (request->load_flags() & net::LOAD_MAIN_FRAME) != 0; | 596 bool is_main_frame = (request->load_flags() & net::LOAD_MAIN_FRAME) != 0; |
| 602 LoginHandler* handler = LoginHandler::Create(auth_info, request); | 597 LoginHandler* handler = LoginHandler::Create(auth_info, request); |
| 603 BrowserThread::PostTask( | 598 BrowserThread::PostTask( |
| 604 BrowserThread::UI, FROM_HERE, | 599 BrowserThread::UI, FROM_HERE, |
| 605 base::Bind(&LoginDialogCallback, request->url(), | 600 base::Bind(&LoginDialogCallback, request->url(), |
| 606 make_scoped_refptr(auth_info), make_scoped_refptr(handler), | 601 make_scoped_refptr(auth_info), make_scoped_refptr(handler), |
| 607 is_main_frame)); | 602 is_main_frame)); |
| 608 return handler; | 603 return handler; |
| 609 } | 604 } |
| OLD | NEW |