OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/content/renderer/autofill_agent.h" | 5 #include "components/autofill/content/renderer/autofill_agent.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "base/strings/string_split.h" | 10 #include "base/strings/string_split.h" |
(...skipping 23 matching lines...) Expand all Loading... |
34 #include "third_party/WebKit/public/platform/WebURLRequest.h" | 34 #include "third_party/WebKit/public/platform/WebURLRequest.h" |
35 #include "third_party/WebKit/public/web/WebDataSource.h" | 35 #include "third_party/WebKit/public/web/WebDataSource.h" |
36 #include "third_party/WebKit/public/web/WebDocument.h" | 36 #include "third_party/WebKit/public/web/WebDocument.h" |
37 #include "third_party/WebKit/public/web/WebElementCollection.h" | 37 #include "third_party/WebKit/public/web/WebElementCollection.h" |
38 #include "third_party/WebKit/public/web/WebFormControlElement.h" | 38 #include "third_party/WebKit/public/web/WebFormControlElement.h" |
39 #include "third_party/WebKit/public/web/WebFormElement.h" | 39 #include "third_party/WebKit/public/web/WebFormElement.h" |
40 #include "third_party/WebKit/public/web/WebFrame.h" | 40 #include "third_party/WebKit/public/web/WebFrame.h" |
41 #include "third_party/WebKit/public/web/WebInputEvent.h" | 41 #include "third_party/WebKit/public/web/WebInputEvent.h" |
42 #include "third_party/WebKit/public/web/WebNode.h" | 42 #include "third_party/WebKit/public/web/WebNode.h" |
43 #include "third_party/WebKit/public/web/WebOptionElement.h" | 43 #include "third_party/WebKit/public/web/WebOptionElement.h" |
| 44 #include "third_party/WebKit/public/web/WebTextAreaElement.h" |
44 #include "third_party/WebKit/public/web/WebView.h" | 45 #include "third_party/WebKit/public/web/WebView.h" |
45 #include "ui/base/l10n/l10n_util.h" | 46 #include "ui/base/l10n/l10n_util.h" |
46 #include "ui/events/keycodes/keyboard_codes.h" | 47 #include "ui/events/keycodes/keyboard_codes.h" |
47 | 48 |
48 using blink::WebAutofillClient; | 49 using blink::WebAutofillClient; |
| 50 using blink::WebElementCollection; |
49 using blink::WebFormControlElement; | 51 using blink::WebFormControlElement; |
50 using blink::WebFormElement; | 52 using blink::WebFormElement; |
51 using blink::WebFrame; | 53 using blink::WebFrame; |
52 using blink::WebInputElement; | 54 using blink::WebInputElement; |
53 using blink::WebKeyboardEvent; | 55 using blink::WebKeyboardEvent; |
54 using blink::WebNode; | 56 using blink::WebNode; |
55 using blink::WebElementCollection; | |
56 using blink::WebOptionElement; | 57 using blink::WebOptionElement; |
57 using blink::WebString; | 58 using blink::WebString; |
| 59 using blink::WebTextAreaElement; |
58 | 60 |
59 namespace autofill { | 61 namespace autofill { |
60 | 62 |
61 namespace { | 63 namespace { |
62 | 64 |
63 // Gets all the data list values (with corresponding label) for the given | 65 // Gets all the data list values (with corresponding label) for the given |
64 // element. | 66 // element. |
65 void GetDataListSuggestions(const blink::WebInputElement& element, | 67 void GetDataListSuggestions(const blink::WebInputElement& element, |
66 bool ignore_current_value, | 68 bool ignore_current_value, |
67 std::vector<base::string16>* values, | 69 std::vector<base::string16>* values, |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 HidePopup(); | 276 HidePopup(); |
275 | 277 |
276 in_flight_request_form_ = form; | 278 in_flight_request_form_ = form; |
277 Send(new AutofillHostMsg_RequestAutocomplete(routing_id(), form_data, url)); | 279 Send(new AutofillHostMsg_RequestAutocomplete(routing_id(), form_data, url)); |
278 } | 280 } |
279 | 281 |
280 void AutofillAgent::setIgnoreTextChanges(bool ignore) { | 282 void AutofillAgent::setIgnoreTextChanges(bool ignore) { |
281 ignore_text_changes_ = ignore; | 283 ignore_text_changes_ = ignore; |
282 } | 284 } |
283 | 285 |
284 void AutofillAgent::InputElementClicked(const WebInputElement& element, | 286 void AutofillAgent::FormControlElementClicked( |
285 bool was_focused, | 287 const WebFormControlElement& element, |
286 bool is_focused) { | 288 bool was_focused) { |
| 289 const WebInputElement* input_element = toWebInputElement(&element); |
| 290 if (!input_element && !IsTextAreaElement(element)) |
| 291 return; |
| 292 |
287 if (was_focused) | 293 if (was_focused) |
288 ShowSuggestions(element, true, false, true, false); | 294 ShowSuggestions(element, true, false, true, false); |
289 } | 295 } |
290 | 296 |
291 void AutofillAgent::InputElementLostFocus() { | 297 void AutofillAgent::FormControlElementLostFocus() { |
292 HidePopup(); | 298 HidePopup(); |
293 } | 299 } |
294 | 300 |
295 void AutofillAgent::textFieldDidEndEditing(const WebInputElement& element) { | 301 void AutofillAgent::textFieldDidEndEditing(const WebInputElement& element) { |
296 password_autofill_agent_->TextFieldDidEndEditing(element); | 302 password_autofill_agent_->TextFieldDidEndEditing(element); |
297 has_shown_autofill_popup_for_current_edit_ = false; | 303 has_shown_autofill_popup_for_current_edit_ = false; |
298 Send(new AutofillHostMsg_DidEndTextFieldEditing(routing_id())); | 304 Send(new AutofillHostMsg_DidEndTextFieldEditing(routing_id())); |
299 } | 305 } |
300 | 306 |
| 307 // TODO(ziran.sun): This function is to be removed once next Blink roll is done |
301 void AutofillAgent::textFieldDidChange(const WebInputElement& element) { | 308 void AutofillAgent::textFieldDidChange(const WebInputElement& element) { |
| 309 const WebFormControlElement control_element = |
| 310 element.toConst<WebFormControlElement>(); |
| 311 textFieldDidChange(control_element); |
| 312 } |
| 313 |
| 314 void AutofillAgent::textFieldDidChange(const WebFormControlElement& element) { |
302 if (ignore_text_changes_) | 315 if (ignore_text_changes_) |
303 return; | 316 return; |
304 | 317 |
| 318 DCHECK(toWebInputElement(&element) || IsTextAreaElement(element)); |
| 319 |
305 if (did_set_node_text_) { | 320 if (did_set_node_text_) { |
306 did_set_node_text_ = false; | 321 did_set_node_text_ = false; |
307 return; | 322 return; |
308 } | 323 } |
309 | 324 |
310 // We post a task for doing the Autofill as the caret position is not set | 325 // We post a task for doing the Autofill as the caret position is not set |
311 // properly at this point (http://bugs.webkit.org/show_bug.cgi?id=16976) and | 326 // properly at this point (http://bugs.webkit.org/show_bug.cgi?id=16976) and |
312 // it is needed to trigger autofill. | 327 // it is needed to trigger autofill. |
313 weak_ptr_factory_.InvalidateWeakPtrs(); | 328 weak_ptr_factory_.InvalidateWeakPtrs(); |
314 base::MessageLoop::current()->PostTask( | 329 base::MessageLoop::current()->PostTask( |
315 FROM_HERE, | 330 FROM_HERE, |
316 base::Bind(&AutofillAgent::TextFieldDidChangeImpl, | 331 base::Bind(&AutofillAgent::TextFieldDidChangeImpl, |
317 weak_ptr_factory_.GetWeakPtr(), | 332 weak_ptr_factory_.GetWeakPtr(), |
318 element)); | 333 element)); |
319 } | 334 } |
320 | 335 |
321 void AutofillAgent::TextFieldDidChangeImpl(const WebInputElement& element) { | 336 void AutofillAgent::TextFieldDidChangeImpl( |
| 337 const WebFormControlElement& element) { |
322 // If the element isn't focused then the changes don't matter. This check is | 338 // If the element isn't focused then the changes don't matter. This check is |
323 // required to properly handle IME interactions. | 339 // required to properly handle IME interactions. |
324 if (!element.focused()) | 340 if (!element.focused()) |
325 return; | 341 return; |
326 | 342 |
327 if (password_generation_agent_ && | 343 const WebInputElement* input_element = toWebInputElement(&element); |
328 password_generation_agent_->TextDidChangeInTextField(element)) { | 344 if (input_element) { |
329 return; | 345 if (password_generation_agent_ && |
330 } | 346 password_generation_agent_->TextDidChangeInTextField(*input_element)) { |
| 347 return; |
| 348 } |
331 | 349 |
332 if (password_autofill_agent_->TextDidChangeInTextField(element)) { | 350 if (password_autofill_agent_->TextDidChangeInTextField(*input_element)) { |
333 element_ = element; | 351 element_ = element; |
334 return; | 352 return; |
| 353 } |
335 } | 354 } |
336 | 355 |
337 ShowSuggestions(element, false, true, false, false); | 356 ShowSuggestions(element, false, true, false, false); |
338 | 357 |
339 FormData form; | 358 FormData form; |
340 FormFieldData field; | 359 FormFieldData field; |
341 if (FindFormAndFieldForInputElement(element, &form, &field, REQUIRE_NONE)) { | 360 if (FindFormAndFieldForFormControlElement(element, |
| 361 &form, |
| 362 &field, |
| 363 REQUIRE_NONE)) { |
342 Send(new AutofillHostMsg_TextFieldDidChange(routing_id(), form, field, | 364 Send(new AutofillHostMsg_TextFieldDidChange(routing_id(), form, field, |
343 base::TimeTicks::Now())); | 365 base::TimeTicks::Now())); |
344 } | 366 } |
345 } | 367 } |
346 | 368 |
347 void AutofillAgent::textFieldDidReceiveKeyDown(const WebInputElement& element, | 369 void AutofillAgent::textFieldDidReceiveKeyDown(const WebInputElement& element, |
348 const WebKeyboardEvent& event) { | 370 const WebKeyboardEvent& event) { |
349 if (password_autofill_agent_->TextFieldHandlingKeyDown(element, event)) { | 371 if (password_autofill_agent_->TextFieldHandlingKeyDown(element, event)) { |
350 element_ = element; | 372 element_ = element; |
351 return; | 373 return; |
352 } | 374 } |
353 | 375 |
354 if (event.windowsKeyCode == ui::VKEY_DOWN || | 376 if (event.windowsKeyCode == ui::VKEY_DOWN || |
355 event.windowsKeyCode == ui::VKEY_UP) | 377 event.windowsKeyCode == ui::VKEY_UP) |
356 ShowSuggestions(element, true, true, true, false); | 378 ShowSuggestions(element, true, true, true, false); |
357 } | 379 } |
358 | 380 |
359 void AutofillAgent::openTextDataListChooser(const WebInputElement& element) { | 381 void AutofillAgent::openTextDataListChooser(const WebInputElement& element) { |
360 ShowSuggestions(element, true, false, false, true); | 382 ShowSuggestions(element, true, false, false, true); |
361 } | 383 } |
362 | 384 |
363 void AutofillAgent::AcceptDataListSuggestion( | 385 void AutofillAgent::AcceptDataListSuggestion( |
364 const base::string16& suggested_value) { | 386 const base::string16& suggested_value) { |
| 387 WebInputElement* input_element = toWebInputElement(&element_); |
| 388 DCHECK(input_element); |
365 base::string16 new_value = suggested_value; | 389 base::string16 new_value = suggested_value; |
366 // If this element takes multiple values then replace the last part with | 390 // If this element takes multiple values then replace the last part with |
367 // the suggestion. | 391 // the suggestion. |
368 if (element_.isMultiple() && | 392 if (input_element->isMultiple() && |
369 element_.formControlType() == WebString::fromUTF8("email")) { | 393 input_element->formControlType() == WebString::fromUTF8("email")) { |
370 std::vector<base::string16> parts; | 394 std::vector<base::string16> parts; |
371 | 395 |
372 base::SplitStringDontTrim(element_.editingValue(), ',', &parts); | 396 base::SplitStringDontTrim(input_element->editingValue(), ',', &parts); |
373 if (parts.size() == 0) | 397 if (parts.size() == 0) |
374 parts.push_back(base::string16()); | 398 parts.push_back(base::string16()); |
375 | 399 |
376 base::string16 last_part = parts.back(); | 400 base::string16 last_part = parts.back(); |
377 // We want to keep just the leading whitespace. | 401 // We want to keep just the leading whitespace. |
378 for (size_t i = 0; i < last_part.size(); ++i) { | 402 for (size_t i = 0; i < last_part.size(); ++i) { |
379 if (!IsWhitespace(last_part[i])) { | 403 if (!IsWhitespace(last_part[i])) { |
380 last_part = last_part.substr(0, i); | 404 last_part = last_part.substr(0, i); |
381 break; | 405 break; |
382 } | 406 } |
383 } | 407 } |
384 last_part.append(suggested_value); | 408 last_part.append(suggested_value); |
385 parts[parts.size() - 1] = last_part; | 409 parts[parts.size() - 1] = last_part; |
386 | 410 |
387 new_value = JoinString(parts, ','); | 411 new_value = JoinString(parts, ','); |
388 } | 412 } |
389 FillFieldWithValue(new_value, &element_); | 413 FillFieldWithValue(new_value, input_element); |
390 } | 414 } |
391 | 415 |
392 void AutofillAgent::OnFieldTypePredictionsAvailable( | 416 void AutofillAgent::OnFieldTypePredictionsAvailable( |
393 const std::vector<FormDataPredictions>& forms) { | 417 const std::vector<FormDataPredictions>& forms) { |
394 for (size_t i = 0; i < forms.size(); ++i) { | 418 for (size_t i = 0; i < forms.size(); ++i) { |
395 form_cache_.ShowPredictions(forms[i]); | 419 form_cache_.ShowPredictions(forms[i]); |
396 } | 420 } |
397 } | 421 } |
398 | 422 |
399 void AutofillAgent::OnFillForm(int query_id, const FormData& form) { | 423 void AutofillAgent::OnFillForm(int query_id, const FormData& form) { |
(...skipping 29 matching lines...) Expand all Loading... |
429 // TODO(isherman): There seem to be rare cases where this code *is* | 453 // TODO(isherman): There seem to be rare cases where this code *is* |
430 // reachable: see [ http://crbug.com/96321#c6 ]. Ideally we would | 454 // reachable: see [ http://crbug.com/96321#c6 ]. Ideally we would |
431 // understand those cases and fix the code to avoid them. However, so far I | 455 // understand those cases and fix the code to avoid them. However, so far I |
432 // have been unable to reproduce such a case locally. If you hit this | 456 // have been unable to reproduce such a case locally. If you hit this |
433 // NOTREACHED(), please file a bug against me. | 457 // NOTREACHED(), please file a bug against me. |
434 NOTREACHED(); | 458 NOTREACHED(); |
435 } | 459 } |
436 } | 460 } |
437 | 461 |
438 void AutofillAgent::OnFillFieldWithValue(const base::string16& value) { | 462 void AutofillAgent::OnFillFieldWithValue(const base::string16& value) { |
439 FillFieldWithValue(value, &element_); | 463 WebInputElement* input_element = toWebInputElement(&element_); |
| 464 if (input_element) |
| 465 FillFieldWithValue(value, input_element); |
440 } | 466 } |
441 | 467 |
442 void AutofillAgent::OnPreviewFieldWithValue(const base::string16& value) { | 468 void AutofillAgent::OnPreviewFieldWithValue(const base::string16& value) { |
443 PreviewFieldWithValue(value, &element_); | 469 WebInputElement* input_element = toWebInputElement(&element_); |
| 470 if (input_element) |
| 471 PreviewFieldWithValue(value, input_element); |
444 } | 472 } |
445 | 473 |
446 void AutofillAgent::OnAcceptDataListSuggestion(const base::string16& value) { | 474 void AutofillAgent::OnAcceptDataListSuggestion(const base::string16& value) { |
447 AcceptDataListSuggestion(value); | 475 AcceptDataListSuggestion(value); |
448 } | 476 } |
449 | 477 |
450 void AutofillAgent::OnAcceptPasswordAutofillSuggestion( | 478 void AutofillAgent::OnAcceptPasswordAutofillSuggestion( |
451 const base::string16& username) { | 479 const base::string16& username) { |
452 // We need to make sure this is handled here because the browser process | 480 // We need to make sure this is handled here because the browser process |
453 // skipped it handling because it believed it would be handled here. If it | 481 // skipped it handling because it believed it would be handled here. If it |
(...skipping 12 matching lines...) Expand all Loading... |
466 if (result == WebFormElement::AutocompleteResultSuccess) { | 494 if (result == WebFormElement::AutocompleteResultSuccess) { |
467 FillFormIncludingNonFocusableElements(form_data, in_flight_request_form_); | 495 FillFormIncludingNonFocusableElements(form_data, in_flight_request_form_); |
468 if (!in_flight_request_form_.checkValidityWithoutDispatchingEvents()) | 496 if (!in_flight_request_form_.checkValidityWithoutDispatchingEvents()) |
469 result = WebFormElement::AutocompleteResultErrorInvalid; | 497 result = WebFormElement::AutocompleteResultErrorInvalid; |
470 } | 498 } |
471 | 499 |
472 in_flight_request_form_.finishRequestAutocomplete(result); | 500 in_flight_request_form_.finishRequestAutocomplete(result); |
473 in_flight_request_form_.reset(); | 501 in_flight_request_form_.reset(); |
474 } | 502 } |
475 | 503 |
476 void AutofillAgent::ShowSuggestions(const WebInputElement& element, | 504 void AutofillAgent::ShowSuggestions(const WebFormControlElement& element, |
477 bool autofill_on_empty_values, | 505 bool autofill_on_empty_values, |
478 bool requires_caret_at_end, | 506 bool requires_caret_at_end, |
479 bool display_warning_if_disabled, | 507 bool display_warning_if_disabled, |
480 bool datalist_only) { | 508 bool datalist_only) { |
481 if (!element.isEnabled() || element.isReadOnly() || !element.isTextField() || | 509 if (!element.isEnabled() || element.isReadOnly()) |
482 element.isPasswordField()) | |
483 return; | 510 return; |
484 if (!datalist_only && !element.suggestedValue().isEmpty()) | 511 |
485 return; | 512 const WebInputElement* input_element = toWebInputElement(&element); |
| 513 if (input_element) { |
| 514 if (!input_element->isTextField() || input_element->isPasswordField()) |
| 515 return; |
| 516 if (!datalist_only && !input_element->suggestedValue().isEmpty()) |
| 517 return; |
| 518 } else { |
| 519 DCHECK(IsTextAreaElement(element)); |
| 520 if (!element.toConst<WebTextAreaElement>().suggestedValue().isEmpty()) |
| 521 return; |
| 522 } |
486 | 523 |
487 // Don't attempt to autofill with values that are too large or if filling | 524 // Don't attempt to autofill with values that are too large or if filling |
488 // criteria are not met. | 525 // criteria are not met. |
489 WebString value = element.editingValue(); | 526 WebString value = element.editingValue(); |
490 if (!datalist_only && | 527 if (!datalist_only && |
491 (value.length() > kMaxDataLength || | 528 (value.length() > kMaxDataLength || |
492 (!autofill_on_empty_values && value.isEmpty()) || | 529 (!autofill_on_empty_values && value.isEmpty()) || |
493 (requires_caret_at_end && | 530 (requires_caret_at_end && |
494 (element.selectionStart() != element.selectionEnd() || | 531 (element.selectionStart() != element.selectionEnd() || |
495 element.selectionEnd() != static_cast<int>(value.length()))))) { | 532 element.selectionEnd() != static_cast<int>(value.length()))))) { |
496 // Any popup currently showing is obsolete. | 533 // Any popup currently showing is obsolete. |
497 HidePopup(); | 534 HidePopup(); |
498 return; | 535 return; |
499 } | 536 } |
500 | 537 |
501 element_ = element; | 538 element_ = element; |
502 if (password_autofill_agent_->ShowSuggestions(element)) { | 539 if (input_element && |
| 540 password_autofill_agent_->ShowSuggestions(*input_element)) { |
503 is_popup_possibly_visible_ = true; | 541 is_popup_possibly_visible_ = true; |
504 return; | 542 return; |
505 } | 543 } |
506 | 544 |
507 // If autocomplete is disabled at the field level, ensure that the native | 545 // If autocomplete is disabled at the field level, ensure that the native |
508 // UI won't try to show a warning, since that may conflict with a custom | 546 // UI won't try to show a warning, since that may conflict with a custom |
509 // popup. Note that we cannot use the WebKit method element.autoComplete() | 547 // popup. Note that we cannot use the WebKit method element.autoComplete() |
510 // as it does not allow us to distinguish the case where autocomplete is | 548 // as it does not allow us to distinguish the case where autocomplete is |
511 // disabled for *both* the element and for the form. | 549 // disabled for *both* the element and for the form. |
512 const base::string16 autocomplete_attribute = | 550 const base::string16 autocomplete_attribute = |
513 element.getAttribute("autocomplete"); | 551 element.getAttribute("autocomplete"); |
514 if (LowerCaseEqualsASCII(autocomplete_attribute, "off")) | 552 if (LowerCaseEqualsASCII(autocomplete_attribute, "off")) |
515 display_warning_if_disabled = false; | 553 display_warning_if_disabled = false; |
516 | 554 |
517 QueryAutofillSuggestions(element, | 555 QueryAutofillSuggestions(element, |
518 display_warning_if_disabled, | 556 display_warning_if_disabled, |
519 datalist_only); | 557 datalist_only); |
520 } | 558 } |
521 | 559 |
522 void AutofillAgent::QueryAutofillSuggestions(const WebInputElement& element, | 560 void AutofillAgent::QueryAutofillSuggestions( |
523 bool display_warning_if_disabled, | 561 const WebFormControlElement& element, |
524 bool datalist_only) { | 562 bool display_warning_if_disabled, |
| 563 bool datalist_only) { |
525 if (!element.document().frame()) | 564 if (!element.document().frame()) |
526 return; | 565 return; |
527 | 566 |
| 567 DCHECK(toWebInputElement(&element) || IsTextAreaElement(element)); |
| 568 |
528 static int query_counter = 0; | 569 static int query_counter = 0; |
529 autofill_query_id_ = query_counter++; | 570 autofill_query_id_ = query_counter++; |
530 display_warning_if_disabled_ = display_warning_if_disabled; | 571 display_warning_if_disabled_ = display_warning_if_disabled; |
531 | 572 |
532 // If autocomplete is disabled at the form level, we want to see if there | 573 // If autocomplete is disabled at the form level, we want to see if there |
533 // would have been any suggestions were it enabled, so that we can show a | 574 // would have been any suggestions were it enabled, so that we can show a |
534 // warning. Otherwise, we want to ignore fields that disable autocomplete, so | 575 // warning. Otherwise, we want to ignore fields that disable autocomplete, so |
535 // that the suggestions list does not include suggestions for these form | 576 // that the suggestions list does not include suggestions for these form |
536 // fields -- see comment 1 on http://crbug.com/69914 | 577 // fields -- see comment 1 on http://crbug.com/69914 |
537 const RequirementsMask requirements = | 578 const RequirementsMask requirements = |
538 element.autoComplete() ? REQUIRE_AUTOCOMPLETE : REQUIRE_NONE; | 579 element.autoComplete() ? REQUIRE_AUTOCOMPLETE : REQUIRE_NONE; |
539 | 580 |
540 FormData form; | 581 FormData form; |
541 FormFieldData field; | 582 FormFieldData field; |
542 if (!FindFormAndFieldForInputElement(element, &form, &field, requirements)) { | 583 if (!FindFormAndFieldForFormControlElement(element, &form, &field, |
| 584 requirements)) { |
543 // If we didn't find the cached form, at least let autocomplete have a shot | 585 // If we didn't find the cached form, at least let autocomplete have a shot |
544 // at providing suggestions. | 586 // at providing suggestions. |
545 WebFormControlElementToFormField(element, EXTRACT_VALUE, &field); | 587 WebFormControlElementToFormField(element, EXTRACT_VALUE, &field); |
546 } | 588 } |
547 if (datalist_only) | 589 if (datalist_only) |
548 field.should_autocomplete = false; | 590 field.should_autocomplete = false; |
549 | 591 |
550 gfx::RectF bounding_box_scaled = | 592 gfx::RectF bounding_box_scaled = |
551 GetScaledBoundingBox(web_view_->pageScaleFactor(), &element_); | 593 GetScaledBoundingBox(web_view_->pageScaleFactor(), &element_); |
552 | 594 |
553 // Find the datalist values and send them to the browser process. | 595 const WebInputElement* input_element = toWebInputElement(&element); |
554 std::vector<base::string16> data_list_values; | 596 if (input_element) { |
555 std::vector<base::string16> data_list_labels; | 597 // Find the datalist values and send them to the browser process. |
556 GetDataListSuggestions(element_, | 598 std::vector<base::string16> data_list_values; |
557 datalist_only, | 599 std::vector<base::string16> data_list_labels; |
558 &data_list_values, | 600 GetDataListSuggestions(*input_element, |
559 &data_list_labels); | 601 datalist_only, |
560 TrimStringVectorForIPC(&data_list_values); | 602 &data_list_values, |
561 TrimStringVectorForIPC(&data_list_labels); | 603 &data_list_labels); |
| 604 TrimStringVectorForIPC(&data_list_values); |
| 605 TrimStringVectorForIPC(&data_list_labels); |
| 606 |
| 607 Send(new AutofillHostMsg_SetDataList(routing_id(), |
| 608 data_list_values, |
| 609 data_list_labels)); |
| 610 } |
562 | 611 |
563 is_popup_possibly_visible_ = true; | 612 is_popup_possibly_visible_ = true; |
564 Send(new AutofillHostMsg_SetDataList(routing_id(), | |
565 data_list_values, | |
566 data_list_labels)); | |
567 | |
568 Send(new AutofillHostMsg_QueryFormFieldAutofill(routing_id(), | 613 Send(new AutofillHostMsg_QueryFormFieldAutofill(routing_id(), |
569 autofill_query_id_, | 614 autofill_query_id_, |
570 form, | 615 form, |
571 field, | 616 field, |
572 bounding_box_scaled, | 617 bounding_box_scaled, |
573 display_warning_if_disabled)); | 618 display_warning_if_disabled)); |
574 } | 619 } |
575 | 620 |
576 void AutofillAgent::FillFieldWithValue(const base::string16& value, | 621 void AutofillAgent::FillFieldWithValue(const base::string16& value, |
577 blink::WebInputElement* node) { | 622 blink::WebInputElement* node) { |
(...skipping 28 matching lines...) Expand all Loading... |
606 // Only monitors dynamic forms created in the top frame. Dynamic forms | 651 // Only monitors dynamic forms created in the top frame. Dynamic forms |
607 // inserted in iframes are not captured yet. | 652 // inserted in iframes are not captured yet. |
608 if (frame && !frame->parent()) { | 653 if (frame && !frame->parent()) { |
609 password_autofill_agent_->OnDynamicFormsSeen(frame); | 654 password_autofill_agent_->OnDynamicFormsSeen(frame); |
610 return; | 655 return; |
611 } | 656 } |
612 } | 657 } |
613 } | 658 } |
614 | 659 |
615 } // namespace autofill | 660 } // namespace autofill |
OLD | NEW |