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/content/renderer/form_cache.h" 6 7 #include "base/logging.h" 8 #include "base/strings/utf_string_conversions.h" 9 #include "components/autofill/content/renderer/form_autofill_util.h" 10 #include "components/autofill/core/common/autofill_constants.h" 11 #include "components/autofill/core/common/form_data.h" 12 #include "components/autofill/core/common/form_data_predictions.h" 13 #include "components/autofill/core/common/form_field_data.h" 14 #include "components/autofill/core/common/form_field_data_predictions.h" 15 #include "grit/component_strings.h" 16 #include "third_party/WebKit/public/platform/WebString.h" 17 #include "third_party/WebKit/public/platform/WebVector.h" 18 #include "third_party/WebKit/public/web/WebDocument.h" 19 #include "third_party/WebKit/public/web/WebFormControlElement.h" 20 #include "third_party/WebKit/public/web/WebFormElement.h" 21 #include "third_party/WebKit/public/web/WebFrame.h" 22 #include "third_party/WebKit/public/web/WebInputElement.h" 23 #include "third_party/WebKit/public/web/WebSelectElement.h" 24 #include "ui/base/l10n/l10n_util.h" 25 26 using WebKit::WebDocument; 27 using WebKit::WebFormControlElement; 28 using WebKit::WebFormElement; 29 using WebKit::WebFrame; 30 using WebKit::WebInputElement; 31 using WebKit::WebSelectElement; 32 using WebKit::WebString; 33 using WebKit::WebVector; 34 35 namespace autofill { 36 37 // Helper function to discard state of various WebFormElements when they go out 38 // of web frame's scope. This is done to release memory that we no longer need 39 // to hold. 40 // K should inherit from WebFormControlElement as the function looks to extract 41 // WebFormElement for K.form(). 42 template <class K, class V> 43 void RemoveOldElements(const WebFrame& frame, std::map<const K, V>* states) { 44 std::vector<K> to_remove; 45 for (typename std::map<const K, V>::const_iterator it = states->begin(); 46 it != states->end(); ++it) { 47 WebFormElement form_element = it->first.form(); 48 if (form_element.isNull()) { 49 to_remove.push_back(it->first); 50 } else { 51 const WebFrame* element_frame = form_element.document().frame(); 52 if (!element_frame || element_frame == &frame) 53 to_remove.push_back(it->first); 54 } 55 } 56 57 for (typename std::vector<K>::const_iterator it = to_remove.begin(); 58 it != to_remove.end(); ++it) { 59 states->erase(*it); 60 } 61 } 62 63 FormCache::FormCache() { 64 } 65 66 FormCache::~FormCache() { 67 } 68 69 void FormCache::ExtractForms(const WebFrame& frame, 70 std::vector<FormData>* forms) { 71 ExtractFormsAndFormElements(frame, kRequiredAutofillFields, forms, NULL); 72 } 73 74 bool FormCache::ExtractFormsAndFormElements( 75 const WebFrame& frame, 76 size_t minimum_required_fields, 77 std::vector<FormData>* forms, 78 std::vector<WebFormElement>* web_form_elements) { 79 // Reset the cache for this frame. 80 ResetFrame(frame); 81 82 WebDocument document = frame.document(); 83 if (document.isNull()) 84 return false; 85 86 web_documents_.insert(document); 87 88 WebVector<WebFormElement> web_forms; 89 document.forms(web_forms); 90 91 size_t num_fields_seen = 0; 92 bool has_skipped_forms = false; 93 for (size_t i = 0; i < web_forms.size(); ++i) { 94 WebFormElement form_element = web_forms[i]; 95 96 std::vector<WebFormControlElement> control_elements; 97 ExtractAutofillableElements(form_element, autofill::REQUIRE_NONE, 98 &control_elements); 99 100 size_t num_editable_elements = 0; 101 for (size_t j = 0; j < control_elements.size(); ++j) { 102 WebFormControlElement element = control_elements[j]; 103 104 // Save original values of <select> elements so we can restore them 105 // when |ClearFormWithNode()| is invoked. 106 if (IsSelectElement(element)) { 107 const WebSelectElement select_element = 108 element.toConst<WebSelectElement>(); 109 initial_select_values_.insert(std::make_pair(select_element, 110 select_element.value())); 111 ++num_editable_elements; 112 } else { 113 const WebInputElement input_element = 114 element.toConst<WebInputElement>(); 115 if (IsCheckableElement(&input_element)) { 116 initial_checked_state_.insert( 117 std::make_pair(input_element, input_element.isChecked())); 118 } else { 119 ++num_editable_elements; 120 } 121 } 122 } 123 124 // To avoid overly expensive computation, we impose a minimum number of 125 // allowable fields. The corresponding maximum number of allowable fields 126 // is imposed by WebFormElementToFormData(). 127 if (num_editable_elements < minimum_required_fields && 128 control_elements.size() > 0) { 129 has_skipped_forms = true; 130 continue; 131 } 132 133 FormData form; 134 ExtractMask extract_mask = 135 static_cast<ExtractMask>(EXTRACT_VALUE | EXTRACT_OPTIONS); 136 137 if (!WebFormElementToFormData(form_element, WebFormControlElement(), 138 REQUIRE_NONE, extract_mask, &form, NULL)) { 139 continue; 140 } 141 142 num_fields_seen += form.fields.size(); 143 if (num_fields_seen > kMaxParseableFields) 144 break; 145 146 if (form.fields.size() >= minimum_required_fields) { 147 forms->push_back(form); 148 if (web_form_elements) 149 web_form_elements->push_back(form_element); 150 } else { 151 has_skipped_forms = true; 152 } 153 } 154 155 // Return true if there are any WebFormElements skipped, else false. 156 return has_skipped_forms; 157 } 158 159 void FormCache::ResetFrame(const WebFrame& frame) { 160 std::vector<WebDocument> documents_to_delete; 161 for (std::set<WebDocument>::const_iterator it = web_documents_.begin(); 162 it != web_documents_.end(); ++it) { 163 const WebFrame* document_frame = it->frame(); 164 if (!document_frame || document_frame == &frame) 165 documents_to_delete.push_back(*it); 166 } 167 168 for (std::vector<WebDocument>::const_iterator it = 169 documents_to_delete.begin(); 170 it != documents_to_delete.end(); ++it) { 171 web_documents_.erase(*it); 172 } 173 174 RemoveOldElements(frame, &initial_select_values_); 175 RemoveOldElements(frame, &initial_checked_state_); 176 } 177 178 bool FormCache::ClearFormWithElement(const WebInputElement& element) { 179 WebFormElement form_element = element.form(); 180 if (form_element.isNull()) 181 return false; 182 183 std::vector<WebFormControlElement> control_elements; 184 ExtractAutofillableElements(form_element, autofill::REQUIRE_NONE, 185 &control_elements); 186 for (size_t i = 0; i < control_elements.size(); ++i) { 187 WebFormControlElement control_element = control_elements[i]; 188 WebInputElement* input_element = toWebInputElement(&control_element); 189 if (IsTextInput(input_element)) { 190 // We don't modify the value of disabled fields. 191 if (!input_element->isEnabled()) 192 continue; 193 194 input_element->setValue(base::string16(), true); 195 input_element->setAutofilled(false); 196 197 // Clearing the value in the focused node (above) can cause selection 198 // to be lost. We force selection range to restore the text cursor. 199 if (element == *input_element) { 200 int length = input_element->value().length(); 201 input_element->setSelectionRange(length, length); 202 } 203 } else if (IsSelectElement(control_element)) { 204 WebSelectElement select_element = control_element.to<WebSelectElement>(); 205 206 std::map<const WebSelectElement, base::string16>::const_iterator 207 initial_value_iter = initial_select_values_.find(select_element); 208 if (initial_value_iter != initial_select_values_.end() && 209 select_element.value() != initial_value_iter->second) { 210 select_element.setValue(initial_value_iter->second); 211 select_element.dispatchFormControlChangeEvent(); 212 } 213 } else { 214 WebInputElement input_element = control_element.to<WebInputElement>(); 215 DCHECK(IsCheckableElement(&input_element)); 216 std::map<const WebInputElement, bool>::const_iterator it = 217 initial_checked_state_.find(input_element); 218 if (it != initial_checked_state_.end() && 219 input_element.isChecked() != it->second) { 220 input_element.setChecked(it->second, true); 221 } 222 } 223 } 224 225 return true; 226 } 227 228 bool FormCache::ShowPredictions(const FormDataPredictions& form) { 229 DCHECK_EQ(form.data.fields.size(), form.fields.size()); 230 231 // Find the form. 232 bool found_form = false; 233 WebFormElement form_element; 234 for (std::set<WebDocument>::const_iterator it = web_documents_.begin(); 235 it != web_documents_.end() && !found_form; ++it) { 236 WebVector<WebFormElement> web_forms; 237 it->forms(web_forms); 238 239 for (size_t i = 0; i < web_forms.size(); ++i) { 240 form_element = web_forms[i]; 241 242 // Note: matching on the form name here which is not guaranteed to be 243 // unique for the page, nor is it guaranteed to be non-empty. Ideally, we 244 // would have a way to uniquely identify the form cross-process. For now, 245 // we'll check form name and form action for identity. 246 // Also note that WebString() == WebString(string16()) does not evaluate 247 // to |true| -- WebKit distinguishes between a "null" string (lhs) and an 248 // "empty" string (rhs). We don't want that distinction, so forcing to 249 // string16. 250 base::string16 element_name = GetFormIdentifier(form_element); 251 GURL action(form_element.document().completeURL(form_element.action())); 252 if (element_name == form.data.name && action == form.data.action) { 253 found_form = true; 254 break; 255 } 256 } 257 } 258 259 if (!found_form) 260 return false; 261 262 std::vector<WebFormControlElement> control_elements; 263 ExtractAutofillableElements(form_element, autofill::REQUIRE_NONE, 264 &control_elements); 265 if (control_elements.size() != form.fields.size()) { 266 // Keep things simple. Don't show predictions for forms that were modified 267 // between page load and the server's response to our query. 268 return false; 269 } 270 271 for (size_t i = 0; i < control_elements.size(); ++i) { 272 WebFormControlElement* element = &control_elements[i]; 273 274 if (base::string16(element->nameForAutofill()) != 275 form.data.fields[i].name) { 276 // Keep things simple. Don't show predictions for elements whose names 277 // were modified between page load and the server's response to our query. 278 continue; 279 } 280 281 std::string placeholder = form.fields[i].overall_type; 282 base::string16 title = l10n_util::GetStringFUTF16( 283 IDS_AUTOFILL_SHOW_PREDICTIONS_TITLE, 284 UTF8ToUTF16(form.fields[i].heuristic_type), 285 UTF8ToUTF16(form.fields[i].server_type), 286 UTF8ToUTF16(form.fields[i].signature), 287 UTF8ToUTF16(form.signature), 288 UTF8ToUTF16(form.experiment_id)); 289 if (!element->hasAttribute("placeholder")) 290 element->setAttribute("placeholder", WebString(UTF8ToUTF16(placeholder))); 291 element->setAttribute("title", WebString(title)); 292 } 293 294 return true; 295 } 296 297 } // namespace autofill 298