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

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

Issue 15949025: In components/autofill, move renderer/ to content/renderer (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Response to reviews Created 7 years, 6 months 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "components/autofill/renderer/form_cache.h"
6
7 #include "base/logging.h"
8 #include "base/utf_string_conversions.h"
9 #include "components/autofill/common/autofill_constants.h"
10 #include "components/autofill/common/form_data.h"
11 #include "components/autofill/common/form_data_predictions.h"
12 #include "components/autofill/common/form_field_data.h"
13 #include "components/autofill/common/form_field_data_predictions.h"
14 #include "components/autofill/renderer/form_autofill_util.h"
15 #include "grit/component_resources.h"
16 #include "third_party/WebKit/public/platform/WebString.h"
17 #include "third_party/WebKit/public/platform/WebVector.h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormControlElement .h"
20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormElement.h"
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h"
23 #include "third_party/WebKit/Source/WebKit/chromium/public/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
OLDNEW
« no previous file with comments | « components/autofill/renderer/form_cache.h ('k') | components/autofill/renderer/page_click_listener.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698