diff options
author | dhollowa@chromium.org <dhollowa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-06 22:53:34 +0000 |
---|---|---|
committer | dhollowa@chromium.org <dhollowa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-06 22:53:34 +0000 |
commit | c50a948dd9c07a71524949a28a5347e11d80da47 (patch) | |
tree | ba101f17831e25bac439c91cd43133d9a5602e84 /chrome | |
parent | 84249ad5f64c5464dea317753da45bf72be2164f (diff) | |
download | chromium_src-c50a948dd9c07a71524949a28a5347e11d80da47.zip chromium_src-c50a948dd9c07a71524949a28a5347e11d80da47.tar.gz chromium_src-c50a948dd9c07a71524949a28a5347e11d80da47.tar.bz2 |
Autofill DOMUI Prefs should work with i18n phone numbers
Adds validation to the phone and fax lists in WebUI based prefs for Autofill. Also adds the start of phone_number_i18n.cc/h module.
BUG=80101
TEST=PhoneNumberI18NTest.PhoneNumbersMatch
Review URL: http://codereview.chromium.org/6935033
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@84518 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/autofill/DEPS | 3 | ||||
-rw-r--r-- | chrome/browser/autofill/phone_number_i18n.cc | 37 | ||||
-rw-r--r-- | chrome/browser/autofill/phone_number_i18n.h | 21 | ||||
-rw-r--r-- | chrome/browser/autofill/phone_number_i18n_unittest.cc | 44 | ||||
-rw-r--r-- | chrome/browser/resources/options/autofill_edit_address_overlay.js | 14 | ||||
-rw-r--r-- | chrome/browser/resources/options/autofill_options_list.js | 69 | ||||
-rw-r--r-- | chrome/browser/ui/webui/options/autofill_options_handler.cc | 89 | ||||
-rw-r--r-- | chrome/browser/ui/webui/options/autofill_options_handler.h | 7 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 3 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 |
10 files changed, 284 insertions, 4 deletions
diff --git a/chrome/browser/autofill/DEPS b/chrome/browser/autofill/DEPS new file mode 100644 index 0000000..c975cbe --- /dev/null +++ b/chrome/browser/autofill/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+third_party/libphonenumber", # For phone number i18n. +] diff --git a/chrome/browser/autofill/phone_number_i18n.cc b/chrome/browser/autofill/phone_number_i18n.cc new file mode 100644 index 0000000..8966d00 --- /dev/null +++ b/chrome/browser/autofill/phone_number_i18n.cc @@ -0,0 +1,37 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/autofill/phone_number_i18n.h" + +#include "base/logging.h" +#include "base/utf_string_conversions.h" +#include "third_party/libphonenumber/cpp/src/phonenumberutil.h" + +using i18n::phonenumbers::PhoneNumber; +using i18n::phonenumbers::PhoneNumberUtil; + +namespace autofill_i18n { + +bool PhoneNumbersMatch(const string16& number_a, + const string16& number_b, + const std::string& country_code) { + DCHECK(country_code.size() == 0 || country_code.size() == 2); + std::string safe_country_code(country_code); + if (safe_country_code.size() == 0) + safe_country_code = "US"; + + PhoneNumberUtil *phone_util = PhoneNumberUtil::GetInstance(); + PhoneNumber phone_number_a; + phone_util->Parse(UTF16ToUTF8(number_a), safe_country_code, &phone_number_a); + PhoneNumber phone_number_b; + phone_util->Parse(UTF16ToUTF8(number_b), safe_country_code, &phone_number_b); + + PhoneNumberUtil::MatchType match = phone_util->IsNumberMatch(phone_number_a, + phone_number_b); + // Allow |NSN_MATCH| for implied country code if one is not set. + return match == PhoneNumberUtil::NSN_MATCH || + match == PhoneNumberUtil::EXACT_MATCH; +} + +} // namespace autofill_i18n diff --git a/chrome/browser/autofill/phone_number_i18n.h b/chrome/browser/autofill/phone_number_i18n.h new file mode 100644 index 0000000..28b4c42 --- /dev/null +++ b/chrome/browser/autofill/phone_number_i18n.h @@ -0,0 +1,21 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_AUTOFILL_PHONE_NUMBER_I18N_H_ +#define CHROME_BROWSER_AUTOFILL_PHONE_NUMBER_I18N_H_ +#pragma once + +#include <string> + +#include "base/string16.h" + +namespace autofill_i18n { + +bool PhoneNumbersMatch(const string16& number_a, + const string16& number_b, + const std::string& country_code); + +} // namespace autofill_i18n + +#endif // CHROME_BROWSER_AUTOFILL_PHONE_NUMBER_I18N_H_ diff --git a/chrome/browser/autofill/phone_number_i18n_unittest.cc b/chrome/browser/autofill/phone_number_i18n_unittest.cc new file mode 100644 index 0000000..d74d124 --- /dev/null +++ b/chrome/browser/autofill/phone_number_i18n_unittest.cc @@ -0,0 +1,44 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/utf_string_conversions.h" +#include "chrome/browser/autofill/phone_number_i18n.h" +#include "testing/gtest/include/gtest/gtest.h" + +using namespace autofill_i18n; + +TEST(PhoneNumberI18NTest, PhoneNumbersMatch) { + // Same numbers, defined country code. + EXPECT_TRUE(PhoneNumbersMatch(ASCIIToUTF16("4158889999"), + ASCIIToUTF16("4158889999"), + "US")); + // Same numbers, undefined country code. + EXPECT_TRUE(PhoneNumbersMatch(ASCIIToUTF16("4158889999"), + ASCIIToUTF16("4158889999"), + "")); + + // Numbers differ by country code only. + EXPECT_TRUE(PhoneNumbersMatch(ASCIIToUTF16("14158889999"), + ASCIIToUTF16("4158889999"), + "US")); + + // Same numbers, different formats. + EXPECT_TRUE(PhoneNumbersMatch(ASCIIToUTF16("4158889999"), + ASCIIToUTF16("415-888-9999"), + "US")); + EXPECT_TRUE(PhoneNumbersMatch(ASCIIToUTF16("4158889999"), + ASCIIToUTF16("(415)888-9999"), + "US")); + EXPECT_TRUE(PhoneNumbersMatch(ASCIIToUTF16("4158889999"), + ASCIIToUTF16("415 888 9999"), + "US")); + EXPECT_TRUE(PhoneNumbersMatch(ASCIIToUTF16("4158889999"), + ASCIIToUTF16("415 TUV WXYZ"), + "US")); + + // Partial matches don't count. + EXPECT_FALSE(PhoneNumbersMatch(ASCIIToUTF16("14158889999"), + ASCIIToUTF16("8889999"), + "US")); +} diff --git a/chrome/browser/resources/options/autofill_edit_address_overlay.js b/chrome/browser/resources/options/autofill_edit_address_overlay.js index e682759..51f5666 100644 --- a/chrome/browser/resources/options/autofill_edit_address_overlay.js +++ b/chrome/browser/resources/options/autofill_edit_address_overlay.js @@ -59,11 +59,11 @@ cr.define('options', function() { list.autoExpands = true; list = $('phone-list'); - options.autofillOptions.AutofillValuesList.decorate(list); + options.autofillOptions.AutofillPhoneValuesList.decorate(list); list.autoExpands = true; list = $('fax-list'); - options.autofillOptions.AutofillValuesList.decorate(list); + options.autofillOptions.AutofillFaxValuesList.decorate(list); list.autoExpands = true; list = $('email-list'); @@ -299,6 +299,16 @@ cr.define('options', function() { $('autofill-address-title').textContent = title; }; + AutofillEditAddressOverlay.setValidatedPhoneNumbers = function(numbers) { + AutofillEditAddressOverlay.getInstance().setMultiValueList_('phone-list', + numbers); + }; + + AutofillEditAddressOverlay.setValidatedFaxNumbers = function(numbers) { + AutofillEditAddressOverlay.getInstance().setMultiValueList_('fax-list', + numbers); + }; + // Export return { AutofillEditAddressOverlay: AutofillEditAddressOverlay diff --git a/chrome/browser/resources/options/autofill_options_list.js b/chrome/browser/resources/options/autofill_options_list.js index 61f563d..3fadeab 100644 --- a/chrome/browser/resources/options/autofill_options_list.js +++ b/chrome/browser/resources/options/autofill_options_list.js @@ -125,7 +125,7 @@ cr.define('options.autofillOptions', function() { if (this.input.value && this.list.dataModel.indexOf(this.input.value) == -1) { // Update with new value. - this.list.dataModel.splice(i, 1, this.input.value); + this.list.validateAndSave(i, 1, this.input.value); } else { // Reject empty values and duplicates. this.list.dataModel.splice(i, 1); @@ -174,7 +174,7 @@ cr.define('options.autofillOptions', function() { if (this.input.value && this.list.dataModel.indexOf(this.input.value) == -1) { - this.list.dataModel.splice(i, 0, this.input.value); + this.list.validateAndSave(i, 0, this.input.value); } else { this.input.value = ''; this.list.dataModel.updateIndex(i); @@ -303,6 +303,69 @@ cr.define('options.autofillOptions', function() { deleteItemAtIndex: function(index) { this.dataModel.splice(index, 1); }, + + /** + * Called when a new list item should be validated; subclasses are + * responsible for implementing if validation is required. + * @param {number} index The index of the item that was inserted or changed. + * @param {number} remove The number items to remove. + * @param {string} value The value of the item to insert. + */ + validateAndSave: function(index, remove, value) { + this.dataModel.splice(index, remove, value); + }, + }; + + /** + * Create a new value list for phone number validation. + * @constructor + * @extends {options.AutofillValuesList} + */ + var AutofillPhoneValuesList = cr.ui.define('list'); + + AutofillPhoneValuesList.prototype = { + __proto__: AutofillValuesList.prototype, + + decorate: function() { + AutofillValuesList.prototype.decorate.call(this); + }, + + /** @inheritDoc */ + validateAndSave: function(index, remove, value) { + var numbers = this.dataModel.slice(0, this.dataModel.length - 1); + numbers.splice(index, remove, value); + var info = new Array(); + info[0] = index; + info[1] = numbers; + info[2] = $('country').value; + chrome.send('validatePhoneNumbers', info); + }, + }; + + /** + * Create a new value list for fax number validation. + * @constructor + * @extends {options.AutofillValuesList} + */ + var AutofillFaxValuesList = cr.ui.define('list'); + + AutofillFaxValuesList.prototype = { + __proto__: AutofillValuesList.prototype, + + decorate: function() { + AutofillValuesList.prototype.decorate.call(this); + }, + + /** @inheritDoc */ + validateAndSave: function(index, remove, value) { + var numbers = this.dataModel.slice(0, this.dataModel.length - 1); + numbers.splice(index, remove, value); + var info = new Array(); + info[0] = index; + info[1] = numbers; + info[2] = $('country').value; + chrome.send('validateFaxNumbers', info); + }, }; return { @@ -313,5 +376,7 @@ cr.define('options.autofillOptions', function() { AutofillAddressList: AutofillAddressList, AutofillCreditCardList: AutofillCreditCardList, AutofillValuesList: AutofillValuesList, + AutofillPhoneValuesList: AutofillPhoneValuesList, + AutofillFaxValuesList: AutofillFaxValuesList, }; }); diff --git a/chrome/browser/ui/webui/options/autofill_options_handler.cc b/chrome/browser/ui/webui/options/autofill_options_handler.cc index ab0038b..d9410f5 100644 --- a/chrome/browser/ui/webui/options/autofill_options_handler.cc +++ b/chrome/browser/ui/webui/options/autofill_options_handler.cc @@ -14,6 +14,7 @@ #include "chrome/browser/autofill/autofill_country.h" #include "chrome/browser/autofill/autofill_profile.h" #include "chrome/browser/autofill/credit_card.h" +#include "chrome/browser/autofill/phone_number_i18n.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/web_ui_util.h" #include "chrome/common/guid.h" @@ -115,6 +116,66 @@ void SetValueList(const ListValue* list, profile->SetMultiInfo(type, values); } +// Pulls the phone (or fax) number |index|, |phone_number_list|, and +// |country_code| from the |args| input. +void ExtractPhoneNumberInformation(const ListValue* args, + size_t* index, + ListValue** phone_number_list, + std::string* country_code) { + // Retrieve index as a |double|, as that is how it comes across from + // JavaScript. + double number = 0.0; + if (!args->GetDouble(0, &number)) { + NOTREACHED(); + return; + } + *index = number; + + if (!args->GetList(1, phone_number_list)) { + NOTREACHED(); + return; + } + + if (!args->GetString(2, country_code)) { + NOTREACHED(); + return; + } +} + +// Searches the |list| for the value at |index|. If this value is present +// in any of the rest of the list, then the item (at |index|) is removed. +// The comparison of phone number values is done on normalized versions of the +// phone number values. +void RemoveDuplicatePhoneNumberAtIndex(size_t index, + const std::string& country_code, + ListValue* list) { + string16 new_value; + list->GetString(index, &new_value); + + bool is_duplicate = false; + for (size_t i = 0; i < list->GetSize() && !is_duplicate; ++i) { + if (i == index) + continue; + + string16 existing_value; + list->GetString(i, &existing_value); + is_duplicate = autofill_i18n::PhoneNumbersMatch(new_value, + existing_value, + country_code); + } + + if (is_duplicate) + list->Remove(index, NULL); +} + +void ValidatePhoneArguments(const ListValue* args, ListValue** list) { + size_t index = 0; + std::string country_code; + ExtractPhoneNumberInformation(args, &index, list, &country_code); + + RemoveDuplicatePhoneNumberAtIndex(index, country_code, *list); +} + } // namespace AutofillOptionsHandler::AutofillOptionsHandler() @@ -181,6 +242,12 @@ void AutofillOptionsHandler::RegisterMessages() { web_ui_->RegisterMessageCallback( "setCreditCard", NewCallback(this, &AutofillOptionsHandler::SetCreditCard)); + web_ui_->RegisterMessageCallback( + "validatePhoneNumbers", + NewCallback(this, &AutofillOptionsHandler::ValidatePhoneNumbers)); + web_ui_->RegisterMessageCallback( + "validateFaxNumbers", + NewCallback(this, &AutofillOptionsHandler::ValidateFaxNumbers)); } ///////////////////////////////////////////////////////////////////////////// @@ -452,3 +519,25 @@ void AutofillOptionsHandler::SetCreditCard(const ListValue* args) { personal_data_->UpdateCreditCard(credit_card); } } + +void AutofillOptionsHandler::ValidatePhoneNumbers(const ListValue* args) { + if (!personal_data_->IsDataLoaded()) + return; + + ListValue* list_value = NULL; + ValidatePhoneArguments(args, &list_value); + + web_ui_->CallJavascriptFunction( + "AutofillEditAddressOverlay.setValidatedPhoneNumbers", *list_value); +} + +void AutofillOptionsHandler::ValidateFaxNumbers(const ListValue* args) { + if (!personal_data_->IsDataLoaded()) + return; + + ListValue* list_value = NULL; + ValidatePhoneArguments(args, &list_value); + + web_ui_->CallJavascriptFunction( + "AutofillEditAddressOverlay.setValidatedFaxNumbers", *list_value); +} diff --git a/chrome/browser/ui/webui/options/autofill_options_handler.h b/chrome/browser/ui/webui/options/autofill_options_handler.h index dd9a0f6..d7a0c241 100644 --- a/chrome/browser/ui/webui/options/autofill_options_handler.h +++ b/chrome/browser/ui/webui/options/autofill_options_handler.h @@ -68,6 +68,13 @@ class AutofillOptionsHandler : public OptionsPageUIHandler, // credit card data. void SetCreditCard(const ListValue* args); + // Validates a list of phone/fax numbers. The resulting validated list of + // numbers is then sent back to the WebUI. + // |args| - an array containing the index of the modified or added number, the + // array of numbers, and the country code string set on the profile. + void ValidatePhoneNumbers(const ListValue* args); + void ValidateFaxNumbers(const ListValue* args); + // The personal data manager, used to load Autofill profiles and credit cards. // Unowned pointer, may not be NULL. PersonalDataManager* personal_data_; diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index c7a69b7..eb36f9d 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -43,6 +43,7 @@ '../third_party/icu/icu.gyp:icuuc', '../third_party/libjingle/libjingle.gyp:libjingle', '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber', + '../third_party/libphonenumber/libphonenumber.gyp:phonenumber_proto', '../third_party/libxml/libxml.gyp:libxml', '../third_party/npapi/npapi.gyp:npapi', '../ui/base/strings/ui_strings.gyp:ui_strings', @@ -193,6 +194,8 @@ 'browser/autofill/phone_field.h', 'browser/autofill/phone_number.cc', 'browser/autofill/phone_number.h', + 'browser/autofill/phone_number_i18n.cc', + 'browser/autofill/phone_number_i18n.h', 'browser/autofill/select_control_handler.cc', 'browser/autofill/select_control_handler.h', 'browser/automation/automation_browser_tracker.cc', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index e6a342b..bb7eba4 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1231,6 +1231,7 @@ 'browser/autofill/personal_data_manager_unittest.cc', 'browser/autofill/phone_field_unittest.cc', 'browser/autofill/phone_number_unittest.cc', + 'browser/autofill/phone_number_i18n_unittest.cc', 'browser/autofill/select_control_handler_unittest.cc', 'browser/automation/automation_provider_unittest.cc', 'browser/automation/automation_tab_helper_unittest.cc', |