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