Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / ui / passwords / manage_passwords_state.cc
blobdda3d3ade7fd5b68dfb15202c60716813a3fc9a3
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;
15 namespace {
17 // Returns a vector containing the values of a map.
18 template <typename Map>
19 std::vector<typename Map::mapped_type> MapToVector(const Map& map) {
20 std::vector<typename Map::mapped_type> ret;
21 ret.reserve(map.size());
22 for (const auto& form_pair : map)
23 ret.push_back(form_pair.second);
24 return ret;
27 // Takes a ScopedPtrMap. Returns a vector of non-owned pointers to the elements
28 // inside the scoped_ptrs.
29 template <typename Map>
30 std::vector<const typename Map::mapped_type::element_type*>
31 ScopedPtrMapToVector(const Map& map) {
32 std::vector<const typename Map::mapped_type::element_type*> ret;
33 ret.reserve(map.size());
34 for (const auto& form_pair : map)
35 ret.push_back(form_pair.second);
36 return ret;
39 ScopedVector<const autofill::PasswordForm> DeepCopyMapToVector(
40 const PasswordFormMap& password_form_map) {
41 ScopedVector<const autofill::PasswordForm> ret;
42 ret.reserve(password_form_map.size());
43 for (const auto& form_pair : password_form_map)
44 ret.push_back(new autofill::PasswordForm(*form_pair.second));
45 return ret.Pass();
48 ScopedVector<const autofill::PasswordForm> ConstifyVector(
49 ScopedVector<autofill::PasswordForm>* forms) {
50 ScopedVector<const autofill::PasswordForm> ret;
51 ret.assign(forms->begin(), forms->end());
52 forms->weak_clear();
53 return ret.Pass();
56 // Updates one form in |forms| that has the same unique key as |updated_form|.
57 // Returns true if the form was found and updated.
58 bool UpdateFormInVector(const autofill::PasswordForm& updated_form,
59 ScopedVector<const autofill::PasswordForm>* forms) {
60 ScopedVector<const autofill::PasswordForm>::iterator it = std::find_if(
61 forms->begin(), forms->end(),
62 [&updated_form](const autofill::PasswordForm* form) {
63 return ArePasswordFormUniqueKeyEqual(*form, updated_form);
64 });
65 if (it != forms->end()) {
66 delete *it;
67 *it = new autofill::PasswordForm(updated_form);
68 return true;
70 return false;
73 // Removes a form from |forms| that has the same unique key as |form_to_delete|.
74 template <class Vector>
75 void RemoveFormFromVector(const autofill::PasswordForm& form_to_delete,
76 Vector* forms) {
77 typename Vector::iterator it = std::find_if(
78 forms->begin(), forms->end(),
79 [&form_to_delete](const autofill::PasswordForm* form) {
80 return ArePasswordFormUniqueKeyEqual(*form, form_to_delete);
81 });
82 if (it != forms->end())
83 forms->erase(it);
86 } // namespace
88 ManagePasswordsState::ManagePasswordsState()
89 : state_(password_manager::ui::INACTIVE_STATE),
90 client_(nullptr) {
93 ManagePasswordsState::~ManagePasswordsState() {}
95 void ManagePasswordsState::OnPendingPassword(
96 scoped_ptr<password_manager::PasswordFormManager> form_manager) {
97 ClearData();
98 form_manager_ = form_manager.Pass();
99 current_forms_weak_ = ScopedPtrMapToVector(form_manager_->best_matches());
100 origin_ = form_manager_->pending_credentials().origin;
101 SetState(password_manager::ui::PENDING_PASSWORD_STATE);
104 void ManagePasswordsState::OnUpdatePassword(
105 scoped_ptr<password_manager::PasswordFormManager> form_manager) {
106 ClearData();
107 form_manager_ = form_manager.Pass();
108 current_forms_weak_ = ScopedPtrMapToVector(form_manager_->best_matches());
109 origin_ = form_manager_->pending_credentials().origin;
110 SetState(password_manager::ui::PENDING_PASSWORD_UPDATE_STATE);
113 void ManagePasswordsState::OnRequestCredentials(
114 ScopedVector<autofill::PasswordForm> local_credentials,
115 ScopedVector<autofill::PasswordForm> federated_credentials,
116 const GURL& origin) {
117 ClearData();
118 local_credentials_forms_ = ConstifyVector(&local_credentials);
119 federated_credentials_forms_ = ConstifyVector(&federated_credentials);
120 origin_ = origin;
121 SetState(password_manager::ui::CREDENTIAL_REQUEST_STATE);
124 void ManagePasswordsState::OnAutoSignin(
125 ScopedVector<autofill::PasswordForm> local_forms) {
126 DCHECK(!local_forms.empty());
127 ClearData();
128 local_credentials_forms_ = ConstifyVector(&local_forms);
129 origin_ = local_credentials_forms_[0]->origin;
130 SetState(password_manager::ui::AUTO_SIGNIN_STATE);
133 void ManagePasswordsState::OnAutomaticPasswordSave(
134 scoped_ptr<PasswordFormManager> form_manager) {
135 ClearData();
136 form_manager_ = form_manager.Pass();
137 autofill::ConstPasswordFormMap current_forms;
138 current_forms.insert(form_manager_->best_matches().begin(),
139 form_manager_->best_matches().end());
140 current_forms[form_manager_->pending_credentials().username_value] =
141 &form_manager_->pending_credentials();
142 current_forms_weak_ = MapToVector(current_forms);
143 origin_ = form_manager_->pending_credentials().origin;
144 SetState(password_manager::ui::CONFIRMATION_STATE);
147 void ManagePasswordsState::OnPasswordAutofilled(
148 const PasswordFormMap& password_form_map) {
149 // TODO(vabr): Revert back to DCHECK once http://crbug.com/486931 is fixed.
150 CHECK(!password_form_map.empty());
151 ClearData();
152 if (password_form_map.begin()->second->IsPublicSuffixMatch()) {
153 // Don't show the UI for PSL matched passwords. They are not stored for this
154 // page and cannot be deleted.
155 origin_ = GURL();
156 SetState(password_manager::ui::INACTIVE_STATE);
157 } else {
158 local_credentials_forms_ = DeepCopyMapToVector(password_form_map);
159 origin_ = local_credentials_forms_.front()->origin;
160 SetState(password_manager::ui::MANAGE_STATE);
164 void ManagePasswordsState::OnInactive() {
165 ClearData();
166 origin_ = GURL();
167 SetState(password_manager::ui::INACTIVE_STATE);
170 void ManagePasswordsState::TransitionToState(
171 password_manager::ui::State state) {
172 DCHECK_NE(password_manager::ui::INACTIVE_STATE, state_);
173 DCHECK_EQ(password_manager::ui::MANAGE_STATE, state);
174 if (state_ == password_manager::ui::CREDENTIAL_REQUEST_STATE) {
175 if (!credentials_callback_.is_null()) {
176 credentials_callback_.Run(password_manager::CredentialInfo());
177 credentials_callback_.Reset();
179 federated_credentials_forms_.clear();
181 SetState(state);
184 void ManagePasswordsState::ProcessLoginsChanged(
185 const password_manager::PasswordStoreChangeList& changes) {
186 if (state() == password_manager::ui::INACTIVE_STATE)
187 return;
189 for (const password_manager::PasswordStoreChange& change : changes) {
190 const autofill::PasswordForm& changed_form = change.form();
191 if (changed_form.blacklisted_by_user)
192 continue;
193 if (change.type() == password_manager::PasswordStoreChange::REMOVE) {
194 DeleteForm(changed_form);
195 } else {
196 if (change.type() == password_manager::PasswordStoreChange::UPDATE)
197 UpdateForm(changed_form);
198 else
199 AddForm(changed_form);
204 void ManagePasswordsState::ClearData() {
205 form_manager_.reset();
206 current_forms_weak_.clear();
207 local_credentials_forms_.clear();
208 federated_credentials_forms_.clear();
209 credentials_callback_.Reset();
212 void ManagePasswordsState::AddForm(const autofill::PasswordForm& form) {
213 if (form.origin != origin_)
214 return;
215 if (UpdateForm(form))
216 return;
217 if (form_manager_) {
218 local_credentials_forms_.push_back(new autofill::PasswordForm(form));
219 current_forms_weak_.push_back(local_credentials_forms_.back());
220 } else {
221 local_credentials_forms_.push_back(new autofill::PasswordForm(form));
225 bool ManagePasswordsState::UpdateForm(const autofill::PasswordForm& form) {
226 if (form_manager_) {
227 // |current_forms_weak_| contains the list of current passwords.
228 std::vector<const autofill::PasswordForm*>::iterator it = std::find_if(
229 current_forms_weak_.begin(), current_forms_weak_.end(),
230 [&form](const autofill::PasswordForm* current_form) {
231 return ArePasswordFormUniqueKeyEqual(form, *current_form);
233 if (it != current_forms_weak_.end()) {
234 RemoveFormFromVector(form, &local_credentials_forms_);
235 local_credentials_forms_.push_back(new autofill::PasswordForm(form));
236 *it = local_credentials_forms_.back();
237 return true;
239 } else {
240 // |current_forms_weak_| isn't used.
241 bool updated_locals = UpdateFormInVector(form, &local_credentials_forms_);
242 return (UpdateFormInVector(form, &federated_credentials_forms_) ||
243 updated_locals);
245 return false;
248 void ManagePasswordsState::DeleteForm(const autofill::PasswordForm& form) {
249 RemoveFormFromVector(form, &current_forms_weak_);
250 RemoveFormFromVector(form, &local_credentials_forms_);
251 RemoveFormFromVector(form, &federated_credentials_forms_);
254 void ManagePasswordsState::SetState(password_manager::ui::State state) {
255 DCHECK(client_);
256 if (client_->IsLoggingActive()) {
257 password_manager::BrowserSavePasswordProgressLogger logger(client_);
258 logger.LogNumber(
259 autofill::SavePasswordProgressLogger::STRING_NEW_UI_STATE,
260 state);
262 state_ = state;