Index: chrome/browser/autofill/autofill_locale_model_unittest.cc |
diff --git a/chrome/browser/autofill/autofill_locale_model_unittest.cc b/chrome/browser/autofill/autofill_locale_model_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a83603455a2b5756be88fd67f5c7a674d966a769 |
--- /dev/null |
+++ b/chrome/browser/autofill/autofill_locale_model_unittest.cc |
@@ -0,0 +1,288 @@ |
+// Copyright (c) 2010 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/autofill_locale_model.h" |
+ |
+#include <string> |
+#include <vector> |
+ |
+#include "chrome/browser/autofill/form_structure.h" |
+#include "chrome/browser/renderer_host/test/test_render_view_host.h" |
+#include "chrome/browser/tab_contents/language_state.h" |
+#include "chrome/browser/tab_contents/tab_contents.h" |
+#include "chrome/browser/tab_contents/test_tab_contents.h" |
+#include "chrome/common/chrome_constants.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "webkit/glue/form_data.h" |
+ |
+namespace { |
+ |
+// Mocks out the original_language() function to return a pre-set value. |
+class MockLanguageState : public LanguageState { |
+ public: |
+ explicit MockLanguageState(const std::string& locale) |
+ : LanguageState(NULL), |
+ original_language_(locale) {} |
+ virtual ~MockLanguageState() {} |
+ |
+ virtual const std::string& original_language() const { |
+ return original_language_; |
+ } |
+ |
+ private: |
+ const std::string& original_language_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(MockLanguageState); |
+}; |
+ |
+// Testing version of AutoFillLocaleModel that exposes access to the model's |
+// registry map. |
+class TestAutoFillLocaleModel : public AutoFillLocaleModel { |
+ public: |
+ TestAutoFillLocaleModel() : AutoFillLocaleModel(NULL) {} |
+ |
+ // Verifies that the regions and languages in the registry map are valid. |
+ void ValidateRegistryMap() { |
+ for (AutoFillRegistryMap::const_iterator it = registries()->begin(); |
+ it != registries()->end(); ++it) { |
+ SCOPED_TRACE("Region: \"" + it->second.region + "\""); |
+ EXPECT_TRUE(AutoFillLocaleModel::IsValidRegionTag(it->second.region)); |
+ |
+ const std::vector<std::string>& languages = it->second.languages; |
+ for (std::vector<std::string>::const_iterator it2 = languages.begin(); |
+ it2 != languages.end(); ++it2) { |
+ SCOPED_TRACE("Language: \"" + *it2 + "\""); |
+ EXPECT_TRUE(AutoFillLocaleModel::IsValidLanguageTag(*it2)); |
+ } |
+ } |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(TestAutoFillLocaleModel); |
+}; |
+ |
+class AutoFillLocaleModelTest : public RenderViewHostTestHarness { |
+ public: |
+ AutoFillLocaleModelTest() {} |
+ virtual ~AutoFillLocaleModelTest() {} |
+ |
+ // Mocks out the GetURL() and language_state() functions to return pre-set |
+ // values. |
+ class MockTabContents : public TestTabContents { |
+ public: |
+ MockTabContents(const TestTabContents* contents, |
+ const std::string& detected_locale, |
+ const GURL& url) |
+ : TestTabContents(contents->profile(), contents->GetSiteInstance()), |
+ language_state_(detected_locale), |
+ url_(url) {} |
+ virtual ~MockTabContents() {} |
+ |
+ virtual const GURL& GetURL() const { return url_; } |
+ virtual LanguageState& language_state() { return language_state_; } |
+ virtual const LanguageState& language_state() const { |
+ return language_state_; |
+ } |
+ |
+ private: |
+ MockLanguageState language_state_; |
+ const GURL url_; |
+ }; |
+ |
+ void RunTest(const std::string& dom_locale, |
+ const std::string& detected_locale, |
+ const std::string& source_registry, |
+ const std::string& target_registry, |
+ const std::string& expected_locale) { |
+ SCOPED_TRACE("\n\tDOM: \"" + dom_locale + "\"" |
+ "\n\tCLD: \"" + detected_locale + "\"" |
+ "\n\tSource registry: \"" + source_registry + "\"" |
+ "\n\tTarget registry: \"" + target_registry + "\""); |
+ |
+ const GURL source_url("http://www.foo." + source_registry + "/form.html"); |
+ MockTabContents tab_contents(contents(), detected_locale, source_url); |
+ |
+ AutoFillLocaleModel model(&tab_contents); |
+ model.set_tab_language_determined(true); |
+ |
+ webkit_glue::FormData form_data; |
+ form_data.origin = source_url; |
+ form_data.action = GURL("http://www.foo." + target_registry + "/go.html"); |
+ form_data.locale = dom_locale; |
+ FormStructure form(form_data); |
+ model.UpdateLocale(&form); |
+ |
+ EXPECT_EQ(expected_locale, form.locale()); |
+ } |
+ |
+ void RunWebsiteTest(const std::string& dom_locale, |
+ const std::string& detected_locale, |
+ const std::string& website, |
+ const std::string& expected_locale) { |
+ SCOPED_TRACE("\n\tDOM: \"" + dom_locale + "\"" |
+ "\n\tCLD: \"" + detected_locale + "\"" |
+ "\n\tSite: \"" + website + "\""); |
+ |
+ const GURL source_url(website); |
+ MockTabContents tab_contents(contents(), detected_locale, source_url); |
+ |
+ AutoFillLocaleModel model(&tab_contents); |
+ model.set_tab_language_determined(true); |
+ |
+ webkit_glue::FormData form_data; |
+ form_data.origin = source_url; |
+ form_data.action = source_url; |
+ form_data.locale = dom_locale; |
+ FormStructure form(form_data); |
+ model.UpdateLocale(&form); |
+ |
+ EXPECT_EQ(expected_locale, form.locale()); |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(AutoFillLocaleModelTest); |
+}; |
+ |
+// TODO(isherman): This test currently assumes that a different function will be |
+// responsible for determining the best region for the locale, and that |
+// DetermineFormLocale() does not promote e.g. "fr" to "fr-FR". |
+// |
+// Make sure that we correctly prioritize our various locale indicators: |
+// * the form's locale according to the DOM, e.g. via the HTML "lang" attribute |
+// * the page's locale according to CLD |
+// * the page's registry |
+TEST_F(AutoFillLocaleModelTest, DetermineFormLocale) { |
+ // If everything matches, this should be easy. |
+ RunTest("en", "en", "com", "com", "en"); |
+ RunTest("en-US", "en-US", "org", "org", "en-US"); |
+ RunTest("fr", "fr", "net", "net", "fr"); |
+ RunTest("fr-CA", "fr-CA", "ca", "ca", "fr-CA"); |
+ |
+ // Match should be as specific as possible. |
+ RunTest("en", "en-US", "com", "com", "en-US"); |
+ RunTest("en-US", "en", "com", "com", "en-US"); |
+ RunTest("fr", "fr-CA", "com", "com", "fr-CA"); |
+ RunTest("fr-CA", "fr", "com", "com", "fr-CA"); |
+ |
+ // Trust the HTML locale attribute, unless it is "en", "en-US", or empty. |
+ // Otherwise trust the page language, unless it is unknown. |
+ RunTest("fr", "en", "com", "com", "fr"); |
+ RunTest("fr-CA", "en-US", "com", "com", "fr-CA"); |
+ RunTest("en-GB", "fr", "com", "com", "en-GB"); |
+ RunTest("en", "fr", "com", "com", "fr"); |
+ RunTest("en-US", "fr", "com", "com", "fr"); |
+ RunTest("", "fr", "com", "com", "fr"); |
+ RunTest("en-US", chrome::kUnknownLanguageCode, "com", "com", "en-US"); |
+ |
+ // The registry can help us choose a region, and sometimes even the language. |
+ RunTest("en", "en", "co.uk", "co.uk", "en-GB"); |
+ RunTest("", "en", "co.uk", "co.uk", "en-GB"); |
+ RunTest("", chrome::kUnknownLanguageCode, "ca", "ca", "fr-CA"); |
+ |
+ // Canadian pages can be in either English or French. |
+ RunTest("fr", "fr", "ca", "ca", "fr-CA"); |
+ RunTest("en", "en", "ca", "ca", "en-CA"); |
+ |
+ // We trust the source url's registry more than the target url's registry. |
+ RunTest("fr", "fr", "com", "ca", "fr-CA"); |
+ RunTest("fr", "fr", "fr", "ca", "fr-FR"); |
+ |
+ // Only use the registry to determine the region when the other indicators |
+ // are empty or match the registry's predictions -- consider "bit.ly" and |
+ // other such cutely named websites. |
+ RunTest("", "en", "fr", "fr", "en"); |
+ RunTest("fr", chrome::kUnknownLanguageCode, "co.uk", "co.uk", "fr"); |
+ |
+ // Case should not affect the match. |
+ RunTest("Fr-cA", "Fr-cA", "ca", "ca", "fr-CA"); |
+ RunTest("RU", chrome::kUnknownLanguageCode, "com", "com", "ru"); |
+ RunTest("EN-us", "fr", "com", "com", "fr"); |
+ RunTest("en", "en", "CO.UK", "CO.UK", "en-GB"); |
+ |
+ // We should trim whitespace. |
+ RunTest(" en-GB ", chrome::kUnknownLanguageCode, "com", "com", "en-GB"); |
+ |
+ // If there are no signals at all, guess "en-US". |
+ RunTest("", chrome::kUnknownLanguageCode, "com", "com", "en-US"); |
+ |
+ // Test a few invalid locales as well, just to make sure nothing breaks. |
+ RunTest("xx-XX", chrome::kUnknownLanguageCode, "com", "com", "en-US"); |
+ RunTest(" x ", chrome::kUnknownLanguageCode, "com", "com", "en-US"); |
+} |
+ |
+// Make sure that our registry map maps to valid regions and languages. |
+TEST_F(AutoFillLocaleModelTest, ValidateRegistryMap) { |
+ TestAutoFillLocaleModel model; |
+ model.ValidateRegistryMap(); |
+} |
+ |
+// Tests that we correctly detect the locale for top international websites. |
+// To add a case to this list, run Chromium in debug mode with the code snippet |
+// below added to AutoFillLocaleModel::UpdateLocale(), then copy in the output. |
+// printf("UpdateLocale()\n" |
+// "\tDOM: \"%s\"\n" |
+// "\tCLD: \"%s\"\n" |
+// "\tsource: \"%s\"\n" |
+// "\ttarget: \"%s\"\n" |
+// "\tpage: \"%s\"\n", |
+// form->locale().c_str(), |
+// tab_contents_->language_state().original_language().c_str(), |
+// form->source_url().spec().c_str(), |
+// form->target_url().spec().c_str(), |
+// tab_contents_->GetURL().spec().c_str()); |
+TEST_F(AutoFillLocaleModelTest, TopWebsiteLocales) { |
+ // Chinese (Simplified): Amazon China |
+ RunWebsiteTest("", "zh-CN", "https://www.amazon.cn/", "zh-CN"); |
+ |
+ // Chinese (Traditional): PChome |
+ RunWebsiteTest("", "zh-TW", "https://ecssl.pchome.com.tw/", "zh-TW"); |
+ |
+ // English/AU: Bookworm |
+ RunWebsiteTest("", "en", "https://www.bookworm.com.au", "en-AU"); |
+ |
+ // English/CA: Chapters/Indigo |
+ RunWebsiteTest("", "en", "https://shop.chapters.indigo.ca", "en-CA"); |
+ |
+ // English/NZ: Fishpond |
+ RunWebsiteTest("", "en", "https://www.fishpond.co.nz/", "en-NZ"); |
+ |
+ // Hebrew |
+ RunWebsiteTest("he", "he", "https://book4book.co.il/", "he-IL"); |
+ |
+ // Italian: bol.it |
+ RunWebsiteTest("", "it", "https://www.bol.it/", "it-IT"); |
+ |
+ // Japanese: rakuten |
+ RunWebsiteTest("", "ja", "https://order.step.rakuten.co.jp/", "ja-JP"); |
+ |
+ // Portuguese/BR: |
+ RunWebsiteTest("", "pt", "https://www.livrariasaraiva.com.br/", "pt-BR"); |
+ |
+ // Spanish/MX: |
+ RunWebsiteTest("", "es", "http://www.librerialeo.com.mx/create_account.php", |
+ "es-MX"); |
+} |
+ |
+// TODO(isherman): for two of these, we can get the right answer just by |
+// guessing the most common region; but for the other two, that would still |
+// give the wrong answer. |
+// Tracks top websites where we detect the form locale incorrectly. |
+TEST_F(AutoFillLocaleModelTest, FAILS_TopWebsiteLocalesThatCurrentlyFail) { |
+ // English/IN: rediff books |
+ RunWebsiteTest("", "en", "http://commerce.rediff.com/", "en-IN"); |
+ |
+ // French: fnac |
+ RunWebsiteTest("", "fr", "https://secure.fnac.com/", "fr-FR"); |
+ |
+ // Japanese/US: Fujisan |
+ RunWebsiteTest("", "ja", "https://www.fujisan.com/control/newcustomer", |
+ "ja-US"); |
+ |
+ // Japanese/US: rakuten, after selecting German as a langauge... |
+ RunWebsiteTest("", "en", "https://en.order.step.rakuten.co.jp/", "en-US"); |
+} |
+ |
+// TODO(isherman): unit test that verifies mapping a locale to a region |
+ |
+} // namespace |