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 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 26 PasswordAutofillManager::~PasswordAutofillManager() { 27 } 28 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 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 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 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 96 void PasswordAutofillManager::Reset() { 97 login_to_password_info_.clear(); 98 } 99 100 bool PasswordAutofillManager::FillSuggestionForTest( 101 const autofill::FormFieldData& field, 102 const base::string16& username) { 103 return FillSuggestion(field, username); 104 } 105 106 bool PasswordAutofillManager::PreviewSuggestionForTest( 107 const autofill::FormFieldData& field, 108 const base::string16& username) { 109 return PreviewSuggestion(field, username); 110 } 111 112 void PasswordAutofillManager::OnPopupShown() { 113 } 114 115 void PasswordAutofillManager::OnPopupHidden() { 116 } 117 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 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 132 void PasswordAutofillManager::RemoveSuggestion(const base::string16& value, 133 int identifier) { 134 NOTREACHED(); 135 } 136 137 void PasswordAutofillManager::ClearPreviewedForm() { 138 PasswordManagerDriver* driver = password_manager_client_->GetDriver(); 139 driver->ClearPreviewedForm(); 140 } 141 142 //////////////////////////////////////////////////////////////////////////////// 143 // PasswordAutofillManager, private: 144 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 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