autocomplete_history_manager.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 "components/autofill/core/browser/autocomplete_history_manager.h" 6 7#include <vector> 8 9#include "base/prefs/pref_service.h" 10#include "base/strings/string16.h" 11#include "base/strings/utf_string_conversions.h" 12#include "components/autofill/core/browser/autofill_driver.h" 13#include "components/autofill/core/browser/autofill_external_delegate.h" 14#include "components/autofill/core/browser/autofill_manager_delegate.h" 15#include "components/autofill/core/browser/validation.h" 16#include "components/autofill/core/common/autofill_pref_names.h" 17#include "components/autofill/core/common/form_data.h" 18 19namespace autofill { 20namespace { 21 22// Limit on the number of suggestions to appear in the pop-up menu under an 23// text input element in a form. 24const int kMaxAutocompleteMenuItems = 6; 25 26bool IsTextField(const FormFieldData& field) { 27 return 28 field.form_control_type == "text" || 29 field.form_control_type == "search" || 30 field.form_control_type == "tel" || 31 field.form_control_type == "url" || 32 field.form_control_type == "email"; 33} 34 35} // namespace 36 37AutocompleteHistoryManager::AutocompleteHistoryManager( 38 AutofillDriver* driver, 39 AutofillManagerDelegate* manager_delegate) 40 : driver_(driver), 41 database_(manager_delegate->GetDatabase()), 42 pending_query_handle_(0), 43 query_id_(0), 44 external_delegate_(NULL), 45 manager_delegate_(manager_delegate), 46 send_ipc_(true) { 47 DCHECK(manager_delegate_); 48} 49 50AutocompleteHistoryManager::~AutocompleteHistoryManager() { 51 CancelPendingQuery(); 52} 53 54void AutocompleteHistoryManager::OnWebDataServiceRequestDone( 55 WebDataServiceBase::Handle h, 56 const WDTypedResult* result) { 57 DCHECK(pending_query_handle_); 58 pending_query_handle_ = 0; 59 60 if (!manager_delegate_->IsAutocompleteEnabled()) { 61 SendSuggestions(NULL); 62 return; 63 } 64 65 DCHECK(result); 66 // Returning early here if |result| is NULL. We've seen this happen on 67 // Linux due to NFS dismounting and causing sql failures. 68 // See http://crbug.com/68783. 69 if (!result) { 70 SendSuggestions(NULL); 71 return; 72 } 73 74 DCHECK_EQ(AUTOFILL_VALUE_RESULT, result->GetType()); 75 const WDResult<std::vector<base::string16> >* autofill_result = 76 static_cast<const WDResult<std::vector<base::string16> >*>(result); 77 std::vector<base::string16> suggestions = autofill_result->GetValue(); 78 SendSuggestions(&suggestions); 79} 80 81void AutocompleteHistoryManager::OnGetAutocompleteSuggestions( 82 int query_id, 83 const base::string16& name, 84 const base::string16& prefix, 85 const std::vector<base::string16>& autofill_values, 86 const std::vector<base::string16>& autofill_labels, 87 const std::vector<base::string16>& autofill_icons, 88 const std::vector<int>& autofill_unique_ids) { 89 CancelPendingQuery(); 90 91 query_id_ = query_id; 92 autofill_values_ = autofill_values; 93 autofill_labels_ = autofill_labels; 94 autofill_icons_ = autofill_icons; 95 autofill_unique_ids_ = autofill_unique_ids; 96 if (!manager_delegate_->IsAutocompleteEnabled()) { 97 SendSuggestions(NULL); 98 return; 99 } 100 101 if (database_.get()) { 102 pending_query_handle_ = database_->GetFormValuesForElementName( 103 name, prefix, kMaxAutocompleteMenuItems, this); 104 } 105} 106 107void AutocompleteHistoryManager::OnFormSubmitted(const FormData& form) { 108 if (!manager_delegate_->IsAutocompleteEnabled()) 109 return; 110 111 if (driver_->IsOffTheRecord()) 112 return; 113 114 // Don't save data that was submitted through JavaScript. 115 if (!form.user_submitted) 116 return; 117 118 // We put the following restriction on stored FormFields: 119 // - non-empty name 120 // - non-empty value 121 // - text field 122 // - value is not a credit card number 123 // - value is not a SSN 124 std::vector<FormFieldData> values; 125 for (std::vector<FormFieldData>::const_iterator iter = 126 form.fields.begin(); 127 iter != form.fields.end(); ++iter) { 128 if (!iter->value.empty() && 129 !iter->name.empty() && 130 IsTextField(*iter) && 131 !autofill::IsValidCreditCardNumber(iter->value) && 132 !autofill::IsSSN(iter->value)) { 133 values.push_back(*iter); 134 } 135 } 136 137 if (!values.empty() && database_.get()) 138 database_->AddFormFields(values); 139} 140 141void AutocompleteHistoryManager::OnRemoveAutocompleteEntry( 142 const base::string16& name, const base::string16& value) { 143 if (database_.get()) 144 database_->RemoveFormValueForElementName(name, value); 145} 146 147void AutocompleteHistoryManager::SetExternalDelegate( 148 AutofillExternalDelegate* delegate) { 149 external_delegate_ = delegate; 150} 151 152void AutocompleteHistoryManager::CancelPendingQuery() { 153 if (pending_query_handle_) { 154 if (database_.get()) 155 database_->CancelRequest(pending_query_handle_); 156 pending_query_handle_ = 0; 157 } 158} 159 160void AutocompleteHistoryManager::SendSuggestions( 161 const std::vector<base::string16>* suggestions) { 162 if (suggestions) { 163 // Combine Autofill and Autocomplete values into values and labels. 164 for (size_t i = 0; i < suggestions->size(); ++i) { 165 bool unique = true; 166 for (size_t j = 0; j < autofill_values_.size(); ++j) { 167 // Don't add duplicate values. 168 if (autofill_values_[j] == (*suggestions)[i]) { 169 unique = false; 170 break; 171 } 172 } 173 174 if (unique) { 175 autofill_values_.push_back((*suggestions)[i]); 176 autofill_labels_.push_back(base::string16()); 177 autofill_icons_.push_back(base::string16()); 178 autofill_unique_ids_.push_back(0); // 0 means no profile. 179 } 180 } 181 } 182 183 external_delegate_->OnSuggestionsReturned(query_id_, 184 autofill_values_, 185 autofill_labels_, 186 autofill_icons_, 187 autofill_unique_ids_); 188 189 query_id_ = 0; 190 autofill_values_.clear(); 191 autofill_labels_.clear(); 192 autofill_icons_.clear(); 193 autofill_unique_ids_.clear(); 194} 195 196} // namespace autofill 197