19720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block// Copyright 2013 The Chromium Authors. All rights reserved.
29720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block// Use of this source code is governed by a BSD-style license that can be
39720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block// found in the LICENSE file.
49720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
59720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "components/autofill/content/renderer/form_cache.h"
69720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
79720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "base/logging.h"
89720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "base/strings/utf_string_conversions.h"
99720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "components/autofill/content/renderer/form_autofill_util.h"
109720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "components/autofill/core/common/autofill_constants.h"
119720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "components/autofill/core/common/form_data.h"
129720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "components/autofill/core/common/form_data_predictions.h"
139720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "components/autofill/core/common/form_field_data.h"
149720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "components/autofill/core/common/form_field_data_predictions.h"
159720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "grit/components_strings.h"
169720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "third_party/WebKit/public/platform/WebString.h"
179720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "third_party/WebKit/public/platform/WebVector.h"
189720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "third_party/WebKit/public/web/WebConsoleMessage.h"
199720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "third_party/WebKit/public/web/WebDocument.h"
209720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "third_party/WebKit/public/web/WebFormControlElement.h"
219720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "third_party/WebKit/public/web/WebFormElement.h"
229720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "third_party/WebKit/public/web/WebInputElement.h"
239720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "third_party/WebKit/public/web/WebLocalFrame.h"
249720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "third_party/WebKit/public/web/WebNodeList.h"
259720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "third_party/WebKit/public/web/WebSelectElement.h"
269720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "third_party/WebKit/public/web/WebTextAreaElement.h"
279720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block#include "ui/base/l10n/l10n_util.h"
289720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
299720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Blockusing blink::WebConsoleMessage;
309720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Blockusing blink::WebDocument;
319720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Blockusing blink::WebFormControlElement;
329720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Blockusing blink::WebFormElement;
339720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Blockusing blink::WebFrame;
349720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Blockusing blink::WebInputElement;
359720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Blockusing blink::WebSelectElement;
369720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Blockusing blink::WebTextAreaElement;
379720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Blockusing blink::WebString;
389720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Blockusing blink::WebVector;
399720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
409720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Blocknamespace autofill {
419720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
429720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block// Helper function to discard state of various WebFormElements when they go out
439720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block// of web frame's scope. This is done to release memory that we no longer need
449720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block// to hold.
459720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block// K should inherit from WebFormControlElement as the function looks to extract
469720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block// WebFormElement for K.form().
479720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Blocktemplate <class K, class V>
489720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Blockvoid RemoveOldElements(const WebFrame& frame, std::map<const K, V>* states) {
499720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  std::vector<K> to_remove;
509720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  for (typename std::map<const K, V>::const_iterator it = states->begin();
519720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block       it != states->end(); ++it) {
529720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    WebFormElement form_element = it->first.form();
539720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    if (form_element.isNull()) {
549720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      to_remove.push_back(it->first);
559720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    } else {
569720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      const WebFrame* element_frame = form_element.document().frame();
579720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      if (!element_frame || element_frame == &frame)
589720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        to_remove.push_back(it->first);
599720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    }
609720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  }
619720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
629720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  for (typename std::vector<K>::const_iterator it = to_remove.begin();
639720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block       it != to_remove.end(); ++it) {
649720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    states->erase(*it);
659720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  }
669720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block}
679720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
689720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve BlockFormCache::FormCache() {
699720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block}
709720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
719720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve BlockFormCache::~FormCache() {
729720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block}
739720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
749720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Blockvoid FormCache::ExtractNewForms(const WebFrame& frame,
759720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block                                std::vector<FormData>* forms) {
769720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  WebDocument document = frame.document();
779720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  if (document.isNull())
789720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    return;
799720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
809720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  web_documents_.insert(document);
819720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
829720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  WebVector<WebFormElement> web_forms;
839720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  document.forms(web_forms);
849720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
859720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  // Log an error message for deprecated attributes, but only the first time
869720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  // the form is parsed.
879720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  bool log_deprecation_messages =
889720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      parsed_forms_.find(&frame) == parsed_forms_.end();
899720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
909720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  size_t num_fields_seen = 0;
919720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  for (size_t i = 0; i < web_forms.size(); ++i) {
929720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    WebFormElement form_element = web_forms[i];
939720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
949720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    std::vector<WebFormControlElement> control_elements;
959720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    ExtractAutofillableElements(form_element, autofill::REQUIRE_NONE,
969720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block                                &control_elements);
979720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
989720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    size_t num_editable_elements = 0;
999720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    for (size_t j = 0; j < control_elements.size(); ++j) {
1009720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      WebFormControlElement element = control_elements[j];
1019720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
1029720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      if (log_deprecation_messages) {
1039720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        std::string autocomplete_attribute =
1049720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block            base::UTF16ToUTF8(element.getAttribute("autocomplete"));
1059720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
1069720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        static const char* const deprecated[] = { "region", "locality" };
1079720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        for (size_t i = 0; i < arraysize(deprecated); ++i) {
1089720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block          if (autocomplete_attribute.find(deprecated[i]) != std::string::npos) {
1099720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block            WebConsoleMessage console_message = WebConsoleMessage(
1109720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block                WebConsoleMessage::LevelWarning,
1119720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block                WebString(base::ASCIIToUTF16(std::string("autocomplete='") +
1129720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block                    deprecated[i] + "' is deprecated and will soon be ignored. "
1139720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block                    "See http://goo.gl/YjeSsW")));
1149720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block            element.document().frame()->addMessageToConsole(console_message);
1159720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block          }
1169720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        }
1179720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      }
1189720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
1199720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      // Save original values of <select> elements so we can restore them
1209720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      // when |ClearFormWithNode()| is invoked.
1219720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      if (IsSelectElement(element)) {
1229720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        const WebSelectElement select_element =
1239720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block            element.toConst<WebSelectElement>();
1249720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        initial_select_values_.insert(std::make_pair(select_element,
1259720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block                                                     select_element.value()));
1269720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        ++num_editable_elements;
1279720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      } else if (IsTextAreaElement(element)) {
1289720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        ++num_editable_elements;
1299720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      } else {
1309720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        const WebInputElement input_element =
1319720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block            element.toConst<WebInputElement>();
1329720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        if (IsCheckableElement(&input_element)) {
1339720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block          initial_checked_state_.insert(
1349720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block              std::make_pair(input_element, input_element.isChecked()));
1359720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        } else {
1369720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block          ++num_editable_elements;
1379720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        }
1389720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      }
1399720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    }
1409720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
1419720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    // To avoid overly expensive computation, we impose a minimum number of
1429720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    // allowable fields.  The corresponding maximum number of allowable fields
1439720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    // is imposed by WebFormElementToFormData().
1449720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    if (num_editable_elements < kRequiredAutofillFields &&
1459720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        control_elements.size() > 0) {
1469720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      continue;
1479720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    }
1489720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
1499720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    FormData form;
1509720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    ExtractMask extract_mask =
1519720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      static_cast<ExtractMask>(EXTRACT_VALUE | EXTRACT_OPTIONS);
1529720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
1539720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    if (!WebFormElementToFormData(form_element, WebFormControlElement(),
1549720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block                                  REQUIRE_NONE, extract_mask, &form, NULL)) {
1559720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      continue;
1569720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    }
1579720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
1589720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    num_fields_seen += form.fields.size();
1599720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    if (num_fields_seen > kMaxParseableFields)
1609720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      break;
1619720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
1629720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    if (form.fields.size() >= kRequiredAutofillFields &&
1639720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        !parsed_forms_[&frame].count(form)) {
1649720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      forms->push_back(form);
1659720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      parsed_forms_[&frame].insert(form);
1669720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    }
1679720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  }
1689720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block}
1699720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
1709720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Blockvoid FormCache::ResetFrame(const WebFrame& frame) {
1719720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  std::vector<WebDocument> documents_to_delete;
1729720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  for (std::set<WebDocument>::const_iterator it = web_documents_.begin();
1739720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block       it != web_documents_.end(); ++it) {
1749720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    const WebFrame* document_frame = it->frame();
1759720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    if (!document_frame || document_frame == &frame)
1769720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      documents_to_delete.push_back(*it);
1779720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  }
1789720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
1799720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  for (std::vector<WebDocument>::const_iterator it =
1809720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block           documents_to_delete.begin();
1819720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block       it != documents_to_delete.end(); ++it) {
1829720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    web_documents_.erase(*it);
1839720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  }
1849720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
1859720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  parsed_forms_[&frame].clear();
1869720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  RemoveOldElements(frame, &initial_select_values_);
1879720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  RemoveOldElements(frame, &initial_checked_state_);
1889720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block}
1899720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
1909720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Blockbool FormCache::ClearFormWithElement(const WebFormControlElement& element) {
1919720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  WebFormElement form_element = element.form();
1929720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  if (form_element.isNull())
1939720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    return false;
1949720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
1959720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  std::vector<WebFormControlElement> control_elements;
1969720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  ExtractAutofillableElements(form_element, autofill::REQUIRE_NONE,
1979720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block                              &control_elements);
1989720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  for (size_t i = 0; i < control_elements.size(); ++i) {
1999720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    WebFormControlElement control_element = control_elements[i];
2009720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    // Don't modify the value of disabled fields.
2019720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    if (!control_element.isEnabled())
2029720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      continue;
2039720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
2049720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    // Don't clear field that was not autofilled
2059720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    if (!control_element.isAutofilled())
2069720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      continue;
2079720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
2089720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    control_element.setAutofilled(false);
2099720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
2109720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    WebInputElement* input_element = toWebInputElement(&control_element);
2119720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    if (IsTextInput(input_element) || IsMonthInput(input_element)) {
2129720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      input_element->setValue(base::string16(), true);
2139720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
2149720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      // Clearing the value in the focused node (above) can cause selection
2159720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      // to be lost. We force selection range to restore the text cursor.
2169720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      if (element == *input_element) {
2179720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        int length = input_element->value().length();
2189720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        input_element->setSelectionRange(length, length);
2199720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      }
2209720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    } else if (IsTextAreaElement(control_element)) {
2219720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      control_element.setValue(base::string16(), true);
2229720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    } else if (IsSelectElement(control_element)) {
2239720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      WebSelectElement select_element = control_element.to<WebSelectElement>();
2249720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
2259720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      std::map<const WebSelectElement, base::string16>::const_iterator
2269720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block          initial_value_iter = initial_select_values_.find(select_element);
2279720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      if (initial_value_iter != initial_select_values_.end() &&
2289720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block          select_element.value() != initial_value_iter->second) {
2299720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        select_element.setValue(initial_value_iter->second, true);
2309720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      }
2319720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    } else {
2329720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      WebInputElement input_element = control_element.to<WebInputElement>();
2339720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      DCHECK(IsCheckableElement(&input_element));
2349720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      std::map<const WebInputElement, bool>::const_iterator it =
2359720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block          initial_checked_state_.find(input_element);
2369720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      if (it != initial_checked_state_.end() &&
2379720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block          input_element.isChecked() != it->second) {
2389720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        input_element.setChecked(it->second, true);
2399720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      }
2409720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    }
2419720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  }
2429720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
2439720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  return true;
2449720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block}
2459720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
2469720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Blockbool FormCache::ShowPredictions(const FormDataPredictions& form) {
2479720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  DCHECK_EQ(form.data.fields.size(), form.fields.size());
2489720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
2499720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  // Find the form.
2509720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  bool found_form = false;
2519720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  WebFormElement form_element;
2529720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  for (std::set<WebDocument>::const_iterator it = web_documents_.begin();
2539720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block       it != web_documents_.end() && !found_form; ++it) {
2549720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    WebVector<WebFormElement> web_forms;
2559720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    it->forms(web_forms);
2569720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
2579720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    for (size_t i = 0; i < web_forms.size(); ++i) {
2589720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      form_element = web_forms[i];
2599720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
2609720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      // Note: matching on the form name here which is not guaranteed to be
2619720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      // unique for the page, nor is it guaranteed to be non-empty.  Ideally, we
2629720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      // would have a way to uniquely identify the form cross-process.  For now,
2639720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      // we'll check form name and form action for identity.
2649720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      // Also note that WebString() == WebString(string16()) does not evaluate
2659720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      // to |true| -- WebKit distinguishes between a "null" string (lhs) and an
2669720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      // "empty" string (rhs).  We don't want that distinction, so forcing to
2679720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      // string16.
2689720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      base::string16 element_name = GetFormIdentifier(form_element);
2699720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      GURL action(form_element.document().completeURL(form_element.action()));
2709720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      if (element_name == form.data.name && action == form.data.action) {
2719720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        found_form = true;
2729720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        break;
2739720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      }
2749720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    }
2759720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  }
2769720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
2779720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  if (!found_form)
2789720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    return false;
2799720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
2809720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  std::vector<WebFormControlElement> control_elements;
2819720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  ExtractAutofillableElements(form_element, autofill::REQUIRE_NONE,
2829720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block                              &control_elements);
2839720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  if (control_elements.size() != form.fields.size()) {
2849720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    // Keep things simple.  Don't show predictions for forms that were modified
2859720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    // between page load and the server's response to our query.
2869720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    return false;
2879720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  }
2889720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
2899720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  for (size_t i = 0; i < control_elements.size(); ++i) {
2909720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    WebFormControlElement* element = &control_elements[i];
2919720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
2929720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    if (base::string16(element->nameForAutofill()) !=
2939720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        form.data.fields[i].name) {
2949720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      // Keep things simple.  Don't show predictions for elements whose names
2959720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      // were modified between page load and the server's response to our query.
2969720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      continue;
2979720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    }
2989720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
2999720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    std::string placeholder = form.fields[i].overall_type;
3009720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    base::string16 title = l10n_util::GetStringFUTF16(
3019720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        IDS_AUTOFILL_SHOW_PREDICTIONS_TITLE,
3029720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        base::UTF8ToUTF16(form.fields[i].heuristic_type),
3039720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        base::UTF8ToUTF16(form.fields[i].server_type),
3049720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        base::UTF8ToUTF16(form.fields[i].signature),
3059720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        base::UTF8ToUTF16(form.signature),
3069720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block        base::UTF8ToUTF16(form.experiment_id));
3079720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    if (!element->hasAttribute("placeholder")) {
3089720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block      element->setAttribute("placeholder",
3099720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block                            WebString(base::UTF8ToUTF16(placeholder)));
3109720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    }
3119720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block    element->setAttribute("title", WebString(title));
3129720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  }
3139720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
3149720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block  return true;
3159720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block}
3169720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block
3179720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block}  // namespace autofill
3189720d5f59b9c1f5d1b9ecbc9173dbcb71bd557beSteve Block