| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/renderer/autofill/form_cache.h" | 5 #include "chrome/renderer/autofill/form_cache.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/utf_string_conversions.h" | 8 #include "base/utf_string_conversions.h" |
| 9 #include "chrome/common/form_data.h" | 9 #include "chrome/common/form_data.h" |
| 10 #include "chrome/common/form_data_predictions.h" | 10 #include "chrome/common/form_data_predictions.h" |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 // The number of fields required by Autofill. Ideally we could send the forms | 36 // The number of fields required by Autofill. Ideally we could send the forms |
| 37 // to Autofill no matter how many fields are in the forms; however, finding the | 37 // to Autofill no matter how many fields are in the forms; however, finding the |
| 38 // label for each field is a costly operation and we can't spare the cycles if | 38 // label for each field is a costly operation and we can't spare the cycles if |
| 39 // it's not necessary. | 39 // it's not necessary. |
| 40 const size_t kRequiredAutofillFields = 3; | 40 const size_t kRequiredAutofillFields = 3; |
| 41 | 41 |
| 42 } // namespace | 42 } // namespace |
| 43 | 43 |
| 44 namespace autofill { | 44 namespace autofill { |
| 45 | 45 |
| 46 // Helper function to discard state of various WebFormElements when they go out |
| 47 // of web frame's scope. This is done to release memory that we no longer need |
| 48 // to hold. |
| 49 // K should inherit from WebFormControlElement as the function looks to extract |
| 50 // WebFormElement for K.form(). |
| 51 template <class K, class V> |
| 52 void RemoveOldElements(const WebFrame& frame, std::map<const K, V>* states) { |
| 53 std::vector<K> to_remove; |
| 54 for (typename std::map<const K, V>::const_iterator it = states->begin(); |
| 55 it != states->end(); ++it) { |
| 56 WebFormElement form_element = it->first.form(); |
| 57 if (form_element.isNull()) { |
| 58 to_remove.push_back(it->first); |
| 59 } else { |
| 60 const WebFrame* element_frame = form_element.document().frame(); |
| 61 if (!element_frame || element_frame == &frame) |
| 62 to_remove.push_back(it->first); |
| 63 } |
| 64 } |
| 65 |
| 66 for (typename std::vector<K>::const_iterator it = to_remove.begin(); |
| 67 it != to_remove.end(); ++it) { |
| 68 states->erase(*it); |
| 69 } |
| 70 } |
| 71 |
| 46 FormCache::FormCache() { | 72 FormCache::FormCache() { |
| 47 } | 73 } |
| 48 | 74 |
| 49 FormCache::~FormCache() { | 75 FormCache::~FormCache() { |
| 50 } | 76 } |
| 51 | 77 |
| 52 void FormCache::ExtractForms(const WebFrame& frame, | 78 void FormCache::ExtractForms(const WebFrame& frame, |
| 53 std::vector<FormData>* forms) { | 79 std::vector<FormData>* forms) { |
| 54 // Reset the cache for this frame. | 80 // Reset the cache for this frame. |
| 55 ResetFrame(frame); | 81 ResetFrame(frame); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 73 for (size_t j = 0; j < control_elements.size(); ++j) { | 99 for (size_t j = 0; j < control_elements.size(); ++j) { |
| 74 WebFormControlElement element = control_elements[j]; | 100 WebFormControlElement element = control_elements[j]; |
| 75 | 101 |
| 76 // Save original values of <select> elements so we can restore them | 102 // Save original values of <select> elements so we can restore them |
| 77 // when |ClearFormWithNode()| is invoked. | 103 // when |ClearFormWithNode()| is invoked. |
| 78 if (IsSelectElement(element)) { | 104 if (IsSelectElement(element)) { |
| 79 const WebSelectElement select_element = | 105 const WebSelectElement select_element = |
| 80 element.toConst<WebSelectElement>(); | 106 element.toConst<WebSelectElement>(); |
| 81 initial_select_values_.insert(std::make_pair(select_element, | 107 initial_select_values_.insert(std::make_pair(select_element, |
| 82 select_element.value())); | 108 select_element.value())); |
| 109 } else { |
| 110 const WebInputElement input_element = |
| 111 element.toConst<WebInputElement>(); |
| 112 if (IsCheckableElement(&input_element)) |
| 113 initial_checked_state_.insert( |
| 114 std::make_pair(input_element, input_element.isChecked())); |
| 83 } | 115 } |
| 84 } | 116 } |
| 85 | 117 |
| 86 // To avoid overly expensive computation, we impose a minimum number of | 118 // To avoid overly expensive computation, we impose a minimum number of |
| 87 // allowable fields. The corresponding maximum number of allowable fields | 119 // allowable fields. The corresponding maximum number of allowable fields |
| 88 // is imposed by WebFormElementToFormData(). | 120 // is imposed by WebFormElementToFormData(). |
| 89 if (control_elements.size() < kRequiredAutofillFields) | 121 if (control_elements.size() < kRequiredAutofillFields) |
| 90 continue; | 122 continue; |
| 91 | 123 |
| 92 FormData form; | 124 FormData form; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 112 if (!document_frame || document_frame == &frame) | 144 if (!document_frame || document_frame == &frame) |
| 113 documents_to_delete.push_back(*it); | 145 documents_to_delete.push_back(*it); |
| 114 } | 146 } |
| 115 | 147 |
| 116 for (std::vector<WebDocument>::const_iterator it = | 148 for (std::vector<WebDocument>::const_iterator it = |
| 117 documents_to_delete.begin(); | 149 documents_to_delete.begin(); |
| 118 it != documents_to_delete.end(); ++it) { | 150 it != documents_to_delete.end(); ++it) { |
| 119 web_documents_.erase(*it); | 151 web_documents_.erase(*it); |
| 120 } | 152 } |
| 121 | 153 |
| 122 std::vector<WebSelectElement> select_values_to_delete; | 154 RemoveOldElements(frame, &initial_select_values_); |
| 123 for (std::map<const WebSelectElement, string16>::const_iterator it = | 155 RemoveOldElements(frame, &initial_checked_state_); |
| 124 initial_select_values_.begin(); | |
| 125 it != initial_select_values_.end(); ++it) { | |
| 126 WebFormElement form_element = it->first.form(); | |
| 127 if (form_element.isNull()) { | |
| 128 select_values_to_delete.push_back(it->first); | |
| 129 } else { | |
| 130 const WebFrame* element_frame = form_element.document().frame(); | |
| 131 if (!element_frame || element_frame == &frame) | |
| 132 select_values_to_delete.push_back(it->first); | |
| 133 } | |
| 134 } | |
| 135 | |
| 136 for (std::vector<WebSelectElement>::const_iterator it = | |
| 137 select_values_to_delete.begin(); | |
| 138 it != select_values_to_delete.end(); ++it) { | |
| 139 initial_select_values_.erase(*it); | |
| 140 } | |
| 141 } | 156 } |
| 142 | 157 |
| 143 bool FormCache::ClearFormWithElement(const WebInputElement& element) { | 158 bool FormCache::ClearFormWithElement(const WebInputElement& element) { |
| 144 WebFormElement form_element = element.form(); | 159 WebFormElement form_element = element.form(); |
| 145 if (form_element.isNull()) | 160 if (form_element.isNull()) |
| 146 return false; | 161 return false; |
| 147 | 162 |
| 148 std::vector<WebFormControlElement> control_elements; | 163 std::vector<WebFormControlElement> control_elements; |
| 149 ExtractAutofillableElements(form_element, autofill::REQUIRE_NONE, | 164 ExtractAutofillableElements(form_element, autofill::REQUIRE_NONE, |
| 150 &control_elements); | 165 &control_elements); |
| 151 for (size_t i = 0; i < control_elements.size(); ++i) { | 166 for (size_t i = 0; i < control_elements.size(); ++i) { |
| 152 WebFormControlElement control_element = control_elements[i]; | 167 WebFormControlElement control_element = control_elements[i]; |
| 153 WebInputElement* input_element = toWebInputElement(&control_element); | 168 WebInputElement* input_element = toWebInputElement(&control_element); |
| 154 if (IsTextInput(input_element)) { | 169 if (IsTextInput(input_element)) { |
| 155 // We don't modify the value of disabled fields. | 170 // We don't modify the value of disabled fields. |
| 156 if (!input_element->isEnabled()) | 171 if (!input_element->isEnabled()) |
| 157 continue; | 172 continue; |
| 158 | 173 |
| 159 input_element->setValue(string16(), true); | 174 input_element->setValue(string16(), true); |
| 160 input_element->setAutofilled(false); | 175 input_element->setAutofilled(false); |
| 161 | 176 |
| 162 // Clearing the value in the focused node (above) can cause selection | 177 // Clearing the value in the focused node (above) can cause selection |
| 163 // to be lost. We force selection range to restore the text cursor. | 178 // to be lost. We force selection range to restore the text cursor. |
| 164 if (element == *input_element) { | 179 if (element == *input_element) { |
| 165 int length = input_element->value().length(); | 180 int length = input_element->value().length(); |
| 166 input_element->setSelectionRange(length, length); | 181 input_element->setSelectionRange(length, length); |
| 167 } | 182 } |
| 168 } else { | 183 } else if (IsSelectElement(control_element)) { |
| 169 DCHECK(IsSelectElement(control_element)); | |
| 170 WebSelectElement select_element = control_element.to<WebSelectElement>(); | 184 WebSelectElement select_element = control_element.to<WebSelectElement>(); |
| 171 | 185 |
| 172 std::map<const WebSelectElement, string16>::const_iterator | 186 std::map<const WebSelectElement, string16>::const_iterator |
| 173 initial_value_iter = initial_select_values_.find(select_element); | 187 initial_value_iter = initial_select_values_.find(select_element); |
| 174 if (initial_value_iter != initial_select_values_.end() && | 188 if (initial_value_iter != initial_select_values_.end() && |
| 175 select_element.value() != initial_value_iter->second) { | 189 select_element.value() != initial_value_iter->second) { |
| 176 select_element.setValue(initial_value_iter->second); | 190 select_element.setValue(initial_value_iter->second); |
| 177 select_element.dispatchFormControlChangeEvent(); | 191 select_element.dispatchFormControlChangeEvent(); |
| 178 } | 192 } |
| 193 } else { |
| 194 WebInputElement input_element = control_element.to<WebInputElement>(); |
| 195 DCHECK(IsCheckableElement(&input_element)); |
| 196 std::map<const WebInputElement, bool>::const_iterator it = |
| 197 initial_checked_state_.find(input_element); |
| 198 if (it != initial_checked_state_.end() && |
| 199 input_element.isChecked() != it->second) { |
| 200 input_element.setChecked(it->second, true); |
| 201 } |
| 179 } | 202 } |
| 180 } | 203 } |
| 181 | 204 |
| 182 return true; | 205 return true; |
| 183 } | 206 } |
| 184 | 207 |
| 185 bool FormCache::ShowPredictions(const FormDataPredictions& form) { | 208 bool FormCache::ShowPredictions(const FormDataPredictions& form) { |
| 186 DCHECK_EQ(form.data.fields.size(), form.fields.size()); | 209 DCHECK_EQ(form.data.fields.size(), form.fields.size()); |
| 187 | 210 |
| 188 // Find the form. | 211 // Find the form. |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 UTF8ToUTF16(form.experiment_id)); | 267 UTF8ToUTF16(form.experiment_id)); |
| 245 if (!element->hasAttribute("placeholder")) | 268 if (!element->hasAttribute("placeholder")) |
| 246 element->setAttribute("placeholder", WebString(UTF8ToUTF16(placeholder))); | 269 element->setAttribute("placeholder", WebString(UTF8ToUTF16(placeholder))); |
| 247 element->setAttribute("title", WebString(title)); | 270 element->setAttribute("title", WebString(title)); |
| 248 } | 271 } |
| 249 | 272 |
| 250 return true; | 273 return true; |
| 251 } | 274 } |
| 252 | 275 |
| 253 } // namespace autofill | 276 } // namespace autofill |
| OLD | NEW |