Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / components / autofill / core / common / form_field_data.cc
blob1ae34468eb39fe9399852ca1c55aa835b28acb5f
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
3 // found in the LICENSE file.
5 #include "components/autofill/core/common/form_field_data.h"
7 #include "base/pickle.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/utf_string_conversions.h"
11 namespace autofill {
13 namespace {
15 // Increment this anytime pickle format is modified as well as provide
16 // deserialization routine from previous kPickleVersion format.
17 const int kPickleVersion = 2;
19 void AddVectorToPickle(std::vector<base::string16> strings,
20 base::Pickle* pickle) {
21 pickle->WriteInt(static_cast<int>(strings.size()));
22 for (size_t i = 0; i < strings.size(); ++i) {
23 pickle->WriteString16(strings[i]);
27 bool ReadStringVector(base::PickleIterator* iter,
28 std::vector<base::string16>* strings) {
29 int size;
30 if (!iter->ReadInt(&size))
31 return false;
33 base::string16 pickle_data;
34 for (int i = 0; i < size; i++) {
35 if (!iter->ReadString16(&pickle_data))
36 return false;
38 strings->push_back(pickle_data);
40 return true;
43 template <typename T>
44 bool ReadAsInt(base::PickleIterator* iter, T* target_value) {
45 int pickle_data;
46 if (!iter->ReadInt(&pickle_data))
47 return false;
49 *target_value = static_cast<T>(pickle_data);
50 return true;
53 bool DeserializeCommonSection1(base::PickleIterator* iter,
54 FormFieldData* field_data) {
55 return iter->ReadString16(&field_data->label) &&
56 iter->ReadString16(&field_data->name) &&
57 iter->ReadString16(&field_data->value) &&
58 iter->ReadString(&field_data->form_control_type) &&
59 iter->ReadString(&field_data->autocomplete_attribute) &&
60 iter->ReadSizeT(&field_data->max_length) &&
61 iter->ReadBool(&field_data->is_autofilled) &&
62 iter->ReadBool(&field_data->is_checked) &&
63 iter->ReadBool(&field_data->is_checkable) &&
64 iter->ReadBool(&field_data->is_focusable) &&
65 iter->ReadBool(&field_data->should_autocomplete);
68 bool DeserializeCommonSection2(base::PickleIterator* iter,
69 FormFieldData* field_data) {
70 return ReadAsInt(iter, &field_data->text_direction) &&
71 ReadStringVector(iter, &field_data->option_values) &&
72 ReadStringVector(iter, &field_data->option_contents);
75 bool DeserializeVersion2Specific(base::PickleIterator* iter,
76 FormFieldData* field_data) {
77 return ReadAsInt(iter, &field_data->role);
80 } // namespace
82 FormFieldData::FormFieldData()
83 : max_length(0),
84 is_autofilled(false),
85 is_checked(false),
86 is_checkable(false),
87 is_focusable(false),
88 should_autocomplete(true),
89 role(ROLE_ATTRIBUTE_OTHER),
90 text_direction(base::i18n::UNKNOWN_DIRECTION) {
93 FormFieldData::~FormFieldData() {
96 bool FormFieldData::SameFieldAs(const FormFieldData& field) const {
97 // A FormFieldData stores a value, but the value is not part of the identity
98 // of the field, so we don't want to compare the values.
99 return label == field.label && name == field.name &&
100 form_control_type == field.form_control_type &&
101 autocomplete_attribute == field.autocomplete_attribute &&
102 max_length == field.max_length &&
103 // is_checked and is_autofilled counts as "value" since these change
104 // when we fill things in.
105 is_checkable == field.is_checkable &&
106 is_focusable == field.is_focusable &&
107 should_autocomplete == field.should_autocomplete &&
108 role == field.role && text_direction == field.text_direction;
109 // The option values/contents which are the list of items in the list
110 // of a drop-down are currently not considered part of the identity of
111 // a form element. This is debatable, since one might base heuristics
112 // on the types of elements that are available. Alternatively, one
113 // could imagine some forms that dynamically change the element
114 // contents (say, insert years starting from the current year) that
115 // should not be considered changes in the structure of the form.
118 bool FormFieldData::operator<(const FormFieldData& field) const {
119 // Like operator==, this ignores the value.
120 if (label < field.label) return true;
121 if (label > field.label) return false;
122 if (name < field.name) return true;
123 if (name > field.name) return false;
124 if (form_control_type < field.form_control_type) return true;
125 if (form_control_type > field.form_control_type) return false;
126 if (autocomplete_attribute < field.autocomplete_attribute) return true;
127 if (autocomplete_attribute > field.autocomplete_attribute) return false;
128 if (max_length < field.max_length) return true;
129 if (max_length > field.max_length) return false;
130 // Skip |is_checked| and |is_autofilled| as in SameFieldAs.
131 if (is_checkable < field.is_checkable) return true;
132 if (is_checkable > field.is_checkable) return false;
133 if (is_focusable < field.is_focusable) return true;
134 if (is_focusable > field.is_focusable) return false;
135 if (should_autocomplete < field.should_autocomplete) return true;
136 if (should_autocomplete > field.should_autocomplete) return false;
137 if (role < field.role) return true;
138 if (role > field.role) return false;
139 if (text_direction < field.text_direction) return true;
140 if (text_direction > field.text_direction) return false;
141 // See operator== above for why we don't check option_values/contents.
142 return false;
145 void SerializeFormFieldData(const FormFieldData& field_data,
146 base::Pickle* pickle) {
147 pickle->WriteInt(kPickleVersion);
148 pickle->WriteString16(field_data.label);
149 pickle->WriteString16(field_data.name);
150 pickle->WriteString16(field_data.value);
151 pickle->WriteString(field_data.form_control_type);
152 pickle->WriteString(field_data.autocomplete_attribute);
153 pickle->WriteSizeT(field_data.max_length);
154 pickle->WriteBool(field_data.is_autofilled);
155 pickle->WriteBool(field_data.is_checked);
156 pickle->WriteBool(field_data.is_checkable);
157 pickle->WriteBool(field_data.is_focusable);
158 pickle->WriteBool(field_data.should_autocomplete);
159 pickle->WriteInt(field_data.role);
160 pickle->WriteInt(field_data.text_direction);
161 AddVectorToPickle(field_data.option_values, pickle);
162 AddVectorToPickle(field_data.option_contents, pickle);
165 bool DeserializeFormFieldData(base::PickleIterator* iter,
166 FormFieldData* field_data) {
167 int version;
168 FormFieldData temp_form_field_data;
169 if (!iter->ReadInt(&version)) {
170 LOG(ERROR) << "Bad pickle of FormFieldData, no version present";
171 return false;
174 switch (version) {
175 case 1: {
176 if (!DeserializeCommonSection1(iter, &temp_form_field_data) ||
177 !DeserializeCommonSection2(iter, &temp_form_field_data)) {
178 LOG(ERROR) << "Could not deserialize FormFieldData from pickle";
179 return false;
181 break;
183 case 2: {
184 if (!DeserializeCommonSection1(iter, &temp_form_field_data) ||
185 !DeserializeVersion2Specific(iter, &temp_form_field_data) ||
186 !DeserializeCommonSection2(iter, &temp_form_field_data)) {
187 LOG(ERROR) << "Could not deserialize FormFieldData from pickle";
188 return false;
190 break;
192 default: {
193 LOG(ERROR) << "Unknown FormFieldData pickle version " << version;
194 return false;
197 *field_data = temp_form_field_data;
198 return true;
201 std::ostream& operator<<(std::ostream& os, const FormFieldData& field) {
202 return os << base::UTF16ToUTF8(field.label) << " "
203 << base::UTF16ToUTF8(field.name) << " "
204 << base::UTF16ToUTF8(field.value) << " " << field.form_control_type
205 << " " << field.autocomplete_attribute << " " << field.max_length
206 << " " << (field.is_autofilled ? "true" : "false") << " "
207 << (field.is_checked ? "true" : "false") << " "
208 << (field.is_checkable ? "true" : "false") << " "
209 << (field.is_focusable ? "true" : "false") << " "
210 << (field.should_autocomplete ? "true" : "false") << " "
211 << field.role << " " << field.text_direction;
214 } // namespace autofill