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