Chromium Code Reviews| Index: components/autofill/content/renderer/autofill_agent.cc |
| diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc |
| index 979976f72c14ee71c8dfd95e7bf5c195d680aedb..913a1bf274c919204cc9cb97fe60fe809858e032 100644 |
| --- a/components/autofill/content/renderer/autofill_agent.cc |
| +++ b/components/autofill/content/renderer/autofill_agent.cc |
| @@ -55,6 +55,7 @@ using blink::WebNode; |
| using blink::WebNodeCollection; |
| using blink::WebOptionElement; |
| using blink::WebString; |
| +using blink::WebTextAreaElement; |
| namespace autofill { |
| @@ -293,7 +294,15 @@ void AutofillAgent::InputElementClicked(const WebInputElement& element, |
| ShowSuggestions(element, true, false, true, false); |
| } |
|
Ilya Sherman
2014/02/14 02:44:40
Is this method needed in addition to the TextAreaE
ziran.sun
2014/02/17 15:43:45
Done.
|
| -void AutofillAgent::InputElementLostFocus() { |
| +void AutofillAgent::TextAreaElementClicked(const WebTextAreaElement& element, |
| + bool was_focused, |
| + bool is_focused) { |
|
Ilya Sherman
2014/02/14 02:44:40
Is is_focused needed?
ziran.sun
2014/02/17 15:43:45
I'm not sure. It doesn't seem that it's called her
Ilya Sherman
2014/02/22 06:24:20
Let's go ahead and remove it if it's not used anym
|
| + if (was_focused) |
| + ShowSuggestions(element, true, false, true, false); |
| +} |
| + |
| +// This applies to both input and textarea elements |
| +void AutofillAgent::FormControlElementLostFocus() { |
| HideAutofillUI(); |
| } |
| @@ -303,6 +312,7 @@ void AutofillAgent::textFieldDidEndEditing(const WebInputElement& element) { |
| Send(new AutofillHostMsg_DidEndTextFieldEditing(routing_id())); |
| } |
| +// This function is to be removed once next Blink roll is done |
|
Ilya Sherman
2014/02/14 02:44:40
Please add a TODO.
ziran.sun
2014/02/17 15:43:45
Done.
|
| void AutofillAgent::textFieldDidChange(const WebInputElement& element) { |
| if (ignore_text_changes_) |
| return; |
| @@ -323,27 +333,57 @@ void AutofillAgent::textFieldDidChange(const WebInputElement& element) { |
| element)); |
|
Ilya Sherman
2014/02/14 02:44:40
Can you call into the other textFieldDidChange fun
ziran.sun
2014/02/17 15:43:45
Done.
|
| } |
| -void AutofillAgent::TextFieldDidChangeImpl(const WebInputElement& element) { |
| - // If the element isn't focused then the changes don't matter. This check is |
| - // required to properly handle IME interactions. |
| - if (!element.focused()) |
| +// Text changes in input text field or textarea field |
| +void AutofillAgent::textFieldDidChange(const WebFormControlElement& element) { |
| + if (ignore_text_changes_) |
| return; |
| - if (password_generation_agent_ && |
| - password_generation_agent_->TextDidChangeInTextField(element)) { |
| + if (did_set_node_text_) { |
| + did_set_node_text_ = false; |
| return; |
| } |
| - if (password_autofill_agent_->TextDidChangeInTextField(element)) { |
| - element_ = element; |
| + // We post a task for doing the Autofill as the caret position is not set |
| + // properly at this point (http://bugs.webkit.org/show_bug.cgi?id=16976) and |
| + // it is needed to trigger autofill. |
| + weak_ptr_factory_.InvalidateWeakPtrs(); |
| + base::MessageLoop::current()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&AutofillAgent::TextFieldDidChangeImpl, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + element)); |
| +} |
| + |
| +void AutofillAgent::TextFieldDidChangeImpl(const WebFormControlElement& element) |
| +{ |
| + // If the element isn't focused then the changes don't matter. This check is |
| + // required to properly handle IME interactions. |
| + if (!element.focused()) |
| return; |
| + |
| + const WebInputElement* input_element = toWebInputElement(&element); |
| + if (IsAutofillableInputElement(input_element)) { |
| + if (password_generation_agent_ && |
| + password_generation_agent_->TextDidChangeInTextField(*input_element)) { |
|
Ilya Sherman
2014/02/14 02:44:40
nit: Indent this line by two more spaces.
ziran.sun
2014/02/17 15:43:45
Done.
|
| + return; |
|
Ilya Sherman
2014/02/14 02:44:40
nit: Indent this line by two fewer spaces.
ziran.sun
2014/02/17 15:43:45
Done.
|
| + } |
| + |
| + if (password_autofill_agent_->TextDidChangeInTextField(*input_element)) { |
| + element_ = element; |
| + return; |
| + } |
| } |
| ShowSuggestions(element, false, true, false, false); |
| FormData form; |
| FormFieldData field; |
| - if (FindFormAndFieldForInputElement(element, &form, &field, REQUIRE_NONE)) { |
| + if ((IsAutofillableInputElement(input_element) || |
| + IsTextAreaElement(element)) && |
|
Ilya Sherman
2014/02/14 02:44:40
Please move the check for whether this is an autof
ziran.sun
2014/02/17 15:43:45
Done.
|
| + FindFormAndFieldForFormControlElement(element, |
| + &form, |
| + &field, |
| + REQUIRE_NONE)) { |
| Send(new AutofillHostMsg_TextFieldDidChange(routing_id(), form, field, |
| base::TimeTicks::Now())); |
| } |
| @@ -367,14 +407,15 @@ void AutofillAgent::openTextDataListChooser(const WebInputElement& element) { |
| void AutofillAgent::AcceptDataListSuggestion( |
| const base::string16& suggested_value) { |
| + WebInputElement* input_element = toWebInputElement(&element_); |
|
Ilya Sherman
2014/02/14 02:44:40
nit: Please add a DCHECK that this conversion succ
ziran.sun
2014/02/17 15:43:45
Done.
|
| base::string16 new_value = suggested_value; |
| // If this element takes multiple values then replace the last part with |
| // the suggestion. |
| - if (element_.isMultiple() && |
| - element_.formControlType() == WebString::fromUTF8("email")) { |
| + if (input_element->isMultiple() && |
| + input_element->formControlType() == WebString::fromUTF8("email")) { |
| std::vector<base::string16> parts; |
| - base::SplitStringDontTrim(element_.editingValue(), ',', &parts); |
| + base::SplitStringDontTrim(input_element->editingValue(), ',', &parts); |
| if (parts.size() == 0) |
| parts.push_back(base::string16()); |
| @@ -391,7 +432,7 @@ void AutofillAgent::AcceptDataListSuggestion( |
| new_value = JoinString(parts, ','); |
| } |
| - SetNodeText(new_value, &element_); |
| + SetNodeText(new_value, input_element); |
| } |
| void AutofillAgent::OnFormDataFilled(int query_id, |
| @@ -453,7 +494,8 @@ void AutofillAgent::OnClearPreviewedForm() { |
| } |
| void AutofillAgent::OnSetNodeText(const base::string16& value) { |
| - SetNodeText(value, &element_); |
| + WebInputElement* input_element = toWebInputElement(&element_); |
|
Ilya Sherman
2014/02/14 02:44:40
Ditto.
ziran.sun
2014/02/17 15:43:45
Done.
|
| + SetNodeText(value, input_element); |
| } |
| void AutofillAgent::OnAcceptDataListSuggestion(const base::string16& value) { |
| @@ -489,34 +531,42 @@ void AutofillAgent::OnRequestAutocompleteResult( |
| void AutofillAgent::OnPageShown() { |
| } |
| -void AutofillAgent::ShowSuggestions(const WebInputElement& element, |
| +void AutofillAgent::ShowSuggestions(const WebFormControlElement& element, |
| bool autofill_on_empty_values, |
| bool requires_caret_at_end, |
| bool display_warning_if_disabled, |
| bool datalist_only) { |
| - if (!element.isEnabled() || element.isReadOnly() || !element.isTextField() || |
| - element.isPasswordField()) |
| - return; |
| - if (!datalist_only && !element.suggestedValue().isEmpty()) |
| + const WebInputElement* input_element = toWebInputElement(&element); |
| + if (!element.isEnabled() || element.isReadOnly()) |
| return; |
| - // Don't attempt to autofill with values that are too large or if filling |
| - // criteria are not met. |
| - WebString value = element.editingValue(); |
| - if (!datalist_only && |
| - (value.length() > kMaxDataLength || |
| - (!autofill_on_empty_values && value.isEmpty()) || |
| - (requires_caret_at_end && |
| - (element.selectionStart() != element.selectionEnd() || |
| - element.selectionEnd() != static_cast<int>(value.length()))))) { |
| - // Any popup currently showing is obsolete. |
| - HideAutofillUI(); |
| + if (IsAutofillableInputElement(input_element)) { |
| + if (!input_element->isTextField() || input_element->isPasswordField()) |
| + return; |
| + if (!datalist_only && !input_element->suggestedValue().isEmpty()) |
| + return; |
| + // Don't attempt to autofill with values that are too large or if filling |
| + // criteria are not met. |
| + WebString value = input_element->editingValue(); |
| + if (!datalist_only && |
| + (value.length() > kMaxDataLength || |
| + (!autofill_on_empty_values && value.isEmpty()) || |
| + (requires_caret_at_end && |
| + (input_element->selectionStart() != input_element->selectionEnd() || |
| + input_element->selectionEnd() != |
| + static_cast<int>(value.length()))))) { |
| + // Any popup currently showing is obsolete. |
| + HideAutofillUI(); |
| + return; |
| + } |
| + |
| + if (password_autofill_agent_->ShowSuggestions(*input_element)) |
| + return; |
|
Ilya Sherman
2014/02/14 02:44:40
It's important that this follow the assignment of
ziran.sun
2014/02/17 15:43:45
Done.
|
| + } else if (IsTextAreaElement(element) && |
| + !element.toConst<WebTextAreaElement>().suggestedValue().isEmpty()) |
| return; |
|
Ilya Sherman
2014/02/14 02:44:40
nit: Please include curly braces on the else, sinc
ziran.sun
2014/02/17 15:43:45
Done.
|
| - } |
| element_ = element; |
| - if (password_autofill_agent_->ShowSuggestions(element)) |
| - return; |
| // If autocomplete is disabled at the field level, ensure that the native |
| // UI won't try to show a warning, since that may conflict with a custom |
| @@ -533,27 +583,32 @@ void AutofillAgent::ShowSuggestions(const WebInputElement& element, |
| datalist_only); |
| } |
| -void AutofillAgent::QueryAutofillSuggestions(const WebInputElement& element, |
| - bool display_warning_if_disabled, |
| - bool datalist_only) { |
| +void AutofillAgent::QueryAutofillSuggestions( |
| + const WebFormControlElement& element, |
| + bool display_warning_if_disabled, |
| + bool datalist_only) { |
| if (!element.document().frame()) |
| return; |
| static int query_counter = 0; |
| autofill_query_id_ = query_counter++; |
| display_warning_if_disabled_ = display_warning_if_disabled; |
| + const WebInputElement* input_element = toWebInputElement(&element); |
| // If autocomplete is disabled at the form level, we want to see if there |
| // would have been any suggestions were it enabled, so that we can show a |
| // warning. Otherwise, we want to ignore fields that disable autocomplete, so |
| // that the suggestions list does not include suggestions for these form |
| // fields -- see comment 1 on http://crbug.com/69914 |
| - const RequirementsMask requirements = |
| - element.autoComplete() ? REQUIRE_AUTOCOMPLETE : REQUIRE_NONE; |
| + RequirementsMask requirements = REQUIRE_NONE; |
| + if (IsAutofillableInputElement(input_element)) |
| + requirements = |
| + input_element->autoComplete() ? REQUIRE_AUTOCOMPLETE : REQUIRE_NONE; |
|
Ilya Sherman
2014/02/14 02:44:40
nit: Please add curly braces, since this spans mul
ziran.sun
2014/02/17 15:43:45
Done.
|
| FormData form; |
| FormFieldData field; |
| - if (!FindFormAndFieldForInputElement(element, &form, &field, requirements)) { |
| + if (!FindFormAndFieldForFormControlElement(element, &form, |
| + &field, requirements)) { |
|
Ilya Sherman
2014/02/14 02:44:40
nit: This is a strange way to wrap the line. Prob
ziran.sun
2014/02/17 15:43:45
Done.
|
| // If we didn't find the cached form, at least let autocomplete have a shot |
| // at providing suggestions. |
| WebFormControlElementToFormField(element, EXTRACT_VALUE, &field); |
| @@ -564,20 +619,21 @@ void AutofillAgent::QueryAutofillSuggestions(const WebInputElement& element, |
| gfx::RectF bounding_box_scaled = |
| GetScaledBoundingBox(web_view_->pageScaleFactor(), &element_); |
| - // Find the datalist values and send them to the browser process. |
| - std::vector<base::string16> data_list_values; |
| - std::vector<base::string16> data_list_labels; |
| - GetDataListSuggestions(element_, |
| + if (IsAutofillableInputElement(input_element)) { |
| + // Find the datalist values and send them to the browser process. |
| + std::vector<base::string16> data_list_values; |
| + std::vector<base::string16> data_list_labels; |
| + GetDataListSuggestions(*input_element, |
| datalist_only, |
| &data_list_values, |
| &data_list_labels); |
| - TrimStringVectorForIPC(&data_list_values); |
| - TrimStringVectorForIPC(&data_list_labels); |
| + TrimStringVectorForIPC(&data_list_values); |
| + TrimStringVectorForIPC(&data_list_labels); |
| - Send(new AutofillHostMsg_SetDataList(routing_id(), |
| + Send(new AutofillHostMsg_SetDataList(routing_id(), |
| data_list_values, |
| data_list_labels)); |
| - |
| + } |
| Send(new AutofillHostMsg_QueryFormFieldAutofill(routing_id(), |
| autofill_query_id_, |
| form, |
| @@ -596,8 +652,11 @@ void AutofillAgent::FillAutofillFormData(const WebNode& node, |
| FormData form; |
| FormFieldData field; |
| - if (!FindFormAndFieldForInputElement(node.toConst<WebInputElement>(), &form, |
| - &field, REQUIRE_AUTOCOMPLETE)) { |
| + if (!FindFormAndFieldForFormControlElement( |
| + node.toConst<WebFormControlElement>(), |
|
Ilya Sherman
2014/02/14 02:44:40
nit: This should be indented four spaces from the
ziran.sun
2014/02/17 15:43:45
Done.
|
| + &form, |
| + &field, |
| + REQUIRE_AUTOCOMPLETE)) { |
| return; |
| } |