This source file includes following definitions.
- ResetLoginHandlerForRequest
- GetSignonRealm
- login_model_
- OnRequestCancelled
- SetPasswordForm
- SetPasswordManager
- GetWebContentsForLogin
- SetAuth
- CancelAuth
- Observe
- WasAuthHandled
- SetModel
- NotifyAuthNeeded
- ReleaseSoon
- AddObservers
- RemoveObservers
- NotifyAuthSupplied
- NotifyAuthCancelled
- TestAndSetAuthHandled
- SetAuthDeferred
- CancelAuthDeferred
- CloseContentsDeferred
- MakeInputForPasswordManager
- LoginDialogCallback
- CreateLoginPrompt
#include "chrome/browser/ui/login/login_prompt.h"
#include <vector>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/password_manager/chrome_password_manager_client.h"
#include "chrome/browser/prerender/prerender_contents.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "components/password_manager/core/browser/password_manager.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/web_contents.h"
#include "grit/generated_resources.h"
#include "net/base/auth.h"
#include "net/base/net_util.h"
#include "net/http/http_transaction_factory.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/text_elider.h"
using autofill::PasswordForm;
using content::BrowserThread;
using content::NavigationController;
using content::RenderViewHost;
using content::RenderViewHostDelegate;
using content::ResourceDispatcherHost;
using content::ResourceRequestInfo;
using content::WebContents;
class LoginHandlerImpl;
void ResetLoginHandlerForRequest(net::URLRequest* request) {
  ResourceDispatcherHost::Get()->ClearLoginDelegateForRequest(request);
}
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 {
    
    signon_realm = url.GetOrigin().spec();
    
  }
  signon_realm.append(auth_info.realm);
  return signon_realm;
}
LoginHandler::LoginHandler(net::AuthChallengeInfo* auth_info,
                           net::URLRequest* request)
    : handled_auth_(false),
      auth_info_(auth_info),
      request_(request),
      http_network_session_(
          request_->context()->http_transaction_factory()->GetSession()),
      password_manager_(NULL),
      login_model_(NULL) {
  
  
  
  DCHECK(request_) << "LoginHandler constructed with NULL request";
  DCHECK(auth_info_.get()) << "LoginHandler constructed with NULL auth info";
  AddRef();  
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(&LoginHandler::AddObservers, this));
  if (!ResourceRequestInfo::ForRequest(request_)->GetAssociatedRenderFrame(
          &render_process_host_id_,  &render_frame_id_)) {
    NOTREACHED();
  }
}
void LoginHandler::OnRequestCancelled() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)) <<
      "Why is OnRequestCancelled called from the UI thread?";
  
  request_ = NULL;
  
  CancelAuth();
}
void LoginHandler::SetPasswordForm(const autofill::PasswordForm& form) {
  password_form_ = form;
}
void LoginHandler::SetPasswordManager(PasswordManager* password_manager) {
  password_manager_ = password_manager;
}
WebContents* LoginHandler::GetWebContentsForLogin() const {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
      render_process_host_id_, render_frame_id_);
  return WebContents::FromRenderFrameHost(rfh);
}
void LoginHandler::SetAuth(const base::string16& username,
                           const base::string16& password) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (TestAndSetAuthHandled())
    return;
  
  if (password_manager_) {
    password_form_.username_value = username;
    password_form_.password_value = password;
    password_manager_->ProvisionallySavePassword(password_form_);
  }
  
  
  
  
  
  
  NotifyAuthSupplied(username, password);
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(&LoginHandler::CloseContentsDeferred, this));
  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      base::Bind(&LoginHandler::SetAuthDeferred, this, username, password));
}
void LoginHandler::CancelAuth() {
  if (TestAndSetAuthHandled())
    return;
  
  if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    NotifyAuthCancelled();
  } else {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::Bind(&LoginHandler::NotifyAuthCancelled, this));
  }
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(&LoginHandler::CloseContentsDeferred, this));
  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      base::Bind(&LoginHandler::CancelAuthDeferred, this));
}
void LoginHandler::Observe(int type,
                           const content::NotificationSource& source,
                           const content::NotificationDetails& details) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(type == chrome::NOTIFICATION_AUTH_SUPPLIED ||
         type == chrome::NOTIFICATION_AUTH_CANCELLED);
  WebContents* requesting_contents = GetWebContentsForLogin();
  if (!requesting_contents)
    return;
  
  if (WasAuthHandled())
    return;
  LoginNotificationDetails* login_details =
      content::Details<LoginNotificationDetails>(details).ptr();
  
  
  DCHECK(login_details->handler() != this);
  
  if (!login_details->handler()->auth_info()->Equals(*auth_info()))
    return;
  
  if (login_details->handler()->http_network_session_ !=
      http_network_session_)
    return;
  
  if (type == chrome::NOTIFICATION_AUTH_SUPPLIED) {
    AuthSuppliedLoginNotificationDetails* supplied_details =
        content::Details<AuthSuppliedLoginNotificationDetails>(details).ptr();
    SetAuth(supplied_details->username(), supplied_details->password());
  } else {
    DCHECK(type == chrome::NOTIFICATION_AUTH_CANCELLED);
    CancelAuth();
  }
}
bool LoginHandler::WasAuthHandled() const {
  base::AutoLock lock(handled_auth_lock_);
  bool was_handled = handled_auth_;
  return was_handled;
}
LoginHandler::~LoginHandler() {
  SetModel(NULL);
}
void LoginHandler::SetModel(LoginModel* model) {
  if (login_model_)
    login_model_->RemoveObserver(this);
  login_model_ = model;
  if (login_model_)
    login_model_->AddObserver(this);
}
void LoginHandler::NotifyAuthNeeded() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (WasAuthHandled())
    return;
  content::NotificationService* service =
      content::NotificationService::current();
  NavigationController* controller = NULL;
  WebContents* requesting_contents = GetWebContentsForLogin();
  if (requesting_contents)
    controller = &requesting_contents->GetController();
  LoginNotificationDetails details(this);
  service->Notify(chrome::NOTIFICATION_AUTH_NEEDED,
                  content::Source<NavigationController>(controller),
                  content::Details<LoginNotificationDetails>(&details));
}
void LoginHandler::ReleaseSoon() {
  if (!TestAndSetAuthHandled()) {
    BrowserThread::PostTask(
        BrowserThread::IO, FROM_HERE,
        base::Bind(&LoginHandler::CancelAuthDeferred, this));
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::Bind(&LoginHandler::NotifyAuthCancelled, this));
  }
  BrowserThread::PostTask(
    BrowserThread::UI, FROM_HERE,
    base::Bind(&LoginHandler::RemoveObservers, this));
  
  BrowserThread::ReleaseSoon(BrowserThread::IO, FROM_HERE, this);
}
void LoginHandler::AddObservers() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  
  
  registrar_.reset(new content::NotificationRegistrar);
  registrar_->Add(this, chrome::NOTIFICATION_AUTH_SUPPLIED,
                  content::NotificationService::AllBrowserContextsAndSources());
  registrar_->Add(this, chrome::NOTIFICATION_AUTH_CANCELLED,
                  content::NotificationService::AllBrowserContextsAndSources());
}
void LoginHandler::RemoveObservers() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  registrar_.reset();
}
void LoginHandler::NotifyAuthSupplied(const base::string16& username,
                                      const base::string16& password) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(WasAuthHandled());
  WebContents* requesting_contents = GetWebContentsForLogin();
  if (!requesting_contents)
    return;
  content::NotificationService* service =
      content::NotificationService::current();
  NavigationController* controller =
      &requesting_contents->GetController();
  AuthSuppliedLoginNotificationDetails details(this, username, password);
  service->Notify(
      chrome::NOTIFICATION_AUTH_SUPPLIED,
      content::Source<NavigationController>(controller),
      content::Details<AuthSuppliedLoginNotificationDetails>(&details));
}
void LoginHandler::NotifyAuthCancelled() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(WasAuthHandled());
  content::NotificationService* service =
      content::NotificationService::current();
  NavigationController* controller = NULL;
  WebContents* requesting_contents = GetWebContentsForLogin();
  if (requesting_contents)
    controller = &requesting_contents->GetController();
  LoginNotificationDetails details(this);
  service->Notify(chrome::NOTIFICATION_AUTH_CANCELLED,
                  content::Source<NavigationController>(controller),
                  content::Details<LoginNotificationDetails>(&details));
}
bool LoginHandler::TestAndSetAuthHandled() {
  base::AutoLock lock(handled_auth_lock_);
  bool was_handled = handled_auth_;
  handled_auth_ = true;
  return was_handled;
}
void LoginHandler::SetAuthDeferred(const base::string16& username,
                                   const base::string16& password) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (request_) {
    request_->SetAuth(net::AuthCredentials(username, password));
    ResetLoginHandlerForRequest(request_);
  }
}
void LoginHandler::CancelAuthDeferred() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (request_) {
    request_->CancelAuth();
    
    DCHECK(request_ != NULL);
    ResetLoginHandlerForRequest(request_);
  }
}
void LoginHandler::CloseContentsDeferred() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  CloseDialog();
}
void MakeInputForPasswordManager(
    const GURL& request_url,
    net::AuthChallengeInfo* auth_info,
    LoginHandler* handler,
    std::vector<PasswordForm>* password_manager_input) {
  PasswordForm dialog_form;
  if (LowerCaseEqualsASCII(auth_info->scheme, "basic")) {
    dialog_form.scheme = PasswordForm::SCHEME_BASIC;
  } else if (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;
    
    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();  
  } else {
    dialog_form.origin = GURL(request_url.scheme() + "://" + host_and_port);
  }
  dialog_form.signon_realm = GetSignonRealm(dialog_form.origin, *auth_info);
  password_manager_input->push_back(dialog_form);
  
  handler->SetPasswordForm(dialog_form);
}
void LoginDialogCallback(const GURL& request_url,
                         net::AuthChallengeInfo* auth_info,
                         LoginHandler* handler) {
  WebContents* parent_contents = handler->GetWebContentsForLogin();
  if (!parent_contents || handler->WasAuthHandled()) {
    
    
    
    handler->CancelAuth();
    return;
  }
  prerender::PrerenderContents* prerender_contents =
      prerender::PrerenderContents::FromWebContents(parent_contents);
  if (prerender_contents) {
    prerender_contents->Destroy(prerender::FINAL_STATUS_AUTH_NEEDED);
    return;
  }
  PasswordManager* password_manager =
      ChromePasswordManagerClient::GetManagerFromWebContents(parent_contents);
  if (!password_manager) {
    
    handler->CancelAuth();
    return;
  }
  
  std::vector<PasswordForm> v;
  MakeInputForPasswordManager(request_url, auth_info, handler, &v);
  password_manager->OnPasswordFormsParsed(v);
  handler->SetPasswordManager(password_manager);
  
  
  base::string16 elided_realm;
  gfx::ElideString(base::UTF8ToUTF16(auth_info->realm), 120, &elided_realm);
  base::string16 host_and_port = base::ASCIIToUTF16(
      request_url.scheme() + "://" + auth_info->challenger.ToString());
  base::string16 explanation = elided_realm.empty() ?
      l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION_NO_REALM,
                                 host_and_port) :
      l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION,
                                 host_and_port,
                                 elided_realm);
  handler->BuildViewForPasswordManager(password_manager, explanation);
}
LoginHandler* CreateLoginPrompt(net::AuthChallengeInfo* auth_info,
                                net::URLRequest* request) {
  LoginHandler* handler = LoginHandler::Create(auth_info, request);
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(&LoginDialogCallback, request->url(),
                 make_scoped_refptr(auth_info), make_scoped_refptr(handler)));
  return handler;
}