| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/autofill/content/renderer/form_autofill_util.h" | 5 #include "components/autofill/content/renderer/form_autofill_util.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <set> | 8 #include <set> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 940 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 951 | 951 |
| 952 // Extracts the fields from |control_elements| with |extract_mask| to | 952 // Extracts the fields from |control_elements| with |extract_mask| to |
| 953 // |form_fields|. The extracted fields are also placed in |element_map|. | 953 // |form_fields|. The extracted fields are also placed in |element_map|. |
| 954 // |form_fields| and |element_map| should start out empty. | 954 // |form_fields| and |element_map| should start out empty. |
| 955 // |fields_extracted| should have as many elements as |control_elements|, | 955 // |fields_extracted| should have as many elements as |control_elements|, |
| 956 // initialized to false. | 956 // initialized to false. |
| 957 // Returns true if the number of fields extracted is within | 957 // Returns true if the number of fields extracted is within |
| 958 // [1, kMaxParseableFields]. | 958 // [1, kMaxParseableFields]. |
| 959 bool ExtractFieldsFromControlElements( | 959 bool ExtractFieldsFromControlElements( |
| 960 const WebVector<WebFormControlElement>& control_elements, | 960 const WebVector<WebFormControlElement>& control_elements, |
| 961 const FieldValueAndPropertiesMaskMap* field_value_and_properties_map, |
| 961 ExtractMask extract_mask, | 962 ExtractMask extract_mask, |
| 962 ScopedVector<FormFieldData>* form_fields, | 963 ScopedVector<FormFieldData>* form_fields, |
| 963 std::vector<bool>* fields_extracted, | 964 std::vector<bool>* fields_extracted, |
| 964 std::map<WebFormControlElement, FormFieldData*>* element_map) { | 965 std::map<WebFormControlElement, FormFieldData*>* element_map) { |
| 965 DCHECK(form_fields->empty()); | 966 DCHECK(form_fields->empty()); |
| 966 DCHECK(element_map->empty()); | 967 DCHECK(element_map->empty()); |
| 967 DCHECK_EQ(control_elements.size(), fields_extracted->size()); | 968 DCHECK_EQ(control_elements.size(), fields_extracted->size()); |
| 968 | 969 |
| 969 for (size_t i = 0; i < control_elements.size(); ++i) { | 970 for (size_t i = 0; i < control_elements.size(); ++i) { |
| 970 const WebFormControlElement& control_element = control_elements[i]; | 971 const WebFormControlElement& control_element = control_elements[i]; |
| 971 | 972 |
| 972 if (!IsAutofillableElement(control_element)) | 973 if (!IsAutofillableElement(control_element)) |
| 973 continue; | 974 continue; |
| 974 | 975 |
| 975 // Create a new FormFieldData, fill it out and map it to the field's name. | 976 // Create a new FormFieldData, fill it out and map it to the field's name. |
| 976 FormFieldData* form_field = new FormFieldData; | 977 FormFieldData* form_field = new FormFieldData; |
| 977 WebFormControlElementToFormField(control_element, extract_mask, form_field); | 978 WebFormControlElementToFormField(control_element, |
| 979 field_value_and_properties_map, |
| 980 extract_mask, form_field); |
| 978 form_fields->push_back(form_field); | 981 form_fields->push_back(form_field); |
| 979 (*element_map)[control_element] = form_field; | 982 (*element_map)[control_element] = form_field; |
| 980 (*fields_extracted)[i] = true; | 983 (*fields_extracted)[i] = true; |
| 981 | 984 |
| 982 // To avoid overly expensive computation, we impose a maximum number of | 985 // To avoid overly expensive computation, we impose a maximum number of |
| 983 // allowable fields. | 986 // allowable fields. |
| 984 if (form_fields->size() > kMaxParseableFields) | 987 if (form_fields->size() > kMaxParseableFields) |
| 985 return false; | 988 return false; |
| 986 } | 989 } |
| 987 | 990 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1054 // 1) |form_element| and an empty |fieldsets|. | 1057 // 1) |form_element| and an empty |fieldsets|. |
| 1055 // or | 1058 // or |
| 1056 // 2) a NULL |form_element|. | 1059 // 2) a NULL |form_element|. |
| 1057 // | 1060 // |
| 1058 // If |field| is not NULL, then |form_control_element| should be not NULL. | 1061 // If |field| is not NULL, then |form_control_element| should be not NULL. |
| 1059 bool FormOrFieldsetsToFormData( | 1062 bool FormOrFieldsetsToFormData( |
| 1060 const blink::WebFormElement* form_element, | 1063 const blink::WebFormElement* form_element, |
| 1061 const blink::WebFormControlElement* form_control_element, | 1064 const blink::WebFormControlElement* form_control_element, |
| 1062 const std::vector<blink::WebElement>& fieldsets, | 1065 const std::vector<blink::WebElement>& fieldsets, |
| 1063 const WebVector<WebFormControlElement>& control_elements, | 1066 const WebVector<WebFormControlElement>& control_elements, |
| 1067 const FieldValueAndPropertiesMaskMap* field_value_and_properties_map, |
| 1064 ExtractMask extract_mask, | 1068 ExtractMask extract_mask, |
| 1065 FormData* form, | 1069 FormData* form, |
| 1066 FormFieldData* field) { | 1070 FormFieldData* field) { |
| 1067 CR_DEFINE_STATIC_LOCAL(WebString, kLabel, ("label")); | 1071 CR_DEFINE_STATIC_LOCAL(WebString, kLabel, ("label")); |
| 1068 | 1072 |
| 1069 if (form_element) | 1073 if (form_element) |
| 1070 DCHECK(fieldsets.empty()); | 1074 DCHECK(fieldsets.empty()); |
| 1071 if (field) | 1075 if (field) |
| 1072 DCHECK(form_control_element); | 1076 DCHECK(form_control_element); |
| 1073 | 1077 |
| 1074 // A map from a FormFieldData's name to the FormFieldData itself. | 1078 // A map from a FormFieldData's name to the FormFieldData itself. |
| 1075 std::map<WebFormControlElement, FormFieldData*> element_map; | 1079 std::map<WebFormControlElement, FormFieldData*> element_map; |
| 1076 | 1080 |
| 1077 // The extracted FormFields. We use pointers so we can store them in | 1081 // The extracted FormFields. We use pointers so we can store them in |
| 1078 // |element_map|. | 1082 // |element_map|. |
| 1079 ScopedVector<FormFieldData> form_fields; | 1083 ScopedVector<FormFieldData> form_fields; |
| 1080 | 1084 |
| 1081 // A vector of bools that indicate whether each field in the form meets the | 1085 // A vector of bools that indicate whether each field in the form meets the |
| 1082 // requirements and thus will be in the resulting |form|. | 1086 // requirements and thus will be in the resulting |form|. |
| 1083 std::vector<bool> fields_extracted(control_elements.size(), false); | 1087 std::vector<bool> fields_extracted(control_elements.size(), false); |
| 1084 | 1088 |
| 1085 if (!ExtractFieldsFromControlElements(control_elements, extract_mask, | 1089 if (!ExtractFieldsFromControlElements( |
| 1086 &form_fields, &fields_extracted, | 1090 control_elements, field_value_and_properties_map, extract_mask, |
| 1087 &element_map)) { | 1091 &form_fields, &fields_extracted, &element_map)) { |
| 1088 return false; | 1092 return false; |
| 1089 } | 1093 } |
| 1090 | 1094 |
| 1091 if (form_element) { | 1095 if (form_element) { |
| 1092 // Loop through the label elements inside the form element. For each label | 1096 // Loop through the label elements inside the form element. For each label |
| 1093 // element, get the corresponding form control element, use the form control | 1097 // element, get the corresponding form control element, use the form control |
| 1094 // element's name as a key into the <name, FormFieldData> map to find the | 1098 // element's name as a key into the <name, FormFieldData> map to find the |
| 1095 // previously created FormFieldData and set the FormFieldData's label to the | 1099 // previously created FormFieldData and set the FormFieldData's label to the |
| 1096 // label.firstChild().nodeValue() of the label element. | 1100 // label.firstChild().nodeValue() of the label element. |
| 1097 WebElementCollection labels = | 1101 WebElementCollection labels = |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1148 for (const auto* iter : form_fields) | 1152 for (const auto* iter : form_fields) |
| 1149 form->fields.push_back(*iter); | 1153 form->fields.push_back(*iter); |
| 1150 return true; | 1154 return true; |
| 1151 } | 1155 } |
| 1152 | 1156 |
| 1153 bool UnownedFormElementsAndFieldSetsToFormData( | 1157 bool UnownedFormElementsAndFieldSetsToFormData( |
| 1154 const std::vector<blink::WebElement>& fieldsets, | 1158 const std::vector<blink::WebElement>& fieldsets, |
| 1155 const std::vector<blink::WebFormControlElement>& control_elements, | 1159 const std::vector<blink::WebFormControlElement>& control_elements, |
| 1156 const blink::WebFormControlElement* element, | 1160 const blink::WebFormControlElement* element, |
| 1157 const blink::WebDocument& document, | 1161 const blink::WebDocument& document, |
| 1162 const FieldValueAndPropertiesMaskMap* field_value_and_properties_map, |
| 1158 ExtractMask extract_mask, | 1163 ExtractMask extract_mask, |
| 1159 FormData* form, | 1164 FormData* form, |
| 1160 FormFieldData* field) { | 1165 FormFieldData* field) { |
| 1161 form->origin = GetCanonicalOriginForDocument(document); | 1166 form->origin = GetCanonicalOriginForDocument(document); |
| 1162 form->is_form_tag = false; | 1167 form->is_form_tag = false; |
| 1163 | 1168 |
| 1164 return FormOrFieldsetsToFormData(nullptr, element, fieldsets, | 1169 return FormOrFieldsetsToFormData( |
| 1165 control_elements, extract_mask, form, field); | 1170 nullptr, element, fieldsets, control_elements, |
| 1171 field_value_and_properties_map, extract_mask, form, field); |
| 1166 } | 1172 } |
| 1167 | 1173 |
| 1168 GURL StripAuthAndParams(const GURL& gurl) { | 1174 GURL StripAuthAndParams(const GURL& gurl) { |
| 1169 // We want to keep the path but strip any authentication data, as well as | 1175 // We want to keep the path but strip any authentication data, as well as |
| 1170 // query and ref portions of URL, for the form action and form origin. | 1176 // query and ref portions of URL, for the form action and form origin. |
| 1171 GURL::Replacements rep; | 1177 GURL::Replacements rep; |
| 1172 rep.ClearUsername(); | 1178 rep.ClearUsername(); |
| 1173 rep.ClearPassword(); | 1179 rep.ClearPassword(); |
| 1174 rep.ClearQuery(); | 1180 rep.ClearQuery(); |
| 1175 rep.ClearRef(); | 1181 rep.ClearRef(); |
| 1176 return gurl.ReplaceComponents(rep); | 1182 return gurl.ReplaceComponents(rep); |
| 1177 } | 1183 } |
| 1178 | 1184 |
| 1179 } // namespace | 1185 } // namespace |
| 1180 | 1186 |
| 1181 ScopedLayoutPreventer::ScopedLayoutPreventer() { | 1187 ScopedLayoutPreventer::ScopedLayoutPreventer() { |
| 1182 DCHECK(!g_prevent_layout) << "Is any other instance of ScopedLayoutPreventer " | 1188 DCHECK(!g_prevent_layout) << "Is any other instance of ScopedLayoutPreventer " |
| 1183 "alive in the same process?"; | 1189 "alive in the same process?"; |
| 1184 g_prevent_layout = true; | 1190 g_prevent_layout = true; |
| 1185 } | 1191 } |
| 1186 | 1192 |
| 1187 ScopedLayoutPreventer::~ScopedLayoutPreventer() { | 1193 ScopedLayoutPreventer::~ScopedLayoutPreventer() { |
| 1188 DCHECK(g_prevent_layout) << "Is any other instance of ScopedLayoutPreventer " | 1194 DCHECK(g_prevent_layout) << "Is any other instance of ScopedLayoutPreventer " |
| 1189 "alive in the same process?"; | 1195 "alive in the same process?"; |
| 1190 g_prevent_layout = false; | 1196 g_prevent_layout = false; |
| 1191 } | 1197 } |
| 1192 | 1198 |
| 1193 bool ExtractFormData(const WebFormElement& form_element, FormData* data) { | 1199 bool ExtractFormData(const WebFormElement& form_element, FormData* data) { |
| 1194 return WebFormElementToFormData( | 1200 return WebFormElementToFormData( |
| 1195 form_element, WebFormControlElement(), | 1201 form_element, WebFormControlElement(), nullptr, |
| 1196 static_cast<form_util::ExtractMask>(form_util::EXTRACT_VALUE | | 1202 static_cast<form_util::ExtractMask>(form_util::EXTRACT_VALUE | |
| 1197 form_util::EXTRACT_OPTION_TEXT | | 1203 form_util::EXTRACT_OPTION_TEXT | |
| 1198 form_util::EXTRACT_OPTIONS), | 1204 form_util::EXTRACT_OPTIONS), |
| 1199 data, NULL); | 1205 data, NULL); |
| 1200 } | 1206 } |
| 1201 | 1207 |
| 1202 bool IsFormVisible(blink::WebFrame* frame, | 1208 bool IsFormVisible(blink::WebFrame* frame, |
| 1203 const GURL& canonical_action, | 1209 const GURL& canonical_action, |
| 1204 const GURL& canonical_origin, | 1210 const GURL& canonical_origin, |
| 1205 const FormData& form_data) { | 1211 const FormData& form_data) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1227 | 1233 |
| 1228 GURL iter_canonical_action = GetCanonicalActionForForm(form); | 1234 GURL iter_canonical_action = GetCanonicalActionForForm(form); |
| 1229 #if !defined(OS_ANDROID) | 1235 #if !defined(OS_ANDROID) |
| 1230 bool form_action_is_empty = iter_canonical_action.is_empty() || | 1236 bool form_action_is_empty = iter_canonical_action.is_empty() || |
| 1231 iter_canonical_action == frame_origin; | 1237 iter_canonical_action == frame_origin; |
| 1232 if (action_is_empty != form_action_is_empty) | 1238 if (action_is_empty != form_action_is_empty) |
| 1233 continue; | 1239 continue; |
| 1234 | 1240 |
| 1235 if (action_is_empty) { // Both actions are empty, compare all fields. | 1241 if (action_is_empty) { // Both actions are empty, compare all fields. |
| 1236 FormData extracted_form_data; | 1242 FormData extracted_form_data; |
| 1237 WebFormElementToFormData(form, WebFormControlElement(), EXTRACT_NONE, | 1243 WebFormElementToFormData(form, WebFormControlElement(), nullptr, |
| 1238 &extracted_form_data, nullptr); | 1244 EXTRACT_NONE, &extracted_form_data, nullptr); |
| 1239 if (form_data.SameFormAs(extracted_form_data)) { | 1245 if (form_data.SameFormAs(extracted_form_data)) { |
| 1240 return true; // Form still exists. | 1246 return true; // Form still exists. |
| 1241 } | 1247 } |
| 1242 } else { // Both actions are non-empty, compare actions only. | 1248 } else { // Both actions are non-empty, compare actions only. |
| 1243 if (canonical_action == iter_canonical_action) { | 1249 if (canonical_action == iter_canonical_action) { |
| 1244 return true; // Form still exists. | 1250 return true; // Form still exists. |
| 1245 } | 1251 } |
| 1246 } | 1252 } |
| 1247 #else // OS_ANDROID | 1253 #else // OS_ANDROID |
| 1248 if (canonical_action == iter_canonical_action) { | 1254 if (canonical_action == iter_canonical_action) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1350 } | 1356 } |
| 1351 | 1357 |
| 1352 std::vector<WebFormControlElement> ExtractAutofillableElementsInForm( | 1358 std::vector<WebFormControlElement> ExtractAutofillableElementsInForm( |
| 1353 const WebFormElement& form_element) { | 1359 const WebFormElement& form_element) { |
| 1354 WebVector<WebFormControlElement> control_elements; | 1360 WebVector<WebFormControlElement> control_elements; |
| 1355 form_element.getFormControlElements(control_elements); | 1361 form_element.getFormControlElements(control_elements); |
| 1356 | 1362 |
| 1357 return ExtractAutofillableElementsFromSet(control_elements); | 1363 return ExtractAutofillableElementsFromSet(control_elements); |
| 1358 } | 1364 } |
| 1359 | 1365 |
| 1360 void WebFormControlElementToFormField(const WebFormControlElement& element, | 1366 void WebFormControlElementToFormField( |
| 1361 ExtractMask extract_mask, | 1367 const WebFormControlElement& element, |
| 1362 FormFieldData* field) { | 1368 const FieldValueAndPropertiesMaskMap* field_value_and_properties_map, |
| 1369 ExtractMask extract_mask, |
| 1370 FormFieldData* field) { |
| 1363 DCHECK(field); | 1371 DCHECK(field); |
| 1364 DCHECK(!element.isNull()); | 1372 DCHECK(!element.isNull()); |
| 1365 CR_DEFINE_STATIC_LOCAL(WebString, kAutocomplete, ("autocomplete")); | 1373 CR_DEFINE_STATIC_LOCAL(WebString, kAutocomplete, ("autocomplete")); |
| 1366 CR_DEFINE_STATIC_LOCAL(WebString, kRole, ("role")); | 1374 CR_DEFINE_STATIC_LOCAL(WebString, kRole, ("role")); |
| 1367 CR_DEFINE_STATIC_LOCAL(WebString, kPlaceholder, ("placeholder")); | 1375 CR_DEFINE_STATIC_LOCAL(WebString, kPlaceholder, ("placeholder")); |
| 1368 CR_DEFINE_STATIC_LOCAL(WebString, kClass, ("class")); | 1376 CR_DEFINE_STATIC_LOCAL(WebString, kClass, ("class")); |
| 1369 | 1377 |
| 1370 // The label is not officially part of a WebFormControlElement; however, the | 1378 // The label is not officially part of a WebFormControlElement; however, the |
| 1371 // labels for all form control elements are scraped from the DOM and set in | 1379 // labels for all form control elements are scraped from the DOM and set in |
| 1372 // WebFormElementToFormData. | 1380 // WebFormElementToFormData. |
| 1373 field->name = element.nameForAutofill(); | 1381 field->name = element.nameForAutofill(); |
| 1374 field->form_control_type = element.formControlType().utf8(); | 1382 field->form_control_type = element.formControlType().utf8(); |
| 1375 field->autocomplete_attribute = element.getAttribute(kAutocomplete).utf8(); | 1383 field->autocomplete_attribute = element.getAttribute(kAutocomplete).utf8(); |
| 1376 if (field->autocomplete_attribute.size() > kMaxDataLength) { | 1384 if (field->autocomplete_attribute.size() > kMaxDataLength) { |
| 1377 // Discard overly long attribute values to avoid DOS-ing the browser | 1385 // Discard overly long attribute values to avoid DOS-ing the browser |
| 1378 // process. However, send over a default string to indicate that the | 1386 // process. However, send over a default string to indicate that the |
| 1379 // attribute was present. | 1387 // attribute was present. |
| 1380 field->autocomplete_attribute = "x-max-data-length-exceeded"; | 1388 field->autocomplete_attribute = "x-max-data-length-exceeded"; |
| 1381 } | 1389 } |
| 1382 if (base::LowerCaseEqualsASCII( | 1390 if (base::LowerCaseEqualsASCII( |
| 1383 base::StringPiece16(element.getAttribute(kRole)), "presentation")) | 1391 base::StringPiece16(element.getAttribute(kRole)), "presentation")) |
| 1384 field->role = FormFieldData::ROLE_ATTRIBUTE_PRESENTATION; | 1392 field->role = FormFieldData::ROLE_ATTRIBUTE_PRESENTATION; |
| 1385 | 1393 |
| 1386 field->placeholder = element.getAttribute(kPlaceholder); | 1394 field->placeholder = element.getAttribute(kPlaceholder); |
| 1387 if (element.hasAttribute(kClass)) | 1395 if (element.hasAttribute(kClass)) |
| 1388 field->css_classes = element.getAttribute(kClass); | 1396 field->css_classes = element.getAttribute(kClass); |
| 1389 | 1397 |
| 1398 if (field_value_and_properties_map) { |
| 1399 FieldValueAndPropertiesMaskMap::const_iterator it = |
| 1400 field_value_and_properties_map->find(element); |
| 1401 if (it != field_value_and_properties_map->end()) |
| 1402 field->properties_mask = it->second.second; |
| 1403 } |
| 1404 |
| 1390 if (!IsAutofillableElement(element)) | 1405 if (!IsAutofillableElement(element)) |
| 1391 return; | 1406 return; |
| 1392 | 1407 |
| 1393 const WebInputElement* input_element = toWebInputElement(&element); | 1408 const WebInputElement* input_element = toWebInputElement(&element); |
| 1394 if (IsAutofillableInputElement(input_element) || | 1409 if (IsAutofillableInputElement(input_element) || |
| 1395 IsTextAreaElement(element) || | 1410 IsTextAreaElement(element) || |
| 1396 IsSelectElement(element)) { | 1411 IsSelectElement(element)) { |
| 1397 field->is_autofilled = element.isAutofilled(); | 1412 field->is_autofilled = element.isAutofilled(); |
| 1398 if (!g_prevent_layout) | 1413 if (!g_prevent_layout) |
| 1399 field->is_focusable = element.isFocusable(); | 1414 field->is_focusable = element.isFocusable(); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1450 // Constrain the maximum data length to prevent a malicious site from DOS'ing | 1465 // Constrain the maximum data length to prevent a malicious site from DOS'ing |
| 1451 // the browser: http://crbug.com/49332 | 1466 // the browser: http://crbug.com/49332 |
| 1452 TruncateString(&value, kMaxDataLength); | 1467 TruncateString(&value, kMaxDataLength); |
| 1453 | 1468 |
| 1454 field->value = value; | 1469 field->value = value; |
| 1455 } | 1470 } |
| 1456 | 1471 |
| 1457 bool WebFormElementToFormData( | 1472 bool WebFormElementToFormData( |
| 1458 const blink::WebFormElement& form_element, | 1473 const blink::WebFormElement& form_element, |
| 1459 const blink::WebFormControlElement& form_control_element, | 1474 const blink::WebFormControlElement& form_control_element, |
| 1475 const FieldValueAndPropertiesMaskMap* field_value_and_properties_map, |
| 1460 ExtractMask extract_mask, | 1476 ExtractMask extract_mask, |
| 1461 FormData* form, | 1477 FormData* form, |
| 1462 FormFieldData* field) { | 1478 FormFieldData* field) { |
| 1463 const WebFrame* frame = form_element.document().frame(); | 1479 const WebFrame* frame = form_element.document().frame(); |
| 1464 if (!frame) | 1480 if (!frame) |
| 1465 return false; | 1481 return false; |
| 1466 | 1482 |
| 1467 form->name = GetFormIdentifier(form_element); | 1483 form->name = GetFormIdentifier(form_element); |
| 1468 form->origin = GetCanonicalOriginForDocument(frame->document()); | 1484 form->origin = GetCanonicalOriginForDocument(frame->document()); |
| 1469 form->action = frame->document().completeURL(form_element.action()); | 1485 form->action = frame->document().completeURL(form_element.action()); |
| 1470 | 1486 |
| 1471 // If the completed URL is not valid, just use the action we get from | 1487 // If the completed URL is not valid, just use the action we get from |
| 1472 // WebKit. | 1488 // WebKit. |
| 1473 if (!form->action.is_valid()) | 1489 if (!form->action.is_valid()) |
| 1474 form->action = GURL(blink::WebStringToGURL(form_element.action())); | 1490 form->action = GURL(blink::WebStringToGURL(form_element.action())); |
| 1475 | 1491 |
| 1476 WebVector<WebFormControlElement> control_elements; | 1492 WebVector<WebFormControlElement> control_elements; |
| 1477 form_element.getFormControlElements(control_elements); | 1493 form_element.getFormControlElements(control_elements); |
| 1478 | 1494 |
| 1479 std::vector<blink::WebElement> dummy_fieldset; | 1495 std::vector<blink::WebElement> dummy_fieldset; |
| 1480 return FormOrFieldsetsToFormData(&form_element, &form_control_element, | 1496 return FormOrFieldsetsToFormData( |
| 1481 dummy_fieldset, control_elements, | 1497 &form_element, &form_control_element, dummy_fieldset, control_elements, |
| 1482 extract_mask, form, field); | 1498 field_value_and_properties_map, extract_mask, form, field); |
| 1483 } | 1499 } |
| 1484 | 1500 |
| 1485 std::vector<WebFormControlElement> GetUnownedFormFieldElements( | 1501 std::vector<WebFormControlElement> GetUnownedFormFieldElements( |
| 1486 const WebElementCollection& elements, | 1502 const WebElementCollection& elements, |
| 1487 std::vector<WebElement>* fieldsets) { | 1503 std::vector<WebElement>* fieldsets) { |
| 1488 std::vector<WebFormControlElement> unowned_fieldset_children; | 1504 std::vector<WebFormControlElement> unowned_fieldset_children; |
| 1489 for (WebElement element = elements.firstItem(); | 1505 for (WebElement element = elements.firstItem(); |
| 1490 !element.isNull(); | 1506 !element.isNull(); |
| 1491 element = elements.nextItem()) { | 1507 element = elements.nextItem()) { |
| 1492 if (element.isFormControlElement()) { | 1508 if (element.isFormControlElement()) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1525 | 1541 |
| 1526 // For now this restriction only applies to English-language pages, because | 1542 // For now this restriction only applies to English-language pages, because |
| 1527 // the keywords are not translated. Note that an empty "lang" attribute | 1543 // the keywords are not translated. Note that an empty "lang" attribute |
| 1528 // counts as English. | 1544 // counts as English. |
| 1529 std::string lang; | 1545 std::string lang; |
| 1530 if (!html_element.isNull()) | 1546 if (!html_element.isNull()) |
| 1531 lang = html_element.getAttribute("lang").utf8(); | 1547 lang = html_element.getAttribute("lang").utf8(); |
| 1532 if (!lang.empty() && | 1548 if (!lang.empty() && |
| 1533 !base::StartsWith(lang, "en", base::CompareCase::INSENSITIVE_ASCII)) { | 1549 !base::StartsWith(lang, "en", base::CompareCase::INSENSITIVE_ASCII)) { |
| 1534 return UnownedFormElementsAndFieldSetsToFormData( | 1550 return UnownedFormElementsAndFieldSetsToFormData( |
| 1535 fieldsets, control_elements, element, document, extract_mask, form, | 1551 fieldsets, control_elements, element, document, nullptr, extract_mask, |
| 1536 field); | 1552 form, field); |
| 1537 } | 1553 } |
| 1538 | 1554 |
| 1539 // A potential problem is that this only checks document.title(), but should | 1555 // A potential problem is that this only checks document.title(), but should |
| 1540 // actually check the main frame's title. Thus it may make bad decisions for | 1556 // actually check the main frame's title. Thus it may make bad decisions for |
| 1541 // iframes. | 1557 // iframes. |
| 1542 base::string16 title(base::ToLowerASCII(base::string16(document.title()))); | 1558 base::string16 title(base::ToLowerASCII(base::string16(document.title()))); |
| 1543 | 1559 |
| 1544 // Don't check the path for url's without a standard format path component, | 1560 // Don't check the path for url's without a standard format path component, |
| 1545 // such as data:. | 1561 // such as data:. |
| 1546 std::string path; | 1562 std::string path; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1560 for (const auto* keyword : kKeywords) { | 1576 for (const auto* keyword : kKeywords) { |
| 1561 // Compare char16 elements of |title| with char elements of |keyword| using | 1577 // Compare char16 elements of |title| with char elements of |keyword| using |
| 1562 // operator==. | 1578 // operator==. |
| 1563 auto title_pos = std::search(title.begin(), title.end(), | 1579 auto title_pos = std::search(title.begin(), title.end(), |
| 1564 keyword, keyword + strlen(keyword)); | 1580 keyword, keyword + strlen(keyword)); |
| 1565 if (title_pos != title.end() || | 1581 if (title_pos != title.end() || |
| 1566 path.find(keyword) != std::string::npos) { | 1582 path.find(keyword) != std::string::npos) { |
| 1567 form->is_formless_checkout = true; | 1583 form->is_formless_checkout = true; |
| 1568 // Found a keyword: treat this as an unowned form. | 1584 // Found a keyword: treat this as an unowned form. |
| 1569 return UnownedFormElementsAndFieldSetsToFormData( | 1585 return UnownedFormElementsAndFieldSetsToFormData( |
| 1570 fieldsets, control_elements, element, document, extract_mask, form, | 1586 fieldsets, control_elements, element, document, nullptr, extract_mask, |
| 1571 field); | 1587 form, field); |
| 1572 } | 1588 } |
| 1573 } | 1589 } |
| 1574 | 1590 |
| 1575 // Since it's not a checkout flow, only add fields that have a non-"off" | 1591 // Since it's not a checkout flow, only add fields that have a non-"off" |
| 1576 // autocomplete attribute to the formless autofill. | 1592 // autocomplete attribute to the formless autofill. |
| 1577 CR_DEFINE_STATIC_LOCAL(WebString, kOffAttribute, ("off")); | 1593 CR_DEFINE_STATIC_LOCAL(WebString, kOffAttribute, ("off")); |
| 1578 std::vector<WebFormControlElement> elements_with_autocomplete; | 1594 std::vector<WebFormControlElement> elements_with_autocomplete; |
| 1579 for (const WebFormControlElement& element : control_elements) { | 1595 for (const WebFormControlElement& element : control_elements) { |
| 1580 blink::WebString autocomplete = element.getAttribute("autocomplete"); | 1596 blink::WebString autocomplete = element.getAttribute("autocomplete"); |
| 1581 if (autocomplete.length() && autocomplete != kOffAttribute) | 1597 if (autocomplete.length() && autocomplete != kOffAttribute) |
| 1582 elements_with_autocomplete.push_back(element); | 1598 elements_with_autocomplete.push_back(element); |
| 1583 } | 1599 } |
| 1584 | 1600 |
| 1585 if (elements_with_autocomplete.empty()) | 1601 if (elements_with_autocomplete.empty()) |
| 1586 return false; | 1602 return false; |
| 1587 | 1603 |
| 1588 return UnownedFormElementsAndFieldSetsToFormData( | 1604 return UnownedFormElementsAndFieldSetsToFormData( |
| 1589 fieldsets, elements_with_autocomplete, element, document, extract_mask, | 1605 fieldsets, elements_with_autocomplete, element, document, nullptr, |
| 1590 form, field); | 1606 extract_mask, form, field); |
| 1591 } | 1607 } |
| 1592 | 1608 |
| 1593 bool UnownedPasswordFormElementsAndFieldSetsToFormData( | 1609 bool UnownedPasswordFormElementsAndFieldSetsToFormData( |
| 1594 const std::vector<blink::WebElement>& fieldsets, | 1610 const std::vector<blink::WebElement>& fieldsets, |
| 1595 const std::vector<blink::WebFormControlElement>& control_elements, | 1611 const std::vector<blink::WebFormControlElement>& control_elements, |
| 1596 const blink::WebFormControlElement* element, | 1612 const blink::WebFormControlElement* element, |
| 1597 const blink::WebDocument& document, | 1613 const blink::WebDocument& document, |
| 1614 const FieldValueAndPropertiesMaskMap* field_value_and_properties_map, |
| 1598 ExtractMask extract_mask, | 1615 ExtractMask extract_mask, |
| 1599 FormData* form, | 1616 FormData* form, |
| 1600 FormFieldData* field) { | 1617 FormFieldData* field) { |
| 1601 return UnownedFormElementsAndFieldSetsToFormData( | 1618 return UnownedFormElementsAndFieldSetsToFormData( |
| 1602 fieldsets, control_elements, element, document, extract_mask, form, | 1619 fieldsets, control_elements, element, document, |
| 1603 field); | 1620 field_value_and_properties_map, extract_mask, form, field); |
| 1604 } | 1621 } |
| 1605 | 1622 |
| 1606 | 1623 |
| 1607 bool FindFormAndFieldForFormControlElement(const WebFormControlElement& element, | 1624 bool FindFormAndFieldForFormControlElement(const WebFormControlElement& element, |
| 1608 FormData* form, | 1625 FormData* form, |
| 1609 FormFieldData* field) { | 1626 FormFieldData* field) { |
| 1610 if (!IsAutofillableElement(element)) | 1627 if (!IsAutofillableElement(element)) |
| 1611 return false; | 1628 return false; |
| 1612 | 1629 |
| 1613 ExtractMask extract_mask = | 1630 ExtractMask extract_mask = |
| 1614 static_cast<ExtractMask>(EXTRACT_VALUE | EXTRACT_OPTIONS); | 1631 static_cast<ExtractMask>(EXTRACT_VALUE | EXTRACT_OPTIONS); |
| 1615 const WebFormElement form_element = element.form(); | 1632 const WebFormElement form_element = element.form(); |
| 1616 if (form_element.isNull()) { | 1633 if (form_element.isNull()) { |
| 1617 // No associated form, try the synthetic form for unowned form elements. | 1634 // No associated form, try the synthetic form for unowned form elements. |
| 1618 WebDocument document = element.document(); | 1635 WebDocument document = element.document(); |
| 1619 std::vector<WebElement> fieldsets; | 1636 std::vector<WebElement> fieldsets; |
| 1620 std::vector<WebFormControlElement> control_elements = | 1637 std::vector<WebFormControlElement> control_elements = |
| 1621 GetUnownedAutofillableFormFieldElements(document.all(), &fieldsets); | 1638 GetUnownedAutofillableFormFieldElements(document.all(), &fieldsets); |
| 1622 return UnownedCheckoutFormElementsAndFieldSetsToFormData( | 1639 return UnownedCheckoutFormElementsAndFieldSetsToFormData( |
| 1623 fieldsets, control_elements, &element, document, extract_mask, | 1640 fieldsets, control_elements, &element, document, extract_mask, |
| 1624 form, field); | 1641 form, field); |
| 1625 } | 1642 } |
| 1626 | 1643 |
| 1627 return WebFormElementToFormData(form_element, | 1644 return WebFormElementToFormData(form_element, element, nullptr, extract_mask, |
| 1628 element, | 1645 form, field); |
| 1629 extract_mask, | |
| 1630 form, | |
| 1631 field); | |
| 1632 } | 1646 } |
| 1633 | 1647 |
| 1634 void FillForm(const FormData& form, const WebFormControlElement& element) { | 1648 void FillForm(const FormData& form, const WebFormControlElement& element) { |
| 1635 WebFormElement form_element = element.form(); | 1649 WebFormElement form_element = element.form(); |
| 1636 if (form_element.isNull()) { | 1650 if (form_element.isNull()) { |
| 1637 ForEachMatchingUnownedFormField(element, | 1651 ForEachMatchingUnownedFormField(element, |
| 1638 form, | 1652 form, |
| 1639 FILTER_ALL_NON_EDITABLE_ELEMENTS, | 1653 FILTER_ALL_NON_EDITABLE_ELEMENTS, |
| 1640 false, /* dont force override */ | 1654 false, /* dont force override */ |
| 1641 &FillFormField); | 1655 &FillFormField); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1795 // Zero selection start is for password manager, which can show usernames | 1809 // Zero selection start is for password manager, which can show usernames |
| 1796 // that do not begin with the user input value. | 1810 // that do not begin with the user input value. |
| 1797 selection_start = (offset == base::string16::npos) ? 0 : offset; | 1811 selection_start = (offset == base::string16::npos) ? 0 : offset; |
| 1798 } | 1812 } |
| 1799 | 1813 |
| 1800 input_element->setSelectionRange(selection_start, suggestion.length()); | 1814 input_element->setSelectionRange(selection_start, suggestion.length()); |
| 1801 } | 1815 } |
| 1802 | 1816 |
| 1803 } // namespace form_util | 1817 } // namespace form_util |
| 1804 } // namespace autofill | 1818 } // namespace autofill |
| OLD | NEW |