| 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_field.h" | 14 #include "chrome/browser/autofill/autofill_field.h" |
| 15 #include "chrome/browser/autofill/autofill_regex_constants.h" |
| 15 #include "chrome/browser/autofill/autofill_scanner.h" | 16 #include "chrome/browser/autofill/autofill_scanner.h" |
| 16 #include "chrome/browser/autofill/field_types.h" | 17 #include "chrome/browser/autofill/field_types.h" |
| 17 #include "ui/base/l10n/l10n_util.h" | 18 #include "ui/base/l10n/l10n_util.h" |
| 18 | 19 |
| 19 namespace { | |
| 20 | |
| 21 // The UTF-8 version of these regular expressions are in | |
| 22 // regular_expressions.txt. | |
| 23 const char kAttentionIgnoredRe[] = "attention|attn"; | |
| 24 const char kRegionIgnoredRe[] = | |
| 25 "province|region|other" | |
| 26 // es | |
| 27 "|provincia" | |
| 28 // pt-BR, pt-PT | |
| 29 "|bairro|suburb"; | |
| 30 const char kCompanyRe[] = | |
| 31 "company|business|organization|organisation" | |
| 32 // de-DE | |
| 33 "|firma|firmenname" | |
| 34 // es | |
| 35 "|empresa" | |
| 36 // fr-FR | |
| 37 "|societe|soci\xc3\xa9t\xc3\xa9" | |
| 38 // it-IT | |
| 39 "|ragione.?sociale" | |
| 40 // ja-JP | |
| 41 "|\xe4\xbc\x9a\xe7\xa4\xbe" | |
| 42 // ru | |
| 43 "|\xd0\xbd\xd0\xb0\xd0\xb7\xd0\xb2\xd0\xb0\xd0\xbd\xd0\xb8\xd0\xb5.?\xd0" | |
| 44 "\xba\xd0\xbe\xd0\xbc\xd0\xbf\xd0\xb0\xd0\xbd\xd0\xb8\xd0\xb8" | |
| 45 // zh-CN | |
| 46 "|\xe5\x8d\x95\xe4\xbd\x8d|\xe5\x85\xac\xe5\x8f\xb8" | |
| 47 // ko-KR | |
| 48 "|\xed\x9a\x8c\xec\x82\xac|\xec\xa7\x81\xec\x9e\xa5"; | |
| 49 const char kAddressLine1Re[] = | |
| 50 "address.*line|address1|addr1|street" | |
| 51 // de-DE | |
| 52 "|strasse|stra\xc3\x9f""e|hausnummer|housenumber" | |
| 53 // en-GB | |
| 54 "|house.?name" | |
| 55 // es | |
| 56 "|direccion|direcci\xc3\xb3n" | |
| 57 // fr-FR | |
| 58 "|adresse" | |
| 59 // it-IT | |
| 60 "|indirizzo" | |
| 61 // ja-JP | |
| 62 "|\xe4\xbd\x8f\xe6\x89\x80""1" | |
| 63 // pt-BR, pt-PT | |
| 64 "|morada|endere\xc3\xa7o" | |
| 65 // ru | |
| 66 "|\xd0\x90\xd0\xb4\xd1\x80\xd0\xb5\xd1\x81" | |
| 67 // zh-CN | |
| 68 "|\xe5\x9c\xb0\xe5\x9d\x80" | |
| 69 // ko-KR | |
| 70 "|\xec\xa3\xbc\xec\x86\x8c.?1"; | |
| 71 const char kAddressLine1LabelRe[] = | |
| 72 "address" | |
| 73 // fr-FR | |
| 74 "|adresse" | |
| 75 // it-IT | |
| 76 "|indirizzo" | |
| 77 // ja-JP | |
| 78 "|\xe4\xbd\x8f\xe6\x89\x80" | |
| 79 // zh-CN | |
| 80 "|\xe5\x9c\xb0\xe5\x9d\x80" | |
| 81 // ko-KR | |
| 82 "|\xec\xa3\xbc\xec\x86\x8c"; | |
| 83 const char kAddressLine2Re[] = | |
| 84 "address.*line2|address2|addr2|street|suite|unit" | |
| 85 // de-DE | |
| 86 "|adresszusatz|erg\xc3\xa4nzende.?angaben" | |
| 87 // es | |
| 88 "|direccion2|colonia|adicional" | |
| 89 // fr-FR | |
| 90 "|addresssuppl|complementnom|appartement" | |
| 91 // it-IT | |
| 92 "|indirizzo2" | |
| 93 // ja-JP | |
| 94 "|\xe4\xbd\x8f\xe6\x89\x80""2" | |
| 95 // pt-BR, pt-PT | |
| 96 "|complemento|addrcomplement" | |
| 97 // ru | |
| 98 "|\xd0\xa3\xd0\xbb\xd0\xb8\xd1\x86\xd0\xb0" | |
| 99 // zh-CN | |
| 100 "|\xe5\x9c\xb0\xe5\x9d\x80""2" | |
| 101 // ko-KR | |
| 102 "|\xec\xa3\xbc\xec\x86\x8c.?2"; | |
| 103 const char kAddressLine2LabelRe[] = | |
| 104 "address" | |
| 105 // fr-FR | |
| 106 "|adresse" | |
| 107 // it-IT | |
| 108 "|indirizzo" | |
| 109 // zh-CN | |
| 110 "|\xe5\x9c\xb0\xe5\x9d\x80" | |
| 111 // ko-KR | |
| 112 "|\xec\xa3\xbc\xec\x86\x8c"; | |
| 113 const char kAddressLine3Re[] = | |
| 114 "address.*line3|address3|addr3|street|line3" | |
| 115 // es | |
| 116 "|municipio" | |
| 117 // fr-FR | |
| 118 "|batiment|residence" | |
| 119 // it-IT | |
| 120 "|indirizzo3"; | |
| 121 const char kCountryRe[] = | |
| 122 "country|countries|location" | |
| 123 // es | |
| 124 "|pa\xc3\xads|pais" | |
| 125 // ja-JP | |
| 126 "|\xe5\x9b\xbd" | |
| 127 // zh-CN | |
| 128 "|\xe5\x9b\xbd\xe5\xae\xb6" | |
| 129 // ko-KR | |
| 130 "|\xea\xb5\xad\xea\xb0\x80|\xeb\x82\x98\xeb\x9d\xbc"; | |
| 131 const char kZipCodeRe[] = | |
| 132 "zip|postal|post.*code|pcode|^1z$" | |
| 133 // de-DE | |
| 134 "|postleitzahl" | |
| 135 // es | |
| 136 "|\\bcp\\b" | |
| 137 // fr-FR | |
| 138 "|\\bcdp\\b" | |
| 139 // it-IT | |
| 140 "|\\bcap\\b" | |
| 141 // ja-JP | |
| 142 "|\xe9\x83\xb5\xe4\xbe\xbf\xe7\x95\xaa\xe5\x8f\xb7" | |
| 143 // pt-BR, pt-PT | |
| 144 "|codigo|codpos|\\bcep\\b" | |
| 145 // ru | |
| 146 "|\xd0\x9f\xd0\xbe\xd1\x87\xd1\x82\xd0\xbe\xd0\xb2\xd1\x8b\xd0\xb9.?\xd0" | |
| 147 "\x98\xd0\xbd\xd0\xb4\xd0\xb5\xd0\xba\xd1\x81" | |
| 148 // zh-CN | |
| 149 "|\xe9\x82\xae\xe6\x94\xbf\xe7\xbc\x96\xe7\xa0\x81|\xe9\x82\xae\xe7\xbc" | |
| 150 "\x96" | |
| 151 // zh-TW | |
| 152 "|\xe9\x83\xb5\xe9\x81\x9e\xe5\x8d\x80\xe8\x99\x9f" | |
| 153 // ko-KR | |
| 154 "|\xec\x9a\xb0\xed\x8e\xb8.?\xeb\xb2\x88\xed\x98\xb8"; | |
| 155 const char kZip4Re[] = | |
| 156 "zip|^-$|post2" | |
| 157 // pt-BR, pt-PT | |
| 158 "|codpos2"; | |
| 159 const char kCityRe[] = | |
| 160 "city|town" | |
| 161 // de-DE | |
| 162 "|\\bort\\b|stadt" | |
| 163 // en-AU | |
| 164 "|suburb" | |
| 165 // es | |
| 166 "|ciudad|provincia|localidad|poblacion" | |
| 167 // fr-FR | |
| 168 "|ville|commune" | |
| 169 // it-IT | |
| 170 "|localita" | |
| 171 // ja-JP | |
| 172 "|\xe5\xb8\x82\xe5\x8c\xba\xe7\x94\xba\xe6\x9d\x91" | |
| 173 // pt-BR, pt-PT | |
| 174 "|cidade" | |
| 175 // ru | |
| 176 "|\xd0\x93\xd0\xbe\xd1\x80\xd0\xbe\xd0\xb4" | |
| 177 // zh-CN | |
| 178 "|\xe5\xb8\x82" | |
| 179 // zh-TW | |
| 180 "|\xe5\x88\x86\xe5\x8d\x80" | |
| 181 // ko-KR | |
| 182 "|^\xec\x8b\x9c[^\xeb\x8f\x84\xc2\xb7\xe3\x83\xbb]|\xec\x8b\x9c[\xc2\xb7" | |
| 183 "\xe3\x83\xbb]?\xea\xb5\xb0[\xc2\xb7\xe3\x83\xbb]?\xea\xb5\xac"; | |
| 184 const char kStateRe[] = | |
| 185 "(?<!united )state|county|region|province" | |
| 186 // de-DE | |
| 187 "|land" | |
| 188 // en-UK | |
| 189 "|county|principality" | |
| 190 // ja-JP | |
| 191 "|\xe9\x83\xbd\xe9\x81\x93\xe5\xba\x9c\xe7\x9c\x8c" | |
| 192 // pt-BR, pt-PT | |
| 193 "|estado|provincia" | |
| 194 // ru | |
| 195 "|\xd0\xbe\xd0\xb1\xd0\xbb\xd0\xb0\xd1\x81\xd1\x82\xd1\x8c" | |
| 196 // zh-CN | |
| 197 "|\xe7\x9c\x81" | |
| 198 // zh-TW | |
| 199 "|\xe5\x9c\xb0\xe5\x8d\x80" | |
| 200 // ko-KR | |
| 201 "|^\xec\x8b\x9c[\xc2\xb7\xe3\x83\xbb]?\xeb\x8f\x84"; | |
| 202 const char kAddressTypeSameAsRe[] = "same as"; | |
| 203 const char kAddressTypeUseMyRe[] = "use my"; | |
| 204 const char kBillingDesignatorRe[] = "bill"; | |
| 205 const char kShippingDesignatorRe[] = "ship"; | |
| 206 | |
| 207 } // namespace | |
| 208 | |
| 209 FormField* AddressField::Parse(AutofillScanner* scanner) { | 20 FormField* AddressField::Parse(AutofillScanner* scanner) { |
| 210 if (scanner->IsEnd()) | 21 if (scanner->IsEnd()) |
| 211 return NULL; | 22 return NULL; |
| 212 | 23 |
| 213 scoped_ptr<AddressField> address_field(new AddressField); | 24 scoped_ptr<AddressField> address_field(new AddressField); |
| 214 const AutofillField* const initial_field = scanner->Cursor(); | 25 const AutofillField* const initial_field = scanner->Cursor(); |
| 215 size_t saved_cursor = scanner->SaveCursor(); | 26 size_t saved_cursor = scanner->SaveCursor(); |
| 216 | 27 |
| 217 string16 attention_ignored = UTF8ToUTF16(kAttentionIgnoredRe); | 28 string16 attention_ignored = UTF8ToUTF16(autofill::kAttentionIgnoredRe); |
| 218 string16 region_ignored = UTF8ToUTF16(kRegionIgnoredRe); | 29 string16 region_ignored = UTF8ToUTF16(autofill::kRegionIgnoredRe); |
| 219 | 30 |
| 220 // Allow address fields to appear in any order. | 31 // Allow address fields to appear in any order. |
| 221 size_t begin_trailing_non_labeled_fields = 0; | 32 size_t begin_trailing_non_labeled_fields = 0; |
| 222 bool has_trailing_non_labeled_fields = false; | 33 bool has_trailing_non_labeled_fields = false; |
| 223 while (!scanner->IsEnd()) { | 34 while (!scanner->IsEnd()) { |
| 224 const size_t cursor = scanner->SaveCursor(); | 35 const size_t cursor = scanner->SaveCursor(); |
| 225 if (ParseAddressLines(scanner, address_field.get()) || | 36 if (ParseAddressLines(scanner, address_field.get()) || |
| 226 ParseCity(scanner, address_field.get()) || | 37 ParseCity(scanner, address_field.get()) || |
| 227 ParseState(scanner, address_field.get()) || | 38 ParseState(scanner, address_field.get()) || |
| 228 ParseZipCode(scanner, address_field.get()) || | 39 ParseZipCode(scanner, address_field.get()) || |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 ok = ok && AddClassification(country_, address_country, map); | 180 ok = ok && AddClassification(country_, address_country, map); |
| 370 return ok; | 181 return ok; |
| 371 } | 182 } |
| 372 | 183 |
| 373 // static | 184 // static |
| 374 bool AddressField::ParseCompany(AutofillScanner* scanner, | 185 bool AddressField::ParseCompany(AutofillScanner* scanner, |
| 375 AddressField* address_field) { | 186 AddressField* address_field) { |
| 376 if (address_field->company_ && !address_field->company_->IsEmpty()) | 187 if (address_field->company_ && !address_field->company_->IsEmpty()) |
| 377 return false; | 188 return false; |
| 378 | 189 |
| 379 return ParseField(scanner, UTF8ToUTF16(kCompanyRe), &address_field->company_); | 190 return ParseField(scanner, UTF8ToUTF16(autofill::kCompanyRe), |
| 191 &address_field->company_); |
| 380 } | 192 } |
| 381 | 193 |
| 382 // static | 194 // static |
| 383 bool AddressField::ParseAddressLines(AutofillScanner* scanner, | 195 bool AddressField::ParseAddressLines(AutofillScanner* scanner, |
| 384 AddressField* address_field) { | 196 AddressField* address_field) { |
| 385 // We only match the string "address" in page text, not in element names, | 197 // We only match the string "address" in page text, not in element names, |
| 386 // because sometimes every element in a group of address fields will have | 198 // because sometimes every element in a group of address fields will have |
| 387 // a name containing the string "address"; for example, on the page | 199 // a name containing the string "address"; for example, on the page |
| 388 // Kohl's - Register Billing Address.html the text element labeled "city" | 200 // Kohl's - Register Billing Address.html the text element labeled "city" |
| 389 // has the name "BILL_TO_ADDRESS<>city". We do match address labels | 201 // has the name "BILL_TO_ADDRESS<>city". We do match address labels |
| 390 // such as "address1", which appear as element names on various pages (eg | 202 // such as "address1", which appear as element names on various pages (eg |
| 391 // AmericanGirl-Registration.html, BloomingdalesBilling.html, | 203 // AmericanGirl-Registration.html, BloomingdalesBilling.html, |
| 392 // EBay Registration Enter Information.html). | 204 // EBay Registration Enter Information.html). |
| 393 if (address_field->address1_) | 205 if (address_field->address1_) |
| 394 return false; | 206 return false; |
| 395 | 207 |
| 396 string16 pattern = UTF8ToUTF16(kAddressLine1Re); | 208 string16 pattern = UTF8ToUTF16(autofill::kAddressLine1Re); |
| 397 string16 label_pattern = UTF8ToUTF16(kAddressLine1LabelRe); | 209 string16 label_pattern = UTF8ToUTF16(autofill::kAddressLine1LabelRe); |
| 398 | 210 |
| 399 if (!ParseField(scanner, pattern, &address_field->address1_) && | 211 if (!ParseField(scanner, pattern, &address_field->address1_) && |
| 400 !ParseFieldSpecifics(scanner, label_pattern, MATCH_LABEL | MATCH_TEXT, | 212 !ParseFieldSpecifics(scanner, label_pattern, MATCH_LABEL | MATCH_TEXT, |
| 401 &address_field->address1_)) { | 213 &address_field->address1_)) { |
| 402 return false; | 214 return false; |
| 403 } | 215 } |
| 404 | 216 |
| 405 // Optionally parse more address lines, which may have empty labels. | 217 // Optionally parse more address lines, which may have empty labels. |
| 406 // Some pages have 3 address lines (eg SharperImageModifyAccount.html) | 218 // Some pages have 3 address lines (eg SharperImageModifyAccount.html) |
| 407 // Some pages even have 4 address lines (e.g. uk/ShoesDirect2.html)! | 219 // Some pages even have 4 address lines (e.g. uk/ShoesDirect2.html)! |
| 408 pattern = UTF8ToUTF16(kAddressLine2Re); | 220 pattern = UTF8ToUTF16(autofill::kAddressLine2Re); |
| 409 label_pattern = UTF8ToUTF16(kAddressLine2LabelRe); | 221 label_pattern = UTF8ToUTF16(autofill::kAddressLine2LabelRe); |
| 410 if (!ParseEmptyLabel(scanner, &address_field->address2_) && | 222 if (!ParseEmptyLabel(scanner, &address_field->address2_) && |
| 411 !ParseField(scanner, pattern, &address_field->address2_)) { | 223 !ParseField(scanner, pattern, &address_field->address2_)) { |
| 412 ParseFieldSpecifics(scanner, label_pattern, MATCH_LABEL | MATCH_TEXT, | 224 ParseFieldSpecifics(scanner, label_pattern, MATCH_LABEL | MATCH_TEXT, |
| 413 &address_field->address2_); | 225 &address_field->address2_); |
| 414 } | 226 } |
| 415 | 227 |
| 416 // Try for a third line, which we will promptly discard. | 228 // Try for a third line, which we will promptly discard. |
| 417 if (address_field->address2_ != NULL) { | 229 if (address_field->address2_ != NULL) { |
| 418 pattern = UTF8ToUTF16(kAddressLine3Re); | 230 pattern = UTF8ToUTF16(autofill::kAddressLine3Re); |
| 419 ParseField(scanner, pattern, NULL); | 231 ParseField(scanner, pattern, NULL); |
| 420 } | 232 } |
| 421 | 233 |
| 422 return true; | 234 return true; |
| 423 } | 235 } |
| 424 | 236 |
| 425 // static | 237 // static |
| 426 bool AddressField::ParseCountry(AutofillScanner* scanner, | 238 bool AddressField::ParseCountry(AutofillScanner* scanner, |
| 427 AddressField* address_field) { | 239 AddressField* address_field) { |
| 428 // Parse a country. The occasional page (e.g. | 240 // Parse a country. The occasional page (e.g. |
| 429 // Travelocity_New Member Information1.html) calls this a "location". | 241 // Travelocity_New Member Information1.html) calls this a "location". |
| 430 if (address_field->country_ && !address_field->country_->IsEmpty()) | 242 if (address_field->country_ && !address_field->country_->IsEmpty()) |
| 431 return false; | 243 return false; |
| 432 | 244 |
| 433 return ParseFieldSpecifics(scanner, | 245 return ParseFieldSpecifics(scanner, |
| 434 UTF8ToUTF16(kCountryRe), | 246 UTF8ToUTF16(autofill::kCountryRe), |
| 435 MATCH_DEFAULT | MATCH_SELECT, | 247 MATCH_DEFAULT | MATCH_SELECT, |
| 436 &address_field->country_); | 248 &address_field->country_); |
| 437 } | 249 } |
| 438 | 250 |
| 439 // static | 251 // static |
| 440 bool AddressField::ParseZipCode(AutofillScanner* scanner, | 252 bool AddressField::ParseZipCode(AutofillScanner* scanner, |
| 441 AddressField* address_field) { | 253 AddressField* address_field) { |
| 442 // Parse a zip code. On some UK pages (e.g. The China Shop2.html) this | 254 // Parse a zip code. On some UK pages (e.g. The China Shop2.html) this |
| 443 // is called a "post code". | 255 // is called a "post code". |
| 444 // | 256 // |
| 445 // HACK: Just for the MapQuest driving directions page we match the | 257 // HACK: Just for the MapQuest driving directions page we match the |
| 446 // exact name "1z", which MapQuest uses to label its zip code field. | 258 // exact name "1z", which MapQuest uses to label its zip code field. |
| 447 // Hopefully before long we'll be smart enough to find the zip code | 259 // Hopefully before long we'll be smart enough to find the zip code |
| 448 // on that page automatically. | 260 // on that page automatically. |
| 449 if (address_field->zip_) | 261 if (address_field->zip_) |
| 450 return false; | 262 return false; |
| 451 | 263 |
| 452 string16 pattern = UTF8ToUTF16(kZipCodeRe); | 264 string16 pattern = UTF8ToUTF16(autofill::kZipCodeRe); |
| 453 if (!ParseField(scanner, pattern, &address_field->zip_)) | 265 if (!ParseField(scanner, pattern, &address_field->zip_)) |
| 454 return false; | 266 return false; |
| 455 | 267 |
| 456 address_field->type_ = kGenericAddress; | 268 address_field->type_ = kGenericAddress; |
| 457 // Look for a zip+4, whose field name will also often contain | 269 // Look for a zip+4, whose field name will also often contain |
| 458 // the substring "zip". | 270 // the substring "zip". |
| 459 ParseField(scanner, | 271 ParseField(scanner, |
| 460 UTF8ToUTF16(kZip4Re), | 272 UTF8ToUTF16(autofill::kZip4Re), |
| 461 &address_field->zip4_); | 273 &address_field->zip4_); |
| 462 | 274 |
| 463 return true; | 275 return true; |
| 464 } | 276 } |
| 465 | 277 |
| 466 // static | 278 // static |
| 467 bool AddressField::ParseCity(AutofillScanner* scanner, | 279 bool AddressField::ParseCity(AutofillScanner* scanner, |
| 468 AddressField* address_field) { | 280 AddressField* address_field) { |
| 469 // Parse a city name. Some UK pages (e.g. The China Shop2.html) use | 281 // Parse a city name. Some UK pages (e.g. The China Shop2.html) use |
| 470 // the term "town". | 282 // the term "town". |
| 471 if (address_field->city_) | 283 if (address_field->city_) |
| 472 return false; | 284 return false; |
| 473 | 285 |
| 474 // Select fields are allowed here. This occurs on top-100 site rediff.com. | 286 // Select fields are allowed here. This occurs on top-100 site rediff.com. |
| 475 return ParseFieldSpecifics(scanner, | 287 return ParseFieldSpecifics(scanner, |
| 476 UTF8ToUTF16(kCityRe), | 288 UTF8ToUTF16(autofill::kCityRe), |
| 477 MATCH_DEFAULT | MATCH_SELECT, | 289 MATCH_DEFAULT | MATCH_SELECT, |
| 478 &address_field->city_); | 290 &address_field->city_); |
| 479 } | 291 } |
| 480 | 292 |
| 481 // static | 293 // static |
| 482 bool AddressField::ParseState(AutofillScanner* scanner, | 294 bool AddressField::ParseState(AutofillScanner* scanner, |
| 483 AddressField* address_field) { | 295 AddressField* address_field) { |
| 484 if (address_field->state_) | 296 if (address_field->state_) |
| 485 return false; | 297 return false; |
| 486 | 298 |
| 487 return ParseFieldSpecifics(scanner, | 299 return ParseFieldSpecifics(scanner, |
| 488 UTF8ToUTF16(kStateRe), | 300 UTF8ToUTF16(autofill::kStateRe), |
| 489 MATCH_DEFAULT | MATCH_SELECT, | 301 MATCH_DEFAULT | MATCH_SELECT, |
| 490 &address_field->state_); | 302 &address_field->state_); |
| 491 } | 303 } |
| 492 | 304 |
| 493 AddressField::AddressType AddressField::AddressTypeFromText( | 305 AddressField::AddressType AddressField::AddressTypeFromText( |
| 494 const string16 &text) { | 306 const string16 &text) { |
| 495 if (text.find(UTF8ToUTF16(kAddressTypeSameAsRe)) != string16::npos || | 307 size_t same_as = text.find(UTF8ToUTF16(autofill::kAddressTypeSameAsRe)); |
| 496 text.find(UTF8ToUTF16(kAddressTypeUseMyRe)) != string16::npos) | 308 size_t use_shipping = text.find(UTF8ToUTF16(autofill::kAddressTypeUseMyRe)); |
| 309 if (same_as != string16::npos || use_shipping != string16::npos) |
| 497 // This text could be a checkbox label such as "same as my billing | 310 // This text could be a checkbox label such as "same as my billing |
| 498 // address" or "use my shipping address". | 311 // address" or "use my shipping address". |
| 499 // ++ It would help if we generally skipped all text that appears | 312 // ++ It would help if we generally skipped all text that appears |
| 500 // after a check box. | 313 // after a check box. |
| 501 return kGenericAddress; | 314 return kGenericAddress; |
| 502 | 315 |
| 503 // Not all pages say "billing address" and "shipping address" explicitly; | 316 // Not all pages say "billing address" and "shipping address" explicitly; |
| 504 // for example, Craft Catalog1.html has "Bill-to Address" and | 317 // for example, Craft Catalog1.html has "Bill-to Address" and |
| 505 // "Ship-to Address". | 318 // "Ship-to Address". |
| 506 size_t bill = text.rfind(UTF8ToUTF16(kBillingDesignatorRe)); | 319 size_t bill = text.rfind(UTF8ToUTF16(autofill::kBillingDesignatorRe)); |
| 507 size_t ship = text.rfind(UTF8ToUTF16(kShippingDesignatorRe)); | 320 size_t ship = text.rfind(UTF8ToUTF16(autofill::kShippingDesignatorRe)); |
| 508 | 321 |
| 509 if (bill == string16::npos && ship == string16::npos) | 322 if (bill == string16::npos && ship == string16::npos) |
| 510 return kGenericAddress; | 323 return kGenericAddress; |
| 511 | 324 |
| 512 if (bill != string16::npos && ship == string16::npos) | 325 if (bill != string16::npos && ship == string16::npos) |
| 513 return kBillingAddress; | 326 return kBillingAddress; |
| 514 | 327 |
| 515 if (bill == string16::npos && ship != string16::npos) | 328 if (bill == string16::npos && ship != string16::npos) |
| 516 return kShippingAddress; | 329 return kShippingAddress; |
| 517 | 330 |
| 518 if (bill > ship) | 331 if (bill > ship) |
| 519 return kBillingAddress; | 332 return kBillingAddress; |
| 520 | 333 |
| 521 return kShippingAddress; | 334 return kShippingAddress; |
| 522 } | 335 } |
| OLD | NEW |