Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / components / autofill / content / renderer / form_autofill_util.cc
index f875435..10d6cca 100644 (file)
@@ -12,6 +12,7 @@
 #include "base/metrics/field_trial.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/common/autofill_data_validation.h"
 #include "components/autofill/core/common/autofill_switches.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/form_field_data.h"
 #include "third_party/WebKit/public/platform/WebVector.h"
 #include "third_party/WebKit/public/web/WebDocument.h"
 #include "third_party/WebKit/public/web/WebElement.h"
+#include "third_party/WebKit/public/web/WebElementCollection.h"
 #include "third_party/WebKit/public/web/WebExceptionCode.h"
 #include "third_party/WebKit/public/web/WebFormControlElement.h"
 #include "third_party/WebKit/public/web/WebFormElement.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
 #include "third_party/WebKit/public/web/WebInputElement.h"
 #include "third_party/WebKit/public/web/WebLabelElement.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
 #include "third_party/WebKit/public/web/WebNode.h"
 #include "third_party/WebKit/public/web/WebNodeList.h"
 #include "third_party/WebKit/public/web/WebOptionElement.h"
 #include "third_party/WebKit/public/web/WebSelectElement.h"
 #include "third_party/WebKit/public/web/WebTextAreaElement.h"
 
-using WebKit::WebDocument;
-using WebKit::WebElement;
-using WebKit::WebExceptionCode;
-using WebKit::WebFormControlElement;
-using WebKit::WebFormElement;
-using WebKit::WebFrame;
-using WebKit::WebInputElement;
-using WebKit::WebLabelElement;
-using WebKit::WebNode;
-using WebKit::WebNodeList;
-using WebKit::WebOptionElement;
-using WebKit::WebSelectElement;
-using WebKit::WebTextAreaElement;
-using WebKit::WebString;
-using WebKit::WebVector;
+using blink::WebDocument;
+using blink::WebElement;
+using blink::WebElementCollection;
+using blink::WebExceptionCode;
+using blink::WebFormControlElement;
+using blink::WebFormElement;
+using blink::WebFrame;
+using blink::WebInputElement;
+using blink::WebLabelElement;
+using blink::WebNode;
+using blink::WebNodeList;
+using blink::WebOptionElement;
+using blink::WebSelectElement;
+using blink::WebTextAreaElement;
+using blink::WebString;
+using blink::WebVector;
 
 namespace autofill {
 namespace {
 
-// The maximum length allowed for form data.
-const size_t kMaxDataLength = 1024;
-
-// A bit field mask for FillForm functions to not fill some fields.
-enum FieldFilterMask {
-  FILTER_NONE                       = 0,
-  FILTER_DISABLED_ELEMENTS          = 1 << 0,
-  FILTER_READONLY_ELEMENTS          = 1 << 1,
-  FILTER_NON_FOCUSABLE_ELEMENTS     = 1 << 2,
-  FILTER_ALL_NON_EDITIABLE_ELEMENTS = FILTER_DISABLED_ELEMENTS |
-                                      FILTER_READONLY_ELEMENTS |
-                                      FILTER_NON_FOCUSABLE_ELEMENTS,
-};
-
 bool IsOptionElement(const WebElement& element) {
   CR_DEFINE_STATIC_LOCAL(WebString, kOption, ("option"));
-  return element.hasTagName(kOption);
+  return element.hasHTMLTagName(kOption);
 }
 
 bool IsScriptElement(const WebElement& element) {
   CR_DEFINE_STATIC_LOCAL(WebString, kScript, ("script"));
-  return element.hasTagName(kScript);
+  return element.hasHTMLTagName(kScript);
 }
 
 bool IsNoScriptElement(const WebElement& element) {
   CR_DEFINE_STATIC_LOCAL(WebString, kNoScript, ("noscript"));
-  return element.hasTagName(kNoScript);
+  return element.hasHTMLTagName(kNoScript);
 }
 
-bool HasTagName(const WebNode& node, const WebKit::WebString& tag) {
+bool HasTagName(const WebNode& node, const blink::WebString& tag) {
   return node.isElementNode() && node.toConst<WebElement>().hasHTMLTagName(tag);
 }
 
@@ -115,17 +104,17 @@ const base::string16 CombineAndCollapseWhitespace(
     const base::string16& suffix,
     bool force_whitespace) {
   base::string16 prefix_trimmed;
-  TrimPositions prefix_trailing_whitespace =
-      TrimWhitespace(prefix, TRIM_TRAILING, &prefix_trimmed);
+  base::TrimPositions prefix_trailing_whitespace =
+      base::TrimWhitespace(prefix, base::TRIM_TRAILING, &prefix_trimmed);
 
   // Recursively compute the children's text.
   base::string16 suffix_trimmed;
-  TrimPositions suffix_leading_whitespace =
-      TrimWhitespace(suffix, TRIM_LEADING, &suffix_trimmed);
+  base::TrimPositions suffix_leading_whitespace =
+      base::TrimWhitespace(suffix, base::TRIM_LEADING, &suffix_trimmed);
 
   if (prefix_trailing_whitespace || suffix_leading_whitespace ||
       force_whitespace) {
-    return prefix_trimmed + ASCIIToUTF16(" ") + suffix_trimmed;
+    return prefix_trimmed + base::ASCIIToUTF16(" ") + suffix_trimmed;
   } else {
     return prefix_trimmed + suffix_trimmed;
   }
@@ -190,7 +179,7 @@ base::string16 FindChildText(const WebNode& node) {
 
   const int kChildSearchDepth = 10;
   base::string16 node_text = FindChildTextInner(child, kChildSearchDepth);
-  TrimWhitespace(node_text, TRIM_ALL, &node_text);
+  base::TrimWhitespace(node_text, base::TRIM_ALL, &node_text);
   return node_text;
 }
 
@@ -242,7 +231,7 @@ base::string16 InferLabelFromPrevious(const WebFormControlElement& element) {
     // If we have identified a partial label and have reached a non-lightweight
     // element, consider the label to be complete.
     base::string16 trimmed_label;
-    TrimWhitespace(inferred_label, TRIM_ALL, &trimmed_label);
+    base::TrimWhitespace(inferred_label, base::TRIM_ALL, &trimmed_label);
     if (!trimmed_label.empty())
       break;
 
@@ -262,7 +251,7 @@ base::string16 InferLabelFromPrevious(const WebFormControlElement& element) {
     break;
   }
 
-  TrimWhitespace(inferred_label, TRIM_ALL, &inferred_label);
+  base::TrimWhitespace(inferred_label, base::TRIM_ALL, &inferred_label);
   return inferred_label;
 }
 
@@ -273,7 +262,7 @@ base::string16 InferLabelFromListItem(const WebFormControlElement& element) {
   WebNode parent = element.parentNode();
   CR_DEFINE_STATIC_LOCAL(WebString, kListItem, ("li"));
   while (!parent.isNull() && parent.isElementNode() &&
-         !parent.to<WebElement>().hasTagName(kListItem)) {
+         !parent.to<WebElement>().hasHTMLTagName(kListItem)) {
     parent = parent.parentNode();
   }
 
@@ -293,7 +282,7 @@ base::string16 InferLabelFromTableColumn(const WebFormControlElement& element) {
   CR_DEFINE_STATIC_LOCAL(WebString, kTableCell, ("td"));
   WebNode parent = element.parentNode();
   while (!parent.isNull() && parent.isElementNode() &&
-         !parent.to<WebElement>().hasTagName(kTableCell)) {
+         !parent.to<WebElement>().hasHTMLTagName(kTableCell)) {
     parent = parent.parentNode();
   }
 
@@ -322,7 +311,7 @@ base::string16 InferLabelFromTableRow(const WebFormControlElement& element) {
   CR_DEFINE_STATIC_LOCAL(WebString, kTableRow, ("tr"));
   WebNode parent = element.parentNode();
   while (!parent.isNull() && parent.isElementNode() &&
-         !parent.to<WebElement>().hasTagName(kTableRow)) {
+         !parent.to<WebElement>().hasHTMLTagName(kTableRow)) {
     parent = parent.parentNode();
   }
 
@@ -389,7 +378,7 @@ base::string16 InferLabelFromDefinitionList(
   CR_DEFINE_STATIC_LOCAL(WebString, kDefinitionData, ("dd"));
   WebNode parent = element.parentNode();
   while (!parent.isNull() && parent.isElementNode() &&
-         !parent.to<WebElement>().hasTagName(kDefinitionData))
+         !parent.to<WebElement>().hasHTMLTagName(kDefinitionData))
     parent = parent.parentNode();
 
   if (parent.isNull() || !HasTagName(parent, kDefinitionData))
@@ -448,6 +437,13 @@ void GetOptionStringsFromElement(const WebSelectElement& select_element,
   option_values->clear();
   option_contents->clear();
   WebVector<WebElement> list_items = select_element.listItems();
+
+  // Constrain the maximum list length to prevent a malicious site from DOS'ing
+  // the browser, without entirely breaking autocomplete for some extreme
+  // legitimate sites: http://crbug.com/49332 and http://crbug.com/363094
+  if (list_items.size() > kMaxListSize)
+    return;
+
   option_values->reserve(list_items.size());
   option_contents->reserve(list_items.size());
   for (size_t i = 0; i < list_items.size(); ++i) {
@@ -462,14 +458,14 @@ void GetOptionStringsFromElement(const WebSelectElement& select_element,
 // The callback type used by |ForEachMatchingFormField()|.
 typedef void (*Callback)(const FormFieldData&,
                          bool, /* is_initiating_element */
-                         WebKit::WebFormControlElement*);
+                         blink::WebFormControlElement*);
 
 // For each autofillable field in |data| that matches a field in the |form|,
 // the |callback| is invoked with the corresponding |form| field data.
 void ForEachMatchingFormField(const WebFormElement& form_element,
                               const WebElement& initiating_element,
                               const FormData& data,
-                              FieldFilterMask filters,
+                              bool only_focusable_elements,
                               bool force_override,
                               Callback callback) {
   std::vector<WebFormControlElement> control_elements;
@@ -507,15 +503,13 @@ void ForEachMatchingFormField(const WebFormElement& form_element,
     // i.e. the field the user is currently editing and interacting with.
     const WebInputElement* input_element = toWebInputElement(element);
     if (!force_override && !is_initiating_element &&
-        ((IsAutofillableInputElement(input_element) &&
-          !input_element->value().isEmpty()) ||
-         (IsTextAreaElement(*element) &&
-          !element->toConst<WebTextAreaElement>().value().isEmpty())))
+        ((IsAutofillableInputElement(input_element) ||
+          IsTextAreaElement(*element)) &&
+         !element->value().isEmpty()))
       continue;
 
-    if (((filters & FILTER_DISABLED_ELEMENTS) && !element->isEnabled()) ||
-        ((filters & FILTER_READONLY_ELEMENTS) && element->isReadOnly()) ||
-        ((filters & FILTER_NON_FOCUSABLE_ELEMENTS) && !element->isFocusable()))
+    if (!element->isEnabled() || element->isReadOnly() ||
+        (only_focusable_elements && !element->isFocusable()))
       continue;
 
     callback(data.fields[i], is_initiating_element, element);
@@ -526,40 +520,36 @@ void ForEachMatchingFormField(const WebFormElement& form_element,
 // Also sets the "autofilled" attribute, causing the background to be yellow.
 void FillFormField(const FormFieldData& data,
                    bool is_initiating_node,
-                   WebKit::WebFormControlElement* field) {
+                   blink::WebFormControlElement* field) {
   // Nothing to fill.
   if (data.value.empty())
     return;
 
-  field->setAutofilled(true);
+  if (!data.is_autofilled)
+    return;
 
   WebInputElement* input_element = toWebInputElement(field);
-  if (IsTextInput(input_element) || IsMonthInput(input_element)) {
-    // If the maxlength attribute contains a negative value, maxLength()
-    // returns the default maxlength value.
-    input_element->setValue(
-        data.value.substr(0, input_element->maxLength()), true);
-    if (is_initiating_node) {
-      int length = input_element->value().length();
-      input_element->setSelectionRange(length, length);
-      // Clear the current IME composition (the underline), if there is one.
-      input_element->document().frame()->unmarkText();
-    }
-  } else if (IsTextAreaElement(*field)) {
-    WebTextAreaElement text_area = field->to<WebTextAreaElement>();
-    if (text_area.value() != data.value) {
-      text_area.setValue(data.value);
-      text_area.dispatchFormControlChangeEvent();
-    }
-  } else if (IsSelectElement(*field)) {
-    WebSelectElement select_element = field->to<WebSelectElement>();
-    if (select_element.value() != data.value) {
-      select_element.setValue(data.value);
-      select_element.dispatchFormControlChangeEvent();
-    }
-  } else {
-    DCHECK(IsCheckableElement(input_element));
+  if (IsCheckableElement(input_element)) {
     input_element->setChecked(data.is_checked, true);
+  } else {
+    base::string16 value = data.value;
+    if (IsTextInput(input_element) || IsMonthInput(input_element)) {
+      // If the maxlength attribute contains a negative value, maxLength()
+      // returns the default maxlength value.
+      value = value.substr(0, input_element->maxLength());
+    }
+    field->setValue(value, true);
+  }
+
+  field->setAutofilled(true);
+
+  if (is_initiating_node &&
+      ((IsTextInput(input_element) || IsMonthInput(input_element)) ||
+       IsTextAreaElement(*field))) {
+    int length = field->value().length();
+    field->setSelectionRange(length, length);
+    // Clear the current IME composition (the underline), if there is one.
+    field->document().frame()->unmarkText();
   }
 }
 
@@ -567,26 +557,35 @@ void FillFormField(const FormFieldData& data,
 // Also sets the "autofilled" attribute, causing the background to be yellow.
 void PreviewFormField(const FormFieldData& data,
                       bool is_initiating_node,
-                      WebKit::WebFormControlElement* field) {
+                      blink::WebFormControlElement* field) {
   // Nothing to preview.
   if (data.value.empty())
     return;
 
-  // Only preview input fields. Excludes checkboxes and radio buttons, as there
-  // is no provision for setSuggestedCheckedValue in WebInputElement.
-  WebInputElement* input_element = toWebInputElement(field);
-  if (!IsTextInput(input_element))
+  if (!data.is_autofilled)
     return;
 
-  // If the maxlength attribute contains a negative value, maxLength()
-  // returns the default maxlength value.
-  input_element->setSuggestedValue(
+  // Preview input, textarea and select fields. For input fields, excludes
+  // checkboxes and radio buttons, as there is no provision for
+  // setSuggestedCheckedValue in WebInputElement.
+  WebInputElement* input_element = toWebInputElement(field);
+  if (IsTextInput(input_element) || IsMonthInput(input_element)) {
+    // If the maxlength attribute contains a negative value, maxLength()
+    // returns the default maxlength value.
+    input_element->setSuggestedValue(
       data.value.substr(0, input_element->maxLength()));
-  input_element->setAutofilled(true);
-  if (is_initiating_node) {
+    input_element->setAutofilled(true);
+  } else if (IsTextAreaElement(*field) || IsSelectElement(*field)) {
+    field->setSuggestedValue(data.value);
+    field->setAutofilled(true);
+  }
+
+  if (is_initiating_node &&
+      (IsTextInput(input_element) || IsTextAreaElement(*field))) {
     // Select the part of the text that the user didn't type.
-    input_element->setSelectionRange(input_element->value().length(),
-                                     input_element->suggestedValue().length());
+    int start = field->value().length();
+    int end = field->suggestedValue().length();
+    field->setSelectionRange(start, end);
   }
 }
 
@@ -606,7 +605,7 @@ std::string RetrievalMethodToString(
 
 // Recursively checks whether |node| or any of its children have a non-empty
 // bounding box. The recursion depth is bounded by |depth|.
-bool IsWebNodeVisibleImpl(const WebKit::WebNode& node, const int depth) {
+bool IsWebNodeVisibleImpl(const blink::WebNode& node, const int depth) {
   if (depth < 0)
     return false;
   if (node.hasNonEmptyBoundingBox())
@@ -614,11 +613,11 @@ bool IsWebNodeVisibleImpl(const WebKit::WebNode& node, const int depth) {
 
   // The childNodes method is not a const method. Therefore it cannot be called
   // on a const reference. Therefore we need a const cast.
-  const WebKit::WebNodeList& children =
-      const_cast<WebKit::WebNode&>(node).childNodes();
+  const blink::WebNodeList& children =
+      const_cast<blink::WebNode&>(node).childNodes();
   size_t length = children.length();
   for (size_t i = 0; i < length; ++i) {
-    const WebKit::WebNode& item = children.item(i);
+    const blink::WebNode& item = children.item(i);
     if (IsWebNodeVisibleImpl(item, depth - 1))
       return true;
   }
@@ -631,28 +630,28 @@ const size_t kMaxParseableFields = 200;
 
 bool IsMonthInput(const WebInputElement* element) {
   CR_DEFINE_STATIC_LOCAL(WebString, kMonth, ("month"));
-  return element && element->formControlType() == kMonth;
+  return element && !element->isNull() && element->formControlType() == kMonth;
 }
 
 // All text fields, including password fields, should be extracted.
 bool IsTextInput(const WebInputElement* element) {
-  return element && element->isTextField();
+  return element && !element->isNull() && element->isTextField();
 }
 
 bool IsSelectElement(const WebFormControlElement& element) {
   // Static for improved performance.
   CR_DEFINE_STATIC_LOCAL(WebString, kSelectOne, ("select-one"));
-  return element.formControlType() == kSelectOne;
+  return !element.isNull() && element.formControlType() == kSelectOne;
 }
 
 bool IsTextAreaElement(const WebFormControlElement& element) {
   // Static for improved performance.
   CR_DEFINE_STATIC_LOCAL(WebString, kTextArea, ("textarea"));
-  return element.formControlType() == kTextArea;
+  return !element.isNull() && element.formControlType() == kTextArea;
 }
 
 bool IsCheckableElement(const WebInputElement* element) {
-  if (!element)
+  if (!element || element->isNull())
     return false;
 
   return element->isCheckbox() || element->isRadioButton();
@@ -673,7 +672,7 @@ const base::string16 GetFormIdentifier(const WebFormElement& form) {
   return identifier;
 }
 
-bool IsWebNodeVisible(const WebKit::WebNode& node) {
+bool IsWebNodeVisible(const blink::WebNode& node) {
   // In the bug http://crbug.com/237216 the form's bounding box is empty
   // however the form has non empty children. Thus we need to look at the
   // form's children.
@@ -684,7 +683,7 @@ bool IsWebNodeVisible(const WebKit::WebNode& node) {
 bool ClickElement(const WebDocument& document,
                   const WebElementDescriptor& element_descriptor) {
   WebString web_descriptor = WebString::fromUTF8(element_descriptor.descriptor);
-  WebKit::WebElement element;
+  blink::WebElement element;
 
   switch (element_descriptor.retrieval_method) {
     case WebElementDescriptor::CSS_SELECTOR: {
@@ -753,9 +752,9 @@ void WebFormControlElementToFormField(const WebFormControlElement& element,
   // labels for all form control elements are scraped from the DOM and set in
   // WebFormElementToFormData.
   field->name = element.nameForAutofill();
-  field->form_control_type = UTF16ToUTF8(element.formControlType());
+  field->form_control_type = base::UTF16ToUTF8(element.formControlType());
   field->autocomplete_attribute =
-      UTF16ToUTF8(element.getAttribute(kAutocomplete));
+      base::UTF16ToUTF8(element.getAttribute(kAutocomplete));
   if (field->autocomplete_attribute.size() > kMaxDataLength) {
     // Discard overly long attribute values to avoid DOS-ing the browser
     // process.  However, send over a default string to indicate that the
@@ -767,17 +766,21 @@ void WebFormControlElementToFormField(const WebFormControlElement& element,
     return;
 
   const WebInputElement* input_element = toWebInputElement(&element);
+  if (IsAutofillableInputElement(input_element) ||
+      IsTextAreaElement(element)) {
+    field->is_autofilled = element.isAutofilled();
+    field->is_focusable = element.isFocusable();
+    field->should_autocomplete = element.autoComplete();
+    field->text_direction = element.directionForFormData() ==
+        "rtl" ? base::i18n::RIGHT_TO_LEFT : base::i18n::LEFT_TO_RIGHT;
+  }
+
   if (IsAutofillableInputElement(input_element)) {
     if (IsTextInput(input_element))
       field->max_length = input_element->maxLength();
 
-    field->is_autofilled = input_element->isAutofilled();
-    field->is_focusable = input_element->isFocusable();
     field->is_checkable = IsCheckableElement(input_element);
     field->is_checked = input_element->isChecked();
-    field->should_autocomplete = input_element->autoComplete();
-    field->text_direction = input_element->directionForFormData() == "rtl" ?
-        base::i18n::RIGHT_TO_LEFT : base::i18n::LEFT_TO_RIGHT;
   } else if (IsTextAreaElement(element)) {
     // Nothing more to do in this case.
   } else if (extract_mask & EXTRACT_OPTIONS) {
@@ -792,27 +795,19 @@ void WebFormControlElementToFormField(const WebFormControlElement& element,
   if (!(extract_mask & EXTRACT_VALUE))
     return;
 
-  base::string16 value;
-  if (IsAutofillableInputElement(input_element)) {
-    value = input_element->value();
-  } else if (IsTextAreaElement(element)) {
-    value = element.toConst<WebTextAreaElement>().value();
-  } else {
-    DCHECK(IsSelectElement(element));
-    const WebSelectElement select_element = element.toConst<WebSelectElement>();
-    value = select_element.value();
+  base::string16 value = element.value();
 
+  if (IsSelectElement(element) && (extract_mask & EXTRACT_OPTION_TEXT)) {
+    const WebSelectElement select_element = element.toConst<WebSelectElement>();
     // Convert the |select_element| value to text if requested.
-    if (extract_mask & EXTRACT_OPTION_TEXT) {
-      WebVector<WebElement> list_items = select_element.listItems();
-      for (size_t i = 0; i < list_items.size(); ++i) {
-        if (IsOptionElement(list_items[i])) {
-          const WebOptionElement option_element =
-              list_items[i].toConst<WebOptionElement>();
-          if (option_element.value() == value) {
-            value = option_element.text();
-            break;
-          }
+    WebVector<WebElement> list_items = select_element.listItems();
+    for (size_t i = 0; i < list_items.size(); ++i) {
+      if (IsOptionElement(list_items[i])) {
+        const WebOptionElement option_element =
+            list_items[i].toConst<WebOptionElement>();
+        if (option_element.value() == value) {
+          value = option_element.text();
+          break;
         }
       }
     }
@@ -827,8 +822,8 @@ void WebFormControlElementToFormField(const WebFormControlElement& element,
 }
 
 bool WebFormElementToFormData(
-    const WebKit::WebFormElement& form_element,
-    const WebKit::WebFormControlElement& form_control_element,
+    const blink::WebFormElement& form_element,
+    const blink::WebFormControlElement& form_control_element,
     RequirementsMask requirements,
     ExtractMask extract_mask,
     FormData* form,
@@ -845,7 +840,6 @@ bool WebFormElementToFormData(
     return false;
 
   form->name = GetFormIdentifier(form_element);
-  form->method = form_element.method();
   form->origin = frame->document().url();
   form->action = frame->document().completeURL(form_element.action());
   form->user_submitted = form_element.wasUserSubmitted();
@@ -902,9 +896,11 @@ bool WebFormElementToFormData(
   // element's name as a key into the <name, FormFieldData> map to find the
   // previously created FormFieldData and set the FormFieldData's label to the
   // label.firstChild().nodeValue() of the label element.
-  WebNodeList labels = form_element.getElementsByTagName(kLabel);
-  for (unsigned i = 0; i < labels.length(); ++i) {
-    WebLabelElement label = labels.item(i).to<WebLabelElement>();
+  WebElementCollection labels = form_element.getElementsByHTMLTagName(kLabel);
+  DCHECK(!labels.isNull());
+  for (WebElement item = labels.firstItem(); !item.isNull();
+       item = labels.nextItem()) {
+    WebLabelElement label = item.to<WebLabelElement>();
     WebFormControlElement field_element =
         label.correspondingControl().to<WebFormControlElement>();
 
@@ -929,7 +925,7 @@ bool WebFormElementToFormData(
       // Concatenate labels because some sites might have multiple label
       // candidates.
       if (!iter->second->label.empty() && !label_text.empty())
-        iter->second->label += ASCIIToUTF16(" ");
+        iter->second->label += base::ASCIIToUTF16(" ");
       iter->second->label += label_text;
     }
   }
@@ -964,10 +960,10 @@ bool WebFormElementToFormData(
   return true;
 }
 
-bool FindFormAndFieldForInputElement(const WebInputElement& element,
-                                     FormData* form,
-                                     FormFieldData* field,
-                                     RequirementsMask requirements) {
+bool FindFormAndFieldForFormControlElement(const WebFormControlElement& element,
+                                           FormData* form,
+                                           FormFieldData* field,
+                                           RequirementsMask requirements) {
   if (!IsAutofillableElement(element))
     return false;
 
@@ -985,7 +981,7 @@ bool FindFormAndFieldForInputElement(const WebInputElement& element,
                                   field);
 }
 
-void FillForm(const FormData& form, const WebInputElement& element) {
+void FillForm(const FormData& form, const WebFormControlElement& element) {
   WebFormElement form_element = element.form();
   if (form_element.isNull())
     return;
@@ -993,8 +989,8 @@ void FillForm(const FormData& form, const WebInputElement& element) {
   ForEachMatchingFormField(form_element,
                            element,
                            form,
-                           FILTER_ALL_NON_EDITIABLE_ELEMENTS,
-                           false, /* dont force override */
+                           true, /* only_focusable_elements */
+                           false, /* don't force override */
                            &FillFormField);
 }
 
@@ -1003,30 +999,15 @@ void FillFormIncludingNonFocusableElements(const FormData& form_data,
   if (form_element.isNull())
     return;
 
-  FieldFilterMask filter_mask = static_cast<FieldFilterMask>(
-      FILTER_DISABLED_ELEMENTS | FILTER_READONLY_ELEMENTS);
   ForEachMatchingFormField(form_element,
                            WebInputElement(),
                            form_data,
-                           filter_mask,
+                           false, /* only_focusable_elements */
                            true, /* force override */
                            &FillFormField);
 }
 
-void FillFormForAllElements(const FormData& form_data,
-                            const WebFormElement& form_element) {
-  if (form_element.isNull())
-    return;
-
-  ForEachMatchingFormField(form_element,
-                           WebInputElement(),
-                           form_data,
-                           FILTER_NONE,
-                           true, /* force override */
-                           &FillFormField);
-}
-
-void PreviewForm(const FormData& form, const WebInputElement& element) {
+void PreviewForm(const FormData& form, const WebFormControlElement& element) {
   WebFormElement form_element = element.form();
   if (form_element.isNull())
     return;
@@ -1034,12 +1015,12 @@ void PreviewForm(const FormData& form, const WebInputElement& element) {
   ForEachMatchingFormField(form_element,
                            element,
                            form,
-                           FILTER_ALL_NON_EDITIABLE_ELEMENTS,
+                           true, /* only_focusable_elements */
                            false, /* dont force override */
                            &PreviewFormField);
 }
 
-bool ClearPreviewedFormWithElement(const WebInputElement& element,
+bool ClearPreviewedFormWithElement(const WebFormControlElement& element,
                                    bool was_autofilled) {
   WebFormElement form_element = element.form();
   if (form_element.isNull())
@@ -1049,38 +1030,51 @@ bool ClearPreviewedFormWithElement(const WebInputElement& element,
   ExtractAutofillableElements(form_element, REQUIRE_AUTOCOMPLETE,
                               &control_elements);
   for (size_t i = 0; i < control_elements.size(); ++i) {
-    // Only text input elements can be previewed.
-    WebInputElement* input_element = toWebInputElement(&control_elements[i]);
-    if (!IsTextInput(input_element))
-      continue;
-
-    // If the input element is not auto-filled, we did not preview it, so there
-    // is nothing to reset.
-    if (!input_element->isAutofilled())
-      continue;
-
     // There might be unrelated elements in this form which have already been
     // auto-filled.  For example, the user might have already filled the address
     // part of a form and now be dealing with the credit card section.  We only
     // want to reset the auto-filled status for fields that were previewed.
-    if (input_element->suggestedValue().isEmpty())
+    WebFormControlElement control_element = control_elements[i];
+
+    // Only text input, textarea and select elements can be previewed.
+    WebInputElement* input_element = toWebInputElement(&control_element);
+    if (!IsTextInput(input_element) &&
+        !IsMonthInput(input_element) &&
+        !IsTextAreaElement(control_element) &&
+        !IsSelectElement(control_element))
+      continue;
+
+    // If the element is not auto-filled, we did not preview it,
+    // so there is nothing to reset.
+    if(!control_element.isAutofilled())
+      continue;
+
+    if ((IsTextInput(input_element) ||
+         IsMonthInput(input_element) ||
+         IsTextAreaElement(control_element) ||
+         IsSelectElement(control_element)) &&
+        control_element.suggestedValue().isEmpty())
       continue;
 
     // Clear the suggested value. For the initiating node, also restore the
     // original value.
-    input_element->setSuggestedValue(WebString());
-    bool is_initiating_node = (element == *input_element);
-    if (is_initiating_node)
-      input_element->setAutofilled(was_autofilled);
-    else
-      input_element->setAutofilled(false);
-
-    // Clearing the suggested value in the focused node (above) can cause
-    // selection to be lost. We force selection range to restore the text
-    // cursor.
-    if (is_initiating_node) {
-      int length = input_element->value().length();
-      input_element->setSelectionRange(length, length);
+    if (IsTextInput(input_element) || IsMonthInput(input_element) ||
+        IsTextAreaElement(control_element)) {
+      control_element.setSuggestedValue(WebString());
+      bool is_initiating_node = (element == control_element);
+      if (is_initiating_node) {
+        control_element.setAutofilled(was_autofilled);
+        // Clearing the suggested value in the focused node (above) can cause
+        // selection to be lost. We force selection range to restore the text
+        // cursor.
+        int length = control_element.value().length();
+        control_element.setSelectionRange(length, length);
+      } else {
+        control_element.setAutofilled(false);
+      }
+    } else if (IsSelectElement(control_element)) {
+      control_element.setSuggestedValue(WebString());
+      control_element.setAutofilled(false);
     }
   }
 
@@ -1107,14 +1101,14 @@ bool FormWithElementIsAutofilled(const WebInputElement& element) {
   return false;
 }
 
-bool IsWebpageEmpty(const WebKit::WebFrame* frame) {
-  WebKit::WebDocument document = frame->document();
+bool IsWebpageEmpty(const blink::WebFrame* frame) {
+  blink::WebDocument document = frame->document();
 
   return IsWebElementEmpty(document.head()) &&
          IsWebElementEmpty(document.body());
 }
 
-bool IsWebElementEmpty(const WebKit::WebElement& element) {
+bool IsWebElementEmpty(const blink::WebElement& element) {
   // This array contains all tags which can be present in an empty page.
   const char* const kAllowedValue[] = {
     "script",
@@ -1127,13 +1121,14 @@ bool IsWebElementEmpty(const WebKit::WebElement& element) {
     return true;
   // The childNodes method is not a const method. Therefore it cannot be called
   // on a const reference. Therefore we need a const cast.
-  const WebKit::WebNodeList& children =
-      const_cast<WebKit::WebElement&>(element).childNodes();
+  const blink::WebNodeList& children =
+      const_cast<blink::WebElement&>(element).childNodes();
   for (size_t i = 0; i < children.length(); ++i) {
-    const WebKit::WebNode& item = children.item(i);
+    const blink::WebNode& item = children.item(i);
 
     if (item.isTextNode() &&
-        !ContainsOnlyWhitespaceASCII(item.nodeValue().utf8()))
+        !base::ContainsOnlyChars(item.nodeValue().utf8(),
+                                 base::kWhitespaceASCII))
       return false;
 
     // We ignore all other items with names which begin with
@@ -1157,4 +1152,12 @@ bool IsWebElementEmpty(const WebKit::WebElement& element) {
   return true;
 }
 
+gfx::RectF GetScaledBoundingBox(float scale, WebFormControlElement* element) {
+  gfx::Rect bounding_box(element->boundsInViewportSpace());
+  return gfx::RectF(bounding_box.x() * scale,
+                    bounding_box.y() * scale,
+                    bounding_box.width() * scale,
+                    bounding_box.height() * scale);
+}
+
 }  // namespace autofill