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.
4
5 #include "chrome/browser/ui/passwords/manage_passwords_state.h"
6
7 #include <algorithm>
8 #include <utility>
9
10 #include "components/autofill/core/browser/logging/log_manager.h"
11 #include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
12 #include "components/password_manager/core/browser/password_form_manager_for_ui.h"
13 #include "components/password_manager/core/browser/password_manager.h"
14 #include "components/password_manager/core/browser/password_manager_client.h"
15
16 using password_manager::PasswordForm;
17 using password_manager::PasswordFormManagerForUI;
18
19 namespace {
20
DeepCopyNonPSLVector(const std::vector<const PasswordForm * > & password_forms)21 std::vector<std::unique_ptr<PasswordForm>> DeepCopyNonPSLVector(
22 const std::vector<const PasswordForm*>& password_forms) {
23 std::vector<std::unique_ptr<PasswordForm>> result;
24 result.reserve(password_forms.size());
25 for (const PasswordForm* form : password_forms) {
26 if (!form->is_public_suffix_match)
27 result.push_back(std::make_unique<PasswordForm>(*form));
28 }
29 return result;
30 }
31
AppendDeepCopyVector(const std::vector<const PasswordForm * > & forms,std::vector<std::unique_ptr<PasswordForm>> * result)32 void AppendDeepCopyVector(const std::vector<const PasswordForm*>& forms,
33 std::vector<std::unique_ptr<PasswordForm>>* result) {
34 result->reserve(result->size() + forms.size());
35 for (auto* form : forms)
36 result->push_back(std::make_unique<PasswordForm>(*form));
37 }
38
39 // Updates one form in |forms| that has the same unique key as |updated_form|.
40 // Returns true if the form was found and updated.
UpdateFormInVector(const PasswordForm & updated_form,std::vector<std::unique_ptr<PasswordForm>> * forms)41 bool UpdateFormInVector(const PasswordForm& updated_form,
42 std::vector<std::unique_ptr<PasswordForm>>* forms) {
43 auto it =
44 std::find_if(forms->begin(), forms->end(),
45 [&updated_form](const std::unique_ptr<PasswordForm>& form) {
46 return ArePasswordFormUniqueKeysEqual(*form, updated_form);
47 });
48 if (it != forms->end()) {
49 **it = updated_form;
50 return true;
51 }
52 return false;
53 }
54
55 // Removes a form from |forms| that has the same unique key as |form_to_delete|.
56 // Returns true iff the form was deleted.
RemoveFormFromVector(const PasswordForm & form_to_delete,std::vector<std::unique_ptr<PasswordForm>> * forms)57 bool RemoveFormFromVector(const PasswordForm& form_to_delete,
58 std::vector<std::unique_ptr<PasswordForm>>* forms) {
59 auto it = std::find_if(
60 forms->begin(), forms->end(),
61 [&form_to_delete](const std::unique_ptr<PasswordForm>& form) {
62 return ArePasswordFormUniqueKeysEqual(*form, form_to_delete);
63 });
64 if (it != forms->end()) {
65 forms->erase(it);
66 return true;
67 }
68 return false;
69 }
70
71 } // namespace
72
ManagePasswordsState()73 ManagePasswordsState::ManagePasswordsState()
74 : state_(password_manager::ui::INACTIVE_STATE), client_(nullptr) {}
75
~ManagePasswordsState()76 ManagePasswordsState::~ManagePasswordsState() {}
77
OnPendingPassword(std::unique_ptr<PasswordFormManagerForUI> form_manager)78 void ManagePasswordsState::OnPendingPassword(
79 std::unique_ptr<PasswordFormManagerForUI> form_manager) {
80 ClearData();
81 form_manager_ = std::move(form_manager);
82 local_credentials_forms_ =
83 DeepCopyNonPSLVector(form_manager_->GetBestMatches());
84 AppendDeepCopyVector(form_manager_->GetFederatedMatches(),
85 &local_credentials_forms_);
86 origin_ = url::Origin::Create(form_manager_->GetURL());
87 SetState(password_manager::ui::PENDING_PASSWORD_STATE);
88 }
89
OnUpdatePassword(std::unique_ptr<password_manager::PasswordFormManagerForUI> form_manager)90 void ManagePasswordsState::OnUpdatePassword(
91 std::unique_ptr<password_manager::PasswordFormManagerForUI> form_manager) {
92 ClearData();
93 form_manager_ = std::move(form_manager);
94 local_credentials_forms_ =
95 DeepCopyNonPSLVector(form_manager_->GetBestMatches());
96 AppendDeepCopyVector(form_manager_->GetFederatedMatches(),
97 &local_credentials_forms_);
98 origin_ = url::Origin::Create(form_manager_->GetURL());
99 SetState(password_manager::ui::PENDING_PASSWORD_UPDATE_STATE);
100 }
101
OnRequestCredentials(std::vector<std::unique_ptr<PasswordForm>> local_credentials,const url::Origin & origin)102 void ManagePasswordsState::OnRequestCredentials(
103 std::vector<std::unique_ptr<PasswordForm>> local_credentials,
104 const url::Origin& origin) {
105 ClearData();
106 local_credentials_forms_ = std::move(local_credentials);
107 origin_ = origin;
108 SetState(password_manager::ui::CREDENTIAL_REQUEST_STATE);
109 }
110
OnAutoSignin(std::vector<std::unique_ptr<PasswordForm>> local_forms,const url::Origin & origin)111 void ManagePasswordsState::OnAutoSignin(
112 std::vector<std::unique_ptr<PasswordForm>> local_forms,
113 const url::Origin& origin) {
114 DCHECK(!local_forms.empty());
115 ClearData();
116 local_credentials_forms_ = std::move(local_forms);
117 origin_ = origin;
118 SetState(password_manager::ui::AUTO_SIGNIN_STATE);
119 }
120
OnAutomaticPasswordSave(std::unique_ptr<PasswordFormManagerForUI> form_manager)121 void ManagePasswordsState::OnAutomaticPasswordSave(
122 std::unique_ptr<PasswordFormManagerForUI> form_manager) {
123 ClearData();
124 form_manager_ = std::move(form_manager);
125 for (const auto* form : form_manager_->GetBestMatches()) {
126 if (form->is_public_suffix_match)
127 continue;
128 local_credentials_forms_.push_back(std::make_unique<PasswordForm>(*form));
129 }
130 AppendDeepCopyVector(form_manager_->GetFederatedMatches(),
131 &local_credentials_forms_);
132 origin_ = url::Origin::Create(form_manager_->GetURL());
133 SetState(password_manager::ui::CONFIRMATION_STATE);
134 }
135
OnPasswordAutofilled(const std::vector<const PasswordForm * > & password_forms,url::Origin origin,const std::vector<const PasswordForm * > * federated_matches)136 void ManagePasswordsState::OnPasswordAutofilled(
137 const std::vector<const PasswordForm*>& password_forms,
138 url::Origin origin,
139 const std::vector<const PasswordForm*>* federated_matches) {
140 DCHECK(!password_forms.empty() ||
141 (federated_matches && !federated_matches->empty()));
142 auto local_credentials_forms = DeepCopyNonPSLVector(password_forms);
143 if (federated_matches)
144 AppendDeepCopyVector(*federated_matches, &local_credentials_forms);
145
146 // Delete |form_manager_| only when the parameters are processed. They may be
147 // coming from |form_manager_|.
148 ClearData();
149
150 if (local_credentials_forms.empty()) {
151 // Don't show the UI for PSL matched passwords. They are not stored for this
152 // page and cannot be deleted.
153 OnInactive();
154 } else {
155 origin_ = std::move(origin);
156 local_credentials_forms_ = std::move(local_credentials_forms);
157 SetState(password_manager::ui::MANAGE_STATE);
158 }
159 }
160
OnInactive()161 void ManagePasswordsState::OnInactive() {
162 ClearData();
163 origin_ = url::Origin();
164 SetState(password_manager::ui::INACTIVE_STATE);
165 }
166
OnPasswordMovable(std::unique_ptr<PasswordFormManagerForUI> form_to_move)167 void ManagePasswordsState::OnPasswordMovable(
168 std::unique_ptr<PasswordFormManagerForUI> form_to_move) {
169 ClearData();
170 form_manager_ = std::move(form_to_move);
171 local_credentials_forms_ =
172 DeepCopyNonPSLVector(form_manager_->GetBestMatches());
173 AppendDeepCopyVector(form_manager_->GetFederatedMatches(),
174 &local_credentials_forms_);
175 origin_ = url::Origin::Create(form_manager_->GetURL());
176 SetState(password_manager::ui::CAN_MOVE_PASSWORD_TO_ACCOUNT_STATE);
177 }
178
TransitionToState(password_manager::ui::State state)179 void ManagePasswordsState::TransitionToState(
180 password_manager::ui::State state) {
181 DCHECK_NE(password_manager::ui::INACTIVE_STATE, state_);
182 DCHECK(state == password_manager::ui::MANAGE_STATE ||
183 state == password_manager::ui::PASSWORD_UPDATED_SAFE_STATE ||
184 state == password_manager::ui::PASSWORD_UPDATED_MORE_TO_FIX ||
185 state == password_manager::ui::PASSWORD_UPDATED_UNSAFE_STATE)
186 << state_;
187 if (state_ == password_manager::ui::CREDENTIAL_REQUEST_STATE) {
188 if (!credentials_callback_.is_null()) {
189 std::move(credentials_callback_).Run(nullptr);
190 }
191 }
192 SetState(state);
193 }
194
ProcessLoginsChanged(const password_manager::PasswordStoreChangeList & changes)195 void ManagePasswordsState::ProcessLoginsChanged(
196 const password_manager::PasswordStoreChangeList& changes) {
197 if (state() == password_manager::ui::INACTIVE_STATE)
198 return;
199
200 bool applied_delete = false;
201 bool all_changes_are_deletion = true;
202 for (const password_manager::PasswordStoreChange& change : changes) {
203 if (change.type() != password_manager::PasswordStoreChange::REMOVE)
204 all_changes_are_deletion = false;
205 const PasswordForm& changed_form = change.form();
206 if (changed_form.blocked_by_user)
207 continue;
208 if (change.type() == password_manager::PasswordStoreChange::REMOVE) {
209 if (RemoveFormFromVector(changed_form, &local_credentials_forms_))
210 applied_delete = true;
211 } else if (change.type() == password_manager::PasswordStoreChange::UPDATE) {
212 UpdateFormInVector(changed_form, &local_credentials_forms_);
213 } else {
214 DCHECK_EQ(password_manager::PasswordStoreChange::ADD, change.type());
215 AddForm(changed_form);
216 }
217 }
218 // Let the password manager know that it should update the list of the
219 // credentials. We react only to deletion because in case the password manager
220 // itself adds a credential, they should not be refetched. The password
221 // generation can be confused as the generated password will be refetched and
222 // autofilled immediately.
223 if (applied_delete && all_changes_are_deletion)
224 client_->UpdateFormManagers();
225 }
226
ProcessUnsyncedCredentialsWillBeDeleted(std::vector<password_manager::PasswordForm> unsynced_credentials)227 void ManagePasswordsState::ProcessUnsyncedCredentialsWillBeDeleted(
228 std::vector<password_manager::PasswordForm> unsynced_credentials) {
229 unsynced_credentials_ = std::move(unsynced_credentials);
230 SetState(password_manager::ui::WILL_DELETE_UNSYNCED_ACCOUNT_PASSWORDS_STATE);
231 }
232
ChooseCredential(const PasswordForm * form)233 void ManagePasswordsState::ChooseCredential(const PasswordForm* form) {
234 DCHECK_EQ(password_manager::ui::CREDENTIAL_REQUEST_STATE, state());
235 DCHECK(!credentials_callback_.is_null());
236
237 std::move(credentials_callback_).Run(form);
238 }
239
ClearData()240 void ManagePasswordsState::ClearData() {
241 form_manager_.reset();
242 local_credentials_forms_.clear();
243 credentials_callback_.Reset();
244 unsynced_credentials_.clear();
245 }
246
AddForm(const PasswordForm & form)247 bool ManagePasswordsState::AddForm(const PasswordForm& form) {
248 if (url::Origin::Create(form.url) != origin_)
249 return false;
250 if (UpdateFormInVector(form, &local_credentials_forms_))
251 return true;
252 local_credentials_forms_.push_back(std::make_unique<PasswordForm>(form));
253 return true;
254 }
255
SetState(password_manager::ui::State state)256 void ManagePasswordsState::SetState(password_manager::ui::State state) {
257 DCHECK(client_);
258 if (client_->GetLogManager()->IsLoggingActive()) {
259 password_manager::BrowserSavePasswordProgressLogger logger(
260 client_->GetLogManager());
261 logger.LogNumber(autofill::SavePasswordProgressLogger::STRING_NEW_UI_STATE,
262 state);
263 }
264 state_ = state;
265 }
266