| 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 6ee6149a5426eee6081416010753ca53800e7154..5f8c298c9562d8a7b9ea433a2480b7ea9475138f 100644
|
| --- a/chrome/browser/ui/login/login_prompt.cc
|
| +++ b/chrome/browser/ui/login/login_prompt.cc
|
| @@ -55,6 +55,8 @@ using content::WebContents;
|
|
|
| class LoginHandlerImpl;
|
|
|
| +namespace {
|
| +
|
| // Helper to remove the ref from an net::URLRequest to the LoginHandler.
|
| // Should only be called from the IO thread, since it accesses an
|
| // net::URLRequest.
|
| @@ -62,30 +64,104 @@ void ResetLoginHandlerForRequest(net::URLRequest* request) {
|
| ResourceDispatcherHost::Get()->ClearLoginDelegateForRequest(request);
|
| }
|
|
|
| -// Get the signon_realm under which this auth info should be stored.
|
| -//
|
| -// The format of the signon_realm for proxy auth is:
|
| -// proxy-host/auth-realm
|
| -// The format of the signon_realm for server auth is:
|
| -// url-scheme://url-host[:url-port]/auth-realm
|
| -//
|
| -// Be careful when changing this function, since you could make existing
|
| -// saved logins un-retrievable.
|
| -std::string GetSignonRealm(const GURL& url,
|
| - const net::AuthChallengeInfo& auth_info) {
|
| - std::string signon_realm;
|
| - if (auth_info.is_proxy) {
|
| - signon_realm = auth_info.challenger.ToString();
|
| - signon_realm.append("/");
|
| +// Helper to create a PasswordForm for PasswordManager to start looking for
|
| +// saved credentials.
|
| +PasswordForm MakeInputForPasswordManager(const GURL& request_url,
|
| + net::AuthChallengeInfo* auth_info) {
|
| + PasswordForm dialog_form;
|
| + if (base::LowerCaseEqualsASCII(auth_info->scheme, "basic")) {
|
| + dialog_form.scheme = PasswordForm::SCHEME_BASIC;
|
| + } else if (base::LowerCaseEqualsASCII(auth_info->scheme, "digest")) {
|
| + dialog_form.scheme = PasswordForm::SCHEME_DIGEST;
|
| } else {
|
| - // Take scheme, host, and port from the url.
|
| - signon_realm = url.GetOrigin().spec();
|
| - // This ends with a "/".
|
| + dialog_form.scheme = PasswordForm::SCHEME_OTHER;
|
| }
|
| - signon_realm.append(auth_info.realm);
|
| - return signon_realm;
|
| + std::string host_and_port(auth_info->challenger.ToString());
|
| + if (auth_info->is_proxy) {
|
| + std::string origin = host_and_port;
|
| + // We don't expect this to already start with http:// or https://.
|
| + DCHECK(origin.find("http://") != 0 && origin.find("https://") != 0);
|
| + origin = std::string("http://") + origin;
|
| + dialog_form.origin = GURL(origin);
|
| + } else if (!auth_info->challenger.Equals(
|
| + net::HostPortPair::FromURL(request_url))) {
|
| + dialog_form.origin = GURL();
|
| + NOTREACHED(); // crbug.com/32718
|
| + } else {
|
| + dialog_form.origin = GURL(request_url.scheme() + "://" + host_and_port);
|
| + }
|
| + dialog_form.signon_realm = GetSignonRealm(dialog_form.origin, *auth_info);
|
| + return dialog_form;
|
| }
|
|
|
| +void ShowLoginPrompt(const GURL& request_url,
|
| + net::AuthChallengeInfo* auth_info,
|
| + LoginHandler* handler) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + WebContents* parent_contents = handler->GetWebContentsForLogin();
|
| + if (!parent_contents)
|
| + return;
|
| + prerender::PrerenderContents* prerender_contents =
|
| + prerender::PrerenderContents::FromWebContents(parent_contents);
|
| + if (prerender_contents) {
|
| + prerender_contents->Destroy(prerender::FINAL_STATUS_AUTH_NEEDED);
|
| + return;
|
| + }
|
| +
|
| + // The realm is controlled by the remote server, so there is no reason
|
| + // to believe it is of a reasonable length.
|
| + base::string16 elided_realm;
|
| + gfx::ElideString(base::UTF8ToUTF16(auth_info->realm), 120, &elided_realm);
|
| +
|
| + std::string languages;
|
| + content::WebContents* web_contents = handler->GetWebContentsForLogin();
|
| + if (web_contents) {
|
| + Profile* profile =
|
| + Profile::FromBrowserContext(web_contents->GetBrowserContext());
|
| + if (profile)
|
| + languages = profile->GetPrefs()->GetString(prefs::kAcceptLanguages);
|
| + }
|
| +
|
| + base::string16 authority =
|
| + url_formatter::FormatUrlForSecurityDisplay(request_url, languages);
|
| + base::string16 explanation =
|
| + elided_realm.empty()
|
| + ? l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION_NO_REALM,
|
| + authority)
|
| + : l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION, authority,
|
| + elided_realm);
|
| +
|
| + password_manager::PasswordManager* password_manager =
|
| + handler->GetPasswordManagerForLogin();
|
| +
|
| + if (!password_manager) {
|
| +#if defined(ENABLE_EXTENSIONS)
|
| + // A WebContents in a <webview> (a GuestView type) does not have a password
|
| + // manager, but still needs to be able to show login prompts.
|
| + if (guest_view::GuestViewBase::FromWebContents(parent_contents)) {
|
| + handler->BuildViewWithoutPasswordManager(explanation);
|
| + return;
|
| + }
|
| +#endif
|
| + handler->CancelAuth();
|
| + return;
|
| + }
|
| +
|
| + if (password_manager && password_manager->client()->IsLoggingActive()) {
|
| + password_manager::BrowserSavePasswordProgressLogger logger(
|
| + password_manager->client());
|
| + logger.LogMessage(
|
| + autofill::SavePasswordProgressLogger::STRING_SHOW_LOGIN_PROMPT_METHOD);
|
| + }
|
| +
|
| + PasswordForm observed_form(
|
| + MakeInputForPasswordManager(request_url, auth_info));
|
| + handler->BuildViewWithPasswordManager(explanation, password_manager,
|
| + observed_form);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| // ----------------------------------------------------------------------------
|
| // LoginHandler
|
|
|
| @@ -106,7 +182,7 @@ LoginHandler::LoginHandler(net::AuthChallengeInfo* auth_info,
|
| password_manager_(NULL),
|
| login_model_(NULL) {
|
| // This constructor is called on the I/O thread, so we cannot load the nib
|
| - // here. BuildView() will be invoked on the UI thread later, so wait with
|
| + // here. BuildViewImpl() will be invoked on the UI thread later, so wait with
|
| // loading the nib until then.
|
| DCHECK(request_) << "LoginHandler constructed with NULL request";
|
| DCHECK(auth_info_.get()) << "LoginHandler constructed with NULL auth info";
|
| @@ -134,13 +210,19 @@ void LoginHandler::OnRequestCancelled() {
|
| CancelAuth();
|
| }
|
|
|
| -void LoginHandler::SetPasswordForm(const autofill::PasswordForm& form) {
|
| - password_form_ = form;
|
| +void LoginHandler::BuildViewWithPasswordManager(
|
| + const base::string16& explanation,
|
| + password_manager::PasswordManager* password_manager,
|
| + const autofill::PasswordForm& observed_form) {
|
| + password_manager_ = password_manager;
|
| + password_form_ = observed_form;
|
| + LoginHandler::LoginModelData model_data(password_manager, observed_form);
|
| + BuildViewImpl(explanation, &model_data);
|
| }
|
|
|
| -void LoginHandler::SetPasswordManager(
|
| - password_manager::PasswordManager* password_manager) {
|
| - password_manager_ = password_manager;
|
| +void LoginHandler::BuildViewWithoutPasswordManager(
|
| + const base::string16& explanation) {
|
| + BuildViewImpl(explanation, nullptr);
|
| }
|
|
|
| WebContents* LoginHandler::GetWebContentsForLogin() const {
|
| @@ -282,8 +364,7 @@ LoginHandler::~LoginHandler() {
|
| }
|
|
|
| void LoginHandler::SetModel(LoginModelData model_data) {
|
| - if (login_model_)
|
| - login_model_->RemoveObserver(this);
|
| + ResetModel();
|
| login_model_ = model_data.model;
|
| login_model_->AddObserverAndDeliverCredentials(this, model_data.form);
|
| }
|
| @@ -438,107 +519,6 @@ void LoginHandler::CloseContentsDeferred() {
|
| interstitial_page->Proceed();
|
| }
|
|
|
| -// Helper to create a PasswordForm for PasswordManager to start looking for
|
| -// saved credentials.
|
| -PasswordForm MakeInputForPasswordManager(const GURL& request_url,
|
| - net::AuthChallengeInfo* auth_info,
|
| - LoginHandler* handler) {
|
| - PasswordForm dialog_form;
|
| - if (base::LowerCaseEqualsASCII(auth_info->scheme, "basic")) {
|
| - dialog_form.scheme = PasswordForm::SCHEME_BASIC;
|
| - } else if (base::LowerCaseEqualsASCII(auth_info->scheme, "digest")) {
|
| - dialog_form.scheme = PasswordForm::SCHEME_DIGEST;
|
| - } else {
|
| - dialog_form.scheme = PasswordForm::SCHEME_OTHER;
|
| - }
|
| - std::string host_and_port(auth_info->challenger.ToString());
|
| - if (auth_info->is_proxy) {
|
| - std::string origin = host_and_port;
|
| - // We don't expect this to already start with http:// or https://.
|
| - DCHECK(origin.find("http://") != 0 && origin.find("https://") != 0);
|
| - origin = std::string("http://") + origin;
|
| - dialog_form.origin = GURL(origin);
|
| - } else if (!auth_info->challenger.Equals(
|
| - net::HostPortPair::FromURL(request_url))) {
|
| - dialog_form.origin = GURL();
|
| - NOTREACHED(); // crbug.com/32718
|
| - } else {
|
| - dialog_form.origin = GURL(request_url.scheme() + "://" + host_and_port);
|
| - }
|
| - dialog_form.signon_realm = GetSignonRealm(dialog_form.origin, *auth_info);
|
| - // Set the password form for the handler (by copy).
|
| - handler->SetPasswordForm(dialog_form);
|
| - return dialog_form;
|
| -}
|
| -
|
| -void ShowLoginPrompt(const GURL& request_url,
|
| - net::AuthChallengeInfo* auth_info,
|
| - LoginHandler* handler) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| - WebContents* parent_contents = handler->GetWebContentsForLogin();
|
| - if (!parent_contents)
|
| - return;
|
| - prerender::PrerenderContents* prerender_contents =
|
| - prerender::PrerenderContents::FromWebContents(parent_contents);
|
| - if (prerender_contents) {
|
| - prerender_contents->Destroy(prerender::FINAL_STATUS_AUTH_NEEDED);
|
| - return;
|
| - }
|
| -
|
| - // The realm is controlled by the remote server, so there is no reason
|
| - // to believe it is of a reasonable length.
|
| - base::string16 elided_realm;
|
| - gfx::ElideString(base::UTF8ToUTF16(auth_info->realm), 120, &elided_realm);
|
| -
|
| - std::string languages;
|
| - content::WebContents* web_contents = handler->GetWebContentsForLogin();
|
| - if (web_contents) {
|
| - Profile* profile =
|
| - Profile::FromBrowserContext(web_contents->GetBrowserContext());
|
| - if (profile)
|
| - languages = profile->GetPrefs()->GetString(prefs::kAcceptLanguages);
|
| - }
|
| -
|
| - base::string16 authority =
|
| - url_formatter::FormatUrlForSecurityDisplay(request_url, languages);
|
| - base::string16 explanation =
|
| - elided_realm.empty()
|
| - ? l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION_NO_REALM,
|
| - authority)
|
| - : l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION, authority,
|
| - elided_realm);
|
| -
|
| - password_manager::PasswordManager* password_manager =
|
| - handler->GetPasswordManagerForLogin();
|
| -
|
| - if (!password_manager) {
|
| -#if defined(ENABLE_EXTENSIONS)
|
| - // A WebContents in a <webview> (a GuestView type) does not have a password
|
| - // manager, but still needs to be able to show login prompts.
|
| - if (guest_view::GuestViewBase::FromWebContents(parent_contents)) {
|
| - handler->BuildView(explanation, nullptr);
|
| - return;
|
| - }
|
| -#endif
|
| - handler->CancelAuth();
|
| - return;
|
| - }
|
| -
|
| - if (password_manager && password_manager->client()->IsLoggingActive()) {
|
| - password_manager::BrowserSavePasswordProgressLogger logger(
|
| - password_manager->client());
|
| - logger.LogMessage(
|
| - autofill::SavePasswordProgressLogger::STRING_SHOW_LOGIN_PROMPT_METHOD);
|
| - }
|
| -
|
| - handler->SetPasswordManager(password_manager);
|
| -
|
| - PasswordForm observed_form(
|
| - MakeInputForPasswordManager(request_url, auth_info, handler));
|
| - LoginHandler::LoginModelData model_data(password_manager, observed_form);
|
| - handler->BuildView(explanation, &model_data);
|
| -}
|
| -
|
| // This callback is run on the UI thread and creates a constrained window with
|
| // a LoginView to prompt the user. If the prompt is triggered because of
|
| // a cross origin navigation in the main frame, a blank interstitial is first
|
| @@ -610,3 +590,27 @@ LoginHandler* CreateLoginPrompt(net::AuthChallengeInfo* auth_info,
|
| is_main_frame));
|
| return handler;
|
| }
|
| +
|
| +// Get the signon_realm under which this auth info should be stored.
|
| +//
|
| +// The format of the signon_realm for proxy auth is:
|
| +// proxy-host/auth-realm
|
| +// The format of the signon_realm for server auth is:
|
| +// url-scheme://url-host[:url-port]/auth-realm
|
| +//
|
| +// Be careful when changing this function, since you could make existing
|
| +// saved logins un-retrievable.
|
| +std::string GetSignonRealm(const GURL& url,
|
| + const net::AuthChallengeInfo& auth_info) {
|
| + std::string signon_realm;
|
| + if (auth_info.is_proxy) {
|
| + signon_realm = auth_info.challenger.ToString();
|
| + signon_realm.append("/");
|
| + } else {
|
| + // Take scheme, host, and port from the url.
|
| + signon_realm = url.GetOrigin().spec();
|
| + // This ends with a "/".
|
| + }
|
| + signon_realm.append(auth_info.realm);
|
| + return signon_realm;
|
| +}
|
|
|