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