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"
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
) {
30 if (!iter
->ReadInt(&size
))
33 base::string16 pickle_data
;
34 for (int i
= 0; i
< size
; i
++) {
35 if (!iter
->ReadString16(&pickle_data
))
38 strings
->push_back(pickle_data
);
44 bool ReadAsInt(base::PickleIterator
* iter
, T
* target_value
) {
46 if (!iter
->ReadInt(&pickle_data
))
49 *target_value
= static_cast<T
>(pickle_data
);
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
);
82 FormFieldData::FormFieldData()
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.
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
) {
168 FormFieldData temp_form_field_data
;
169 if (!iter
->ReadInt(&version
)) {
170 LOG(ERROR
) << "Bad pickle of FormFieldData, no version present";
176 if (!DeserializeCommonSection1(iter
, &temp_form_field_data
) ||
177 !DeserializeCommonSection2(iter
, &temp_form_field_data
)) {
178 LOG(ERROR
) << "Could not deserialize FormFieldData from pickle";
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";
193 LOG(ERROR
) << "Unknown FormFieldData pickle version " << version
;
197 *field_data
= temp_form_field_data
;
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