Home | History | Annotate | Download | only in password_manager
      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
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/password_manager/password_manager_delegate_impl.h"
      6 
      7 #include "base/memory/singleton.h"
      8 #include "base/metrics/histogram.h"
      9 #include "base/strings/utf_string_conversions.h"
     10 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
     11 #include "chrome/browser/infobars/infobar_service.h"
     12 #include "chrome/browser/password_manager/password_form_manager.h"
     13 #include "chrome/browser/password_manager/password_manager.h"
     14 #include "chrome/browser/profiles/profile.h"
     15 #include "chrome/browser/ui/sync/one_click_signin_helper.h"
     16 #include "components/autofill/content/browser/autofill_driver_impl.h"
     17 #include "components/autofill/core/browser/autofill_manager.h"
     18 #include "components/autofill/core/common/autofill_messages.h"
     19 #include "content/public/browser/navigation_entry.h"
     20 #include "content/public/browser/render_view_host.h"
     21 #include "content/public/browser/web_contents.h"
     22 #include "content/public/common/password_form.h"
     23 #include "content/public/common/ssl_status.h"
     24 #include "google_apis/gaia/gaia_urls.h"
     25 #include "grit/chromium_strings.h"
     26 #include "grit/generated_resources.h"
     27 #include "grit/theme_resources.h"
     28 #include "net/cert/cert_status_flags.h"
     29 #include "ui/base/l10n/l10n_util.h"
     30 
     31 
     32 // SavePasswordInfoBarDelegate ------------------------------------------------
     33 
     34 // After a successful *new* login attempt, we take the PasswordFormManager in
     35 // provisional_save_manager_ and move it to a SavePasswordInfoBarDelegate while
     36 // the user makes up their mind with the "save password" infobar. Note if the
     37 // login is one we already know about, the end of the line is
     38 // provisional_save_manager_ because we just update it on success and so such
     39 // forms never end up in an infobar.
     40 class SavePasswordInfoBarDelegate : public ConfirmInfoBarDelegate {
     41  public:
     42   // If we won't be showing the one-click signin infobar, creates a save
     43   // password infobar delegate and adds it to the InfoBarService for
     44   // |web_contents|.
     45   static void Create(content::WebContents* web_contents,
     46                      PasswordFormManager* form_to_save);
     47 
     48  private:
     49   enum ResponseType {
     50     NO_RESPONSE = 0,
     51     REMEMBER_PASSWORD,
     52     DONT_REMEMBER_PASSWORD,
     53     NUM_RESPONSE_TYPES,
     54   };
     55 
     56   SavePasswordInfoBarDelegate(InfoBarService* infobar_service,
     57                               PasswordFormManager* form_to_save);
     58   virtual ~SavePasswordInfoBarDelegate();
     59 
     60   // ConfirmInfoBarDelegate
     61   virtual int GetIconID() const OVERRIDE;
     62   virtual Type GetInfoBarType() const OVERRIDE;
     63   virtual string16 GetMessageText() const OVERRIDE;
     64   virtual string16 GetButtonLabel(InfoBarButton button) const OVERRIDE;
     65   virtual bool Accept() OVERRIDE;
     66   virtual bool Cancel() OVERRIDE;
     67 
     68   virtual InfoBarAutomationType GetInfoBarAutomationType() const OVERRIDE;
     69 
     70   // The PasswordFormManager managing the form we're asking the user about,
     71   // and should update as per her decision.
     72   scoped_ptr<PasswordFormManager> form_to_save_;
     73 
     74   // Used to track the results we get from the info bar.
     75   ResponseType infobar_response_;
     76 
     77   DISALLOW_COPY_AND_ASSIGN(SavePasswordInfoBarDelegate);
     78 };
     79 
     80 // static
     81 void SavePasswordInfoBarDelegate::Create(content::WebContents* web_contents,
     82                                          PasswordFormManager* form_to_save) {
     83 #if defined(ENABLE_ONE_CLICK_SIGNIN)
     84   // Don't show the password manager infobar if this form is for a google
     85   // account and we are going to show the one-click signin infobar.
     86   GURL realm(form_to_save->realm());
     87   // TODO(mathp): Checking only against associated_username() causes a bug
     88   // referenced here: crbug.com/133275
     89   if (((realm == GURL(GaiaUrls::GetInstance()->gaia_login_form_realm())) ||
     90        (realm == GURL("https://www.google.com/"))) &&
     91       OneClickSigninHelper::CanOffer(
     92           web_contents, OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
     93           UTF16ToUTF8(form_to_save->associated_username()), NULL))
     94     return;
     95 #endif
     96 
     97   InfoBarService* infobar_service =
     98       InfoBarService::FromWebContents(web_contents);
     99   infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>(
    100       new SavePasswordInfoBarDelegate(infobar_service, form_to_save)));
    101 }
    102 
    103 SavePasswordInfoBarDelegate::SavePasswordInfoBarDelegate(
    104     InfoBarService* infobar_service,
    105     PasswordFormManager* form_to_save)
    106     : ConfirmInfoBarDelegate(infobar_service),
    107       form_to_save_(form_to_save),
    108       infobar_response_(NO_RESPONSE) {
    109 }
    110 
    111 SavePasswordInfoBarDelegate::~SavePasswordInfoBarDelegate() {
    112   UMA_HISTOGRAM_ENUMERATION("PasswordManager.InfoBarResponse",
    113                             infobar_response_, NUM_RESPONSE_TYPES);
    114 }
    115 
    116 int SavePasswordInfoBarDelegate::GetIconID() const {
    117   return IDR_INFOBAR_SAVE_PASSWORD;
    118 }
    119 
    120 InfoBarDelegate::Type SavePasswordInfoBarDelegate::GetInfoBarType() const {
    121   return PAGE_ACTION_TYPE;
    122 }
    123 
    124 string16 SavePasswordInfoBarDelegate::GetMessageText() const {
    125   return l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT);
    126 }
    127 
    128 string16 SavePasswordInfoBarDelegate::GetButtonLabel(
    129     InfoBarButton button) const {
    130   return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
    131       IDS_PASSWORD_MANAGER_SAVE_BUTTON : IDS_PASSWORD_MANAGER_BLACKLIST_BUTTON);
    132 }
    133 
    134 bool SavePasswordInfoBarDelegate::Accept() {
    135   DCHECK(form_to_save_.get());
    136   form_to_save_->Save();
    137   infobar_response_ = REMEMBER_PASSWORD;
    138   return true;
    139 }
    140 
    141 bool SavePasswordInfoBarDelegate::Cancel() {
    142   DCHECK(form_to_save_.get());
    143   form_to_save_->PermanentlyBlacklist();
    144   infobar_response_ = DONT_REMEMBER_PASSWORD;
    145   return true;
    146 }
    147 
    148 InfoBarDelegate::InfoBarAutomationType
    149     SavePasswordInfoBarDelegate::GetInfoBarAutomationType() const {
    150   return PASSWORD_INFOBAR;
    151 }
    152 
    153 
    154 // PasswordManagerDelegateImpl ------------------------------------------------
    155 
    156 DEFINE_WEB_CONTENTS_USER_DATA_KEY(PasswordManagerDelegateImpl);
    157 
    158 PasswordManagerDelegateImpl::PasswordManagerDelegateImpl(
    159     content::WebContents* web_contents)
    160     : web_contents_(web_contents) {
    161 }
    162 
    163 PasswordManagerDelegateImpl::~PasswordManagerDelegateImpl() {
    164 }
    165 
    166 void PasswordManagerDelegateImpl::FillPasswordForm(
    167     const autofill::PasswordFormFillData& form_data) {
    168   web_contents_->GetRenderViewHost()->Send(
    169       new AutofillMsg_FillPasswordForm(
    170           web_contents_->GetRenderViewHost()->GetRoutingID(),
    171           form_data));
    172 }
    173 
    174 void PasswordManagerDelegateImpl::AddSavePasswordInfoBarIfPermitted(
    175     PasswordFormManager* form_to_save) {
    176   SavePasswordInfoBarDelegate::Create(web_contents_, form_to_save);
    177 }
    178 
    179 Profile* PasswordManagerDelegateImpl::GetProfile() {
    180   return Profile::FromBrowserContext(web_contents_->GetBrowserContext());
    181 }
    182 
    183 bool PasswordManagerDelegateImpl::DidLastPageLoadEncounterSSLErrors() {
    184   content::NavigationEntry* entry =
    185       web_contents_->GetController().GetActiveEntry();
    186   if (!entry) {
    187     NOTREACHED();
    188     return false;
    189   }
    190 
    191   return net::IsCertStatusError(entry->GetSSL().cert_status);
    192 }
    193