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