summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authordhollowa@chromium.org <dhollowa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-06 22:53:34 +0000
committerdhollowa@chromium.org <dhollowa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-06 22:53:34 +0000
commitc50a948dd9c07a71524949a28a5347e11d80da47 (patch)
treeba101f17831e25bac439c91cd43133d9a5602e84 /chrome
parent84249ad5f64c5464dea317753da45bf72be2164f (diff)
downloadchromium_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/DEPS3
-rw-r--r--chrome/browser/autofill/phone_number_i18n.cc37
-rw-r--r--chrome/browser/autofill/phone_number_i18n.h21
-rw-r--r--chrome/browser/autofill/phone_number_i18n_unittest.cc44
-rw-r--r--chrome/browser/resources/options/autofill_edit_address_overlay.js14
-rw-r--r--chrome/browser/resources/options/autofill_options_list.js69
-rw-r--r--chrome/browser/ui/webui/options/autofill_options_handler.cc89
-rw-r--r--chrome/browser/ui/webui/options/autofill_options_handler.h7
-rw-r--r--chrome/chrome_browser.gypi3
-rw-r--r--chrome/chrome_tests.gypi1
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',