Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / passwords / manage_passwords_bubble_model.cc
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.
4
5 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
6
7 #include "base/strings/string_split.h"
8 #include "base/strings/string_util.h"
9 #include "chrome/browser/password_manager/password_store_factory.h"
10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/browser_finder.h"
12 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
13 #include "chrome/grit/generated_resources.h"
14 #include "components/password_manager/core/browser/password_store.h"
15 #include "components/password_manager/core/common/password_manager_ui.h"
16 #include "ui/base/l10n/l10n_util.h"
17 #include "ui/base/resource/resource_bundle.h"
18
19 using autofill::PasswordFormMap;
20 using content::WebContents;
21 namespace metrics_util = password_manager::metrics_util;
22
23 namespace {
24
25 enum FieldType { USERNAME_FIELD, PASSWORD_FIELD };
26
27 const int kUsernameFieldSize = 30;
28 const int kPasswordFieldSize = 22;
29
30 // Returns the width of |type| field.
31 int GetFieldWidth(FieldType type) {
32   return ui::ResourceBundle::GetSharedInstance()
33       .GetFontList(ui::ResourceBundle::SmallFont)
34       .GetExpectedTextWidth(type == USERNAME_FIELD ? kUsernameFieldSize
35                                                    : kPasswordFieldSize);
36 }
37
38 void SetupLinkifiedText(const base::string16& string_with_separator,
39                         base::string16* text,
40                         gfx::Range* link_range) {
41   std::vector<base::string16> pieces;
42   base::SplitStringDontTrim(string_with_separator,
43                             '|',  // separator
44                             &pieces);
45   DCHECK_EQ(3u, pieces.size());
46   *link_range = gfx::Range(pieces[0].size(),
47                            pieces[0].size() + pieces[1].size());
48   *text = JoinString(pieces, base::string16());
49 }
50
51 }  // namespace
52
53 ManagePasswordsBubbleModel::ManagePasswordsBubbleModel(
54     content::WebContents* web_contents)
55     : content::WebContentsObserver(web_contents),
56       display_disposition_(
57           metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING),
58       dismissal_reason_(metrics_util::NOT_DISPLAYED) {
59   ManagePasswordsUIController* controller =
60       ManagePasswordsUIController::FromWebContents(web_contents);
61
62   // TODO(mkwst): Reverse this logic. The controller should populate the model
63   // directly rather than the model pulling from the controller. Perhaps like
64   // `controller->PopulateModel(this)`.
65   state_ = controller->state();
66   if (password_manager::ui::IsPendingState(state_))
67     pending_credentials_ = controller->PendingCredentials();
68   best_matches_ = controller->best_matches();
69
70   if (password_manager::ui::IsPendingState(state_)) {
71     title_ = l10n_util::GetStringUTF16(IDS_SAVE_PASSWORD);
72   } else if (state_ == password_manager::ui::BLACKLIST_STATE) {
73     title_ = l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_BLACKLISTED_TITLE);
74   } else if (state_ == password_manager::ui::CONFIRMATION_STATE) {
75     title_ =
76         l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_TITLE);
77   } else {
78     title_ = l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_TITLE);
79   }
80
81   SetupLinkifiedText(
82       l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_TEXT),
83       &save_confirmation_text_,
84       &save_confirmation_link_range_);
85
86   manage_link_ =
87       l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_MANAGE_PASSWORDS_LINK);
88 }
89
90 ManagePasswordsBubbleModel::~ManagePasswordsBubbleModel() {}
91
92 void ManagePasswordsBubbleModel::OnBubbleShown(
93     ManagePasswordsBubble::DisplayReason reason) {
94   if (reason == ManagePasswordsBubble::USER_ACTION) {
95     if (password_manager::ui::IsPendingState(state_)) {
96       display_disposition_ = metrics_util::MANUAL_WITH_PASSWORD_PENDING;
97     } else if (state_ == password_manager::ui::BLACKLIST_STATE) {
98       display_disposition_ = metrics_util::MANUAL_BLACKLISTED;
99     } else {
100       display_disposition_ = metrics_util::MANUAL_MANAGE_PASSWORDS;
101     }
102   } else {
103     if (state_ == password_manager::ui::CONFIRMATION_STATE) {
104       display_disposition_ =
105           metrics_util::AUTOMATIC_GENERATED_PASSWORD_CONFIRMATION;
106     } else {
107       display_disposition_ = metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING;
108     }
109   }
110   metrics_util::LogUIDisplayDisposition(display_disposition_);
111
112   // Default to a dismissal reason of "no interaction". If the user interacts
113   // with the button in such a way that it closes, we'll reset this value
114   // accordingly.
115   dismissal_reason_ = metrics_util::NO_DIRECT_INTERACTION;
116 }
117
118 void ManagePasswordsBubbleModel::OnBubbleHidden() {
119   if (dismissal_reason_ == metrics_util::NOT_DISPLAYED)
120     return;
121
122   metrics_util::LogUIDismissalReason(dismissal_reason_);
123 }
124
125 void ManagePasswordsBubbleModel::OnNopeClicked() {
126   dismissal_reason_ = metrics_util::CLICKED_NOPE;
127   state_ = password_manager::ui::PENDING_PASSWORD_STATE;
128 }
129
130 void ManagePasswordsBubbleModel::OnNeverForThisSiteClicked() {
131   dismissal_reason_ = metrics_util::CLICKED_NEVER;
132   ManagePasswordsUIController* manage_passwords_ui_controller =
133       ManagePasswordsUIController::FromWebContents(web_contents());
134   manage_passwords_ui_controller->NeverSavePassword();
135   state_ = password_manager::ui::BLACKLIST_STATE;
136 }
137
138 void ManagePasswordsBubbleModel::OnUnblacklistClicked() {
139   dismissal_reason_ = metrics_util::CLICKED_UNBLACKLIST;
140   ManagePasswordsUIController* manage_passwords_ui_controller =
141       ManagePasswordsUIController::FromWebContents(web_contents());
142   manage_passwords_ui_controller->UnblacklistSite();
143   state_ = password_manager::ui::MANAGE_STATE;
144 }
145
146 void ManagePasswordsBubbleModel::OnSaveClicked() {
147   dismissal_reason_ = metrics_util::CLICKED_SAVE;
148   ManagePasswordsUIController* manage_passwords_ui_controller =
149       ManagePasswordsUIController::FromWebContents(web_contents());
150   manage_passwords_ui_controller->SavePassword();
151   state_ = password_manager::ui::MANAGE_STATE;
152 }
153
154 void ManagePasswordsBubbleModel::OnDoneClicked() {
155   dismissal_reason_ = metrics_util::CLICKED_DONE;
156 }
157
158 // TODO(gcasto): Is it worth having this be separate from OnDoneClicked()?
159 // User intent is pretty similar in both cases.
160 void ManagePasswordsBubbleModel::OnOKClicked() {
161   dismissal_reason_ = metrics_util::CLICKED_OK;
162 }
163
164 void ManagePasswordsBubbleModel::OnManageLinkClicked() {
165   dismissal_reason_ = metrics_util::CLICKED_MANAGE;
166   ManagePasswordsUIController::FromWebContents(web_contents())
167       ->NavigateToPasswordManagerSettingsPage();
168 }
169
170 void ManagePasswordsBubbleModel::OnPasswordAction(
171     const autofill::PasswordForm& password_form,
172     PasswordAction action) {
173   if (!web_contents())
174     return;
175   Profile* profile =
176       Profile::FromBrowserContext(web_contents()->GetBrowserContext());
177   password_manager::PasswordStore* password_store =
178       PasswordStoreFactory::GetForProfile(profile, Profile::EXPLICIT_ACCESS)
179           .get();
180   DCHECK(password_store);
181   if (action == REMOVE_PASSWORD)
182     password_store->RemoveLogin(password_form);
183   else
184     password_store->AddLogin(password_form);
185 }
186
187 // static
188 int ManagePasswordsBubbleModel::UsernameFieldWidth() {
189   return GetFieldWidth(USERNAME_FIELD);
190 }
191
192 // static
193 int ManagePasswordsBubbleModel::PasswordFieldWidth() {
194   return GetFieldWidth(PASSWORD_FIELD);
195 }