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