Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / password_manager / password_manager_delegate_impl.cc
blob1bb9e34ba931e267bcefa00295e329eeb5e14ddf
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.
5 #include "chrome/browser/password_manager/password_manager_delegate_impl.h"
7 #include "base/memory/singleton.h"
8 #include "base/metrics/histogram.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/timer/elapsed_timer.h"
11 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
12 #include "chrome/browser/infobars/infobar.h"
13 #include "chrome/browser/infobars/infobar_service.h"
14 #include "chrome/browser/password_manager/password_form_manager.h"
15 #include "chrome/browser/password_manager/password_manager.h"
16 #include "chrome/browser/password_manager/password_manager_metrics_util.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/sync/one_click_signin_helper.h"
19 #include "components/autofill/content/browser/autofill_driver_impl.h"
20 #include "components/autofill/content/common/autofill_messages.h"
21 #include "components/autofill/core/browser/autofill_manager.h"
22 #include "components/autofill/core/common/password_form.h"
23 #include "content/public/browser/navigation_details.h"
24 #include "content/public/browser/navigation_entry.h"
25 #include "content/public/browser/render_view_host.h"
26 #include "content/public/browser/web_contents.h"
27 #include "content/public/common/page_transition_types.h"
28 #include "content/public/common/ssl_status.h"
29 #include "google_apis/gaia/gaia_urls.h"
30 #include "grit/chromium_strings.h"
31 #include "grit/generated_resources.h"
32 #include "grit/theme_resources.h"
33 #include "net/cert/cert_status_flags.h"
34 #include "ui/base/l10n/l10n_util.h"
37 // SavePasswordInfoBarDelegate ------------------------------------------------
39 // After a successful *new* login attempt, we take the PasswordFormManager in
40 // provisional_save_manager_ and move it to a SavePasswordInfoBarDelegate while
41 // the user makes up their mind with the "save password" infobar. Note if the
42 // login is one we already know about, the end of the line is
43 // provisional_save_manager_ because we just update it on success and so such
44 // forms never end up in an infobar.
45 class SavePasswordInfoBarDelegate : public ConfirmInfoBarDelegate {
46 public:
47 // If we won't be showing the one-click signin infobar, creates a save
48 // password infobar and delegate and adds the infobar to the InfoBarService
49 // for |web_contents|. |uma_histogram_suffix| is empty, or one of the
50 // "group_X" suffixes used in the histogram names for infobar usage reporting;
51 // if empty, the usage is not reported, otherwise the suffix is used to choose
52 // the right histogram.
53 static void Create(content::WebContents* web_contents,
54 PasswordFormManager* form_to_save,
55 const std::string& uma_histogram_suffix);
57 private:
58 enum ResponseType {
59 NO_RESPONSE = 0,
60 REMEMBER_PASSWORD,
61 NEVER_REMEMBER_PASSWORD,
62 INFOBAR_DISMISSED,
63 NUM_RESPONSE_TYPES,
66 SavePasswordInfoBarDelegate(PasswordFormManager* form_to_save,
67 const std::string& uma_histogram_suffix);
68 virtual ~SavePasswordInfoBarDelegate();
70 // InfoBarDelegate
71 virtual bool ShouldExpire(const content::LoadCommittedDetails& details)
72 const OVERRIDE;
74 // ConfirmInfoBarDelegate
75 virtual int GetIconID() const OVERRIDE;
76 virtual Type GetInfoBarType() const OVERRIDE;
77 virtual base::string16 GetMessageText() const OVERRIDE;
78 virtual base::string16 GetButtonLabel(InfoBarButton button) const OVERRIDE;
79 virtual bool Accept() OVERRIDE;
80 virtual bool Cancel() OVERRIDE;
81 virtual void InfoBarDismissed() OVERRIDE;
83 virtual InfoBarAutomationType GetInfoBarAutomationType() const OVERRIDE;
85 // The PasswordFormManager managing the form we're asking the user about,
86 // and should update as per her decision.
87 scoped_ptr<PasswordFormManager> form_to_save_;
89 // Used to track the results we get from the info bar.
90 ResponseType infobar_response_;
92 // Measures the "Save password?" prompt lifetime. Used to report an UMA
93 // signal.
94 base::ElapsedTimer timer_;
96 // The group name corresponding to the domain name of |form_to_save_| if the
97 // form is on a monitored domain. Otherwise, an empty string.
98 const std::string uma_histogram_suffix_;
100 DISALLOW_COPY_AND_ASSIGN(SavePasswordInfoBarDelegate);
103 // static
104 void SavePasswordInfoBarDelegate::Create(
105 content::WebContents* web_contents,
106 PasswordFormManager* form_to_save,
107 const std::string& uma_histogram_suffix) {
108 #if defined(ENABLE_ONE_CLICK_SIGNIN)
109 // Don't show the password manager infobar if this form is for a google
110 // account and we are going to show the one-click signin infobar.
111 GURL realm(form_to_save->realm());
112 // TODO(mathp): Checking only against associated_username() causes a bug
113 // referenced here: crbug.com/133275
114 if (((realm == GaiaUrls::GetInstance()->gaia_login_form_realm()) ||
115 (realm == GURL("https://www.google.com/"))) &&
116 OneClickSigninHelper::CanOffer(
117 web_contents, OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
118 base::UTF16ToUTF8(form_to_save->associated_username()), NULL))
119 return;
120 #endif
122 InfoBarService::FromWebContents(web_contents)->AddInfoBar(
123 ConfirmInfoBarDelegate::CreateInfoBar(scoped_ptr<ConfirmInfoBarDelegate>(
124 new SavePasswordInfoBarDelegate(form_to_save,
125 uma_histogram_suffix))));
128 SavePasswordInfoBarDelegate::SavePasswordInfoBarDelegate(
129 PasswordFormManager* form_to_save,
130 const std::string& uma_histogram_suffix)
131 : ConfirmInfoBarDelegate(),
132 form_to_save_(form_to_save),
133 infobar_response_(NO_RESPONSE),
134 uma_histogram_suffix_(uma_histogram_suffix) {
135 if (!uma_histogram_suffix_.empty()) {
136 password_manager_metrics_util::LogUMAHistogramBoolean(
137 "PasswordManager.SavePasswordPromptDisplayed_" + uma_histogram_suffix_,
138 true);
142 SavePasswordInfoBarDelegate::~SavePasswordInfoBarDelegate() {
143 UMA_HISTOGRAM_ENUMERATION("PasswordManager.InfoBarResponse",
144 infobar_response_, NUM_RESPONSE_TYPES);
146 // The shortest period for which the prompt needs to live, so that we don't
147 // consider it killed prematurely, as might happen, e.g., if a pre-rendered
148 // page gets swapped in (and the current WebContents is destroyed).
149 const base::TimeDelta kMinimumPromptDisplayTime =
150 base::TimeDelta::FromSeconds(1);
152 if (!uma_histogram_suffix_.empty()) {
153 password_manager_metrics_util::LogUMAHistogramEnumeration(
154 "PasswordManager.SavePasswordPromptResponse_" + uma_histogram_suffix_,
155 infobar_response_, NUM_RESPONSE_TYPES);
156 password_manager_metrics_util::LogUMAHistogramBoolean(
157 "PasswordManager.SavePasswordPromptDisappearedQuickly_" +
158 uma_histogram_suffix_,
159 timer_.Elapsed() < kMinimumPromptDisplayTime);
163 bool SavePasswordInfoBarDelegate::ShouldExpire(
164 const content::LoadCommittedDetails& details) const {
165 bool is_not_redirect = !(details.entry->GetTransitionType() &
166 content::PAGE_TRANSITION_IS_REDIRECT_MASK);
167 return is_not_redirect && InfoBarDelegate::ShouldExpire(details);
170 int SavePasswordInfoBarDelegate::GetIconID() const {
171 return IDR_INFOBAR_SAVE_PASSWORD;
174 InfoBarDelegate::Type SavePasswordInfoBarDelegate::GetInfoBarType() const {
175 return PAGE_ACTION_TYPE;
178 base::string16 SavePasswordInfoBarDelegate::GetMessageText() const {
179 return l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT);
182 base::string16 SavePasswordInfoBarDelegate::GetButtonLabel(
183 InfoBarButton button) const {
184 return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
185 IDS_PASSWORD_MANAGER_SAVE_BUTTON : IDS_PASSWORD_MANAGER_BLACKLIST_BUTTON);
188 bool SavePasswordInfoBarDelegate::Accept() {
189 DCHECK(form_to_save_.get());
190 form_to_save_->Save();
191 infobar_response_ = REMEMBER_PASSWORD;
192 return true;
195 bool SavePasswordInfoBarDelegate::Cancel() {
196 DCHECK(form_to_save_.get());
197 form_to_save_->PermanentlyBlacklist();
198 infobar_response_ = NEVER_REMEMBER_PASSWORD;
199 return true;
202 void SavePasswordInfoBarDelegate::InfoBarDismissed() {
203 DCHECK(form_to_save_.get());
204 infobar_response_ = INFOBAR_DISMISSED;
207 InfoBarDelegate::InfoBarAutomationType
208 SavePasswordInfoBarDelegate::GetInfoBarAutomationType() const {
209 return PASSWORD_INFOBAR;
213 // PasswordManagerDelegateImpl ------------------------------------------------
215 DEFINE_WEB_CONTENTS_USER_DATA_KEY(PasswordManagerDelegateImpl);
217 PasswordManagerDelegateImpl::PasswordManagerDelegateImpl(
218 content::WebContents* web_contents)
219 : web_contents_(web_contents) {
222 PasswordManagerDelegateImpl::~PasswordManagerDelegateImpl() {
225 void PasswordManagerDelegateImpl::FillPasswordForm(
226 const autofill::PasswordFormFillData& form_data) {
227 web_contents_->GetRenderViewHost()->Send(
228 new AutofillMsg_FillPasswordForm(
229 web_contents_->GetRenderViewHost()->GetRoutingID(),
230 form_data));
233 void PasswordManagerDelegateImpl::AddSavePasswordInfoBarIfPermitted(
234 PasswordFormManager* form_to_save) {
235 std::string uma_histogram_suffix(
236 password_manager_metrics_util::GroupIdToString(
237 password_manager_metrics_util::MonitoredDomainGroupId(
238 form_to_save->realm(), GetProfile()->GetPrefs())));
239 SavePasswordInfoBarDelegate::Create(
240 web_contents_, form_to_save, uma_histogram_suffix);
243 Profile* PasswordManagerDelegateImpl::GetProfile() {
244 return Profile::FromBrowserContext(web_contents_->GetBrowserContext());
247 bool PasswordManagerDelegateImpl::DidLastPageLoadEncounterSSLErrors() {
248 content::NavigationEntry* entry =
249 web_contents_->GetController().GetActiveEntry();
250 if (!entry) {
251 NOTREACHED();
252 return false;
255 return net::IsCertStatusError(entry->GetSSL().cert_status);