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