Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / ui / passwords / manage_passwords_bubble_model.cc
blobb87b2615640462cc44126d504463b0e2bff165e2
1 // Copyright 2013 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/ui/passwords/manage_passwords_bubble_model.h"
7 #include "base/command_line.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/password_manager/password_store_factory.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/ui/browser.h"
12 #include "chrome/browser/ui/browser_finder.h"
13 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
14 #include "chrome/browser/ui/passwords/password_bubble_experiment.h"
15 #include "chrome/grit/generated_resources.h"
16 #include "components/feedback/feedback_data.h"
17 #include "components/feedback/feedback_util.h"
18 #include "components/password_manager/core/browser/password_store.h"
19 #include "components/password_manager/core/common/credential_manager_types.h"
20 #include "components/password_manager/core/common/password_manager_ui.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/common/content_switches.h"
23 #include "ui/base/l10n/l10n_util.h"
24 #include "ui/base/resource/resource_bundle.h"
26 using autofill::PasswordFormMap;
27 using feedback::FeedbackData;
28 using content::WebContents;
29 namespace metrics_util = password_manager::metrics_util;
31 namespace {
33 enum FieldType { USERNAME_FIELD, PASSWORD_FIELD };
35 const int kUsernameFieldSize = 30;
36 const int kPasswordFieldSize = 22;
38 // Returns the width of |type| field.
39 int GetFieldWidth(FieldType type) {
40 return ui::ResourceBundle::GetSharedInstance()
41 .GetFontList(ui::ResourceBundle::SmallFont)
42 .GetExpectedTextWidth(type == USERNAME_FIELD ? kUsernameFieldSize
43 : kPasswordFieldSize);
46 Profile* GetProfileFromWebContents(content::WebContents* web_contents) {
47 if (!web_contents)
48 return nullptr;
49 return Profile::FromBrowserContext(web_contents->GetBrowserContext());
52 void RecordExperimentStatistics(content::WebContents* web_contents,
53 metrics_util::UIDismissalReason reason) {
54 Profile* profile = GetProfileFromWebContents(web_contents);
55 if (!profile)
56 return;
57 password_bubble_experiment::RecordBubbleClosed(profile->GetPrefs(), reason);
60 ScopedVector<const autofill::PasswordForm> DeepCopyForms(
61 const std::vector<const autofill::PasswordForm*>& forms) {
62 ScopedVector<const autofill::PasswordForm> result;
63 result.reserve(forms.size());
64 std::transform(forms.begin(), forms.end(), std::back_inserter(result),
65 [](const autofill::PasswordForm* form) {
66 return new autofill::PasswordForm(*form);
67 });
68 return result.Pass();
71 } // namespace
73 ManagePasswordsBubbleModel::ManagePasswordsBubbleModel(
74 content::WebContents* web_contents)
75 : content::WebContentsObserver(web_contents),
76 never_save_passwords_(false),
77 display_disposition_(metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING),
78 dismissal_reason_(metrics_util::NOT_DISPLAYED) {
79 ManagePasswordsUIController* controller =
80 ManagePasswordsUIController::FromWebContents(web_contents);
82 origin_ = controller->origin();
83 state_ = controller->state();
84 if (state_ == password_manager::ui::PENDING_PASSWORD_STATE) {
85 pending_password_ = controller->PendingPassword();
86 local_credentials_ = DeepCopyForms(controller->GetCurrentForms());
87 } else if (state_ == password_manager::ui::CONFIRMATION_STATE) {
88 // We don't need anything.
89 } else if (state_ == password_manager::ui::CREDENTIAL_REQUEST_STATE) {
90 local_credentials_ = DeepCopyForms(controller->GetCurrentForms());
91 federated_credentials_ = DeepCopyForms(controller->GetFederatedForms());
92 } else if (state_ == password_manager::ui::AUTO_SIGNIN_STATE) {
93 pending_password_ = *controller->GetCurrentForms()[0];
94 } else {
95 local_credentials_ = DeepCopyForms(controller->GetCurrentForms());
98 if (state_ == password_manager::ui::PENDING_PASSWORD_STATE) {
99 title_ = PendingStateTitleBasedOnSavePasswordPref();
100 } else if (state_ == password_manager::ui::BLACKLIST_STATE) {
101 title_ = l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_BLACKLISTED_TITLE);
102 } else if (state_ == password_manager::ui::CONFIRMATION_STATE) {
103 title_ =
104 l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_TITLE);
105 } else if (state_ == password_manager::ui::CREDENTIAL_REQUEST_STATE) {
106 title_ = l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_CHOOSE_TITLE);
107 } else if (state_ == password_manager::ui::AUTO_SIGNIN_STATE) {
108 // There is no title.
109 } else {
110 title_ = IsNewUIActive() ?
111 l10n_util::GetStringFUTF16(IDS_MANAGE_ACCOUNTS_TITLE,
112 base::UTF8ToUTF16(origin_.spec())) :
113 l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_TITLE);
116 if (state_ == password_manager::ui::CONFIRMATION_STATE) {
117 base::string16 save_confirmation_link =
118 l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_LINK);
119 size_t offset;
120 save_confirmation_text_ =
121 l10n_util::GetStringFUTF16(IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_TEXT,
122 save_confirmation_link, &offset);
123 save_confirmation_link_range_ =
124 gfx::Range(offset, offset + save_confirmation_link.length());
127 manage_link_ =
128 l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_MANAGE_PASSWORDS_LINK);
131 ManagePasswordsBubbleModel::~ManagePasswordsBubbleModel() {}
133 void ManagePasswordsBubbleModel::OnBubbleShown(
134 ManagePasswordsBubble::DisplayReason reason) {
135 if (reason == ManagePasswordsBubble::USER_ACTION) {
136 if (state_ == password_manager::ui::PENDING_PASSWORD_STATE) {
137 display_disposition_ = metrics_util::MANUAL_WITH_PASSWORD_PENDING;
138 } else if (state_ == password_manager::ui::BLACKLIST_STATE) {
139 display_disposition_ = metrics_util::MANUAL_BLACKLISTED;
140 } else {
141 display_disposition_ = metrics_util::MANUAL_MANAGE_PASSWORDS;
143 } else {
144 if (state_ == password_manager::ui::CONFIRMATION_STATE) {
145 display_disposition_ =
146 metrics_util::AUTOMATIC_GENERATED_PASSWORD_CONFIRMATION;
147 } else if (state_ == password_manager::ui::CREDENTIAL_REQUEST_STATE) {
148 display_disposition_ = metrics_util::AUTOMATIC_CREDENTIAL_REQUEST;
149 } else if (state_ == password_manager::ui::AUTO_SIGNIN_STATE) {
150 display_disposition_ = metrics_util::AUTOMATIC_SIGNIN_TOAST;
151 } else {
152 display_disposition_ = metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING;
155 metrics_util::LogUIDisplayDisposition(display_disposition_);
157 // Default to a dismissal reason of "no interaction". If the user interacts
158 // with the button in such a way that it closes, we'll reset this value
159 // accordingly.
160 dismissal_reason_ = metrics_util::NO_DIRECT_INTERACTION;
162 ManagePasswordsUIController* controller =
163 ManagePasswordsUIController::FromWebContents(web_contents());
164 controller->OnBubbleShown();
167 void ManagePasswordsBubbleModel::OnBubbleHidden() {
168 ManagePasswordsUIController* manage_passwords_ui_controller =
169 web_contents() ?
170 ManagePasswordsUIController::FromWebContents(web_contents())
171 : nullptr;
172 if (manage_passwords_ui_controller)
173 manage_passwords_ui_controller->OnBubbleHidden();
174 if (dismissal_reason_ == metrics_util::NOT_DISPLAYED)
175 return;
177 metrics_util::LogUIDismissalReason(dismissal_reason_);
178 // Other use cases have been reported in the callbacks like OnSaveClicked().
179 if (state_ == password_manager::ui::PENDING_PASSWORD_STATE &&
180 dismissal_reason_ == metrics_util::NO_DIRECT_INTERACTION)
181 RecordExperimentStatistics(web_contents(), dismissal_reason_);
184 void ManagePasswordsBubbleModel::OnNopeClicked() {
185 dismissal_reason_ = metrics_util::CLICKED_NOPE;
186 RecordExperimentStatistics(web_contents(), dismissal_reason_);
187 if (state_ != password_manager::ui::CREDENTIAL_REQUEST_STATE)
188 state_ = password_manager::ui::PENDING_PASSWORD_STATE;
191 void ManagePasswordsBubbleModel::OnConfirmationForNeverForThisSite() {
192 never_save_passwords_ = true;
193 title_ = PendingStateTitleBasedOnSavePasswordPref();
196 void ManagePasswordsBubbleModel::OnUndoNeverForThisSite() {
197 never_save_passwords_ = false;
198 title_ = PendingStateTitleBasedOnSavePasswordPref();
201 void ManagePasswordsBubbleModel::OnNeverForThisSiteClicked() {
202 dismissal_reason_ = metrics_util::CLICKED_NEVER;
203 RecordExperimentStatistics(web_contents(), dismissal_reason_);
204 ManagePasswordsUIController* manage_passwords_ui_controller =
205 ManagePasswordsUIController::FromWebContents(web_contents());
206 manage_passwords_ui_controller->NeverSavePassword();
207 state_ = password_manager::ui::BLACKLIST_STATE;
210 void ManagePasswordsBubbleModel::OnUnblacklistClicked() {
211 dismissal_reason_ = metrics_util::CLICKED_UNBLACKLIST;
212 ManagePasswordsUIController* manage_passwords_ui_controller =
213 ManagePasswordsUIController::FromWebContents(web_contents());
214 manage_passwords_ui_controller->UnblacklistSite();
215 state_ = password_manager::ui::MANAGE_STATE;
218 void ManagePasswordsBubbleModel::OnSaveClicked() {
219 dismissal_reason_ = metrics_util::CLICKED_SAVE;
220 RecordExperimentStatistics(web_contents(), dismissal_reason_);
221 ManagePasswordsUIController* manage_passwords_ui_controller =
222 ManagePasswordsUIController::FromWebContents(web_contents());
223 manage_passwords_ui_controller->SavePassword();
224 state_ = password_manager::ui::MANAGE_STATE;
227 void ManagePasswordsBubbleModel::OnDoneClicked() {
228 dismissal_reason_ = metrics_util::CLICKED_DONE;
231 // TODO(gcasto): Is it worth having this be separate from OnDoneClicked()?
232 // User intent is pretty similar in both cases.
233 void ManagePasswordsBubbleModel::OnOKClicked() {
234 dismissal_reason_ = metrics_util::CLICKED_OK;
237 void ManagePasswordsBubbleModel::OnManageLinkClicked() {
238 dismissal_reason_ = metrics_util::CLICKED_MANAGE;
239 ManagePasswordsUIController::FromWebContents(web_contents())
240 ->NavigateToPasswordManagerSettingsPage();
243 void ManagePasswordsBubbleModel::OnAutoSignInToastTimeout() {
244 dismissal_reason_ = metrics_util::AUTO_SIGNIN_TOAST_TIMEOUT;
247 void ManagePasswordsBubbleModel::OnAutoSignInClicked() {
248 dismissal_reason_ = metrics_util::AUTO_SIGNIN_TOAST_CLICKED;
249 ManagePasswordsUIController* manage_passwords_ui_controller =
250 ManagePasswordsUIController::FromWebContents(web_contents());
251 manage_passwords_ui_controller->ManageAccounts();
252 state_ = password_manager::ui::MANAGE_STATE;
255 void ManagePasswordsBubbleModel::OnPasswordAction(
256 const autofill::PasswordForm& password_form,
257 PasswordAction action) {
258 if (!web_contents())
259 return;
260 Profile* profile =
261 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
262 password_manager::PasswordStore* password_store =
263 PasswordStoreFactory::GetForProfile(
264 profile, ServiceAccessType::EXPLICIT_ACCESS).get();
265 DCHECK(password_store);
266 if (action == REMOVE_PASSWORD)
267 password_store->RemoveLogin(password_form);
268 else
269 password_store->AddLogin(password_form);
272 void ManagePasswordsBubbleModel::OnChooseCredentials(
273 const autofill::PasswordForm& password_form,
274 password_manager::CredentialType credential_type) {
275 dismissal_reason_ = metrics_util::CLICKED_CREDENTIAL;
276 ManagePasswordsUIController* manage_passwords_ui_controller =
277 ManagePasswordsUIController::FromWebContents(web_contents());
278 manage_passwords_ui_controller->ChooseCredential(password_form,
279 credential_type);
280 state_ = password_manager::ui::INACTIVE_STATE;
283 Profile* ManagePasswordsBubbleModel::GetProfile() const {
284 return GetProfileFromWebContents(web_contents());
287 bool ManagePasswordsBubbleModel::IsNewUIActive() const {
288 return base::CommandLine::ForCurrentProcess()->HasSwitch(
289 switches::kEnableCredentialManagerAPI);
292 // static
293 int ManagePasswordsBubbleModel::UsernameFieldWidth() {
294 return GetFieldWidth(USERNAME_FIELD);
297 // static
298 int ManagePasswordsBubbleModel::PasswordFieldWidth() {
299 return GetFieldWidth(PASSWORD_FIELD);
302 base::string16
303 ManagePasswordsBubbleModel::PendingStateTitleBasedOnSavePasswordPref() const {
304 int message_id = 0;
305 if (never_save_passwords_)
306 message_id = IDS_MANAGE_PASSWORDS_BLACKLIST_CONFIRMATION_TITLE;
307 else if (IsNewUIActive())
308 message_id = IDS_PASSWORD_MANAGER_SAVE_PASSWORD_SMART_LOCK_PROMPT;
309 else
310 message_id = IDS_SAVE_PASSWORD;
311 return l10n_util::GetStringUTF16(message_id);