1 // Copyright 2015 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_state.h"
7 #include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
8 #include "components/password_manager/core/browser/password_form_manager.h"
9 #include "components/password_manager/core/browser/password_manager_client.h"
10 #include "components/password_manager/core/common/credential_manager_types.h"
12 using password_manager::PasswordFormManager
;
13 using autofill::PasswordFormMap
;
17 // Converts the map with pointers or const pointers to the vector of const
20 std::vector
<const T
*> MapToVector(
21 const std::map
<base::string16
, T
*>& map
) {
22 std::vector
<const autofill::PasswordForm
*> ret
;
23 ret
.reserve(map
.size());
24 for (const auto& form_pair
: map
)
25 ret
.push_back(form_pair
.second
);
29 ScopedVector
<const autofill::PasswordForm
> DeepCopyMapToVector(
30 const PasswordFormMap
& password_form_map
) {
31 ScopedVector
<const autofill::PasswordForm
> ret
;
32 ret
.reserve(password_form_map
.size());
33 for (const auto& form_pair
: password_form_map
)
34 ret
.push_back(new autofill::PasswordForm(*form_pair
.second
));
38 ScopedVector
<const autofill::PasswordForm
> ConstifyVector(
39 ScopedVector
<autofill::PasswordForm
>* forms
) {
40 ScopedVector
<const autofill::PasswordForm
> ret
;
41 ret
.assign(forms
->begin(), forms
->end());
46 // True if the unique keys for the forms are the same. The unique key is
47 // (origin, username_element, username_value, password_element, signon_realm).
48 bool IsEqualUniqueKey(const autofill::PasswordForm
& left
,
49 const autofill::PasswordForm
& right
) {
50 return left
.signon_realm
== right
.signon_realm
&&
51 left
.origin
== right
.origin
&&
52 left
.username_element
== right
.username_element
&&
53 left
.username_value
== right
.username_value
&&
54 left
.password_element
== right
.password_element
;
57 // Updates one form in |forms| that has the same unique key as |updated_form|.
58 // Returns true if the form was found and updated.
59 bool UpdateFormInVector(const autofill::PasswordForm
& updated_form
,
60 ScopedVector
<const autofill::PasswordForm
>* forms
) {
61 ScopedVector
<const autofill::PasswordForm
>::iterator it
= std::find_if(
62 forms
->begin(), forms
->end(),
63 [&updated_form
](const autofill::PasswordForm
* form
) {
64 return IsEqualUniqueKey(*form
, updated_form
);
66 if (it
!= forms
->end()) {
68 *it
= new autofill::PasswordForm(updated_form
);
74 // Removes a form from |forms| that has the same unique key as |form_to_delete|.
75 template <class Vector
>
76 void RemoveFormFromVector(const autofill::PasswordForm
& form_to_delete
,
78 typename
Vector::iterator it
= std::find_if(
79 forms
->begin(), forms
->end(),
80 [&form_to_delete
](const autofill::PasswordForm
* form
) {
81 return IsEqualUniqueKey(*form
, form_to_delete
);
83 if (it
!= forms
->end())
87 // Inserts |form| to the beginning of |forms| if it's blacklisted or to the end
88 // otherwise. UnblacklistSite() expects the first saved password to be the
89 // blacklisted credential.
90 template <class Vector
>
91 void InsertFormToVector(const autofill::PasswordForm
* form
,
93 typename
Vector::iterator it
= form
->blacklisted_by_user
? forms
->begin()
95 forms
->insert(it
, form
);
100 ManagePasswordsState::ManagePasswordsState()
101 : state_(password_manager::ui::INACTIVE_STATE
),
105 ManagePasswordsState::~ManagePasswordsState() {}
107 void ManagePasswordsState::OnPendingPassword(
108 scoped_ptr
<password_manager::PasswordFormManager
> form_manager
) {
110 form_manager_
= form_manager
.Pass();
111 current_forms_weak_
= MapToVector(form_manager_
->best_matches());
112 origin_
= form_manager_
->pending_credentials().origin
;
113 SetState(password_manager::ui::PENDING_PASSWORD_STATE
);
116 void ManagePasswordsState::OnRequestCredentials(
117 ScopedVector
<autofill::PasswordForm
> local_credentials
,
118 ScopedVector
<autofill::PasswordForm
> federated_credentials
,
119 const GURL
& origin
) {
121 local_credentials_forms_
= ConstifyVector(&local_credentials
);
122 federated_credentials_forms_
= ConstifyVector(&federated_credentials
);
124 SetState(password_manager::ui::CREDENTIAL_REQUEST_STATE
);
127 void ManagePasswordsState::OnAutoSignin(
128 ScopedVector
<autofill::PasswordForm
> local_forms
) {
129 DCHECK(!local_forms
.empty());
131 local_credentials_forms_
= ConstifyVector(&local_forms
);
132 origin_
= local_credentials_forms_
[0]->origin
;
133 SetState(password_manager::ui::AUTO_SIGNIN_STATE
);
136 void ManagePasswordsState::OnAutomaticPasswordSave(
137 scoped_ptr
<PasswordFormManager
> form_manager
) {
139 form_manager_
= form_manager
.Pass();
140 autofill::ConstPasswordFormMap current_forms
;
141 current_forms
.insert(form_manager_
->best_matches().begin(),
142 form_manager_
->best_matches().end());
143 current_forms
[form_manager_
->associated_username()] =
144 &form_manager_
->pending_credentials();
145 current_forms_weak_
= MapToVector(current_forms
);
146 origin_
= form_manager_
->pending_credentials().origin
;
147 SetState(password_manager::ui::CONFIRMATION_STATE
);
150 void ManagePasswordsState::OnPasswordAutofilled(
151 const PasswordFormMap
& password_form_map
) {
152 DCHECK(!password_form_map
.empty());
154 if (password_form_map
.begin()->second
->IsPublicSuffixMatch()) {
155 // Don't show the UI for PSL matched passwords. They are not stored for this
156 // page and cannot be deleted.
158 SetState(password_manager::ui::INACTIVE_STATE
);
160 local_credentials_forms_
= DeepCopyMapToVector(password_form_map
);
161 origin_
= local_credentials_forms_
.front()->origin
;
162 SetState(password_manager::ui::MANAGE_STATE
);
166 void ManagePasswordsState::OnBlacklistBlockedAutofill(
167 const autofill::PasswordFormMap
& password_form_map
) {
168 DCHECK(!password_form_map
.empty());
170 local_credentials_forms_
= DeepCopyMapToVector(password_form_map
);
171 origin_
= local_credentials_forms_
.front()->origin
;
172 DCHECK(local_credentials_forms_
.front()->blacklisted_by_user
);
173 SetState(password_manager::ui::BLACKLIST_STATE
);
176 void ManagePasswordsState::OnInactive() {
179 SetState(password_manager::ui::INACTIVE_STATE
);
182 void ManagePasswordsState::TransitionToState(
183 password_manager::ui::State state
) {
184 DCHECK_NE(password_manager::ui::INACTIVE_STATE
, state_
);
185 DCHECK(state
== password_manager::ui::BLACKLIST_STATE
||
186 state
== password_manager::ui::MANAGE_STATE
);
187 if (state_
== password_manager::ui::CREDENTIAL_REQUEST_STATE
) {
188 if (!credentials_callback_
.is_null()) {
189 credentials_callback_
.Run(password_manager::CredentialInfo());
190 credentials_callback_
.Reset();
192 federated_credentials_forms_
.clear();
197 void ManagePasswordsState::ProcessLoginsChanged(
198 const password_manager::PasswordStoreChangeList
& changes
) {
199 if (state() == password_manager::ui::INACTIVE_STATE
)
202 for (const password_manager::PasswordStoreChange
& change
: changes
) {
203 const autofill::PasswordForm
& changed_form
= change
.form();
204 if (change
.type() == password_manager::PasswordStoreChange::REMOVE
) {
205 DeleteForm(changed_form
);
206 if (changed_form
.blacklisted_by_user
&&
207 state() == password_manager::ui::BLACKLIST_STATE
&&
208 changed_form
.origin
== origin_
) {
209 TransitionToState(password_manager::ui::MANAGE_STATE
);
212 if (change
.type() == password_manager::PasswordStoreChange::UPDATE
)
213 UpdateForm(changed_form
);
215 AddForm(changed_form
);
216 if (changed_form
.blacklisted_by_user
&&
217 changed_form
.origin
== origin_
) {
218 TransitionToState(password_manager::ui::BLACKLIST_STATE
);
224 void ManagePasswordsState::ClearData() {
225 form_manager_
.reset();
226 current_forms_weak_
.clear();
227 local_credentials_forms_
.clear();
228 federated_credentials_forms_
.clear();
229 credentials_callback_
.Reset();
232 void ManagePasswordsState::AddForm(const autofill::PasswordForm
& form
) {
233 if (form
.origin
!= origin_
)
235 if (UpdateForm(form
))
238 local_credentials_forms_
.push_back(new autofill::PasswordForm(form
));
239 InsertFormToVector(local_credentials_forms_
.back(), ¤t_forms_weak_
);
241 InsertFormToVector(new autofill::PasswordForm(form
),
242 &local_credentials_forms_
);
246 bool ManagePasswordsState::UpdateForm(const autofill::PasswordForm
& form
) {
248 // |current_forms_weak_| contains the list of current passwords.
249 std::vector
<const autofill::PasswordForm
*>::iterator it
= std::find_if(
250 current_forms_weak_
.begin(), current_forms_weak_
.end(),
251 [&form
](const autofill::PasswordForm
* current_form
) {
252 return IsEqualUniqueKey(form
, *current_form
);
254 if (it
!= current_forms_weak_
.end()) {
255 RemoveFormFromVector(form
, &local_credentials_forms_
);
256 local_credentials_forms_
.push_back(new autofill::PasswordForm(form
));
257 *it
= local_credentials_forms_
.back();
261 // |current_forms_weak_| isn't used.
262 bool updated_locals
= UpdateFormInVector(form
, &local_credentials_forms_
);
263 return (UpdateFormInVector(form
, &federated_credentials_forms_
) ||
269 void ManagePasswordsState::DeleteForm(const autofill::PasswordForm
& form
) {
270 RemoveFormFromVector(form
, ¤t_forms_weak_
);
271 RemoveFormFromVector(form
, &local_credentials_forms_
);
272 RemoveFormFromVector(form
, &federated_credentials_forms_
);
275 void ManagePasswordsState::SetState(password_manager::ui::State state
) {
277 if (client_
->IsLoggingActive()) {
278 password_manager::BrowserSavePasswordProgressLogger
logger(client_
);
280 autofill::SavePasswordProgressLogger::STRING_NEW_UI_STATE
,