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