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.
4
5 #include "components/autofill/core/common/form_data.h"
6
7 #include <stddef.h>
8 #include <tuple>
9
10 #include "base/base64.h"
11 #include "base/pickle.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "components/autofill/core/common/form_field_data.h"
15 #include "components/autofill/core/common/logging/log_buffer.h"
16
17 namespace autofill {
18
19 namespace {
20
21 const int kFormDataPickleVersion = 6;
22
ReadGURL(base::PickleIterator * iter,GURL * url)23 bool ReadGURL(base::PickleIterator* iter, GURL* url) {
24 std::string spec;
25 if (!iter->ReadString(&spec))
26 return false;
27
28 *url = GURL(spec);
29 return true;
30 }
31
ReadOrigin(base::PickleIterator * iter,url::Origin * origin)32 bool ReadOrigin(base::PickleIterator* iter, url::Origin* origin) {
33 std::string spec;
34 if (!iter->ReadString(&spec))
35 return false;
36
37 *origin = url::Origin::Create(GURL(spec));
38 return true;
39 }
40
SerializeFormFieldDataVector(const std::vector<FormFieldData> & fields,base::Pickle * pickle)41 void SerializeFormFieldDataVector(const std::vector<FormFieldData>& fields,
42 base::Pickle* pickle) {
43 pickle->WriteInt(static_cast<int>(fields.size()));
44 for (size_t i = 0; i < fields.size(); ++i) {
45 SerializeFormFieldData(fields[i], pickle);
46 }
47 }
48
DeserializeFormFieldDataVector(base::PickleIterator * iter,std::vector<FormFieldData> * fields)49 bool DeserializeFormFieldDataVector(base::PickleIterator* iter,
50 std::vector<FormFieldData>* fields) {
51 int size;
52 if (!iter->ReadInt(&size))
53 return false;
54
55 FormFieldData temp;
56 for (int i = 0; i < size; ++i) {
57 if (!DeserializeFormFieldData(iter, &temp))
58 return false;
59
60 fields->push_back(temp);
61 }
62 return true;
63 }
64
LogDeserializationError(int version)65 void LogDeserializationError(int version) {
66 DVLOG(1) << "Could not deserialize version " << version
67 << " FormData from pickle.";
68 }
69
70 } // namespace
71
72 FormData::FormData() = default;
73
74 FormData::FormData(const FormData&) = default;
75
76 FormData& FormData::operator=(const FormData&) = default;
77
78 FormData::FormData(FormData&&) = default;
79
80 FormData& FormData::operator=(FormData&&) = default;
81
82 FormData::~FormData() = default;
83
SameFormAs(const FormData & form) const84 bool FormData::SameFormAs(const FormData& form) const {
85 if (name != form.name || id_attribute != form.id_attribute ||
86 name_attribute != form.name_attribute || url != form.url ||
87 action != form.action || is_form_tag != form.is_form_tag ||
88 is_formless_checkout != form.is_formless_checkout ||
89 fields.size() != form.fields.size())
90 return false;
91 for (size_t i = 0; i < fields.size(); ++i) {
92 if (!fields[i].SameFieldAs(form.fields[i]))
93 return false;
94 }
95 return true;
96 }
97
SimilarFormAs(const FormData & form) const98 bool FormData::SimilarFormAs(const FormData& form) const {
99 if (name != form.name || id_attribute != form.id_attribute ||
100 name_attribute != form.name_attribute || url != form.url ||
101 action != form.action || is_action_empty != form.is_action_empty ||
102 is_form_tag != form.is_form_tag ||
103 is_formless_checkout != form.is_formless_checkout ||
104 fields.size() != form.fields.size()) {
105 return false;
106 }
107 for (size_t i = 0; i < fields.size(); ++i) {
108 if (!fields[i].SimilarFieldAs(form.fields[i]))
109 return false;
110 }
111 return true;
112 }
113
DynamicallySameFormAs(const FormData & form) const114 bool FormData::DynamicallySameFormAs(const FormData& form) const {
115 if (name != form.name || id_attribute != form.id_attribute ||
116 name_attribute != form.name_attribute ||
117 fields.size() != form.fields.size())
118 return false;
119 for (size_t i = 0; i < fields.size(); ++i) {
120 if (!fields[i].DynamicallySameFieldAs(form.fields[i]))
121 return false;
122 }
123 return true;
124 }
125
operator ()(const FormData & a,const FormData & b) const126 bool FormData::IdentityComparator::operator()(const FormData& a,
127 const FormData& b) const {
128 // |unique_renderer_id| uniquely identifies the form, if and only if it is
129 // set; the other members compared below together uniquely identify the form
130 // as well.
131 auto tie = [](const FormData& f) {
132 return std::tie(f.unique_renderer_id, f.name, f.id_attribute,
133 f.name_attribute, f.url, f.action, f.is_form_tag,
134 f.is_formless_checkout);
135 };
136 if (tie(a) < tie(b))
137 return true;
138 if (tie(b) < tie(a))
139 return false;
140 return std::lexicographical_compare(a.fields.begin(), a.fields.end(),
141 b.fields.begin(), b.fields.end(),
142 FormFieldData::IdentityComparator());
143 }
144
FormHasNonEmptyPasswordField(const FormData & form)145 bool FormHasNonEmptyPasswordField(const FormData& form) {
146 for (const auto& field : form.fields) {
147 if (field.IsPasswordInputElement()) {
148 if (!field.value.empty() || !field.typed_value.empty())
149 return true;
150 }
151 }
152 return false;
153 }
154
operator <<(std::ostream & os,const FormData & form)155 std::ostream& operator<<(std::ostream& os, const FormData& form) {
156 os << base::UTF16ToUTF8(form.name) << " " << form.url << " " << form.action
157 << " " << form.main_frame_origin << " " << form.is_form_tag << " "
158 << form.is_formless_checkout << " "
159 << "Fields:";
160 for (size_t i = 0; i < form.fields.size(); ++i) {
161 os << form.fields[i] << ",";
162 }
163 return os;
164 }
165
SerializeFormData(const FormData & form_data,base::Pickle * pickle)166 void SerializeFormData(const FormData& form_data, base::Pickle* pickle) {
167 pickle->WriteInt(kFormDataPickleVersion);
168 pickle->WriteString16(form_data.name);
169 pickle->WriteString(form_data.url.spec());
170 pickle->WriteString(form_data.action.spec());
171 SerializeFormFieldDataVector(form_data.fields, pickle);
172 pickle->WriteBool(form_data.is_form_tag);
173 pickle->WriteBool(form_data.is_formless_checkout);
174 pickle->WriteString(form_data.main_frame_origin.Serialize());
175 }
176
DeserializeFormData(base::PickleIterator * iter,FormData * form_data)177 bool DeserializeFormData(base::PickleIterator* iter, FormData* form_data) {
178 int version;
179 FormData temp_form_data;
180 if (!iter->ReadInt(&version)) {
181 DVLOG(1) << "Bad pickle of FormData, no version present";
182 return false;
183 }
184
185 if (version < 1 || version > kFormDataPickleVersion) {
186 DVLOG(1) << "Unknown FormData pickle version " << version;
187 return false;
188 }
189
190 if (!iter->ReadString16(&temp_form_data.name)) {
191 LogDeserializationError(version);
192 return false;
193 }
194
195 if (version == 1) {
196 base::string16 method;
197 if (!iter->ReadString16(&method)) {
198 LogDeserializationError(version);
199 return false;
200 }
201 }
202
203 bool unused_user_submitted;
204 if (!ReadGURL(iter, &temp_form_data.url) ||
205 !ReadGURL(iter, &temp_form_data.action) ||
206 // user_submitted was removed/no longer serialized in version 4.
207 (version < 4 && !iter->ReadBool(&unused_user_submitted)) ||
208 !DeserializeFormFieldDataVector(iter, &temp_form_data.fields)) {
209 LogDeserializationError(version);
210 return false;
211 }
212
213 if (version >= 3) {
214 if (!iter->ReadBool(&temp_form_data.is_form_tag)) {
215 LogDeserializationError(version);
216 return false;
217 }
218 } else {
219 form_data->is_form_tag = true;
220 }
221
222 if (version >= 5) {
223 if (!iter->ReadBool(&temp_form_data.is_formless_checkout)) {
224 LogDeserializationError(version);
225 return false;
226 }
227 }
228
229 if (version >= 6) {
230 if (!ReadOrigin(iter, &temp_form_data.main_frame_origin)) {
231 LogDeserializationError(version);
232 return false;
233 }
234 }
235
236 *form_data = temp_form_data;
237 return true;
238 }
239
operator <<(LogBuffer & buffer,const FormData & form)240 LogBuffer& operator<<(LogBuffer& buffer, const FormData& form) {
241 buffer << Tag{"div"} << Attrib{"class", "form"};
242 buffer << Tag{"table"};
243 buffer << Tr{} << "Form name:" << form.name;
244 buffer << Tr{} << "Unique renderer Id:" << form.unique_renderer_id.value();
245 buffer << Tr{} << "URL:" << form.url;
246 buffer << Tr{} << "Action:" << form.action;
247 buffer << Tr{} << "Is action empty:" << form.is_action_empty;
248 buffer << Tr{} << "Is <form> tag:" << form.is_form_tag;
249 for (size_t i = 0; i < form.fields.size(); ++i) {
250 buffer << Tag{"tr"};
251 buffer << Tag{"td"} << "Field " << i << ": " << CTag{};
252 buffer << Tag{"td"};
253 buffer << Tag{"table"} << form.fields.at(i) << CTag{"table"};
254 buffer << CTag{"td"};
255 buffer << CTag{"tr"};
256 }
257 buffer << CTag{"table"};
258 buffer << CTag{"div"};
259 return buffer;
260 }
261
FormDataEqualForTesting(const FormData & lhs,const FormData & rhs)262 bool FormDataEqualForTesting(const FormData& lhs, const FormData& rhs) {
263 FormData::IdentityComparator less;
264 return !less(lhs, rhs) && !less(rhs, lhs);
265 }
266
267 } // namespace autofill
268