1 // Copyright 2013 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 "base/logging.h"
6 #include "components/autofill/core/browser/autofill_driver.h"
7 #include "components/autofill/core/browser/popup_item_ids.h"
8 #include "components/autofill/core/common/autofill_data_validation.h"
9 #include "components/password_manager/core/browser/password_autofill_manager.h"
10 #include "components/password_manager/core/browser/password_manager_client.h"
11 #include "components/password_manager/core/browser/password_manager_driver.h"
12
13 namespace password_manager {
14
15 ////////////////////////////////////////////////////////////////////////////////
16 // PasswordAutofillManager, public:
17
PasswordAutofillManager(PasswordManagerClient * password_manager_client,autofill::AutofillClient * autofill_client)18 PasswordAutofillManager::PasswordAutofillManager(
19 PasswordManagerClient* password_manager_client,
20 autofill::AutofillClient* autofill_client)
21 : password_manager_client_(password_manager_client),
22 autofill_client_(autofill_client),
23 weak_ptr_factory_(this) {
24 }
25
~PasswordAutofillManager()26 PasswordAutofillManager::~PasswordAutofillManager() {
27 }
28
FillSuggestion(const autofill::FormFieldData & field,const base::string16 & username)29 bool PasswordAutofillManager::FillSuggestion(
30 const autofill::FormFieldData& field,
31 const base::string16& username) {
32 autofill::PasswordFormFillData fill_data;
33 base::string16 password;
34 if (FindLoginInfo(field, &fill_data) &&
35 GetPasswordForUsername(username, fill_data, &password)) {
36 PasswordManagerDriver* driver = password_manager_client_->GetDriver();
37 driver->FillSuggestion(username, password);
38 return true;
39 }
40 return false;
41 }
42
PreviewSuggestion(const autofill::FormFieldData & field,const base::string16 & username)43 bool PasswordAutofillManager::PreviewSuggestion(
44 const autofill::FormFieldData& field,
45 const base::string16& username) {
46 autofill::PasswordFormFillData fill_data;
47 base::string16 password;
48 if (FindLoginInfo(field, &fill_data) &&
49 GetPasswordForUsername(username, fill_data, &password)) {
50 PasswordManagerDriver* driver = password_manager_client_->GetDriver();
51 driver->PreviewSuggestion(username, password);
52 return true;
53 }
54 return false;
55 }
56
OnAddPasswordFormMapping(const autofill::FormFieldData & field,const autofill::PasswordFormFillData & fill_data)57 void PasswordAutofillManager::OnAddPasswordFormMapping(
58 const autofill::FormFieldData& field,
59 const autofill::PasswordFormFillData& fill_data) {
60 if (!autofill::IsValidFormFieldData(field) ||
61 !autofill::IsValidPasswordFormFillData(fill_data))
62 return;
63
64 login_to_password_info_[field] = fill_data;
65 }
66
OnShowPasswordSuggestions(const autofill::FormFieldData & field,const gfx::RectF & bounds,const std::vector<base::string16> & suggestions,const std::vector<base::string16> & realms)67 void PasswordAutofillManager::OnShowPasswordSuggestions(
68 const autofill::FormFieldData& field,
69 const gfx::RectF& bounds,
70 const std::vector<base::string16>& suggestions,
71 const std::vector<base::string16>& realms) {
72 if (!autofill::IsValidString16Vector(suggestions) ||
73 !autofill::IsValidString16Vector(realms) ||
74 suggestions.size() != realms.size())
75 return;
76
77 form_field_ = field;
78
79 if (suggestions.empty()) {
80 autofill_client_->HideAutofillPopup();
81 return;
82 }
83
84 std::vector<base::string16> empty(suggestions.size());
85 std::vector<int> password_ids(suggestions.size(),
86 autofill::POPUP_ITEM_ID_PASSWORD_ENTRY);
87 autofill_client_->ShowAutofillPopup(bounds,
88 field.text_direction,
89 suggestions,
90 realms,
91 empty,
92 password_ids,
93 weak_ptr_factory_.GetWeakPtr());
94 }
95
Reset()96 void PasswordAutofillManager::Reset() {
97 login_to_password_info_.clear();
98 }
99
FillSuggestionForTest(const autofill::FormFieldData & field,const base::string16 & username)100 bool PasswordAutofillManager::FillSuggestionForTest(
101 const autofill::FormFieldData& field,
102 const base::string16& username) {
103 return FillSuggestion(field, username);
104 }
105
PreviewSuggestionForTest(const autofill::FormFieldData & field,const base::string16 & username)106 bool PasswordAutofillManager::PreviewSuggestionForTest(
107 const autofill::FormFieldData& field,
108 const base::string16& username) {
109 return PreviewSuggestion(field, username);
110 }
111
OnPopupShown()112 void PasswordAutofillManager::OnPopupShown() {
113 }
114
OnPopupHidden()115 void PasswordAutofillManager::OnPopupHidden() {
116 }
117
DidSelectSuggestion(const base::string16 & value,int identifier)118 void PasswordAutofillManager::DidSelectSuggestion(const base::string16& value,
119 int identifier) {
120 ClearPreviewedForm();
121 bool success = PreviewSuggestion(form_field_, value);
122 DCHECK(success);
123 }
124
DidAcceptSuggestion(const base::string16 & value,int identifier)125 void PasswordAutofillManager::DidAcceptSuggestion(const base::string16& value,
126 int identifier) {
127 bool success = FillSuggestion(form_field_, value);
128 DCHECK(success);
129 autofill_client_->HideAutofillPopup();
130 }
131
RemoveSuggestion(const base::string16 & value,int identifier)132 void PasswordAutofillManager::RemoveSuggestion(const base::string16& value,
133 int identifier) {
134 NOTREACHED();
135 }
136
ClearPreviewedForm()137 void PasswordAutofillManager::ClearPreviewedForm() {
138 PasswordManagerDriver* driver = password_manager_client_->GetDriver();
139 driver->ClearPreviewedForm();
140 }
141
142 ////////////////////////////////////////////////////////////////////////////////
143 // PasswordAutofillManager, private:
144
GetPasswordForUsername(const base::string16 & current_username,const autofill::PasswordFormFillData & fill_data,base::string16 * password)145 bool PasswordAutofillManager::GetPasswordForUsername(
146 const base::string16& current_username,
147 const autofill::PasswordFormFillData& fill_data,
148 base::string16* password) {
149 // TODO(dubroy): When password access requires some kind of authentication
150 // (e.g. Keychain access on Mac OS), use |password_manager_client_| here to
151 // fetch the actual password. See crbug.com/178358 for more context.
152
153 // Look for any suitable matches to current field text.
154 if (fill_data.basic_data.fields[0].value == current_username) {
155 *password = fill_data.basic_data.fields[1].value;
156 return true;
157 }
158
159 // Scan additional logins for a match.
160 for (autofill::PasswordFormFillData::LoginCollection::const_iterator iter =
161 fill_data.additional_logins.begin();
162 iter != fill_data.additional_logins.end();
163 ++iter) {
164 if (iter->first == current_username) {
165 *password = iter->second.password;
166 return true;
167 }
168 }
169
170 for (autofill::PasswordFormFillData::UsernamesCollection::const_iterator
171 usernames_iter = fill_data.other_possible_usernames.begin();
172 usernames_iter != fill_data.other_possible_usernames.end();
173 ++usernames_iter) {
174 for (size_t i = 0; i < usernames_iter->second.size(); ++i) {
175 if (usernames_iter->second[i] == current_username) {
176 *password = usernames_iter->first.password;
177 return true;
178 }
179 }
180 }
181
182 return false;
183 }
184
FindLoginInfo(const autofill::FormFieldData & field,autofill::PasswordFormFillData * found_password)185 bool PasswordAutofillManager::FindLoginInfo(
186 const autofill::FormFieldData& field,
187 autofill::PasswordFormFillData* found_password) {
188 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(field);
189 if (iter == login_to_password_info_.end())
190 return false;
191
192 *found_password = iter->second;
193 return true;
194 }
195
196 } // namespace password_manager
197