1 // Copyright 2016 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 "components/password_manager/core/browser/form_saver_impl.h"
6
7 #include <memory>
8 #include <vector>
9
10 #include "base/strings/string16.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/time/time.h"
13 #include "components/password_manager/core/browser/password_manager_util.h"
14 #include "components/password_manager/core/browser/password_store.h"
15 #include "google_apis/gaia/gaia_auth_util.h"
16 #include "google_apis/gaia/gaia_urls.h"
17 #include "url/gurl.h"
18 #include "url/origin.h"
19
20 using autofill::FormData;
21 using autofill::FormFieldData;
22 using autofill::PasswordForm;
23
24 namespace password_manager {
25
26 namespace {
27
28 // Remove all information from |form| that is not required for signature
29 // calculation.
SanitizeFormData(FormData * form)30 void SanitizeFormData(FormData* form) {
31 form->main_frame_origin = url::Origin();
32 for (FormFieldData& field : form->fields) {
33 field.label.clear();
34 field.value.clear();
35 field.autocomplete_attribute.clear();
36 field.option_values.clear();
37 field.option_contents.clear();
38 field.placeholder.clear();
39 field.css_classes.clear();
40 field.id_attribute.clear();
41 field.name_attribute.clear();
42 }
43 }
44
45 // Do the clean up of |matches| after |pending| was just pushed to the store.
PostProcessMatches(const PasswordForm & pending,const std::vector<const PasswordForm * > & matches,const base::string16 & old_password,PasswordStore * store)46 void PostProcessMatches(const PasswordForm& pending,
47 const std::vector<const PasswordForm*>& matches,
48 const base::string16& old_password,
49 PasswordStore* store) {
50 DCHECK(!pending.blacklisted_by_user);
51
52 // Update existing matches in the password store.
53 for (const auto* match : matches) {
54 if (match->IsFederatedCredential() ||
55 ArePasswordFormUniqueKeysEqual(pending, *match))
56 continue;
57 // Delete obsolete empty username credentials.
58 const bool same_password = match->password_value == pending.password_value;
59 const bool username_was_added =
60 match->username_value.empty() && !pending.username_value.empty();
61 if (same_password && username_was_added && !match->is_public_suffix_match) {
62 store->RemoveLogin(*match);
63 continue;
64 }
65 const bool same_username = match->username_value == pending.username_value;
66 if (same_username) {
67 // Maybe update the password value.
68 const bool form_has_old_password = match->password_value == old_password;
69 if (form_has_old_password) {
70 PasswordForm form_to_update = *match;
71 form_to_update.password_value = pending.password_value;
72 SanitizeFormData(&form_to_update.form_data);
73 store->UpdateLogin(std::move(form_to_update));
74 }
75 }
76 }
77 }
78
79 } // namespace
80
FormSaverImpl(PasswordStore * store)81 FormSaverImpl::FormSaverImpl(PasswordStore* store) : store_(store) {
82 DCHECK(store);
83 }
84
85 FormSaverImpl::~FormSaverImpl() = default;
86
PermanentlyBlacklist(PasswordStore::FormDigest digest)87 PasswordForm FormSaverImpl::PermanentlyBlacklist(
88 PasswordStore::FormDigest digest) {
89 PasswordForm blacklisted =
90 password_manager_util::MakeNormalizedBlacklistedForm(std::move(digest));
91 blacklisted.date_created = base::Time::Now();
92 store_->AddLogin(blacklisted);
93 return blacklisted;
94 }
95
Unblacklist(const PasswordStore::FormDigest & digest)96 void FormSaverImpl::Unblacklist(const PasswordStore::FormDigest& digest) {
97 store_->Unblacklist(digest, /*completion=*/base::DoNothing());
98 }
99
Save(PasswordForm pending,const std::vector<const PasswordForm * > & matches,const base::string16 & old_password)100 void FormSaverImpl::Save(PasswordForm pending,
101 const std::vector<const PasswordForm*>& matches,
102 const base::string16& old_password) {
103 SanitizeFormData(&pending.form_data);
104 store_->AddLogin(pending);
105 // Update existing matches in the password store.
106 PostProcessMatches(pending, matches, old_password, store_);
107 }
108
Update(autofill::PasswordForm pending,const std::vector<const autofill::PasswordForm * > & matches,const base::string16 & old_password)109 void FormSaverImpl::Update(
110 autofill::PasswordForm pending,
111 const std::vector<const autofill::PasswordForm*>& matches,
112 const base::string16& old_password) {
113 SanitizeFormData(&pending.form_data);
114 store_->UpdateLogin(pending);
115 // Update existing matches in the password store.
116 PostProcessMatches(pending, matches, old_password, store_);
117 }
118
UpdateReplace(autofill::PasswordForm pending,const std::vector<const autofill::PasswordForm * > & matches,const base::string16 & old_password,const autofill::PasswordForm & old_unique_key)119 void FormSaverImpl::UpdateReplace(
120 autofill::PasswordForm pending,
121 const std::vector<const autofill::PasswordForm*>& matches,
122 const base::string16& old_password,
123 const autofill::PasswordForm& old_unique_key) {
124 SanitizeFormData(&pending.form_data);
125 store_->UpdateLoginWithPrimaryKey(pending, old_unique_key);
126 // Update existing matches in the password store.
127 PostProcessMatches(pending, matches, old_password, store_);
128 }
129
Remove(const PasswordForm & form)130 void FormSaverImpl::Remove(const PasswordForm& form) {
131 store_->RemoveLogin(form);
132 }
133
Clone()134 std::unique_ptr<FormSaver> FormSaverImpl::Clone() {
135 return std::make_unique<FormSaverImpl>(store_);
136 }
137
138 } // namespace password_manager
139