Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: chrome/renderer/autofill/form_cache.cc

Issue 11415221: Add support for autofilling radio buttons and checkboxes. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: fix the nit. Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698