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 |