diff options
author | rouslan <rouslan@chromium.org> | 2016-02-16 13:52:24 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-02-16 21:53:49 +0000 |
commit | eb3f08b2ec5edb33108b07ca784508969ff95384 (patch) | |
tree | 0a1ee4f6e019c0a3972da6c9b748fce62e1b8aca | |
parent | 6044a028d31c8459afb0a7ef5df5ab99f51a0db4 (diff) | |
download | chromium_src-eb3f08b2ec5edb33108b07ca784508969ff95384.zip chromium_src-eb3f08b2ec5edb33108b07ca784508969ff95384.tar.gz chromium_src-eb3f08b2ec5edb33108b07ca784508969ff95384.tar.bz2 |
[spellcheck] Preserve the order of spellcheck languages.
GetDictionaries() is used for displaying spellcheck languages in
the context menu. The ordering of languages should be always preserved
for UI consistency.
BUG=584517
Review URL: https://codereview.chromium.org/1679073002
Cr-Commit-Position: refs/heads/master@{#375670}
-rw-r--r-- | chrome/browser/spellchecker/spellcheck_service.cc | 52 | ||||
-rw-r--r-- | chrome/browser/spellchecker/spellcheck_service.h | 24 | ||||
-rw-r--r-- | chrome/browser/spellchecker/spellcheck_service_unittest.cc | 126 | ||||
-rw-r--r-- | chrome/common/spellcheck_common.h | 8 |
4 files changed, 127 insertions, 83 deletions
diff --git a/chrome/browser/spellchecker/spellcheck_service.cc b/chrome/browser/spellchecker/spellcheck_service.cc index b766b24..7360f06 100644 --- a/chrome/browser/spellchecker/spellcheck_service.cc +++ b/chrome/browser/spellchecker/spellcheck_service.cc @@ -4,7 +4,7 @@ #include "chrome/browser/spellchecker/spellcheck_service.h" -#include <algorithm> +#include <set> #include "base/logging.h" #include "base/strings/string_split.h" @@ -129,34 +129,32 @@ base::WeakPtr<SpellcheckService> SpellcheckService::GetWeakPtr() { #if !defined(OS_MACOSX) // static -size_t SpellcheckService::GetSpellCheckLanguages( - base::SupportsUserData* context, - std::vector<std::string>* languages) { - PrefService* prefs = user_prefs::UserPrefs::Get(context); - StringPrefMember accept_languages_pref; - accept_languages_pref.Init(prefs::kAcceptLanguages, prefs); - - std::vector<std::string> accept_languages = base::SplitString( - accept_languages_pref.GetValue(), ",", - base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - - StringListPrefMember dictionaries_pref; - dictionaries_pref.Init(prefs::kSpellCheckDictionaries, prefs); - *languages = dictionaries_pref.GetValue(); - size_t enabled_spellcheck_languages = languages->size(); - - for (std::vector<std::string>::const_iterator i = accept_languages.begin(); - i != accept_languages.end(); ++i) { - std::string language = - chrome::spellcheck_common::GetCorrespondingSpellCheckLanguage(*i); - if (!language.empty() && - std::find(languages->begin(), languages->end(), language) == - languages->end()) { - languages->push_back(language); - } +void SpellcheckService::GetDictionaries(base::SupportsUserData* browser_context, + std::vector<Dictionary>* dictionaries) { + PrefService* prefs = user_prefs::UserPrefs::Get(browser_context); + std::set<std::string> spellcheck_dictionaries; + for (const auto& value : *prefs->GetList(prefs::kSpellCheckDictionaries)) { + std::string dictionary; + if (value->GetAsString(&dictionary)) + spellcheck_dictionaries.insert(dictionary); } - return enabled_spellcheck_languages; + dictionaries->clear(); + std::vector<std::string> accept_languages = + base::SplitString(prefs->GetString(prefs::kAcceptLanguages), ",", + base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + for (const auto& accept_language : accept_languages) { + Dictionary dictionary; + dictionary.language = + chrome::spellcheck_common::GetCorrespondingSpellCheckLanguage( + accept_language); + if (dictionary.language.empty()) + continue; + + dictionary.used_for_spellcheck = + spellcheck_dictionaries.count(dictionary.language) > 0; + dictionaries->push_back(dictionary); + } } #endif // !OS_MACOSX diff --git a/chrome/browser/spellchecker/spellcheck_service.h b/chrome/browser/spellchecker/spellcheck_service.h index b2a03b4..f2ddd19 100644 --- a/chrome/browser/spellchecker/spellcheck_service.h +++ b/chrome/browser/spellchecker/spellcheck_service.h @@ -63,19 +63,29 @@ class SpellcheckService : public KeyedService, DICT_UNKNOWN, }; + // A dictionary that can be used for spellcheck. + struct Dictionary { + // The shortest unambiguous identifier for a language from + // |g_supported_spellchecker_languages|. For example, "bg" for Bulgarian, + // because Chrome has only one Bulgarian language. However, "en-US" for + // English (United States), because Chrome has several versions of English. + std::string language; + + // Whether |language| is currently used for spellcheck. + bool used_for_spellcheck; + }; + explicit SpellcheckService(content::BrowserContext* context); ~SpellcheckService() override; base::WeakPtr<SpellcheckService> GetWeakPtr(); #if !defined(OS_MACOSX) - // Computes |languages| to display in the context menu over a text area for - // changing spellcheck languages. Returns the number of languages that are - // enabled, which are always at the beginning of |languages|. - // TODO(port): this should take a vector of base::string16, but the - // implementation has some dependencies in l10n util that need porting first. - static size_t GetSpellCheckLanguages(base::SupportsUserData* context, - std::vector<std::string>* languages); + // Returns all currently configured |dictionaries| to display in the context + // menu over a text area. The context menu is used for selecting the + // dictionaries used for spellcheck. + static void GetDictionaries(base::SupportsUserData* browser_context, + std::vector<Dictionary>* dictionaries); #endif // !OS_MACOSX // Signals the event attached by AttachTestEvent() to report the specified diff --git a/chrome/browser/spellchecker/spellcheck_service_unittest.cc b/chrome/browser/spellchecker/spellcheck_service_unittest.cc index 1d46e0c..bdd0a76 100644 --- a/chrome/browser/spellchecker/spellcheck_service_unittest.cc +++ b/chrome/browser/spellchecker/spellcheck_service_unittest.cc @@ -4,12 +4,13 @@ #include "chrome/browser/spellchecker/spellcheck_service.h" -#include <stddef.h> +#include <ostream> #include "base/command_line.h" #include "base/macros.h" #include "base/message_loop/message_loop.h" #include "base/strings/string_split.h" +#include "base/strings/string_util.h" #include "base/supports_user_data.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" @@ -19,31 +20,68 @@ #include "content/public/test/test_browser_thread.h" #include "testing/gtest/include/gtest/gtest.h" -struct SpellcheckLanguageTestCase { - SpellcheckLanguageTestCase(const std::string& accept_languages, - const std::string& unsplit_spellcheck_dictionaries, - size_t num_expected_enabled_spellcheck_languages, - const std::string& unsplit_expected_languages) +struct TestCase { + TestCase(const std::string& accept_languages, + const std::string& unsplit_spellcheck_dictionaries, + const std::string& unsplit_expected_languages, + const std::string& unsplit_expected_languages_used_for_spellcheck) : accept_languages(accept_languages), - num_expected_enabled_spellcheck_languages( - num_expected_enabled_spellcheck_languages) { - spellcheck_dictionaries = base::SplitString( - unsplit_spellcheck_dictionaries, ",", - base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - expected_spellcheck_languages = base::SplitString( - unsplit_expected_languages, ",", - base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + spellcheck_dictionaries( + base::SplitString(unsplit_spellcheck_dictionaries, + ",", + base::TRIM_WHITESPACE, + base::SPLIT_WANT_ALL)) { + std::vector<std::string> languages = + base::SplitString(unsplit_expected_languages, ",", + base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + + std::vector<std::string> used_for_spellcheck = + base::SplitString(unsplit_expected_languages_used_for_spellcheck, ",", + base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + + SpellcheckService::Dictionary dictionary; + for (const auto& language : languages) { + dictionary.language = language; + dictionary.used_for_spellcheck = + std::find(used_for_spellcheck.begin(), used_for_spellcheck.end(), + language) != used_for_spellcheck.end(); + expected_dictionaries.push_back(dictionary); + } } - ~SpellcheckLanguageTestCase() {} + + ~TestCase() {} std::string accept_languages; std::vector<std::string> spellcheck_dictionaries; - size_t num_expected_enabled_spellcheck_languages; - std::vector<std::string> expected_spellcheck_languages; + std::vector<SpellcheckService::Dictionary> expected_dictionaries; }; -class SpellcheckServiceUnitTest - : public testing::TestWithParam<SpellcheckLanguageTestCase> { +bool operator==(const SpellcheckService::Dictionary& lhs, + const SpellcheckService::Dictionary& rhs) { + return lhs.language == rhs.language && + lhs.used_for_spellcheck == rhs.used_for_spellcheck; +} + +std::ostream& operator<<(std::ostream& out, + const SpellcheckService::Dictionary& dictionary) { + out << "{\"" << dictionary.language << "\", used_for_spellcheck=" + << (dictionary.used_for_spellcheck ? "true " : "false") << "}"; + return out; +} + +std::ostream& operator<<(std::ostream& out, const TestCase& test_case) { + out << "prefs::kAcceptLanguages=[" << test_case.accept_languages + << "], prefs::kSpellCheckDictionaries=[" + << base::JoinString(test_case.spellcheck_dictionaries, ",") + << "], expected=["; + for (const auto& dictionary : test_case.expected_dictionaries) { + out << dictionary << ","; + } + out << "]"; + return out; +} + +class SpellcheckServiceUnitTest : public testing::TestWithParam<TestCase> { public: SpellcheckServiceUnitTest() : ui_thread_(content::BrowserThread::UI, &message_loop_) { @@ -61,7 +99,8 @@ class SpellcheckServiceUnitTest TestingPrefServiceSimple* prefs() { return &prefs_; } private: - struct : public base::SupportsUserData {} context_; + struct : public base::SupportsUserData { + } context_; TestingPrefServiceSimple prefs_; base::MessageLoop message_loop_; content::TestBrowserThread ui_thread_; @@ -70,38 +109,27 @@ class SpellcheckServiceUnitTest }; INSTANTIATE_TEST_CASE_P( - SpellcheckLanguageTestCases, + TestCases, SpellcheckServiceUnitTest, testing::Values( - SpellcheckLanguageTestCase("en,en-US", "en-US", 1UL, "en-US"), - SpellcheckLanguageTestCase("en-US,en", "en-US", 1UL, "en-US"), - SpellcheckLanguageTestCase("en,en-US,en-AU", - "en-US", - 1UL, - "en-US,en-AU"), - SpellcheckLanguageTestCase("en,en-US,fr", "en-US", 1UL, "en-US,fr"), - SpellcheckLanguageTestCase("en,en-JP,fr,aa", "fr", 1UL, "fr"), - SpellcheckLanguageTestCase("en,en-US", "en-US", 1UL, "en-US"), - SpellcheckLanguageTestCase("en-US,en", "en-US", 1UL, "en-US"), - SpellcheckLanguageTestCase("en,fr,en-US,en-AU", - "en-US,fr", - 2UL, - "en-US,fr,en-AU"), - SpellcheckLanguageTestCase("en,en-JP,fr,zz,en-US", - "fr", - 1UL, - "fr,en-US"))); - -TEST_P(SpellcheckServiceUnitTest, GetSpellcheckLanguages) { + TestCase("en,en-JP,fr,aa", "fr", "fr", "fr"), + TestCase("en,en-JP,fr,zz,en-US", "fr", "fr,en-US", "fr"), + TestCase("en,en-US,en-AU", "en-AU", "en-US,en-AU", "en-AU"), + TestCase("en,en-US,en-AU", "en-US", "en-US,en-AU", "en-US"), + TestCase("en,en-US", "en-US", "en-US", "en-US"), + TestCase("en,en-US,fr", "en-US", "en-US,fr", "en-US"), + TestCase("en,fr,en-US,en-AU", "en-US,fr", "fr,en-US,en-AU", "fr,en-US"), + TestCase("en-US,en", "en-US", "en-US", "en-US"), + TestCase("hu-HU,hr-HR", "hr", "hu,hr", "hr"))); + +TEST_P(SpellcheckServiceUnitTest, GetDictionaries) { prefs()->SetString(prefs::kAcceptLanguages, GetParam().accept_languages); - base::ListValue dictionaries; - dictionaries.AppendStrings(GetParam().spellcheck_dictionaries); - prefs()->Set(prefs::kSpellCheckDictionaries, dictionaries); + base::ListValue spellcheck_dictionaries; + spellcheck_dictionaries.AppendStrings(GetParam().spellcheck_dictionaries); + prefs()->Set(prefs::kSpellCheckDictionaries, spellcheck_dictionaries); - std::vector<std::string> spellcheck_languages; - EXPECT_EQ(GetParam().num_expected_enabled_spellcheck_languages, - SpellcheckService::GetSpellCheckLanguages(context(), - &spellcheck_languages)); + std::vector<SpellcheckService::Dictionary> dictionaries; + SpellcheckService::GetDictionaries(context(), &dictionaries); - EXPECT_EQ(GetParam().expected_spellcheck_languages, spellcheck_languages); + EXPECT_EQ(GetParam().expected_dictionaries, dictionaries); } diff --git a/chrome/common/spellcheck_common.h b/chrome/common/spellcheck_common.h index b237b26..a7bc3dd 100644 --- a/chrome/common/spellcheck_common.h +++ b/chrome/common/spellcheck_common.h @@ -42,6 +42,14 @@ static const size_t MAX_CUSTOM_DICTIONARY_WORD_BYTES = 99; base::FilePath GetVersionedFileName(const std::string& input_language, const base::FilePath& dict_dir); +// Returns the spellcheck language that should be used for |language|. For +// example, converts "hu-HU" into "hu", because we have only one variant of +// Hungarian. Converts "en-US" into "en-US", because we have several variants of +// English dictionaries. +// +// Returns an empty string if no spellcheck language found. For example, there's +// no single dictionary for English, so this function returns an empty string +// for "en". std::string GetCorrespondingSpellCheckLanguage(const std::string& language); // Get SpellChecker supported languages. |