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 23void 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 53SavePasswordInfoBarDelegate::~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 78void SavePasswordInfoBarDelegate::SetUseAdditionalPasswordAuthentication( 79 bool use_additional_authentication) { 80 form_to_save_->SetUseAdditionalPasswordAuthentication( 81 use_additional_authentication); 82} 83 84SavePasswordInfoBarDelegate::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 106scoped_ptr<infobars::InfoBar> SavePasswordInfoBarDelegate::CreateInfoBar( 107 scoped_ptr<SavePasswordInfoBarDelegate> delegate) { 108 return ConfirmInfoBarDelegate::CreateInfoBar( 109 delegate.PassAs<ConfirmInfoBarDelegate>()); 110} 111#endif 112 113bool SavePasswordInfoBarDelegate::ShouldExpire( 114 const NavigationDetails& details) const { 115 return !details.is_redirect && 116 infobars::InfoBarDelegate::ShouldExpire(details); 117} 118 119int SavePasswordInfoBarDelegate::GetIconID() const { 120 return IDR_INFOBAR_SAVE_PASSWORD; 121} 122 123infobars::InfoBarDelegate::Type SavePasswordInfoBarDelegate::GetInfoBarType() 124 const { 125 return PAGE_ACTION_TYPE; 126} 127 128base::string16 SavePasswordInfoBarDelegate::GetMessageText() const { 129 return l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT); 130} 131 132base::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 138bool 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 145bool 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 152void SavePasswordInfoBarDelegate::InfoBarDismissed() { 153 DCHECK(form_to_save_.get()); 154 infobar_response_ = password_manager::metrics_util::INFOBAR_DISMISSED; 155} 156 157infobars::InfoBarDelegate::InfoBarAutomationType 158SavePasswordInfoBarDelegate::GetInfoBarAutomationType() const { 159 return PASSWORD_INFOBAR; 160} 161