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

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

Issue 12434004: Move remaining Autofill code to //components/autofill. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix long lines Created 7 years, 9 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 | Annotate | Revision Log
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 "chrome/renderer/autofill/form_cache.h"
6
7 #include "base/logging.h"
8 #include "base/utf_string_conversions.h"
9 #include "chrome/renderer/autofill/form_autofill_util.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 "grit/generated_resources.h"
15 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
16 #include "third_party/WebKit/Source/Platform/chromium/public/WebVector.h"
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormControlElement .h"
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormElement.h"
20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h"
22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSelectElement.h"
23 #include "ui/base/l10n/l10n_util.h"
24
25 using WebKit::WebDocument;
26 using WebKit::WebFormControlElement;
27 using WebKit::WebFormElement;
28 using WebKit::WebFrame;
29 using WebKit::WebInputElement;
30 using WebKit::WebSelectElement;
31 using WebKit::WebString;
32 using WebKit::WebVector;
33
34 namespace {
35
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
38 // label for each field is a costly operation and we can't spare the cycles if
39 // it's not necessary.
40 const size_t kRequiredAutofillFields = 3;
41
42 } // namespace
43
44 namespace autofill {
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
72 FormCache::FormCache() {
73 }
74
75 FormCache::~FormCache() {
76 }
77
78 void FormCache::ExtractForms(const WebFrame& frame,
79 std::vector<FormData>* forms) {
80 ExtractFormsAndFormElements(frame, forms, NULL);
81 }
82
83 void FormCache::ExtractFormsAndFormElements(
84 const WebFrame& frame,
85 std::vector<FormData>* forms,
86 std::vector<WebFormElement>* web_form_elements) {
87 // Reset the cache for this frame.
88 ResetFrame(frame);
89
90 WebDocument document = frame.document();
91 if (document.isNull())
92 return;
93
94 web_documents_.insert(document);
95
96 WebVector<WebFormElement> web_forms;
97 document.forms(web_forms);
98
99 size_t num_fields_seen = 0;
100 for (size_t i = 0; i < web_forms.size(); ++i) {
101 WebFormElement form_element = web_forms[i];
102
103 std::vector<WebFormControlElement> control_elements;
104 ExtractAutofillableElements(form_element, autofill::REQUIRE_NONE,
105 &control_elements);
106
107 size_t num_editable_elements = 0;
108 for (size_t j = 0; j < control_elements.size(); ++j) {
109 WebFormControlElement element = control_elements[j];
110
111 // Save original values of <select> elements so we can restore them
112 // when |ClearFormWithNode()| is invoked.
113 if (IsSelectElement(element)) {
114 const WebSelectElement select_element =
115 element.toConst<WebSelectElement>();
116 initial_select_values_.insert(std::make_pair(select_element,
117 select_element.value()));
118 ++num_editable_elements;
119 } else {
120 const WebInputElement input_element =
121 element.toConst<WebInputElement>();
122 if (IsCheckableElement(&input_element)) {
123 initial_checked_state_.insert(
124 std::make_pair(input_element, input_element.isChecked()));
125 } else {
126 ++num_editable_elements;
127 }
128 }
129 }
130
131 // To avoid overly expensive computation, we impose a minimum number of
132 // allowable fields. The corresponding maximum number of allowable fields
133 // is imposed by WebFormElementToFormData().
134 if (num_editable_elements < kRequiredAutofillFields)
135 continue;
136
137 FormData form;
138 ExtractMask extract_mask =
139 static_cast<ExtractMask>(EXTRACT_VALUE | EXTRACT_OPTIONS);
140
141 if (!WebFormElementToFormData(form_element, WebFormControlElement(),
142 REQUIRE_NONE, extract_mask, &form, NULL)) {
143 continue;
144 }
145
146 num_fields_seen += form.fields.size();
147 if (num_fields_seen > kMaxParseableFields)
148 break;
149
150 if (form.fields.size() >= kRequiredAutofillFields) {
151 forms->push_back(form);
152 if (web_form_elements)
153 web_form_elements->push_back(form_element);
154 }
155 }
156 }
157
158 void FormCache::ResetFrame(const WebFrame& frame) {
159 std::vector<WebDocument> documents_to_delete;
160 for (std::set<WebDocument>::const_iterator it = web_documents_.begin();
161 it != web_documents_.end(); ++it) {
162 const WebFrame* document_frame = it->frame();
163 if (!document_frame || document_frame == &frame)
164 documents_to_delete.push_back(*it);
165 }
166
167 for (std::vector<WebDocument>::const_iterator it =
168 documents_to_delete.begin();
169 it != documents_to_delete.end(); ++it) {
170 web_documents_.erase(*it);
171 }
172
173 RemoveOldElements(frame, &initial_select_values_);
174 RemoveOldElements(frame, &initial_checked_state_);
175 }
176
177 bool FormCache::ClearFormWithElement(const WebInputElement& element) {
178 WebFormElement form_element = element.form();
179 if (form_element.isNull())
180 return false;
181
182 std::vector<WebFormControlElement> control_elements;
183 ExtractAutofillableElements(form_element, autofill::REQUIRE_NONE,
184 &control_elements);
185 for (size_t i = 0; i < control_elements.size(); ++i) {
186 WebFormControlElement control_element = control_elements[i];
187 WebInputElement* input_element = toWebInputElement(&control_element);
188 if (IsTextInput(input_element)) {
189 // We don't modify the value of disabled fields.
190 if (!input_element->isEnabled())
191 continue;
192
193 input_element->setValue(string16(), true);
194 input_element->setAutofilled(false);
195
196 // Clearing the value in the focused node (above) can cause selection
197 // to be lost. We force selection range to restore the text cursor.
198 if (element == *input_element) {
199 int length = input_element->value().length();
200 input_element->setSelectionRange(length, length);
201 }
202 } else if (IsSelectElement(control_element)) {
203 WebSelectElement select_element = control_element.to<WebSelectElement>();
204
205 std::map<const WebSelectElement, string16>::const_iterator
206 initial_value_iter = initial_select_values_.find(select_element);
207 if (initial_value_iter != initial_select_values_.end() &&
208 select_element.value() != initial_value_iter->second) {
209 select_element.setValue(initial_value_iter->second);
210 select_element.dispatchFormControlChangeEvent();
211 }
212 } else {
213 WebInputElement input_element = control_element.to<WebInputElement>();
214 DCHECK(IsCheckableElement(&input_element));
215 std::map<const WebInputElement, bool>::const_iterator it =
216 initial_checked_state_.find(input_element);
217 if (it != initial_checked_state_.end() &&
218 input_element.isChecked() != it->second) {
219 input_element.setChecked(it->second, true);
220 }
221 }
222 }
223
224 return true;
225 }
226
227 bool FormCache::ShowPredictions(const FormDataPredictions& form) {
228 DCHECK_EQ(form.data.fields.size(), form.fields.size());
229
230 // Find the form.
231 bool found_form = false;
232 WebFormElement form_element;
233 for (std::set<WebDocument>::const_iterator it = web_documents_.begin();
234 it != web_documents_.end() && !found_form; ++it) {
235 WebVector<WebFormElement> web_forms;
236 it->forms(web_forms);
237
238 for (size_t i = 0; i < web_forms.size(); ++i) {
239 form_element = web_forms[i];
240
241 // Note: matching on the form name here which is not guaranteed to be
242 // unique for the page, nor is it guaranteed to be non-empty. Ideally, we
243 // would have a way to uniquely identify the form cross-process. For now,
244 // we'll check form name and form action for identity.
245 // Also note that WebString() == WebString(string16()) does not evaluate
246 // to |true| -- WebKit distinguishes between a "null" string (lhs) and an
247 // "empty" string (rhs). We don't want that distinction, so forcing to
248 // string16.
249 string16 element_name = GetFormIdentifier(form_element);
250 GURL action(form_element.document().completeURL(form_element.action()));
251 if (element_name == form.data.name && action == form.data.action) {
252 found_form = true;
253 break;
254 }
255 }
256 }
257
258 if (!found_form)
259 return false;
260
261 std::vector<WebFormControlElement> control_elements;
262 ExtractAutofillableElements(form_element, autofill::REQUIRE_NONE,
263 &control_elements);
264 if (control_elements.size() != form.fields.size()) {
265 // Keep things simple. Don't show predictions for forms that were modified
266 // between page load and the server's response to our query.
267 return false;
268 }
269
270 for (size_t i = 0; i < control_elements.size(); ++i) {
271 WebFormControlElement* element = &control_elements[i];
272
273 if (string16(element->nameForAutofill()) != form.data.fields[i].name) {
274 // Keep things simple. Don't show predictions for elements whose names
275 // were modified between page load and the server's response to our query.
276 continue;
277 }
278
279 std::string placeholder = form.fields[i].overall_type;
280 string16 title = l10n_util::GetStringFUTF16(
281 IDS_AUTOFILL_SHOW_PREDICTIONS_TITLE,
282 UTF8ToUTF16(form.fields[i].heuristic_type),
283 UTF8ToUTF16(form.fields[i].server_type),
284 UTF8ToUTF16(form.fields[i].signature),
285 UTF8ToUTF16(form.signature),
286 UTF8ToUTF16(form.experiment_id));
287 if (!element->hasAttribute("placeholder"))
288 element->setAttribute("placeholder", WebString(UTF8ToUTF16(placeholder)));
289 element->setAttribute("title", WebString(title));
290 }
291
292 return true;
293 }
294
295 } // namespace autofill
OLDNEW
« no previous file with comments | « chrome/renderer/autofill/form_cache.h ('k') | chrome/renderer/autofill/password_autofill_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698