// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "webkit/glue/form_field.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
#include "third_party/WebKit/WebKit/chromium/public/WebElement.h"
#include "third_party/WebKit/WebKit/chromium/public/WebLabelElement.h"
#include "third_party/WebKit/WebKit/chromium/public/WebNode.h"
#include "third_party/WebKit/WebKit/chromium/public/WebNodeList.h"
using WebKit::WebElement;
using WebKit::WebLabelElement;
using WebKit::WebInputElement;
using WebKit::WebNode;
using WebKit::WebNodeList;
// TODO(jhawkins): Remove the following methods once AutoFill has been switched
// over to using FormData.
// WARNING: This code must stay in sync with the corresponding code in
// FormManager until we can remove this.
namespace {
string16 InferLabelForElement(const WebInputElement& element) {
string16 inferred_label;
WebNode previous = element.previousSibling();
if (!previous.isNull()) {
if (previous.isTextNode()) {
inferred_label = previous.nodeValue();
TrimWhitespace(inferred_label, TRIM_ALL, &inferred_label);
}
// If we didn't find text, check for previous paragraph.
// Eg.
Some Text
// Note the lack of whitespace between
and elements.
if (inferred_label.empty()) {
if (previous.isElementNode()) {
WebElement element = previous.toElement();
if (element.hasTagName("p")) {
inferred_label = element.innerText();
TrimWhitespace(inferred_label, TRIM_ALL, &inferred_label);
}
}
}
// If we didn't find paragraph, check for previous paragraph to this.
// Eg.
Some Text
// Note the whitespace between
and elements.
if (inferred_label.empty()) {
previous = previous.previousSibling();
if (!previous.isNull() && previous.isElementNode()) {
WebElement element = previous.toElement();
if (element.hasTagName("p")) {
inferred_label = element.innerText();
TrimWhitespace(inferred_label, TRIM_ALL, &inferred_label);
}
}
}
}
return inferred_label;
}
string16 LabelForElement(const WebInputElement& element) {
WebNodeList labels = element.document().getElementsByTagName("label");
for (unsigned i = 0; i < labels.length(); ++i) {
WebElement e = labels.item(i).toElement();
if (e.hasTagName("label")) {
WebLabelElement label = e.toElement();
if (label.correspondingControl() == element)
return label.innerText();
}
}
// Infer the label from context if not found in label element.
return InferLabelForElement(element);
}
} // namespace
namespace webkit_glue {
FormField::FormField() {
}
FormField::FormField(const WebInputElement& input_element) {
name_ = input_element.nameForAutofill();
label_ = LabelForElement(input_element);
value_ = input_element.value();
TrimWhitespace(value_, TRIM_LEADING, &value_);
form_control_type_ = input_element.formControlType();
input_type_ = input_element.inputType();
}
FormField::FormField(const string16& label,
const string16& name,
const string16& value,
const string16& form_control_type,
WebInputElement::InputType input_type)
: label_(label),
name_(name),
value_(value),
form_control_type_(form_control_type),
input_type_(input_type) {
}
bool FormField::operator==(const FormField& field) const {
// A FormField stores a value, but the value is not part of the identity of
// the field, so we don't want to compare the values.
return (label_ == field.label_ &&
name_ == field.name_ &&
form_control_type_ == field.form_control_type_ &&
input_type_ == field.input_type_);
}
bool FormField::operator!=(const FormField& field) const {
return !operator==(field);
}
std::ostream& operator<<(std::ostream& os, const FormField& field) {
return os
<< UTF16ToUTF8(field.label())
<< " "
<< UTF16ToUTF8(field.name())
<< " "
<< UTF16ToUTF8(field.value())
<< " "
<< UTF16ToUTF8(field.form_control_type())
<< " "
<< field.input_type();
}
} // namespace webkit_glue