1 // Copyright 2014 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/save_password_infobar_delegate.h" 6 7 #include "base/metrics/histogram.h" 8 #include "base/strings/utf_string_conversions.h" 9 #include "chrome/browser/infobars/infobar_service.h" 10 #include "chrome/browser/ui/sync/one_click_signin_helper.h" 11 #include "chrome/grit/chromium_strings.h" 12 #include "chrome/grit/generated_resources.h" 13 #include "components/infobars/core/infobar.h" 14 #include "components/password_manager/core/browser/password_form_manager.h" 15 #include "components/signin/core/common/profile_management_switches.h" 16 #include "content/public/browser/navigation_entry.h" 17 #include "content/public/browser/web_contents.h" 18 #include "google_apis/gaia/gaia_urls.h" 19 #include "grit/theme_resources.h" 20 #include "ui/base/l10n/l10n_util.h" 21 22 // static 23 void SavePasswordInfoBarDelegate::Create( 24 content::WebContents* web_contents, 25 scoped_ptr<password_manager::PasswordFormManager> form_to_save, 26 const std::string& uma_histogram_suffix) { 27 #if defined(ENABLE_ONE_CLICK_SIGNIN) 28 // Don't show the password manager infobar if this form is for a google 29 // account and we are going to show the one-click signin infobar. 30 GURL realm(form_to_save->realm()); 31 // TODO(mathp): Checking only against associated_username() causes a bug 32 // referenced here: crbug.com/133275 33 // TODO(vabr): The check IsEnableWebBasedSignin is a hack for the time when 34 // OneClickSignin is disabled. http://crbug.com/339804 35 if (((realm == GaiaUrls::GetInstance()->gaia_login_form_realm()) || 36 (realm == GURL("https://www.google.com/"))) && 37 switches::IsEnableWebBasedSignin() && 38 OneClickSigninHelper::CanOffer( 39 web_contents, 40 OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 41 base::UTF16ToUTF8(form_to_save->associated_username()), 42 NULL)) 43 return; 44 #endif 45 46 InfoBarService::FromWebContents(web_contents)->AddInfoBar( 47 SavePasswordInfoBarDelegate::CreateInfoBar( 48 scoped_ptr<SavePasswordInfoBarDelegate>( 49 new SavePasswordInfoBarDelegate(form_to_save.Pass(), 50 uma_histogram_suffix)))); 51 } 52 53 SavePasswordInfoBarDelegate::~SavePasswordInfoBarDelegate() { 54 UMA_HISTOGRAM_ENUMERATION("PasswordManager.InfoBarResponse", 55 infobar_response_, 56 password_manager::metrics_util::NUM_RESPONSE_TYPES); 57 58 password_manager::metrics_util::LogUIDismissalReason(infobar_response_); 59 60 // The shortest period for which the prompt needs to live, so that we don't 61 // consider it killed prematurely, as might happen, e.g., if a pre-rendered 62 // page gets swapped in (and the current WebContents is destroyed). 63 const base::TimeDelta kMinimumPromptDisplayTime = 64 base::TimeDelta::FromSeconds(1); 65 66 if (!uma_histogram_suffix_.empty()) { 67 password_manager::metrics_util::LogUMAHistogramEnumeration( 68 "PasswordManager.SavePasswordPromptResponse_" + uma_histogram_suffix_, 69 infobar_response_, 70 password_manager::metrics_util::NUM_RESPONSE_TYPES); 71 password_manager::metrics_util::LogUMAHistogramBoolean( 72 "PasswordManager.SavePasswordPromptDisappearedQuickly_" + 73 uma_histogram_suffix_, 74 timer_.Elapsed() < kMinimumPromptDisplayTime); 75 } 76 } 77 78 void SavePasswordInfoBarDelegate::SetUseAdditionalPasswordAuthentication( 79 bool use_additional_authentication) { 80 form_to_save_->SetUseAdditionalPasswordAuthentication( 81 use_additional_authentication); 82 } 83 84 SavePasswordInfoBarDelegate::SavePasswordInfoBarDelegate( 85 scoped_ptr<password_manager::PasswordFormManager> form_to_save, 86 const std::string& uma_histogram_suffix) 87 : ConfirmInfoBarDelegate(), 88 form_to_save_(form_to_save.Pass()), 89 infobar_response_(password_manager::metrics_util::NO_RESPONSE), 90 uma_histogram_suffix_(uma_histogram_suffix) { 91 if (!uma_histogram_suffix_.empty()) { 92 password_manager::metrics_util::LogUMAHistogramBoolean( 93 "PasswordManager.SavePasswordPromptDisplayed_" + uma_histogram_suffix_, 94 true); 95 } 96 } 97 98 #if !defined(OS_ANDROID) 99 // On Android, the save password infobar supports an additional checkbox to 100 // require additional authentication before autofilling a saved password. 101 // Because of this non-standard UI, the Android version is special cased and 102 // constructed in: 103 // chrome/browser/ui/android/infobars/save_password_infobar.cc 104 105 // static 106 scoped_ptr<infobars::InfoBar> SavePasswordInfoBarDelegate::CreateInfoBar( 107 scoped_ptr<SavePasswordInfoBarDelegate> delegate) { 108 return ConfirmInfoBarDelegate::CreateInfoBar( 109 delegate.PassAs<ConfirmInfoBarDelegate>()); 110 } 111 #endif 112 113 bool SavePasswordInfoBarDelegate::ShouldExpire( 114 const NavigationDetails& details) const { 115 return !details.is_redirect && 116 infobars::InfoBarDelegate::ShouldExpire(details); 117 } 118 119 int SavePasswordInfoBarDelegate::GetIconID() const { 120 return IDR_INFOBAR_SAVE_PASSWORD; 121 } 122 123 infobars::InfoBarDelegate::Type SavePasswordInfoBarDelegate::GetInfoBarType() 124 const { 125 return PAGE_ACTION_TYPE; 126 } 127 128 base::string16 SavePasswordInfoBarDelegate::GetMessageText() const { 129 return l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT); 130 } 131 132 base::string16 SavePasswordInfoBarDelegate::GetButtonLabel( 133 InfoBarButton button) const { 134 return l10n_util::GetStringUTF16((button == BUTTON_OK) ? 135 IDS_PASSWORD_MANAGER_SAVE_BUTTON : IDS_PASSWORD_MANAGER_BLACKLIST_BUTTON); 136 } 137 138 bool SavePasswordInfoBarDelegate::Accept() { 139 DCHECK(form_to_save_.get()); 140 form_to_save_->Save(); 141 infobar_response_ = password_manager::metrics_util::REMEMBER_PASSWORD; 142 return true; 143 } 144 145 bool SavePasswordInfoBarDelegate::Cancel() { 146 DCHECK(form_to_save_.get()); 147 form_to_save_->PermanentlyBlacklist(); 148 infobar_response_ = password_manager::metrics_util::NEVER_REMEMBER_PASSWORD; 149 return true; 150 } 151 152 void SavePasswordInfoBarDelegate::InfoBarDismissed() { 153 DCHECK(form_to_save_.get()); 154 infobar_response_ = password_manager::metrics_util::INFOBAR_DISMISSED; 155 } 156 157 infobars::InfoBarDelegate::InfoBarAutomationType 158 SavePasswordInfoBarDelegate::GetInfoBarAutomationType() const { 159 return PASSWORD_INFOBAR; 160 } 161