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

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

Issue 13973004: Convert string16 -> base::string16 in components/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 8 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
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 "components/autofill/renderer/form_autofill_util.h" 5 #include "components/autofill/renderer/form_autofill_util.h"
6 6
7 #include <map> 7 #include <map>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 // has leading whitespace. 97 // has leading whitespace.
98 // A few examples: 98 // A few examples:
99 // * CombineAndCollapseWhitespace("foo", "bar", false) -> "foobar" 99 // * CombineAndCollapseWhitespace("foo", "bar", false) -> "foobar"
100 // * CombineAndCollapseWhitespace("foo", "bar", true) -> "foo bar" 100 // * CombineAndCollapseWhitespace("foo", "bar", true) -> "foo bar"
101 // * CombineAndCollapseWhitespace("foo ", "bar", false) -> "foo bar" 101 // * CombineAndCollapseWhitespace("foo ", "bar", false) -> "foo bar"
102 // * CombineAndCollapseWhitespace("foo", " bar", false) -> "foo bar" 102 // * CombineAndCollapseWhitespace("foo", " bar", false) -> "foo bar"
103 // * CombineAndCollapseWhitespace("foo", " bar", true) -> "foo bar" 103 // * CombineAndCollapseWhitespace("foo", " bar", true) -> "foo bar"
104 // * CombineAndCollapseWhitespace("foo ", " bar", false) -> "foo bar" 104 // * CombineAndCollapseWhitespace("foo ", " bar", false) -> "foo bar"
105 // * CombineAndCollapseWhitespace(" foo", "bar ", false) -> " foobar " 105 // * CombineAndCollapseWhitespace(" foo", "bar ", false) -> " foobar "
106 // * CombineAndCollapseWhitespace(" foo", "bar ", true) -> " foo bar " 106 // * CombineAndCollapseWhitespace(" foo", "bar ", true) -> " foo bar "
107 const string16 CombineAndCollapseWhitespace(const string16& prefix, 107 const base::string16 CombineAndCollapseWhitespace(
108 const string16& suffix, 108 const base::string16& prefix,
109 bool force_whitespace) { 109 const base::string16& suffix,
110 string16 prefix_trimmed; 110 bool force_whitespace) {
111 base::string16 prefix_trimmed;
111 TrimPositions prefix_trailing_whitespace = 112 TrimPositions prefix_trailing_whitespace =
112 TrimWhitespace(prefix, TRIM_TRAILING, &prefix_trimmed); 113 TrimWhitespace(prefix, TRIM_TRAILING, &prefix_trimmed);
113 114
114 // Recursively compute the children's text. 115 // Recursively compute the children's text.
115 string16 suffix_trimmed; 116 base::string16 suffix_trimmed;
116 TrimPositions suffix_leading_whitespace = 117 TrimPositions suffix_leading_whitespace =
117 TrimWhitespace(suffix, TRIM_LEADING, &suffix_trimmed); 118 TrimWhitespace(suffix, TRIM_LEADING, &suffix_trimmed);
118 119
119 if (prefix_trailing_whitespace || suffix_leading_whitespace || 120 if (prefix_trailing_whitespace || suffix_leading_whitespace ||
120 force_whitespace) { 121 force_whitespace) {
121 return prefix_trimmed + ASCIIToUTF16(" ") + suffix_trimmed; 122 return prefix_trimmed + ASCIIToUTF16(" ") + suffix_trimmed;
122 } else { 123 } else {
123 return prefix_trimmed + suffix_trimmed; 124 return prefix_trimmed + suffix_trimmed;
124 } 125 }
125 } 126 }
126 127
127 // This is a helper function for the FindChildText() function (see below). 128 // This is a helper function for the FindChildText() function (see below).
128 // Search depth is limited with the |depth| parameter. 129 // Search depth is limited with the |depth| parameter.
129 string16 FindChildTextInner(const WebNode& node, int depth) { 130 base::string16 FindChildTextInner(const WebNode& node, int depth) {
130 if (depth <= 0 || node.isNull()) 131 if (depth <= 0 || node.isNull())
131 return string16(); 132 return base::string16();
132 133
133 // Skip over comments. 134 // Skip over comments.
134 if (node.nodeType() == WebNode::CommentNode) 135 if (node.nodeType() == WebNode::CommentNode)
135 return FindChildTextInner(node.nextSibling(), depth - 1); 136 return FindChildTextInner(node.nextSibling(), depth - 1);
136 137
137 if (node.nodeType() != WebNode::ElementNode && 138 if (node.nodeType() != WebNode::ElementNode &&
138 node.nodeType() != WebNode::TextNode) 139 node.nodeType() != WebNode::TextNode)
139 return string16(); 140 return base::string16();
140 141
141 // Ignore elements known not to contain inferable labels. 142 // Ignore elements known not to contain inferable labels.
142 if (node.isElementNode()) { 143 if (node.isElementNode()) {
143 const WebElement element = node.toConst<WebElement>(); 144 const WebElement element = node.toConst<WebElement>();
144 if (IsOptionElement(element) || 145 if (IsOptionElement(element) ||
145 IsScriptElement(element) || 146 IsScriptElement(element) ||
146 IsNoScriptElement(element) || 147 IsNoScriptElement(element) ||
147 (element.isFormControlElement() && 148 (element.isFormControlElement() &&
148 IsAutofillableElement(element.toConst<WebFormControlElement>()))) { 149 IsAutofillableElement(element.toConst<WebFormControlElement>()))) {
149 return string16(); 150 return base::string16();
150 } 151 }
151 } 152 }
152 153
153 // Extract the text exactly at this node. 154 // Extract the text exactly at this node.
154 string16 node_text = node.nodeValue(); 155 base::string16 node_text = node.nodeValue();
155 156
156 // Recursively compute the children's text. 157 // Recursively compute the children's text.
157 // Preserve inter-element whitespace separation. 158 // Preserve inter-element whitespace separation.
158 string16 child_text = FindChildTextInner(node.firstChild(), depth - 1); 159 base::string16 child_text = FindChildTextInner(node.firstChild(), depth - 1);
159 bool add_space = node.nodeType() == WebNode::TextNode && node_text.empty(); 160 bool add_space = node.nodeType() == WebNode::TextNode && node_text.empty();
160 node_text = CombineAndCollapseWhitespace(node_text, child_text, add_space); 161 node_text = CombineAndCollapseWhitespace(node_text, child_text, add_space);
161 162
162 // Recursively compute the siblings' text. 163 // Recursively compute the siblings' text.
163 // Again, preserve inter-element whitespace separation. 164 // Again, preserve inter-element whitespace separation.
164 string16 sibling_text = FindChildTextInner(node.nextSibling(), depth - 1); 165 base::string16 sibling_text =
166 FindChildTextInner(node.nextSibling(), depth - 1);
165 add_space = node.nodeType() == WebNode::TextNode && node_text.empty(); 167 add_space = node.nodeType() == WebNode::TextNode && node_text.empty();
166 node_text = CombineAndCollapseWhitespace(node_text, sibling_text, add_space); 168 node_text = CombineAndCollapseWhitespace(node_text, sibling_text, add_space);
167 169
168 return node_text; 170 return node_text;
169 } 171 }
170 172
171 // Returns the aggregated values of the descendants of |element| that are 173 // Returns the aggregated values of the descendants of |element| that are
172 // non-empty text nodes. This is a faster alternative to |innerText()| for 174 // non-empty text nodes. This is a faster alternative to |innerText()| for
173 // performance critical operations. It does a full depth-first search so can be 175 // performance critical operations. It does a full depth-first search so can be
174 // used when the structure is not directly known. However, unlike with 176 // used when the structure is not directly known. However, unlike with
175 // |innerText()|, the search depth and breadth are limited to a fixed threshold. 177 // |innerText()|, the search depth and breadth are limited to a fixed threshold.
176 // Whitespace is trimmed from text accumulated at descendant nodes. 178 // Whitespace is trimmed from text accumulated at descendant nodes.
177 string16 FindChildText(const WebNode& node) { 179 base::string16 FindChildText(const WebNode& node) {
178 if (node.isTextNode()) 180 if (node.isTextNode())
179 return node.nodeValue(); 181 return node.nodeValue();
180 182
181 WebNode child = node.firstChild(); 183 WebNode child = node.firstChild();
182 184
183 const int kChildSearchDepth = 10; 185 const int kChildSearchDepth = 10;
184 string16 node_text = FindChildTextInner(child, kChildSearchDepth); 186 base::string16 node_text = FindChildTextInner(child, kChildSearchDepth);
185 TrimWhitespace(node_text, TRIM_ALL, &node_text); 187 TrimWhitespace(node_text, TRIM_ALL, &node_text);
186 return node_text; 188 return node_text;
187 } 189 }
188 190
189 // Helper for |InferLabelForElement()| that infers a label, if possible, from 191 // Helper for |InferLabelForElement()| that infers a label, if possible, from
190 // a previous sibling of |element|, 192 // a previous sibling of |element|,
191 // e.g. Some Text <input ...> 193 // e.g. Some Text <input ...>
192 // or Some <span>Text</span> <input ...> 194 // or Some <span>Text</span> <input ...>
193 // or <p>Some Text</p><input ...> 195 // or <p>Some Text</p><input ...>
194 // or <label>Some Text</label> <input ...> 196 // or <label>Some Text</label> <input ...>
195 // or Some Text <img><input ...> 197 // or Some Text <img><input ...>
196 // or <b>Some Text</b><br/> <input ...>. 198 // or <b>Some Text</b><br/> <input ...>.
197 string16 InferLabelFromPrevious(const WebFormControlElement& element) { 199 base::string16 InferLabelFromPrevious(const WebFormControlElement& element) {
198 string16 inferred_label; 200 base::string16 inferred_label;
199 WebNode previous = element; 201 WebNode previous = element;
200 while (true) { 202 while (true) {
201 previous = previous.previousSibling(); 203 previous = previous.previousSibling();
202 if (previous.isNull()) 204 if (previous.isNull())
203 break; 205 break;
204 206
205 // Skip over comments. 207 // Skip over comments.
206 WebNode::NodeType node_type = previous.nodeType(); 208 WebNode::NodeType node_type = previous.nodeType();
207 if (node_type == WebNode::CommentNode) 209 if (node_type == WebNode::CommentNode)
208 continue; 210 continue;
209 211
210 // Otherwise, only consider normal HTML elements and their contents. 212 // Otherwise, only consider normal HTML elements and their contents.
211 if (node_type != WebNode::TextNode && 213 if (node_type != WebNode::TextNode &&
212 node_type != WebNode::ElementNode) 214 node_type != WebNode::ElementNode)
213 break; 215 break;
214 216
215 // A label might be split across multiple "lightweight" nodes. 217 // A label might be split across multiple "lightweight" nodes.
216 // Coalesce any text contained in multiple consecutive 218 // Coalesce any text contained in multiple consecutive
217 // (a) plain text nodes or 219 // (a) plain text nodes or
218 // (b) inline HTML elements that are essentially equivalent to text nodes. 220 // (b) inline HTML elements that are essentially equivalent to text nodes.
219 CR_DEFINE_STATIC_LOCAL(WebString, kBold, ("b")); 221 CR_DEFINE_STATIC_LOCAL(WebString, kBold, ("b"));
220 CR_DEFINE_STATIC_LOCAL(WebString, kStrong, ("strong")); 222 CR_DEFINE_STATIC_LOCAL(WebString, kStrong, ("strong"));
221 CR_DEFINE_STATIC_LOCAL(WebString, kSpan, ("span")); 223 CR_DEFINE_STATIC_LOCAL(WebString, kSpan, ("span"));
222 CR_DEFINE_STATIC_LOCAL(WebString, kFont, ("font")); 224 CR_DEFINE_STATIC_LOCAL(WebString, kFont, ("font"));
223 if (previous.isTextNode() || 225 if (previous.isTextNode() ||
224 HasTagName(previous, kBold) || HasTagName(previous, kStrong) || 226 HasTagName(previous, kBold) || HasTagName(previous, kStrong) ||
225 HasTagName(previous, kSpan) || HasTagName(previous, kFont)) { 227 HasTagName(previous, kSpan) || HasTagName(previous, kFont)) {
226 string16 value = FindChildText(previous); 228 base::string16 value = FindChildText(previous);
227 // A text node's value will be empty if it is for a line break. 229 // A text node's value will be empty if it is for a line break.
228 bool add_space = previous.isTextNode() && value.empty(); 230 bool add_space = previous.isTextNode() && value.empty();
229 inferred_label = 231 inferred_label =
230 CombineAndCollapseWhitespace(value, inferred_label, add_space); 232 CombineAndCollapseWhitespace(value, inferred_label, add_space);
231 continue; 233 continue;
232 } 234 }
233 235
234 // If we have identified a partial label and have reached a non-lightweight 236 // If we have identified a partial label and have reached a non-lightweight
235 // element, consider the label to be complete. 237 // element, consider the label to be complete.
236 string16 trimmed_label; 238 base::string16 trimmed_label;
237 TrimWhitespace(inferred_label, TRIM_ALL, &trimmed_label); 239 TrimWhitespace(inferred_label, TRIM_ALL, &trimmed_label);
238 if (!trimmed_label.empty()) 240 if (!trimmed_label.empty())
239 break; 241 break;
240 242
241 // <img> and <br> tags often appear between the input element and its 243 // <img> and <br> tags often appear between the input element and its
242 // label text, so skip over them. 244 // label text, so skip over them.
243 CR_DEFINE_STATIC_LOCAL(WebString, kImage, ("img")); 245 CR_DEFINE_STATIC_LOCAL(WebString, kImage, ("img"));
244 CR_DEFINE_STATIC_LOCAL(WebString, kBreak, ("br")); 246 CR_DEFINE_STATIC_LOCAL(WebString, kBreak, ("br"));
245 if (HasTagName(previous, kImage) || HasTagName(previous, kBreak)) 247 if (HasTagName(previous, kImage) || HasTagName(previous, kBreak))
246 continue; 248 continue;
247 249
248 // We only expect <p> and <label> tags to contain the full label text. 250 // We only expect <p> and <label> tags to contain the full label text.
249 CR_DEFINE_STATIC_LOCAL(WebString, kPage, ("p")); 251 CR_DEFINE_STATIC_LOCAL(WebString, kPage, ("p"));
250 CR_DEFINE_STATIC_LOCAL(WebString, kLabel, ("label")); 252 CR_DEFINE_STATIC_LOCAL(WebString, kLabel, ("label"));
251 if (HasTagName(previous, kPage) || HasTagName(previous, kLabel)) 253 if (HasTagName(previous, kPage) || HasTagName(previous, kLabel))
252 inferred_label = FindChildText(previous); 254 inferred_label = FindChildText(previous);
253 255
254 break; 256 break;
255 } 257 }
256 258
257 TrimWhitespace(inferred_label, TRIM_ALL, &inferred_label); 259 TrimWhitespace(inferred_label, TRIM_ALL, &inferred_label);
258 return inferred_label; 260 return inferred_label;
259 } 261 }
260 262
261 // Helper for |InferLabelForElement()| that infers a label, if possible, from 263 // Helper for |InferLabelForElement()| that infers a label, if possible, from
262 // enclosing list item, 264 // enclosing list item,
263 // e.g. <li>Some Text<input ...><input ...><input ...></tr> 265 // e.g. <li>Some Text<input ...><input ...><input ...></tr>
264 string16 InferLabelFromListItem(const WebFormControlElement& element) { 266 base::string16 InferLabelFromListItem(const WebFormControlElement& element) {
265 WebNode parent = element.parentNode(); 267 WebNode parent = element.parentNode();
266 CR_DEFINE_STATIC_LOCAL(WebString, kListItem, ("li")); 268 CR_DEFINE_STATIC_LOCAL(WebString, kListItem, ("li"));
267 while (!parent.isNull() && parent.isElementNode() && 269 while (!parent.isNull() && parent.isElementNode() &&
268 !parent.to<WebElement>().hasTagName(kListItem)) { 270 !parent.to<WebElement>().hasTagName(kListItem)) {
269 parent = parent.parentNode(); 271 parent = parent.parentNode();
270 } 272 }
271 273
272 if (!parent.isNull() && HasTagName(parent, kListItem)) 274 if (!parent.isNull() && HasTagName(parent, kListItem))
273 return FindChildText(parent); 275 return FindChildText(parent);
274 276
275 return string16(); 277 return base::string16();
276 } 278 }
277 279
278 // Helper for |InferLabelForElement()| that infers a label, if possible, from 280 // Helper for |InferLabelForElement()| that infers a label, if possible, from
279 // surrounding table structure, 281 // surrounding table structure,
280 // e.g. <tr><td>Some Text</td><td><input ...></td></tr> 282 // e.g. <tr><td>Some Text</td><td><input ...></td></tr>
281 // or <tr><th>Some Text</th><td><input ...></td></tr> 283 // or <tr><th>Some Text</th><td><input ...></td></tr>
282 // or <tr><td><b>Some Text</b></td><td><b><input ...></b></td></tr> 284 // or <tr><td><b>Some Text</b></td><td><b><input ...></b></td></tr>
283 // or <tr><th><b>Some Text</b></th><td><b><input ...></b></td></tr> 285 // or <tr><th><b>Some Text</b></th><td><b><input ...></b></td></tr>
284 string16 InferLabelFromTableColumn(const WebFormControlElement& element) { 286 base::string16 InferLabelFromTableColumn(const WebFormControlElement& element) {
285 CR_DEFINE_STATIC_LOCAL(WebString, kTableCell, ("td")); 287 CR_DEFINE_STATIC_LOCAL(WebString, kTableCell, ("td"));
286 WebNode parent = element.parentNode(); 288 WebNode parent = element.parentNode();
287 while (!parent.isNull() && parent.isElementNode() && 289 while (!parent.isNull() && parent.isElementNode() &&
288 !parent.to<WebElement>().hasTagName(kTableCell)) { 290 !parent.to<WebElement>().hasTagName(kTableCell)) {
289 parent = parent.parentNode(); 291 parent = parent.parentNode();
290 } 292 }
291 293
292 if (parent.isNull()) 294 if (parent.isNull())
293 return string16(); 295 return base::string16();
294 296
295 // Check all previous siblings, skipping non-element nodes, until we find a 297 // Check all previous siblings, skipping non-element nodes, until we find a
296 // non-empty text block. 298 // non-empty text block.
297 string16 inferred_label; 299 base::string16 inferred_label;
298 WebNode previous = parent.previousSibling(); 300 WebNode previous = parent.previousSibling();
299 CR_DEFINE_STATIC_LOCAL(WebString, kTableHeader, ("th")); 301 CR_DEFINE_STATIC_LOCAL(WebString, kTableHeader, ("th"));
300 while (inferred_label.empty() && !previous.isNull()) { 302 while (inferred_label.empty() && !previous.isNull()) {
301 if (HasTagName(previous, kTableCell) || HasTagName(previous, kTableHeader)) 303 if (HasTagName(previous, kTableCell) || HasTagName(previous, kTableHeader))
302 inferred_label = FindChildText(previous); 304 inferred_label = FindChildText(previous);
303 305
304 previous = previous.previousSibling(); 306 previous = previous.previousSibling();
305 } 307 }
306 308
307 return inferred_label; 309 return inferred_label;
308 } 310 }
309 311
310 // Helper for |InferLabelForElement()| that infers a label, if possible, from 312 // Helper for |InferLabelForElement()| that infers a label, if possible, from
311 // surrounding table structure, 313 // surrounding table structure,
312 // e.g. <tr><td>Some Text</td></tr><tr><td><input ...></td></tr> 314 // e.g. <tr><td>Some Text</td></tr><tr><td><input ...></td></tr>
313 string16 InferLabelFromTableRow(const WebFormControlElement& element) { 315 base::string16 InferLabelFromTableRow(const WebFormControlElement& element) {
314 CR_DEFINE_STATIC_LOCAL(WebString, kTableRow, ("tr")); 316 CR_DEFINE_STATIC_LOCAL(WebString, kTableRow, ("tr"));
315 WebNode parent = element.parentNode(); 317 WebNode parent = element.parentNode();
316 while (!parent.isNull() && parent.isElementNode() && 318 while (!parent.isNull() && parent.isElementNode() &&
317 !parent.to<WebElement>().hasTagName(kTableRow)) { 319 !parent.to<WebElement>().hasTagName(kTableRow)) {
318 parent = parent.parentNode(); 320 parent = parent.parentNode();
319 } 321 }
320 322
321 if (parent.isNull()) 323 if (parent.isNull())
322 return string16(); 324 return base::string16();
323 325
324 // Check all previous siblings, skipping non-element nodes, until we find a 326 // Check all previous siblings, skipping non-element nodes, until we find a
325 // non-empty text block. 327 // non-empty text block.
326 string16 inferred_label; 328 base::string16 inferred_label;
327 WebNode previous = parent.previousSibling(); 329 WebNode previous = parent.previousSibling();
328 while (inferred_label.empty() && !previous.isNull()) { 330 while (inferred_label.empty() && !previous.isNull()) {
329 if (HasTagName(previous, kTableRow)) 331 if (HasTagName(previous, kTableRow))
330 inferred_label = FindChildText(previous); 332 inferred_label = FindChildText(previous);
331 333
332 previous = previous.previousSibling(); 334 previous = previous.previousSibling();
333 } 335 }
334 336
335 return inferred_label; 337 return inferred_label;
336 } 338 }
337 339
338 // Helper for |InferLabelForElement()| that infers a label, if possible, from 340 // Helper for |InferLabelForElement()| that infers a label, if possible, from
339 // a surrounding div table, 341 // a surrounding div table,
340 // e.g. <div>Some Text<span><input ...></span></div> 342 // e.g. <div>Some Text<span><input ...></span></div>
341 // e.g. <div>Some Text</div><div><input ...></div> 343 // e.g. <div>Some Text</div><div><input ...></div>
342 string16 InferLabelFromDivTable(const WebFormControlElement& element) { 344 base::string16 InferLabelFromDivTable(const WebFormControlElement& element) {
343 WebNode node = element.parentNode(); 345 WebNode node = element.parentNode();
344 bool looking_for_parent = true; 346 bool looking_for_parent = true;
345 347
346 // Search the sibling and parent <div>s until we find a candidate label. 348 // Search the sibling and parent <div>s until we find a candidate label.
347 string16 inferred_label; 349 base::string16 inferred_label;
348 CR_DEFINE_STATIC_LOCAL(WebString, kDiv, ("div")); 350 CR_DEFINE_STATIC_LOCAL(WebString, kDiv, ("div"));
349 CR_DEFINE_STATIC_LOCAL(WebString, kTable, ("table")); 351 CR_DEFINE_STATIC_LOCAL(WebString, kTable, ("table"));
350 CR_DEFINE_STATIC_LOCAL(WebString, kFieldSet, ("fieldset")); 352 CR_DEFINE_STATIC_LOCAL(WebString, kFieldSet, ("fieldset"));
351 while (inferred_label.empty() && !node.isNull()) { 353 while (inferred_label.empty() && !node.isNull()) {
352 if (HasTagName(node, kDiv)) { 354 if (HasTagName(node, kDiv)) {
353 looking_for_parent = false; 355 looking_for_parent = false;
354 inferred_label = FindChildText(node); 356 inferred_label = FindChildText(node);
355 } else if (looking_for_parent && 357 } else if (looking_for_parent &&
356 (HasTagName(node, kTable) || HasTagName(node, kFieldSet))) { 358 (HasTagName(node, kTable) || HasTagName(node, kFieldSet))) {
357 // If the element is in a table or fieldset, its label most likely is too. 359 // If the element is in a table or fieldset, its label most likely is too.
(...skipping 11 matching lines...) Expand all
369 node = node.previousSibling(); 371 node = node.previousSibling();
370 } 372 }
371 373
372 return inferred_label; 374 return inferred_label;
373 } 375 }
374 376
375 // Helper for |InferLabelForElement()| that infers a label, if possible, from 377 // Helper for |InferLabelForElement()| that infers a label, if possible, from
376 // a surrounding definition list, 378 // a surrounding definition list,
377 // e.g. <dl><dt>Some Text</dt><dd><input ...></dd></dl> 379 // e.g. <dl><dt>Some Text</dt><dd><input ...></dd></dl>
378 // e.g. <dl><dt><b>Some Text</b></dt><dd><b><input ...></b></dd></dl> 380 // e.g. <dl><dt><b>Some Text</b></dt><dd><b><input ...></b></dd></dl>
379 string16 InferLabelFromDefinitionList(const WebFormControlElement& element) { 381 base::string16 InferLabelFromDefinitionList(
382 const WebFormControlElement& element) {
380 CR_DEFINE_STATIC_LOCAL(WebString, kDefinitionData, ("dd")); 383 CR_DEFINE_STATIC_LOCAL(WebString, kDefinitionData, ("dd"));
381 WebNode parent = element.parentNode(); 384 WebNode parent = element.parentNode();
382 while (!parent.isNull() && parent.isElementNode() && 385 while (!parent.isNull() && parent.isElementNode() &&
383 !parent.to<WebElement>().hasTagName(kDefinitionData)) 386 !parent.to<WebElement>().hasTagName(kDefinitionData))
384 parent = parent.parentNode(); 387 parent = parent.parentNode();
385 388
386 if (parent.isNull() || !HasTagName(parent, kDefinitionData)) 389 if (parent.isNull() || !HasTagName(parent, kDefinitionData))
387 return string16(); 390 return base::string16();
388 391
389 // Skip by any intervening text nodes. 392 // Skip by any intervening text nodes.
390 WebNode previous = parent.previousSibling(); 393 WebNode previous = parent.previousSibling();
391 while (!previous.isNull() && previous.isTextNode()) 394 while (!previous.isNull() && previous.isTextNode())
392 previous = previous.previousSibling(); 395 previous = previous.previousSibling();
393 396
394 CR_DEFINE_STATIC_LOCAL(WebString, kDefinitionTag, ("dt")); 397 CR_DEFINE_STATIC_LOCAL(WebString, kDefinitionTag, ("dt"));
395 if (previous.isNull() || !HasTagName(previous, kDefinitionTag)) 398 if (previous.isNull() || !HasTagName(previous, kDefinitionTag))
396 return string16(); 399 return base::string16();
397 400
398 return FindChildText(previous); 401 return FindChildText(previous);
399 } 402 }
400 403
401 // Infers corresponding label for |element| from surrounding context in the DOM, 404 // Infers corresponding label for |element| from surrounding context in the DOM,
402 // e.g. the contents of the preceding <p> tag or text element. 405 // e.g. the contents of the preceding <p> tag or text element.
403 string16 InferLabelForElement(const WebFormControlElement& element) { 406 base::string16 InferLabelForElement(const WebFormControlElement& element) {
404 string16 inferred_label = InferLabelFromPrevious(element); 407 base::string16 inferred_label = InferLabelFromPrevious(element);
405 if (!inferred_label.empty()) 408 if (!inferred_label.empty())
406 return inferred_label; 409 return inferred_label;
407 410
408 // If we didn't find a label, check for list item case. 411 // If we didn't find a label, check for list item case.
409 inferred_label = InferLabelFromListItem(element); 412 inferred_label = InferLabelFromListItem(element);
410 if (!inferred_label.empty()) 413 if (!inferred_label.empty())
411 return inferred_label; 414 return inferred_label;
412 415
413 // If we didn't find a label, check for table cell case. 416 // If we didn't find a label, check for table cell case.
414 inferred_label = InferLabelFromTableColumn(element); 417 inferred_label = InferLabelFromTableColumn(element);
(...skipping 10 matching lines...) Expand all
425 if (!inferred_label.empty()) 428 if (!inferred_label.empty())
426 return inferred_label; 429 return inferred_label;
427 430
428 // If we didn't find a label, check for div table case. 431 // If we didn't find a label, check for div table case.
429 return InferLabelFromDivTable(element); 432 return InferLabelFromDivTable(element);
430 } 433 }
431 434
432 // Fills |option_strings| with the values of the <option> elements present in 435 // Fills |option_strings| with the values of the <option> elements present in
433 // |select_element|. 436 // |select_element|.
434 void GetOptionStringsFromElement(const WebSelectElement& select_element, 437 void GetOptionStringsFromElement(const WebSelectElement& select_element,
435 std::vector<string16>* option_values, 438 std::vector<base::string16>* option_values,
436 std::vector<string16>* option_contents) { 439 std::vector<base::string16>* option_contents) {
437 DCHECK(!select_element.isNull()); 440 DCHECK(!select_element.isNull());
438 441
439 option_values->clear(); 442 option_values->clear();
440 option_contents->clear(); 443 option_contents->clear();
441 WebVector<WebElement> list_items = select_element.listItems(); 444 WebVector<WebElement> list_items = select_element.listItems();
442 option_values->reserve(list_items.size()); 445 option_values->reserve(list_items.size());
443 option_contents->reserve(list_items.size()); 446 option_contents->reserve(list_items.size());
444 for (size_t i = 0; i < list_items.size(); ++i) { 447 for (size_t i = 0; i < list_items.size(); ++i) {
445 if (IsOptionElement(list_items[i])) { 448 if (IsOptionElement(list_items[i])) {
446 const WebOptionElement option = list_items[i].toConst<WebOptionElement>(); 449 const WebOptionElement option = list_items[i].toConst<WebOptionElement>();
(...skipping 28 matching lines...) Expand all
475 } 478 }
476 479
477 // It's possible that the site has injected fields into the form after the 480 // It's possible that the site has injected fields into the form after the
478 // page has loaded, so we can't assert that the size of the cached control 481 // page has loaded, so we can't assert that the size of the cached control
479 // elements is equal to the size of the fields in |form|. Fortunately, the 482 // elements is equal to the size of the fields in |form|. Fortunately, the
480 // one case in the wild where this happens, paypal.com signup form, the fields 483 // one case in the wild where this happens, paypal.com signup form, the fields
481 // are appended to the end of the form and are not visible. 484 // are appended to the end of the form and are not visible.
482 for (size_t i = 0; i < control_elements.size(); ++i) { 485 for (size_t i = 0; i < control_elements.size(); ++i) {
483 WebFormControlElement* element = &control_elements[i]; 486 WebFormControlElement* element = &control_elements[i];
484 487
485 if (string16(element->nameForAutofill()) != data.fields[i].name) { 488 if (base::string16(element->nameForAutofill()) != data.fields[i].name) {
486 // This case should be reachable only for pathological websites, which 489 // This case should be reachable only for pathological websites, which
487 // rename form fields while the user is interacting with the Autofill 490 // rename form fields while the user is interacting with the Autofill
488 // popup. I (isherman) am not aware of any such websites, and so am 491 // popup. I (isherman) am not aware of any such websites, and so am
489 // optimistically including a NOTREACHED(). If you ever trip this check, 492 // optimistically including a NOTREACHED(). If you ever trip this check,
490 // please file a bug against me. 493 // please file a bug against me.
491 NOTREACHED(); 494 NOTREACHED();
492 continue; 495 continue;
493 } 496 }
494 497
495 bool is_initiating_element = (*element == initiating_element); 498 bool is_initiating_element = (*element == initiating_element);
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 if (!element) 608 if (!element)
606 return false; 609 return false;
607 610
608 return element->isCheckbox() || element->isRadioButton(); 611 return element->isCheckbox() || element->isRadioButton();
609 } 612 }
610 613
611 bool IsAutofillableInputElement(const WebInputElement* element) { 614 bool IsAutofillableInputElement(const WebInputElement* element) {
612 return IsTextInput(element) || IsCheckableElement(element); 615 return IsTextInput(element) || IsCheckableElement(element);
613 } 616 }
614 617
615 const string16 GetFormIdentifier(const WebFormElement& form) { 618 const base::string16 GetFormIdentifier(const WebFormElement& form) {
616 string16 identifier = form.name(); 619 base::string16 identifier = form.name();
617 CR_DEFINE_STATIC_LOCAL(WebString, kId, ("id")); 620 CR_DEFINE_STATIC_LOCAL(WebString, kId, ("id"));
618 if (identifier.empty()) 621 if (identifier.empty())
619 identifier = form.getAttribute(kId); 622 identifier = form.getAttribute(kId);
620 623
621 return identifier; 624 return identifier;
622 } 625 }
623 626
624 bool ClickElement(const WebDocument& document, 627 bool ClickElement(const WebDocument& document,
625 const WebElementDescriptor& element_descriptor) { 628 const WebElementDescriptor& element_descriptor) {
626 WebString web_descriptor = WebString::fromUTF8(element_descriptor.descriptor); 629 WebString web_descriptor = WebString::fromUTF8(element_descriptor.descriptor);
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
720 DCHECK(IsSelectElement(element)); 723 DCHECK(IsSelectElement(element));
721 const WebSelectElement select_element = element.toConst<WebSelectElement>(); 724 const WebSelectElement select_element = element.toConst<WebSelectElement>();
722 GetOptionStringsFromElement(select_element, 725 GetOptionStringsFromElement(select_element,
723 &field->option_values, 726 &field->option_values,
724 &field->option_contents); 727 &field->option_contents);
725 } 728 }
726 729
727 if (!(extract_mask & EXTRACT_VALUE)) 730 if (!(extract_mask & EXTRACT_VALUE))
728 return; 731 return;
729 732
730 string16 value; 733 base::string16 value;
731 if (IsAutofillableInputElement(input_element)) { 734 if (IsAutofillableInputElement(input_element)) {
732 value = input_element->value(); 735 value = input_element->value();
733 } else { 736 } else {
734 DCHECK(IsSelectElement(element)); 737 DCHECK(IsSelectElement(element));
735 const WebSelectElement select_element = element.toConst<WebSelectElement>(); 738 const WebSelectElement select_element = element.toConst<WebSelectElement>();
736 value = select_element.value(); 739 value = select_element.value();
737 740
738 // Convert the |select_element| value to text if requested. 741 // Convert the |select_element| value to text if requested.
739 if (extract_mask & EXTRACT_OPTION_TEXT) { 742 if (extract_mask & EXTRACT_OPTION_TEXT) {
740 WebVector<WebElement> list_items = select_element.listItems(); 743 WebVector<WebElement> list_items = select_element.listItems();
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
782 form->origin = frame->document().url(); 785 form->origin = frame->document().url();
783 form->action = frame->document().completeURL(form_element.action()); 786 form->action = frame->document().completeURL(form_element.action());
784 form->user_submitted = form_element.wasUserSubmitted(); 787 form->user_submitted = form_element.wasUserSubmitted();
785 788
786 // If the completed URL is not valid, just use the action we get from 789 // If the completed URL is not valid, just use the action we get from
787 // WebKit. 790 // WebKit.
788 if (!form->action.is_valid()) 791 if (!form->action.is_valid())
789 form->action = GURL(form_element.action()); 792 form->action = GURL(form_element.action());
790 793
791 // A map from a FormFieldData's name to the FormFieldData itself. 794 // A map from a FormFieldData's name to the FormFieldData itself.
792 std::map<string16, FormFieldData*> name_map; 795 std::map<base::string16, FormFieldData*> name_map;
793 796
794 // The extracted FormFields. We use pointers so we can store them in 797 // The extracted FormFields. We use pointers so we can store them in
795 // |name_map|. 798 // |name_map|.
796 ScopedVector<FormFieldData> form_fields; 799 ScopedVector<FormFieldData> form_fields;
797 800
798 WebVector<WebFormControlElement> control_elements; 801 WebVector<WebFormControlElement> control_elements;
799 form_element.getFormControlElements(control_elements); 802 form_element.getFormControlElements(control_elements);
800 803
801 // A vector of bools that indicate whether each field in the form meets the 804 // A vector of bools that indicate whether each field in the form meets the
802 // requirements and thus will be in the resulting |form|. 805 // requirements and thus will be in the resulting |form|.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
834 // element, get the corresponding form control element, use the form control 837 // element, get the corresponding form control element, use the form control
835 // element's name as a key into the <name, FormFieldData> map to find the 838 // element's name as a key into the <name, FormFieldData> map to find the
836 // previously created FormFieldData and set the FormFieldData's label to the 839 // previously created FormFieldData and set the FormFieldData's label to the
837 // label.firstChild().nodeValue() of the label element. 840 // label.firstChild().nodeValue() of the label element.
838 WebNodeList labels = form_element.getElementsByTagName(kLabel); 841 WebNodeList labels = form_element.getElementsByTagName(kLabel);
839 for (unsigned i = 0; i < labels.length(); ++i) { 842 for (unsigned i = 0; i < labels.length(); ++i) {
840 WebLabelElement label = labels.item(i).to<WebLabelElement>(); 843 WebLabelElement label = labels.item(i).to<WebLabelElement>();
841 WebFormControlElement field_element = 844 WebFormControlElement field_element =
842 label.correspondingControl().to<WebFormControlElement>(); 845 label.correspondingControl().to<WebFormControlElement>();
843 846
844 string16 element_name; 847 base::string16 element_name;
845 if (field_element.isNull()) { 848 if (field_element.isNull()) {
846 // Sometimes site authors will incorrectly specify the corresponding 849 // Sometimes site authors will incorrectly specify the corresponding
847 // field element's name rather than its id, so we compensate here. 850 // field element's name rather than its id, so we compensate here.
848 element_name = label.getAttribute(kFor); 851 element_name = label.getAttribute(kFor);
849 } else if ( 852 } else if (
850 !field_element.isFormControlElement() || 853 !field_element.isFormControlElement() ||
851 field_element.formControlType() == kHidden) { 854 field_element.formControlType() == kHidden) {
852 continue; 855 continue;
853 } else { 856 } else {
854 element_name = field_element.nameForAutofill(); 857 element_name = field_element.nameForAutofill();
855 } 858 }
856 859
857 std::map<string16, FormFieldData*>::iterator iter = 860 std::map<base::string16, FormFieldData*>::iterator iter =
858 name_map.find(element_name); 861 name_map.find(element_name);
859 if (iter != name_map.end()) { 862 if (iter != name_map.end()) {
860 string16 label_text = FindChildText(label); 863 base::string16 label_text = FindChildText(label);
861 864
862 // Concatenate labels because some sites might have multiple label 865 // Concatenate labels because some sites might have multiple label
863 // candidates. 866 // candidates.
864 if (!iter->second->label.empty() && !label_text.empty()) 867 if (!iter->second->label.empty() && !label_text.empty())
865 iter->second->label += ASCIIToUTF16(" "); 868 iter->second->label += ASCIIToUTF16(" ");
866 iter->second->label += label_text; 869 iter->second->label += label_text;
867 } 870 }
868 } 871 }
869 872
870 // Loop through the form control elements, extracting the label text from 873 // Loop through the form control elements, extracting the label text from
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1019 continue; 1022 continue;
1020 1023
1021 if (input_element->isAutofilled()) 1024 if (input_element->isAutofilled())
1022 return true; 1025 return true;
1023 } 1026 }
1024 1027
1025 return false; 1028 return false;
1026 } 1029 }
1027 1030
1028 } // namespace autofill 1031 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698