| 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 "components/autofill/browser/address_field.h" | 5 #include "components/autofill/browser/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 "components/autofill/browser/autofill_field.h" | 14 #include "components/autofill/browser/autofill_field.h" |
| 15 #include "components/autofill/browser/autofill_regex_constants.h" | 15 #include "components/autofill/browser/autofill_regex_constants.h" |
| 16 #include "components/autofill/browser/autofill_scanner.h" | 16 #include "components/autofill/browser/autofill_scanner.h" |
| 17 #include "components/autofill/browser/field_types.h" | 17 #include "components/autofill/browser/field_types.h" |
| 18 #include "ui/base/l10n/l10n_util.h" | 18 #include "ui/base/l10n/l10n_util.h" |
| 19 | 19 |
| 20 FormField* AddressField::Parse(AutofillScanner* scanner) { | 20 FormField* AddressField::Parse(AutofillScanner* scanner) { |
| 21 if (scanner->IsEnd()) | 21 if (scanner->IsEnd()) |
| 22 return NULL; | 22 return NULL; |
| 23 | 23 |
| 24 scoped_ptr<AddressField> address_field(new AddressField); | 24 scoped_ptr<AddressField> address_field(new AddressField); |
| 25 const AutofillField* const initial_field = scanner->Cursor(); | 25 const AutofillField* const initial_field = scanner->Cursor(); |
| 26 size_t saved_cursor = scanner->SaveCursor(); | 26 size_t saved_cursor = scanner->SaveCursor(); |
| 27 | 27 |
| 28 string16 attention_ignored = UTF8ToUTF16(autofill::kAttentionIgnoredRe); | 28 base::string16 attention_ignored = UTF8ToUTF16(autofill::kAttentionIgnoredRe); |
| 29 string16 region_ignored = UTF8ToUTF16(autofill::kRegionIgnoredRe); | 29 base::string16 region_ignored = UTF8ToUTF16(autofill::kRegionIgnoredRe); |
| 30 | 30 |
| 31 // Allow address fields to appear in any order. | 31 // Allow address fields to appear in any order. |
| 32 size_t begin_trailing_non_labeled_fields = 0; | 32 size_t begin_trailing_non_labeled_fields = 0; |
| 33 bool has_trailing_non_labeled_fields = false; | 33 bool has_trailing_non_labeled_fields = false; |
| 34 while (!scanner->IsEnd()) { | 34 while (!scanner->IsEnd()) { |
| 35 const size_t cursor = scanner->SaveCursor(); | 35 const size_t cursor = scanner->SaveCursor(); |
| 36 if (ParseAddressLines(scanner, address_field.get()) || | 36 if (ParseAddressLines(scanner, address_field.get()) || |
| 37 ParseCity(scanner, address_field.get()) || | 37 ParseCity(scanner, address_field.get()) || |
| 38 ParseState(scanner, address_field.get()) || | 38 ParseState(scanner, address_field.get()) || |
| 39 ParseZipCode(scanner, address_field.get()) || | 39 ParseZipCode(scanner, address_field.get()) || |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 } | 84 } |
| 85 | 85 |
| 86 scanner->RewindTo(saved_cursor); | 86 scanner->RewindTo(saved_cursor); |
| 87 return NULL; | 87 return NULL; |
| 88 } | 88 } |
| 89 | 89 |
| 90 AddressField::AddressType AddressField::FindType() const { | 90 AddressField::AddressType AddressField::FindType() const { |
| 91 // First look at the field name, which itself will sometimes contain | 91 // First look at the field name, which itself will sometimes contain |
| 92 // "bill" or "ship". | 92 // "bill" or "ship". |
| 93 if (company_) { | 93 if (company_) { |
| 94 string16 name = StringToLowerASCII(company_->name); | 94 base::string16 name = StringToLowerASCII(company_->name); |
| 95 return AddressTypeFromText(name); | 95 return AddressTypeFromText(name); |
| 96 } | 96 } |
| 97 if (address1_) { | 97 if (address1_) { |
| 98 string16 name = StringToLowerASCII(address1_->name); | 98 base::string16 name = StringToLowerASCII(address1_->name); |
| 99 return AddressTypeFromText(name); | 99 return AddressTypeFromText(name); |
| 100 } | 100 } |
| 101 if (address2_) { | 101 if (address2_) { |
| 102 string16 name = StringToLowerASCII(address2_->name); | 102 base::string16 name = StringToLowerASCII(address2_->name); |
| 103 return AddressTypeFromText(name); | 103 return AddressTypeFromText(name); |
| 104 } | 104 } |
| 105 if (city_) { | 105 if (city_) { |
| 106 string16 name = StringToLowerASCII(city_->name); | 106 base::string16 name = StringToLowerASCII(city_->name); |
| 107 return AddressTypeFromText(name); | 107 return AddressTypeFromText(name); |
| 108 } | 108 } |
| 109 if (zip_) { | 109 if (zip_) { |
| 110 string16 name = StringToLowerASCII(zip_->name); | 110 base::string16 name = StringToLowerASCII(zip_->name); |
| 111 return AddressTypeFromText(name); | 111 return AddressTypeFromText(name); |
| 112 } | 112 } |
| 113 if (state_) { | 113 if (state_) { |
| 114 string16 name = StringToLowerASCII(state_->name); | 114 base::string16 name = StringToLowerASCII(state_->name); |
| 115 return AddressTypeFromText(name); | 115 return AddressTypeFromText(name); |
| 116 } | 116 } |
| 117 if (country_) { | 117 if (country_) { |
| 118 string16 name = StringToLowerASCII(country_->name); | 118 base::string16 name = StringToLowerASCII(country_->name); |
| 119 return AddressTypeFromText(name); | 119 return AddressTypeFromText(name); |
| 120 } | 120 } |
| 121 | 121 |
| 122 return kGenericAddress; | 122 return kGenericAddress; |
| 123 } | 123 } |
| 124 | 124 |
| 125 AddressField::AddressField() | 125 AddressField::AddressField() |
| 126 : company_(NULL), | 126 : company_(NULL), |
| 127 address1_(NULL), | 127 address1_(NULL), |
| 128 address2_(NULL), | 128 address2_(NULL), |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 // 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 |
| 199 // a name containing the string "address"; for example, on the page | 199 // a name containing the string "address"; for example, on the page |
| 200 // Kohl's - Register Billing Address.html the text element labeled "city" | 200 // Kohl's - Register Billing Address.html the text element labeled "city" |
| 201 // 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 |
| 202 // 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 |
| 203 // AmericanGirl-Registration.html, BloomingdalesBilling.html, | 203 // AmericanGirl-Registration.html, BloomingdalesBilling.html, |
| 204 // EBay Registration Enter Information.html). | 204 // EBay Registration Enter Information.html). |
| 205 if (address_field->address1_) | 205 if (address_field->address1_) |
| 206 return false; | 206 return false; |
| 207 | 207 |
| 208 string16 pattern = UTF8ToUTF16(autofill::kAddressLine1Re); | 208 base::string16 pattern = UTF8ToUTF16(autofill::kAddressLine1Re); |
| 209 string16 label_pattern = UTF8ToUTF16(autofill::kAddressLine1LabelRe); | 209 base::string16 label_pattern = UTF8ToUTF16(autofill::kAddressLine1LabelRe); |
| 210 | 210 |
| 211 if (!ParseField(scanner, pattern, &address_field->address1_) && | 211 if (!ParseField(scanner, pattern, &address_field->address1_) && |
| 212 !ParseFieldSpecifics(scanner, label_pattern, MATCH_LABEL | MATCH_TEXT, | 212 !ParseFieldSpecifics(scanner, label_pattern, MATCH_LABEL | MATCH_TEXT, |
| 213 &address_field->address1_)) { | 213 &address_field->address1_)) { |
| 214 return false; | 214 return false; |
| 215 } | 215 } |
| 216 | 216 |
| 217 // Optionally parse more address lines, which may have empty labels. | 217 // Optionally parse more address lines, which may have empty labels. |
| 218 // Some pages have 3 address lines (eg SharperImageModifyAccount.html) | 218 // Some pages have 3 address lines (eg SharperImageModifyAccount.html) |
| 219 // 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)! |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 // 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 |
| 255 // is called a "post code". | 255 // is called a "post code". |
| 256 // | 256 // |
| 257 // HACK: Just for the MapQuest driving directions page we match the | 257 // HACK: Just for the MapQuest driving directions page we match the |
| 258 // 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. |
| 259 // 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 |
| 260 // on that page automatically. | 260 // on that page automatically. |
| 261 if (address_field->zip_) | 261 if (address_field->zip_) |
| 262 return false; | 262 return false; |
| 263 | 263 |
| 264 string16 pattern = UTF8ToUTF16(autofill::kZipCodeRe); | 264 base::string16 pattern = UTF8ToUTF16(autofill::kZipCodeRe); |
| 265 if (!ParseField(scanner, pattern, &address_field->zip_)) | 265 if (!ParseField(scanner, pattern, &address_field->zip_)) |
| 266 return false; | 266 return false; |
| 267 | 267 |
| 268 address_field->type_ = kGenericAddress; | 268 address_field->type_ = kGenericAddress; |
| 269 // 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 |
| 270 // the substring "zip". | 270 // the substring "zip". |
| 271 ParseField(scanner, | 271 ParseField(scanner, |
| 272 UTF8ToUTF16(autofill::kZip4Re), | 272 UTF8ToUTF16(autofill::kZip4Re), |
| 273 &address_field->zip4_); | 273 &address_field->zip4_); |
| 274 | 274 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 296 if (address_field->state_) | 296 if (address_field->state_) |
| 297 return false; | 297 return false; |
| 298 | 298 |
| 299 return ParseFieldSpecifics(scanner, | 299 return ParseFieldSpecifics(scanner, |
| 300 UTF8ToUTF16(autofill::kStateRe), | 300 UTF8ToUTF16(autofill::kStateRe), |
| 301 MATCH_DEFAULT | MATCH_SELECT, | 301 MATCH_DEFAULT | MATCH_SELECT, |
| 302 &address_field->state_); | 302 &address_field->state_); |
| 303 } | 303 } |
| 304 | 304 |
| 305 AddressField::AddressType AddressField::AddressTypeFromText( | 305 AddressField::AddressType AddressField::AddressTypeFromText( |
| 306 const string16 &text) { | 306 const base::string16 &text) { |
| 307 size_t same_as = text.find(UTF8ToUTF16(autofill::kAddressTypeSameAsRe)); | 307 size_t same_as = text.find(UTF8ToUTF16(autofill::kAddressTypeSameAsRe)); |
| 308 size_t use_shipping = text.find(UTF8ToUTF16(autofill::kAddressTypeUseMyRe)); | 308 size_t use_shipping = text.find(UTF8ToUTF16(autofill::kAddressTypeUseMyRe)); |
| 309 if (same_as != string16::npos || use_shipping != string16::npos) | 309 if (same_as != base::string16::npos || use_shipping != base::string16::npos) |
| 310 // 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 |
| 311 // address" or "use my shipping address". | 311 // address" or "use my shipping address". |
| 312 // ++ It would help if we generally skipped all text that appears | 312 // ++ It would help if we generally skipped all text that appears |
| 313 // after a check box. | 313 // after a check box. |
| 314 return kGenericAddress; | 314 return kGenericAddress; |
| 315 | 315 |
| 316 // Not all pages say "billing address" and "shipping address" explicitly; | 316 // Not all pages say "billing address" and "shipping address" explicitly; |
| 317 // for example, Craft Catalog1.html has "Bill-to Address" and | 317 // for example, Craft Catalog1.html has "Bill-to Address" and |
| 318 // "Ship-to Address". | 318 // "Ship-to Address". |
| 319 size_t bill = text.rfind(UTF8ToUTF16(autofill::kBillingDesignatorRe)); | 319 size_t bill = text.rfind(UTF8ToUTF16(autofill::kBillingDesignatorRe)); |
| 320 size_t ship = text.rfind(UTF8ToUTF16(autofill::kShippingDesignatorRe)); | 320 size_t ship = text.rfind(UTF8ToUTF16(autofill::kShippingDesignatorRe)); |
| 321 | 321 |
| 322 if (bill == string16::npos && ship == string16::npos) | 322 if (bill == base::string16::npos && ship == base::string16::npos) |
| 323 return kGenericAddress; | 323 return kGenericAddress; |
| 324 | 324 |
| 325 if (bill != string16::npos && ship == string16::npos) | 325 if (bill != base::string16::npos && ship == base::string16::npos) |
| 326 return kBillingAddress; | 326 return kBillingAddress; |
| 327 | 327 |
| 328 if (bill == string16::npos && ship != string16::npos) | 328 if (bill == base::string16::npos && ship != base::string16::npos) |
| 329 return kShippingAddress; | 329 return kShippingAddress; |
| 330 | 330 |
| 331 if (bill > ship) | 331 if (bill > ship) |
| 332 return kBillingAddress; | 332 return kBillingAddress; |
| 333 | 333 |
| 334 return kShippingAddress; | 334 return kShippingAddress; |
| 335 } | 335 } |
| OLD | NEW |