| 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 |