| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "chrome/browser/autofill/address_field.h" | 5 #include "chrome/browser/autofill/address_field.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| 11 #include "base/string16.h" | 11 #include "base/string16.h" |
| 12 #include "base/string_util.h" | 12 #include "base/string_util.h" |
| 13 #include "base/utf_string_conversions.h" | 13 #include "base/utf_string_conversions.h" |
| 14 #include "chrome/browser/autofill/autofill_ecml.h" |
| 14 #include "chrome/browser/autofill/autofill_field.h" | 15 #include "chrome/browser/autofill/autofill_field.h" |
| 15 #include "chrome/browser/autofill/autofill_scanner.h" | 16 #include "chrome/browser/autofill/autofill_scanner.h" |
| 16 #include "grit/autofill_resources.h" | 17 #include "grit/autofill_resources.h" |
| 17 #include "ui/base/l10n/l10n_util.h" | 18 #include "ui/base/l10n/l10n_util.h" |
| 18 | 19 |
| 19 bool AddressField::GetFieldInfo(FieldTypeMap* field_type_map) const { | 20 using autofill::GetEcmlPattern; |
| 20 AutofillFieldType address_company; | |
| 21 AutofillFieldType address_line1; | |
| 22 AutofillFieldType address_line2; | |
| 23 AutofillFieldType address_city; | |
| 24 AutofillFieldType address_state; | |
| 25 AutofillFieldType address_zip; | |
| 26 AutofillFieldType address_country; | |
| 27 | |
| 28 switch (type_) { | |
| 29 case kShippingAddress: | |
| 30 // Fall through. Autofill does not support shipping addresses. | |
| 31 case kGenericAddress: | |
| 32 address_company = COMPANY_NAME; | |
| 33 address_line1 = ADDRESS_HOME_LINE1; | |
| 34 address_line2 = ADDRESS_HOME_LINE2; | |
| 35 address_city = ADDRESS_HOME_CITY; | |
| 36 address_state = ADDRESS_HOME_STATE; | |
| 37 address_zip = ADDRESS_HOME_ZIP; | |
| 38 address_country = ADDRESS_HOME_COUNTRY; | |
| 39 break; | |
| 40 | |
| 41 case kBillingAddress: | |
| 42 address_company = COMPANY_NAME; | |
| 43 address_line1 = ADDRESS_BILLING_LINE1; | |
| 44 address_line2 = ADDRESS_BILLING_LINE2; | |
| 45 address_city = ADDRESS_BILLING_CITY; | |
| 46 address_state = ADDRESS_BILLING_STATE; | |
| 47 address_zip = ADDRESS_BILLING_ZIP; | |
| 48 address_country = ADDRESS_BILLING_COUNTRY; | |
| 49 break; | |
| 50 | |
| 51 default: | |
| 52 NOTREACHED(); | |
| 53 return false; | |
| 54 } | |
| 55 | |
| 56 bool ok = Add(field_type_map, company_, address_company); | |
| 57 ok = ok && Add(field_type_map, address1_, address_line1); | |
| 58 ok = ok && Add(field_type_map, address2_, address_line2); | |
| 59 ok = ok && Add(field_type_map, city_, address_city); | |
| 60 ok = ok && Add(field_type_map, state_, address_state); | |
| 61 ok = ok && Add(field_type_map, zip_, address_zip); | |
| 62 ok = ok && Add(field_type_map, country_, address_country); | |
| 63 return ok; | |
| 64 } | |
| 65 | 21 |
| 66 AddressField* AddressField::Parse(AutofillScanner* scanner, bool is_ecml) { | 22 AddressField* AddressField::Parse(AutofillScanner* scanner, bool is_ecml) { |
| 67 if (scanner->IsEnd()) | 23 if (scanner->IsEnd()) |
| 68 return NULL; | 24 return NULL; |
| 69 | 25 |
| 70 scoped_ptr<AddressField> address_field(new AddressField); | 26 scoped_ptr<AddressField> address_field(new AddressField); |
| 71 const AutofillField* initial_field = scanner->Cursor(); | 27 const AutofillField* initial_field = scanner->Cursor(); |
| 72 scanner->SaveCursor(); | 28 scanner->SaveCursor(); |
| 73 | 29 |
| 74 string16 attention_ignored = | 30 string16 attention_ignored = |
| 75 l10n_util::GetStringUTF16(IDS_AUTOFILL_ATTENTION_IGNORED_RE); | 31 l10n_util::GetStringUTF16(IDS_AUTOFILL_ATTENTION_IGNORED_RE); |
| 76 string16 region_ignored = | 32 string16 region_ignored = |
| 77 l10n_util::GetStringUTF16(IDS_AUTOFILL_REGION_IGNORED_RE); | 33 l10n_util::GetStringUTF16(IDS_AUTOFILL_REGION_IGNORED_RE); |
| 78 | 34 |
| 79 // Allow address fields to appear in any order. | 35 // Allow address fields to appear in any order. |
| 80 while (!scanner->IsEnd()) { | 36 while (!scanner->IsEnd()) { |
| 81 if (ParseCompany(scanner, is_ecml, address_field.get()) || | 37 if (ParseCompany(scanner, is_ecml, address_field.get()) || |
| 82 ParseAddressLines(scanner, is_ecml, address_field.get()) || | 38 ParseAddressLines(scanner, is_ecml, address_field.get()) || |
| 83 ParseCity(scanner, is_ecml, address_field.get()) || | 39 ParseCity(scanner, is_ecml, address_field.get()) || |
| 84 ParseState(scanner, is_ecml, address_field.get()) || | 40 ParseState(scanner, is_ecml, address_field.get()) || |
| 85 ParseZipCode(scanner, is_ecml, address_field.get()) || | 41 ParseZipCode(scanner, is_ecml, address_field.get()) || |
| 86 ParseCountry(scanner, is_ecml, address_field.get())) { | 42 ParseCountry(scanner, is_ecml, address_field.get())) { |
| 87 continue; | 43 continue; |
| 88 } else if (ParseText(scanner, attention_ignored) || | 44 } else if (ParseField(scanner, attention_ignored, NULL) || |
| 89 ParseText(scanner, region_ignored)) { | 45 ParseField(scanner, region_ignored, NULL)) { |
| 90 // We ignore the following: | 46 // We ignore the following: |
| 91 // * Attention. | 47 // * Attention. |
| 92 // * Province/Region/Other. | 48 // * Province/Region/Other. |
| 93 continue; | 49 continue; |
| 94 } else if (scanner->Cursor() != initial_field && ParseEmpty(scanner)) { | 50 } else if (scanner->Cursor() != initial_field && |
| 51 ParseEmptyLabel(scanner, NULL)) { |
| 95 // Ignore non-labeled fields within an address; the page | 52 // Ignore non-labeled fields within an address; the page |
| 96 // MapQuest Driving Directions North America.html contains such a field. | 53 // MapQuest Driving Directions North America.html contains such a field. |
| 97 // We only ignore such fields after we've parsed at least one other field; | 54 // We only ignore such fields after we've parsed at least one other field; |
| 98 // otherwise we'd effectively parse address fields before other field | 55 // otherwise we'd effectively parse address fields before other field |
| 99 // types after any non-labeled fields, and we want email address fields to | 56 // types after any non-labeled fields, and we want email address fields to |
| 100 // have precedence since some pages contain fields labeled | 57 // have precedence since some pages contain fields labeled |
| 101 // "Email address". | 58 // "Email address". |
| 102 continue; | 59 continue; |
| 103 } else { | 60 } else { |
| 104 // No field found. | 61 // No field found. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 128 return kGenericAddress; | 85 return kGenericAddress; |
| 129 | 86 |
| 130 // First look at the field name, which itself will sometimes contain | 87 // First look at the field name, which itself will sometimes contain |
| 131 // "bill" or "ship". We could check for the ECML type prefixes | 88 // "bill" or "ship". We could check for the ECML type prefixes |
| 132 // here, but there's no need to since ECML's prefixes Ecom_BillTo | 89 // here, but there's no need to since ECML's prefixes Ecom_BillTo |
| 133 // and Ecom_ShipTo contain "bill" and "ship" anyway. | 90 // and Ecom_ShipTo contain "bill" and "ship" anyway. |
| 134 string16 name = StringToLowerASCII(address1_->name); | 91 string16 name = StringToLowerASCII(address1_->name); |
| 135 return AddressTypeFromText(name); | 92 return AddressTypeFromText(name); |
| 136 } | 93 } |
| 137 | 94 |
| 138 bool AddressField::IsFullAddress() { | |
| 139 return address1_ != NULL; | |
| 140 } | |
| 141 | |
| 142 AddressField::AddressField() | 95 AddressField::AddressField() |
| 143 : company_(NULL), | 96 : company_(NULL), |
| 144 address1_(NULL), | 97 address1_(NULL), |
| 145 address2_(NULL), | 98 address2_(NULL), |
| 146 city_(NULL), | 99 city_(NULL), |
| 147 state_(NULL), | 100 state_(NULL), |
| 148 zip_(NULL), | 101 zip_(NULL), |
| 149 zip4_(NULL), | 102 zip4_(NULL), |
| 150 country_(NULL), | 103 country_(NULL), |
| 151 type_(kGenericAddress) { | 104 type_(kGenericAddress) { |
| 152 } | 105 } |
| 153 | 106 |
| 107 bool AddressField::ClassifyField(FieldTypeMap* map) const { |
| 108 AutofillFieldType address_company; |
| 109 AutofillFieldType address_line1; |
| 110 AutofillFieldType address_line2; |
| 111 AutofillFieldType address_city; |
| 112 AutofillFieldType address_state; |
| 113 AutofillFieldType address_zip; |
| 114 AutofillFieldType address_country; |
| 115 |
| 116 switch (type_) { |
| 117 case kShippingAddress: |
| 118 // Fall through. Autofill does not support shipping addresses. |
| 119 case kGenericAddress: |
| 120 address_company = COMPANY_NAME; |
| 121 address_line1 = ADDRESS_HOME_LINE1; |
| 122 address_line2 = ADDRESS_HOME_LINE2; |
| 123 address_city = ADDRESS_HOME_CITY; |
| 124 address_state = ADDRESS_HOME_STATE; |
| 125 address_zip = ADDRESS_HOME_ZIP; |
| 126 address_country = ADDRESS_HOME_COUNTRY; |
| 127 break; |
| 128 |
| 129 case kBillingAddress: |
| 130 address_company = COMPANY_NAME; |
| 131 address_line1 = ADDRESS_BILLING_LINE1; |
| 132 address_line2 = ADDRESS_BILLING_LINE2; |
| 133 address_city = ADDRESS_BILLING_CITY; |
| 134 address_state = ADDRESS_BILLING_STATE; |
| 135 address_zip = ADDRESS_BILLING_ZIP; |
| 136 address_country = ADDRESS_BILLING_COUNTRY; |
| 137 break; |
| 138 |
| 139 default: |
| 140 NOTREACHED(); |
| 141 return false; |
| 142 } |
| 143 |
| 144 bool ok = AddClassification(company_, address_company, map); |
| 145 ok = ok && AddClassification(address1_, address_line1, map); |
| 146 ok = ok && AddClassification(address2_, address_line2, map); |
| 147 ok = ok && AddClassification(city_, address_city, map); |
| 148 ok = ok && AddClassification(state_, address_state, map); |
| 149 ok = ok && AddClassification(zip_, address_zip, map); |
| 150 ok = ok && AddClassification(country_, address_country, map); |
| 151 return ok; |
| 152 } |
| 153 |
| 154 // static | 154 // static |
| 155 bool AddressField::ParseCompany(AutofillScanner* scanner, | 155 bool AddressField::ParseCompany(AutofillScanner* scanner, |
| 156 bool is_ecml, | 156 bool is_ecml, |
| 157 AddressField* address_field) { | 157 AddressField* address_field) { |
| 158 if (address_field->company_ && !address_field->company_->IsEmpty()) | 158 if (address_field->company_ && !address_field->company_->IsEmpty()) |
| 159 return false; | 159 return false; |
| 160 | 160 |
| 161 string16 pattern; | 161 string16 pattern; |
| 162 if (is_ecml) { | 162 if (is_ecml) { |
| 163 pattern = GetEcmlPattern(kEcmlShipToCompanyName, | 163 pattern = GetEcmlPattern(kEcmlShipToCompanyName, |
| 164 kEcmlBillToCompanyName, '|'); | 164 kEcmlBillToCompanyName, '|'); |
| 165 } else { | 165 } else { |
| 166 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_COMPANY_RE); | 166 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_COMPANY_RE); |
| 167 } | 167 } |
| 168 | 168 |
| 169 return ParseText(scanner, pattern, &address_field->company_); | 169 return ParseField(scanner, pattern, &address_field->company_); |
| 170 } | 170 } |
| 171 | 171 |
| 172 // static | 172 // static |
| 173 bool AddressField::ParseAddressLines(AutofillScanner* scanner, | 173 bool AddressField::ParseAddressLines(AutofillScanner* scanner, |
| 174 bool is_ecml, | 174 bool is_ecml, |
| 175 AddressField* address_field) { | 175 AddressField* address_field) { |
| 176 // We only match the string "address" in page text, not in element names, | 176 // We only match the string "address" in page text, not in element names, |
| 177 // because sometimes every element in a group of address fields will have | 177 // because sometimes every element in a group of address fields will have |
| 178 // a name containing the string "address"; for example, on the page | 178 // a name containing the string "address"; for example, on the page |
| 179 // Kohl's - Register Billing Address.html the text element labeled "city" | 179 // Kohl's - Register Billing Address.html the text element labeled "city" |
| 180 // has the name "BILL_TO_ADDRESS<>city". We do match address labels | 180 // has the name "BILL_TO_ADDRESS<>city". We do match address labels |
| 181 // such as "address1", which appear as element names on various pages (eg | 181 // such as "address1", which appear as element names on various pages (eg |
| 182 // AmericanGirl-Registration.html, BloomingdalesBilling.html, | 182 // AmericanGirl-Registration.html, BloomingdalesBilling.html, |
| 183 // EBay Registration Enter Information.html). | 183 // EBay Registration Enter Information.html). |
| 184 if (address_field->address1_) | 184 if (address_field->address1_) |
| 185 return false; | 185 return false; |
| 186 | 186 |
| 187 string16 pattern; | 187 string16 pattern; |
| 188 if (is_ecml) { | 188 if (is_ecml) { |
| 189 pattern = GetEcmlPattern(kEcmlShipToAddress1, kEcmlBillToAddress1, '|'); | 189 pattern = GetEcmlPattern(kEcmlShipToAddress1, kEcmlBillToAddress1, '|'); |
| 190 if (!ParseText(scanner, pattern, &address_field->address1_)) | 190 if (!ParseField(scanner, pattern, &address_field->address1_)) |
| 191 return false; | 191 return false; |
| 192 } else { | 192 } else { |
| 193 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_LINE_1_RE); | 193 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_LINE_1_RE); |
| 194 string16 label_pattern = | 194 string16 label_pattern = |
| 195 l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_LINE_1_LABEL_RE); | 195 l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_LINE_1_LABEL_RE); |
| 196 | 196 |
| 197 if (!ParseText(scanner, pattern, &address_field->address1_) && | 197 if (!ParseField(scanner, pattern, &address_field->address1_) && |
| 198 !ParseLabelText(scanner, label_pattern, &address_field->address1_)) | 198 !ParseFieldSpecifics(scanner, label_pattern, MATCH_LABEL, |
| 199 &address_field->address1_)) { |
| 199 return false; | 200 return false; |
| 201 } |
| 200 } | 202 } |
| 201 | 203 |
| 202 // Optionally parse more address lines, which may have empty labels. | 204 // Optionally parse more address lines, which may have empty labels. |
| 203 // Some pages have 3 address lines (eg SharperImageModifyAccount.html) | 205 // Some pages have 3 address lines (eg SharperImageModifyAccount.html) |
| 204 // Some pages even have 4 address lines (e.g. uk/ShoesDirect2.html)! | 206 // Some pages even have 4 address lines (e.g. uk/ShoesDirect2.html)! |
| 205 if (is_ecml) { | 207 if (is_ecml) { |
| 206 pattern = GetEcmlPattern(kEcmlShipToAddress2, kEcmlBillToAddress2, '|'); | 208 pattern = GetEcmlPattern(kEcmlShipToAddress2, kEcmlBillToAddress2, '|'); |
| 207 if (!ParseEmptyText(scanner, &address_field->address2_)) | 209 if (!ParseEmptyLabel(scanner, &address_field->address2_)) |
| 208 ParseText(scanner, pattern, &address_field->address2_); | 210 ParseField(scanner, pattern, &address_field->address2_); |
| 209 } else { | 211 } else { |
| 210 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_LINE_2_RE); | 212 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_LINE_2_RE); |
| 211 string16 label_pattern = | 213 string16 label_pattern = |
| 212 l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_LINE_1_LABEL_RE); | 214 l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_LINE_1_LABEL_RE); |
| 213 if (!ParseEmptyText(scanner, &address_field->address2_) && | 215 if (!ParseEmptyLabel(scanner, &address_field->address2_) && |
| 214 !ParseText(scanner, pattern, &address_field->address2_)) | 216 !ParseField(scanner, pattern, &address_field->address2_)) { |
| 215 ParseLabelText(scanner, label_pattern, &address_field->address2_); | 217 ParseFieldSpecifics(scanner, label_pattern, MATCH_LABEL, |
| 218 &address_field->address2_); |
| 219 } |
| 216 } | 220 } |
| 217 | 221 |
| 218 // Try for a third line, which we will promptly discard. | 222 // Try for a third line, which we will promptly discard. |
| 219 if (address_field->address2_ != NULL) { | 223 if (address_field->address2_ != NULL) { |
| 220 if (is_ecml) { | 224 if (is_ecml) { |
| 221 pattern = GetEcmlPattern(kEcmlShipToAddress3, kEcmlBillToAddress3, '|'); | 225 pattern = GetEcmlPattern(kEcmlShipToAddress3, kEcmlBillToAddress3, '|'); |
| 222 ParseText(scanner, pattern); | 226 ParseField(scanner, pattern, NULL); |
| 223 } else { | 227 } else { |
| 224 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_LINE_3_RE); | 228 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_LINE_3_RE); |
| 225 if (!ParseEmptyText(scanner, NULL)) | 229 if (!ParseEmptyLabel(scanner, NULL)) |
| 226 ParseText(scanner, pattern, NULL); | 230 ParseField(scanner, pattern, NULL); |
| 227 } | 231 } |
| 228 } | 232 } |
| 229 | 233 |
| 230 return true; | 234 return true; |
| 231 } | 235 } |
| 232 | 236 |
| 233 // static | 237 // static |
| 234 bool AddressField::ParseCountry(AutofillScanner* scanner, | 238 bool AddressField::ParseCountry(AutofillScanner* scanner, |
| 235 bool is_ecml, | 239 bool is_ecml, |
| 236 AddressField* address_field) { | 240 AddressField* address_field) { |
| 237 // Parse a country. The occasional page (e.g. | 241 // Parse a country. The occasional page (e.g. |
| 238 // Travelocity_New Member Information1.html) calls this a "location". | 242 // Travelocity_New Member Information1.html) calls this a "location". |
| 239 // Note: ECML standard uses 2 letter country code (ISO 3166) | 243 // Note: ECML standard uses 2 letter country code (ISO 3166) |
| 240 if (address_field->country_ && !address_field->country_->IsEmpty()) | 244 if (address_field->country_ && !address_field->country_->IsEmpty()) |
| 241 return false; | 245 return false; |
| 242 | 246 |
| 243 string16 pattern; | 247 string16 pattern; |
| 244 if (is_ecml) | 248 if (is_ecml) |
| 245 pattern = GetEcmlPattern(kEcmlShipToCountry, kEcmlBillToCountry, '|'); | 249 pattern = GetEcmlPattern(kEcmlShipToCountry, kEcmlBillToCountry, '|'); |
| 246 else | 250 else |
| 247 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_COUNTRY_RE); | 251 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_COUNTRY_RE); |
| 248 | 252 |
| 249 return ParseText(scanner, pattern, &address_field->country_); | 253 return ParseField(scanner, pattern, &address_field->country_); |
| 250 } | 254 } |
| 251 | 255 |
| 252 // static | 256 // static |
| 253 bool AddressField::ParseZipCode(AutofillScanner* scanner, | 257 bool AddressField::ParseZipCode(AutofillScanner* scanner, |
| 254 bool is_ecml, | 258 bool is_ecml, |
| 255 AddressField* address_field) { | 259 AddressField* address_field) { |
| 256 // Parse a zip code. On some UK pages (e.g. The China Shop2.html) this | 260 // Parse a zip code. On some UK pages (e.g. The China Shop2.html) this |
| 257 // is called a "post code". | 261 // is called a "post code". |
| 258 // | 262 // |
| 259 // HACK: Just for the MapQuest driving directions page we match the | 263 // HACK: Just for the MapQuest driving directions page we match the |
| 260 // exact name "1z", which MapQuest uses to label its zip code field. | 264 // exact name "1z", which MapQuest uses to label its zip code field. |
| 261 // Hopefully before long we'll be smart enough to find the zip code | 265 // Hopefully before long we'll be smart enough to find the zip code |
| 262 // on that page automatically. | 266 // on that page automatically. |
| 263 if (address_field->zip_) | 267 if (address_field->zip_) |
| 264 return false; | 268 return false; |
| 265 | 269 |
| 266 string16 pattern; | 270 string16 pattern; |
| 267 if (is_ecml) { | 271 if (is_ecml) { |
| 268 pattern = GetEcmlPattern(kEcmlShipToPostalCode, kEcmlBillToPostalCode, '|'); | 272 pattern = GetEcmlPattern(kEcmlShipToPostalCode, kEcmlBillToPostalCode, '|'); |
| 269 } else { | 273 } else { |
| 270 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_ZIP_CODE_RE); | 274 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_ZIP_CODE_RE); |
| 271 } | 275 } |
| 272 | 276 |
| 273 AddressType tempType; | 277 AddressType tempType; |
| 274 string16 name = scanner->Cursor()->name; | 278 string16 name = scanner->Cursor()->name; |
| 275 | 279 |
| 276 // Note: comparisons using the ecml compliant name as a prefix must be used in | 280 // Note: comparisons using the ECML compliant name as a prefix must be used in |
| 277 // order to accommodate Google Checkout. See FormFieldSet::GetEcmlPattern for | 281 // order to accommodate Google Checkout. See |GetEcmlPattern| for more detail. |
| 278 // more detail. | |
| 279 string16 bill_to_postal_code_field(ASCIIToUTF16(kEcmlBillToPostalCode)); | 282 string16 bill_to_postal_code_field(ASCIIToUTF16(kEcmlBillToPostalCode)); |
| 280 if (StartsWith(name, bill_to_postal_code_field, false)) { | 283 if (StartsWith(name, bill_to_postal_code_field, false)) { |
| 281 tempType = kBillingAddress; | 284 tempType = kBillingAddress; |
| 282 } else if (StartsWith(name, bill_to_postal_code_field, false)) { | 285 } else if (StartsWith(name, bill_to_postal_code_field, false)) { |
| 283 tempType = kShippingAddress; | 286 tempType = kShippingAddress; |
| 284 } else { | 287 } else { |
| 285 tempType = kGenericAddress; | 288 tempType = kGenericAddress; |
| 286 } | 289 } |
| 287 | 290 |
| 288 if (!ParseText(scanner, pattern, &address_field->zip_)) | 291 if (!ParseField(scanner, pattern, &address_field->zip_)) |
| 289 return false; | 292 return false; |
| 290 | 293 |
| 291 address_field->type_ = tempType; | 294 address_field->type_ = tempType; |
| 292 if (!is_ecml) { | 295 if (!is_ecml) { |
| 293 // Look for a zip+4, whose field name will also often contain | 296 // Look for a zip+4, whose field name will also often contain |
| 294 // the substring "zip". | 297 // the substring "zip". |
| 295 ParseText(scanner, | 298 ParseField(scanner, |
| 296 l10n_util::GetStringUTF16(IDS_AUTOFILL_ZIP_4_RE), | 299 l10n_util::GetStringUTF16(IDS_AUTOFILL_ZIP_4_RE), |
| 297 &address_field->zip4_); | 300 &address_field->zip4_); |
| 298 } | 301 } |
| 299 | 302 |
| 300 return true; | 303 return true; |
| 301 } | 304 } |
| 302 | 305 |
| 303 // static | 306 // static |
| 304 bool AddressField::ParseCity(AutofillScanner* scanner, | 307 bool AddressField::ParseCity(AutofillScanner* scanner, |
| 305 bool is_ecml, | 308 bool is_ecml, |
| 306 AddressField* address_field) { | 309 AddressField* address_field) { |
| 307 // Parse a city name. Some UK pages (e.g. The China Shop2.html) use | 310 // Parse a city name. Some UK pages (e.g. The China Shop2.html) use |
| 308 // the term "town". | 311 // the term "town". |
| 309 if (address_field->city_) | 312 if (address_field->city_) |
| 310 return false; | 313 return false; |
| 311 | 314 |
| 312 string16 pattern; | 315 string16 pattern; |
| 313 if (is_ecml) | 316 if (is_ecml) |
| 314 pattern = GetEcmlPattern(kEcmlShipToCity, kEcmlBillToCity, '|'); | 317 pattern = GetEcmlPattern(kEcmlShipToCity, kEcmlBillToCity, '|'); |
| 315 else | 318 else |
| 316 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_CITY_RE); | 319 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_CITY_RE); |
| 317 | 320 |
| 318 return ParseText(scanner, pattern, &address_field->city_); | 321 return ParseField(scanner, pattern, &address_field->city_); |
| 319 } | 322 } |
| 320 | 323 |
| 321 // static | 324 // static |
| 322 bool AddressField::ParseState(AutofillScanner* scanner, | 325 bool AddressField::ParseState(AutofillScanner* scanner, |
| 323 bool is_ecml, | 326 bool is_ecml, |
| 324 AddressField* address_field) { | 327 AddressField* address_field) { |
| 325 if (address_field->state_) | 328 if (address_field->state_) |
| 326 return false; | 329 return false; |
| 327 | 330 |
| 328 string16 pattern; | 331 string16 pattern; |
| 329 if (is_ecml) | 332 if (is_ecml) |
| 330 pattern = GetEcmlPattern(kEcmlShipToStateProv, kEcmlBillToStateProv, '|'); | 333 pattern = GetEcmlPattern(kEcmlShipToStateProv, kEcmlBillToStateProv, '|'); |
| 331 else | 334 else |
| 332 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_STATE_RE); | 335 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_STATE_RE); |
| 333 | 336 |
| 334 return ParseText(scanner, pattern, &address_field->state_); | 337 return ParseField(scanner, pattern, &address_field->state_); |
| 335 } | 338 } |
| 336 | 339 |
| 337 AddressType AddressField::AddressTypeFromText(const string16 &text) { | 340 AddressType AddressField::AddressTypeFromText(const string16 &text) { |
| 338 if (text.find(l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_TYPE_SAME_AS_RE)) | 341 if (text.find(l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_TYPE_SAME_AS_RE)) |
| 339 != string16::npos || | 342 != string16::npos || |
| 340 text.find(l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_TYPE_USE_MY_RE)) | 343 text.find(l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_TYPE_USE_MY_RE)) |
| 341 != string16::npos) | 344 != string16::npos) |
| 342 // This text could be a checkbox label such as "same as my billing | 345 // This text could be a checkbox label such as "same as my billing |
| 343 // address" or "use my shipping address". | 346 // address" or "use my shipping address". |
| 344 // ++ It would help if we generally skipped all text that appears | 347 // ++ It would help if we generally skipped all text that appears |
| (...skipping 15 matching lines...) Expand all Loading... |
| 360 return kBillingAddress; | 363 return kBillingAddress; |
| 361 | 364 |
| 362 if (bill == string16::npos && ship != string16::npos) | 365 if (bill == string16::npos && ship != string16::npos) |
| 363 return kShippingAddress; | 366 return kShippingAddress; |
| 364 | 367 |
| 365 if (bill > ship) | 368 if (bill > ship) |
| 366 return kBillingAddress; | 369 return kBillingAddress; |
| 367 | 370 |
| 368 return kShippingAddress; | 371 return kShippingAddress; |
| 369 } | 372 } |
| OLD | NEW |