blob: 8c4de77911563e9908e019746bef924df8901b88 [file] [log] [blame]
[email protected]3db3ff62010-01-07 00:35:391// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/autofill/phone_number.h"
6
7#include "base/basictypes.h"
8#include "base/string_util.h"
9#include "chrome/browser/autofill/autofill_type.h"
10#include "chrome/browser/autofill/field_types.h"
11
12static const string16 kPhoneNumberSeparators = ASCIIToUTF16(" .()-");
13
14static const AutoFillType::FieldTypeSubGroup kAutoFillPhoneTypes[] = {
15 AutoFillType::PHONE_NUMBER,
16 AutoFillType::PHONE_CITY_CODE,
17 AutoFillType::PHONE_COUNTRY_CODE,
18 AutoFillType::PHONE_CITY_AND_NUMBER,
19 AutoFillType::PHONE_WHOLE_NUMBER,
20};
21
22static const int kAutoFillPhoneLength = arraysize(kAutoFillPhoneTypes);
23
24void PhoneNumber::GetPossibleFieldTypes(const string16& text,
25 FieldTypeSet* possible_types) const {
26 string16 stripped_text(text);
27 StripPunctuation(&stripped_text);
28 if (!Validate(stripped_text))
29 return;
30
31 if (IsNumber(stripped_text))
32 possible_types->insert(GetNumberType());
33
34 if (IsCityCode(stripped_text))
35 possible_types->insert(GetCityCodeType());
36
37 if (IsCountryCode(stripped_text))
38 possible_types->insert(GetCountryCodeType());
39
40 if (IsCityAndNumber(stripped_text))
41 possible_types->insert(GetCityAndNumberType());
42
43 if (IsWholeNumber(stripped_text))
44 possible_types->insert(GetWholeNumberType());
45}
46
47string16 PhoneNumber::GetFieldText(const AutoFillType& type) const {
48 AutoFillFieldType field_type = type.field_type();
49 if (field_type == GetNumberType())
50 return number();
51
52 if (field_type == GetCityCodeType())
53 return city_code();
54
55 if (field_type == GetCountryCodeType())
56 return country_code();
57
58 if (field_type == GetCityAndNumberType())
59 return CityAndNumber();
60
61 if (field_type == GetWholeNumberType())
62 return WholeNumber();
63
64 return EmptyString16();
65}
66
67void PhoneNumber::FindInfoMatches(const AutoFillType& type,
68 const string16& info,
69 std::vector<string16>* matched_text) const {
70 if (matched_text == NULL) {
71 DLOG(ERROR) << "NULL matched vector passed in";
72 return;
73 }
74
75 string16 number(info);
76 StripPunctuation(&number);
77 if (!Validate(number))
78 return;
79
80 string16 match;
81 if (type.field_type() == UNKNOWN_TYPE) {
82 for (int i = 0; i < kAutoFillPhoneLength; ++i) {
83 if (FindInfoMatchesHelper(kAutoFillPhoneTypes[i], info, &match))
84 matched_text->push_back(match);
85 }
86 } else {
87 if (FindInfoMatchesHelper(type.subgroup(), info, &match))
88 matched_text->push_back(match);
89 }
90}
91
92void PhoneNumber::SetInfo(const AutoFillType& type, const string16& value) {
93 string16 number(value);
94 StripPunctuation(&number);
95 if (!Validate(number))
96 return;
97
98 FieldTypeSubGroup subgroup = type.subgroup();
99 if (subgroup == AutoFillType::PHONE_NUMBER)
100 set_number(number);
101 else if (subgroup == AutoFillType::PHONE_CITY_CODE)
102 set_city_code(number);
103 else if (subgroup == AutoFillType::PHONE_COUNTRY_CODE)
104 set_country_code(number);
105 else
106 NOTREACHED();
107 // TODO(jhawkins): Add extension support.
108 // else if (subgroup == AutoFillType::PHONE_EXTENSION)
109 // set_extension(number);
110}
111
112string16 PhoneNumber::WholeNumber() const {
113 string16 whole_number;
114 if (!country_code_.empty())
115 whole_number.append(country_code_);
116
117 if (!city_code_.empty())
118 whole_number.append(city_code_);
119
120 if (!number_.empty())
121 whole_number.append(number_);
122
123 return whole_number;
124}
125
126void PhoneNumber::set_number(const string16& number) {
127 string16 digits(number);
128 StripPunctuation(&digits);
129 number_ = digits;
130}
131
132PhoneNumber::PhoneNumber(const PhoneNumber& phone_number)
[email protected]225c8f52010-02-05 22:23:20133 : FormGroup(),
134 country_code_(phone_number.country_code_),
[email protected]3db3ff62010-01-07 00:35:39135 city_code_(phone_number.city_code_),
136 number_(phone_number.number_),
137 extension_(phone_number.extension_) {
138}
139
140bool PhoneNumber::FindInfoMatchesHelper(const FieldTypeSubGroup& subgroup,
141 const string16& info,
142 string16* match) const {
143 if (match == NULL) {
144 DLOG(ERROR) << "NULL match string passed in";
145 return false;
146 }
147
148 match->clear();
149 if (subgroup == AutoFillType::PHONE_NUMBER &&
150 StartsWith(number(), info, true)) {
151 *match = number();
152 } else if (subgroup == AutoFillType::PHONE_CITY_CODE &&
153 StartsWith(city_code(), info, true)) {
154 *match = city_code();
155 } else if (subgroup == AutoFillType::PHONE_COUNTRY_CODE &&
156 StartsWith(country_code(), info, true)) {
157 *match = country_code();
158 } else if (subgroup == AutoFillType::PHONE_CITY_AND_NUMBER &&
159 StartsWith(CityAndNumber(), info, true)) {
160 *match = CityAndNumber();
161 } else if (subgroup == AutoFillType::PHONE_WHOLE_NUMBER &&
162 StartsWith(WholeNumber(), info, true)) {
163 *match = WholeNumber();
164 }
165
166 return !match->empty();
167}
168
169bool PhoneNumber::IsNumber(const string16& text) const {
170 if (text.length() <= number_.length())
171 return false;
172
173 return StartsWith(number_, text, false);
174}
175
176bool PhoneNumber::IsCityCode(const string16& text) const {
177 if (text.length() <= city_code_.length())
178 return false;
179
180 return StartsWith(city_code_, text, false);
181}
182
183bool PhoneNumber::IsCountryCode(const string16& text) const {
184 if (text.length() <= country_code_.length())
185 return false;
186
187 return StartsWith(country_code_, text, false);
188}
189
190bool PhoneNumber::IsCityAndNumber(const string16& text) const {
191 string16 city_and_number(CityAndNumber());
192 if (text.length() > city_and_number.length())
193 return false;
194
195 return StartsWith(city_and_number, text, false);
196}
197
198bool PhoneNumber::IsWholeNumber(const string16& text) const {
199 string16 whole_number(WholeNumber());
200 if (text.length() > whole_number.length())
201 return false;
202
203 return StartsWith(whole_number, text, false);
204}
205
206bool PhoneNumber::Validate(const string16& number) const {
207 for (size_t i = 0; i < number.length(); ++i) {
208 if (!IsAsciiDigit(number[i]))
209 return false;
210 }
211
212 return true;
213}
214
215void PhoneNumber::StripPunctuation(string16* number) const {
[email protected]0443f9122010-02-05 01:44:17216 RemoveChars(*number, kPhoneNumberSeparators.c_str(), number);
[email protected]3db3ff62010-01-07 00:35:39217}