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