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.
5 #include "components/password_manager/core/browser/password_autofill_manager.h"
9 #include "base/logging.h"
10 #include "base/strings/string16.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "components/autofill/core/browser/autofill_driver.h"
14 #include "components/autofill/core/browser/popup_item_ids.h"
15 #include "components/autofill/core/common/autofill_data_validation.h"
16 #include "components/password_manager/core/browser/password_manager_client.h"
17 #include "components/password_manager/core/browser/password_manager_driver.h"
19 namespace password_manager {
23 // This function attempts to fill |suggestions| and |realms| form |fill_data|
24 // based on |current_username|. Unless |show_all| is true, it only picks
25 // suggestions where the username has |current_username| as a prefix.
26 void GetSuggestions(const autofill::PasswordFormFillData& fill_data,
27 const base::string16& current_username,
28 std::vector<base::string16>* suggestions,
29 std::vector<base::string16>* realms,
33 fill_data.basic_data.fields[0].value, current_username, false)) {
34 suggestions->push_back(fill_data.basic_data.fields[0].value);
35 realms->push_back(base::UTF8ToUTF16(fill_data.preferred_realm));
38 for (const auto& login : fill_data.additional_logins) {
39 if (show_all || StartsWith(login.first, current_username, false)) {
40 suggestions->push_back(login.first);
41 realms->push_back(base::UTF8ToUTF16(login.second.realm));
45 for (const auto& usernames : fill_data.other_possible_usernames) {
46 for (size_t i = 0; i < usernames.second.size(); ++i) {
48 StartsWith(usernames.second[i], current_username, false)) {
49 suggestions->push_back(usernames.second[i]);
50 realms->push_back(base::UTF8ToUTF16(usernames.first.realm));
58 ////////////////////////////////////////////////////////////////////////////////
59 // PasswordAutofillManager, public:
61 PasswordAutofillManager::PasswordAutofillManager(
62 PasswordManagerClient* password_manager_client,
63 autofill::AutofillClient* autofill_client)
64 : password_manager_client_(password_manager_client),
65 autofill_client_(autofill_client),
66 weak_ptr_factory_(this) {
69 PasswordAutofillManager::~PasswordAutofillManager() {
72 bool PasswordAutofillManager::FillSuggestion(int key,
73 const base::string16& username) {
74 autofill::PasswordFormFillData fill_data;
75 base::string16 password;
76 if (FindLoginInfo(key, &fill_data) &&
77 GetPasswordForUsername(username, fill_data, &password)) {
78 PasswordManagerDriver* driver = password_manager_client_->GetDriver();
79 driver->FillSuggestion(username, password);
85 bool PasswordAutofillManager::PreviewSuggestion(
87 const base::string16& username) {
88 autofill::PasswordFormFillData fill_data;
89 base::string16 password;
90 if (FindLoginInfo(key, &fill_data) &&
91 GetPasswordForUsername(username, fill_data, &password)) {
92 PasswordManagerDriver* driver = password_manager_client_->GetDriver();
93 driver->PreviewSuggestion(username, password);
99 void PasswordAutofillManager::OnAddPasswordFormMapping(
101 const autofill::PasswordFormFillData& fill_data) {
102 if (!autofill::IsValidPasswordFormFillData(fill_data))
105 login_to_password_info_[key] = fill_data;
108 void PasswordAutofillManager::OnShowPasswordSuggestions(
110 base::i18n::TextDirection text_direction,
111 const base::string16& typed_username,
113 const gfx::RectF& bounds) {
114 std::vector<base::string16> suggestions;
115 std::vector<base::string16> realms;
116 LoginToPasswordInfoMap::const_iterator fill_data_it =
117 login_to_password_info_.find(key);
118 if (fill_data_it == login_to_password_info_.end()) {
119 // Probably a compromised renderer.
123 GetSuggestions(fill_data_it->second, typed_username, &suggestions, &realms,
125 DCHECK_EQ(suggestions.size(), realms.size());
127 form_data_key_ = key;
129 if (suggestions.empty()) {
130 autofill_client_->HideAutofillPopup();
134 std::vector<base::string16> empty(suggestions.size());
135 std::vector<int> password_ids(suggestions.size(),
136 autofill::POPUP_ITEM_ID_PASSWORD_ENTRY);
137 autofill_client_->ShowAutofillPopup(bounds,
143 weak_ptr_factory_.GetWeakPtr());
146 void PasswordAutofillManager::Reset() {
147 login_to_password_info_.clear();
150 bool PasswordAutofillManager::FillSuggestionForTest(
152 const base::string16& username) {
153 return FillSuggestion(key, username);
156 bool PasswordAutofillManager::PreviewSuggestionForTest(
158 const base::string16& username) {
159 return PreviewSuggestion(key, username);
162 void PasswordAutofillManager::OnPopupShown() {
165 void PasswordAutofillManager::OnPopupHidden() {
168 void PasswordAutofillManager::DidSelectSuggestion(const base::string16& value,
170 ClearPreviewedForm();
171 bool success = PreviewSuggestion(form_data_key_, value);
175 void PasswordAutofillManager::DidAcceptSuggestion(const base::string16& value,
177 bool success = FillSuggestion(form_data_key_, value);
179 autofill_client_->HideAutofillPopup();
182 void PasswordAutofillManager::RemoveSuggestion(const base::string16& value,
187 void PasswordAutofillManager::ClearPreviewedForm() {
188 PasswordManagerDriver* driver = password_manager_client_->GetDriver();
189 driver->ClearPreviewedForm();
192 ////////////////////////////////////////////////////////////////////////////////
193 // PasswordAutofillManager, private:
195 bool PasswordAutofillManager::GetPasswordForUsername(
196 const base::string16& current_username,
197 const autofill::PasswordFormFillData& fill_data,
198 base::string16* password) {
199 // TODO(dubroy): When password access requires some kind of authentication
200 // (e.g. Keychain access on Mac OS), use |password_manager_client_| here to
201 // fetch the actual password. See crbug.com/178358 for more context.
203 // Look for any suitable matches to current field text.
204 if (fill_data.basic_data.fields[0].value == current_username) {
205 *password = fill_data.basic_data.fields[1].value;
209 // Scan additional logins for a match.
210 for (autofill::PasswordFormFillData::LoginCollection::const_iterator iter =
211 fill_data.additional_logins.begin();
212 iter != fill_data.additional_logins.end();
214 if (iter->first == current_username) {
215 *password = iter->second.password;
220 for (autofill::PasswordFormFillData::UsernamesCollection::const_iterator
221 usernames_iter = fill_data.other_possible_usernames.begin();
222 usernames_iter != fill_data.other_possible_usernames.end();
224 for (size_t i = 0; i < usernames_iter->second.size(); ++i) {
225 if (usernames_iter->second[i] == current_username) {
226 *password = usernames_iter->first.password;
235 bool PasswordAutofillManager::FindLoginInfo(
237 autofill::PasswordFormFillData* found_password) {
238 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(key);
239 if (iter == login_to_password_info_.end())
242 *found_password = iter->second;
246 } // namespace password_manager