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