| 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/core/browser/phone_field.h" | 5 #include "components/autofill/core/browser/phone_field.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/strings/string16.h" | 9 #include "base/strings/string16.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| 11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
| 12 #include "components/autofill/core/browser/autofill_field.h" | 12 #include "components/autofill/core/browser/autofill_field.h" |
| 13 #include "components/autofill/core/browser/autofill_regex_constants.h" | 13 #include "components/autofill/core/browser/autofill_regex_constants.h" |
| 14 #include "components/autofill/core/browser/autofill_scanner.h" | 14 #include "components/autofill/core/browser/autofill_scanner.h" |
| 15 | 15 |
| 16 namespace autofill { | 16 namespace autofill { |
| 17 namespace { | 17 namespace { |
| 18 | 18 |
| 19 // This string includes all area code separators, including NoText. | 19 // This string includes all area code separators, including NoText. |
| 20 base::string16 GetAreaRegex() { | 20 std::string GetAreaRegex() { |
| 21 base::string16 area_code = base::UTF8ToUTF16(kAreaCodeRe); | 21 std::string area_code = kAreaCodeRe; |
| 22 area_code.append(base::ASCIIToUTF16("|")); // Regexp separator. | 22 area_code.append("|"); // Regexp separator. |
| 23 area_code.append(base::UTF8ToUTF16(kAreaCodeNotextRe)); | 23 area_code.append(kAreaCodeNotextRe); |
| 24 return area_code; | 24 return area_code; |
| 25 } | 25 } |
| 26 | 26 |
| 27 } // namespace | 27 } // namespace |
| 28 | 28 |
| 29 PhoneField::~PhoneField() {} | 29 PhoneField::~PhoneField() {} |
| 30 | 30 |
| 31 // Phone field grammars - first matched grammar will be parsed. Grammars are | 31 // Phone field grammars - first matched grammar will be parsed. Grammars are |
| 32 // separated by { REGEX_SEPARATOR, FIELD_NONE, 0 }. Suffix and extension are | 32 // separated by { REGEX_SEPARATOR, FIELD_NONE, 0 }. Suffix and extension are |
| 33 // parsed separately unless they are necessary parts of the match. | 33 // parsed separately unless they are necessary parts of the match. |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 { REGEX_PHONE, FIELD_PHONE, 10 }, | 112 { REGEX_PHONE, FIELD_PHONE, 10 }, |
| 113 { REGEX_SEPARATOR, FIELD_NONE, 0 }, | 113 { REGEX_SEPARATOR, FIELD_NONE, 0 }, |
| 114 // Phone: <phone> (Ext: <ext>)? | 114 // Phone: <phone> (Ext: <ext>)? |
| 115 { REGEX_PHONE, FIELD_PHONE, 0 }, | 115 { REGEX_PHONE, FIELD_PHONE, 0 }, |
| 116 { REGEX_SEPARATOR, FIELD_NONE, 0 }, | 116 { REGEX_SEPARATOR, FIELD_NONE, 0 }, |
| 117 }; | 117 }; |
| 118 | 118 |
| 119 // static | 119 // static |
| 120 scoped_ptr<FormField> PhoneField::Parse(AutofillScanner* scanner) { | 120 scoped_ptr<FormField> PhoneField::Parse(AutofillScanner* scanner) { |
| 121 if (scanner->IsEnd()) | 121 if (scanner->IsEnd()) |
| 122 return NULL; | 122 return nullptr; |
| 123 | 123 |
| 124 scanner->SaveCursor(); | 124 size_t start_cursor = scanner->SaveCursor(); |
| 125 | 125 |
| 126 // The form owns the following variables, so they should not be deleted. | 126 // The form owns the following variables, so they should not be deleted. |
| 127 AutofillField* parsed_fields[FIELD_MAX]; | 127 AutofillField* parsed_fields[FIELD_MAX]; |
| 128 | 128 |
| 129 for (size_t i = 0; i < arraysize(kPhoneFieldGrammars); ++i) { | 129 for (size_t i = 0; i < arraysize(kPhoneFieldGrammars); ++i) { |
| 130 memset(parsed_fields, 0, sizeof(parsed_fields)); | 130 memset(parsed_fields, 0, sizeof(parsed_fields)); |
| 131 scanner->SaveCursor(); | 131 size_t saved_cursor = scanner->SaveCursor(); |
| 132 | 132 |
| 133 // Attempt to parse according to the next grammar. | 133 // Attempt to parse according to the next grammar. |
| 134 for (; i < arraysize(kPhoneFieldGrammars) && | 134 for (; i < arraysize(kPhoneFieldGrammars) && |
| 135 kPhoneFieldGrammars[i].regex != REGEX_SEPARATOR; ++i) { | 135 kPhoneFieldGrammars[i].regex != REGEX_SEPARATOR; ++i) { |
| 136 if (!ParseFieldSpecifics( | 136 if (!ParsePhoneField( |
| 137 scanner, | 137 scanner, |
| 138 GetRegExp(kPhoneFieldGrammars[i].regex), | 138 GetRegExp(kPhoneFieldGrammars[i].regex), |
| 139 MATCH_DEFAULT | MATCH_TELEPHONE, | |
| 140 &parsed_fields[kPhoneFieldGrammars[i].phone_part])) | 139 &parsed_fields[kPhoneFieldGrammars[i].phone_part])) |
| 141 break; | 140 break; |
| 142 if (kPhoneFieldGrammars[i].max_size && | 141 if (kPhoneFieldGrammars[i].max_size && |
| 143 (!parsed_fields[kPhoneFieldGrammars[i].phone_part]->max_length || | 142 (!parsed_fields[kPhoneFieldGrammars[i].phone_part]->max_length || |
| 144 kPhoneFieldGrammars[i].max_size < | 143 kPhoneFieldGrammars[i].max_size < |
| 145 parsed_fields[kPhoneFieldGrammars[i].phone_part]->max_length)) { | 144 parsed_fields[kPhoneFieldGrammars[i].phone_part]->max_length)) { |
| 146 break; | 145 break; |
| 147 } | 146 } |
| 148 } | 147 } |
| 149 | 148 |
| 150 if (i >= arraysize(kPhoneFieldGrammars)) { | 149 if (i >= arraysize(kPhoneFieldGrammars)) { |
| 151 scanner->Rewind(); | 150 scanner->RewindTo(saved_cursor); |
| 152 return NULL; // Parsing failed. | 151 return nullptr; // Parsing failed. |
| 153 } | 152 } |
| 154 if (kPhoneFieldGrammars[i].regex == REGEX_SEPARATOR) | 153 if (kPhoneFieldGrammars[i].regex == REGEX_SEPARATOR) |
| 155 break; // Parsing succeeded. | 154 break; // Parsing succeeded. |
| 156 | 155 |
| 157 // Proceed to the next grammar. | 156 // Proceed to the next grammar. |
| 158 do { | 157 do { |
| 159 ++i; | 158 ++i; |
| 160 } while (i < arraysize(kPhoneFieldGrammars) && | 159 } while (i < arraysize(kPhoneFieldGrammars) && |
| 161 kPhoneFieldGrammars[i].regex != REGEX_SEPARATOR); | 160 kPhoneFieldGrammars[i].regex != REGEX_SEPARATOR); |
| 162 | 161 |
| 162 scanner->RewindTo(saved_cursor); |
| 163 if (i + 1 == arraysize(kPhoneFieldGrammars)) { | 163 if (i + 1 == arraysize(kPhoneFieldGrammars)) { |
| 164 scanner->Rewind(); | 164 return nullptr; // Tried through all the possibilities - did not match. |
| 165 return NULL; // Tried through all the possibilities - did not match. | |
| 166 } | 165 } |
| 167 | |
| 168 scanner->Rewind(); | |
| 169 } | 166 } |
| 170 | 167 |
| 171 if (!parsed_fields[FIELD_PHONE]) { | 168 if (!parsed_fields[FIELD_PHONE]) { |
| 172 scanner->Rewind(); | 169 scanner->RewindTo(start_cursor); |
| 173 return NULL; | 170 return nullptr; |
| 174 } | 171 } |
| 175 | 172 |
| 176 scoped_ptr<PhoneField> phone_field(new PhoneField); | 173 scoped_ptr<PhoneField> phone_field(new PhoneField); |
| 177 for (int i = 0; i < FIELD_MAX; ++i) | 174 for (int i = 0; i < FIELD_MAX; ++i) |
| 178 phone_field->parsed_phone_fields_[i] = parsed_fields[i]; | 175 phone_field->parsed_phone_fields_[i] = parsed_fields[i]; |
| 179 | 176 |
| 180 // Look for optional fields. | 177 // Look for optional fields. |
| 181 | 178 |
| 182 // Look for a third text box. | 179 // Look for a third text box. |
| 183 if (!phone_field->parsed_phone_fields_[FIELD_SUFFIX]) { | 180 if (!phone_field->parsed_phone_fields_[FIELD_SUFFIX]) { |
| 184 if (!ParseField(scanner, base::UTF8ToUTF16(kPhoneSuffixRe), | 181 if (!ParsePhoneField(scanner, kPhoneSuffixRe, |
| 185 &phone_field->parsed_phone_fields_[FIELD_SUFFIX])) { | 182 &phone_field->parsed_phone_fields_[FIELD_SUFFIX])) { |
| 186 ParseField(scanner, base::UTF8ToUTF16(kPhoneSuffixSeparatorRe), | 183 ParsePhoneField(scanner, kPhoneSuffixSeparatorRe, |
| 187 &phone_field->parsed_phone_fields_[FIELD_SUFFIX]); | 184 &phone_field->parsed_phone_fields_[FIELD_SUFFIX]); |
| 188 } | 185 } |
| 189 } | 186 } |
| 190 | 187 |
| 191 // Now look for an extension. | 188 // Now look for an extension. |
| 192 ParseField(scanner, base::UTF8ToUTF16(kPhoneExtensionRe), | 189 // The extension is not actually used, so this just eats the field so other |
| 193 &phone_field->parsed_phone_fields_[FIELD_EXTENSION]); | 190 // parsers do not mistaken it for something else. |
| 191 ParsePhoneField(scanner, |
| 192 kPhoneExtensionRe, |
| 193 &phone_field->parsed_phone_fields_[FIELD_EXTENSION]); |
| 194 | 194 |
| 195 return phone_field.Pass(); | 195 return phone_field.Pass(); |
| 196 } | 196 } |
| 197 | 197 |
| 198 bool PhoneField::ClassifyField(ServerFieldTypeMap* map) const { | 198 bool PhoneField::ClassifyField(ServerFieldTypeMap* map) const { |
| 199 bool ok = true; | 199 bool ok = true; |
| 200 | 200 |
| 201 DCHECK(parsed_phone_fields_[FIELD_PHONE]); // Phone was correctly parsed. | 201 DCHECK(parsed_phone_fields_[FIELD_PHONE]); // Phone was correctly parsed. |
| 202 | 202 |
| 203 if ((parsed_phone_fields_[FIELD_COUNTRY_CODE] != NULL) || | 203 if ((parsed_phone_fields_[FIELD_COUNTRY_CODE]) || |
| 204 (parsed_phone_fields_[FIELD_AREA_CODE] != NULL) || | 204 (parsed_phone_fields_[FIELD_AREA_CODE]) || |
| 205 (parsed_phone_fields_[FIELD_SUFFIX] != NULL)) { | 205 (parsed_phone_fields_[FIELD_SUFFIX])) { |
| 206 if (parsed_phone_fields_[FIELD_COUNTRY_CODE] != NULL) { | 206 if (parsed_phone_fields_[FIELD_COUNTRY_CODE]) { |
| 207 ok = ok && AddClassification(parsed_phone_fields_[FIELD_COUNTRY_CODE], | 207 ok = ok && AddClassification(parsed_phone_fields_[FIELD_COUNTRY_CODE], |
| 208 PHONE_HOME_COUNTRY_CODE, | 208 PHONE_HOME_COUNTRY_CODE, |
| 209 map); | 209 map); |
| 210 } | 210 } |
| 211 | 211 |
| 212 ServerFieldType field_number_type = PHONE_HOME_NUMBER; | 212 ServerFieldType field_number_type = PHONE_HOME_NUMBER; |
| 213 if (parsed_phone_fields_[FIELD_AREA_CODE] != NULL) { | 213 if (parsed_phone_fields_[FIELD_AREA_CODE]) { |
| 214 ok = ok && AddClassification(parsed_phone_fields_[FIELD_AREA_CODE], | 214 ok = ok && AddClassification(parsed_phone_fields_[FIELD_AREA_CODE], |
| 215 PHONE_HOME_CITY_CODE, | 215 PHONE_HOME_CITY_CODE, |
| 216 map); | 216 map); |
| 217 } else if (parsed_phone_fields_[FIELD_COUNTRY_CODE] != NULL) { | 217 } else if (parsed_phone_fields_[FIELD_COUNTRY_CODE]) { |
| 218 // Only if we can find country code without city code, it means the phone | 218 // Only if we can find country code without city code, it means the phone |
| 219 // number include city code. | 219 // number include city code. |
| 220 field_number_type = PHONE_HOME_CITY_AND_NUMBER; | 220 field_number_type = PHONE_HOME_CITY_AND_NUMBER; |
| 221 } | 221 } |
| 222 // We tag the prefix as PHONE_HOME_NUMBER, then when filling the form | 222 // We tag the prefix as PHONE_HOME_NUMBER, then when filling the form |
| 223 // we fill only the prefix depending on the size of the input field. | 223 // we fill only the prefix depending on the size of the input field. |
| 224 ok = ok && AddClassification(parsed_phone_fields_[FIELD_PHONE], | 224 ok = ok && AddClassification(parsed_phone_fields_[FIELD_PHONE], |
| 225 field_number_type, | 225 field_number_type, |
| 226 map); | 226 map); |
| 227 // We tag the suffix as PHONE_HOME_NUMBER, then when filling the form | 227 // We tag the suffix as PHONE_HOME_NUMBER, then when filling the form |
| 228 // we fill only the suffix depending on the size of the input field. | 228 // we fill only the suffix depending on the size of the input field. |
| 229 if (parsed_phone_fields_[FIELD_SUFFIX] != NULL) { | 229 if (parsed_phone_fields_[FIELD_SUFFIX]) { |
| 230 ok = ok && AddClassification(parsed_phone_fields_[FIELD_SUFFIX], | 230 ok = ok && AddClassification(parsed_phone_fields_[FIELD_SUFFIX], |
| 231 PHONE_HOME_NUMBER, | 231 PHONE_HOME_NUMBER, |
| 232 map); | 232 map); |
| 233 } | 233 } |
| 234 } else { | 234 } else { |
| 235 ok = AddClassification(parsed_phone_fields_[FIELD_PHONE], | 235 ok = AddClassification(parsed_phone_fields_[FIELD_PHONE], |
| 236 PHONE_HOME_WHOLE_NUMBER, | 236 PHONE_HOME_WHOLE_NUMBER, |
| 237 map); | 237 map); |
| 238 } | 238 } |
| 239 | 239 |
| 240 return ok; | 240 return ok; |
| 241 } | 241 } |
| 242 | 242 |
| 243 PhoneField::PhoneField() { | 243 PhoneField::PhoneField() { |
| 244 memset(parsed_phone_fields_, 0, sizeof(parsed_phone_fields_)); | 244 memset(parsed_phone_fields_, 0, sizeof(parsed_phone_fields_)); |
| 245 } | 245 } |
| 246 | 246 |
| 247 // static | 247 // static |
| 248 base::string16 PhoneField::GetRegExp(RegexType regex_id) { | 248 std::string PhoneField::GetRegExp(RegexType regex_id) { |
| 249 switch (regex_id) { | 249 switch (regex_id) { |
| 250 case REGEX_COUNTRY: | 250 case REGEX_COUNTRY: |
| 251 return base::UTF8ToUTF16(kCountryCodeRe); | 251 return kCountryCodeRe; |
| 252 case REGEX_AREA: | 252 case REGEX_AREA: |
| 253 return GetAreaRegex(); | 253 return GetAreaRegex(); |
| 254 case REGEX_AREA_NOTEXT: | 254 case REGEX_AREA_NOTEXT: |
| 255 return base::UTF8ToUTF16(kAreaCodeNotextRe); | 255 return kAreaCodeNotextRe; |
| 256 case REGEX_PHONE: | 256 case REGEX_PHONE: |
| 257 return base::UTF8ToUTF16(kPhoneRe); | 257 return kPhoneRe; |
| 258 case REGEX_PREFIX_SEPARATOR: | 258 case REGEX_PREFIX_SEPARATOR: |
| 259 return base::UTF8ToUTF16(kPhonePrefixSeparatorRe); | 259 return kPhonePrefixSeparatorRe; |
| 260 case REGEX_PREFIX: | 260 case REGEX_PREFIX: |
| 261 return base::UTF8ToUTF16(kPhonePrefixRe); | 261 return kPhonePrefixRe; |
| 262 case REGEX_SUFFIX_SEPARATOR: | 262 case REGEX_SUFFIX_SEPARATOR: |
| 263 return base::UTF8ToUTF16(kPhoneSuffixSeparatorRe); | 263 return kPhoneSuffixSeparatorRe; |
| 264 case REGEX_SUFFIX: | 264 case REGEX_SUFFIX: |
| 265 return base::UTF8ToUTF16(kPhoneSuffixRe); | 265 return kPhoneSuffixRe; |
| 266 case REGEX_EXTENSION: | 266 case REGEX_EXTENSION: |
| 267 return base::UTF8ToUTF16(kPhoneExtensionRe); | 267 return kPhoneExtensionRe; |
| 268 default: | 268 default: |
| 269 NOTREACHED(); | 269 NOTREACHED(); |
| 270 break; | 270 break; |
| 271 } | 271 } |
| 272 return base::string16(); | 272 return std::string(); |
| 273 } |
| 274 |
| 275 // static |
| 276 bool PhoneField::ParsePhoneField(AutofillScanner* scanner, |
| 277 const std::string& regex, |
| 278 AutofillField** field) { |
| 279 return ParseFieldSpecifics(scanner, |
| 280 base::UTF8ToUTF16(regex), |
| 281 MATCH_DEFAULT | MATCH_TELEPHONE, |
| 282 field); |
| 273 } | 283 } |
| 274 | 284 |
| 275 } // namespace autofill | 285 } // namespace autofill |
| OLD | NEW |