Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(180)

Unified Diff: chrome/browser/chromeos/preferences_unittest.cc

Issue 312023002: Sync starting language and input method preferences (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/preferences_unittest.cc
diff --git a/chrome/browser/chromeos/preferences_unittest.cc b/chrome/browser/chromeos/preferences_unittest.cc
index c8d6f9367018408335918c38b01e0031dbefd61e..41877c43d12a5f7bc535ca98a244ef5f22ce0d6c 100644
--- a/chrome/browser/chromeos/preferences_unittest.cc
+++ b/chrome/browser/chromeos/preferences_unittest.cc
@@ -4,26 +4,81 @@
#include "chrome/browser/chromeos/preferences.h"
+#include "base/json/json_string_value_serializer.h"
#include "base/prefs/pref_member.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "chrome/browser/chromeos/input_method/input_method_configuration.h"
+#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/chromeos/input_method/mock_input_method_manager.h"
#include "chrome/browser/chromeos/login/users/fake_user_manager.h"
#include "chrome/browser/chromeos/login/users/user_manager.h"
+#include "chrome/browser/chromeos/system/fake_input_device_settings.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_pref_service_syncable.h"
+#include "chromeos/ime/extension_ime_util.h"
+#include "chromeos/ime/input_method_whitelist.h"
+#include "chromeos/ime/mock_component_extension_ime_manager_delegate.h"
#include "components/pref_registry/pref_registry_syncable.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
+#include "sync/api/attachments/attachment_id.h"
+#include "sync/api/attachments/attachment_service_proxy_for_test.h"
+#include "sync/api/fake_sync_change_processor.h"
+#include "sync/api/sync_change.h"
+#include "sync/api/sync_data.h"
+#include "sync/api/sync_error_factory.h"
+#include "sync/api/sync_error_factory_mock.h"
+#include "sync/api/syncable_service.h"
+#include "sync/protocol/preference_specifics.pb.h"
+#include "sync/protocol/sync.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
namespace chromeos {
namespace {
-class MyMockInputMethodManager : public input_method::MockInputMethodManager {
+const char kIdentityIMEID[] =
+ "_ext_ime_iafoklpfplgfnoimmaejoeondnjnlcfpIdentityIME";
+const char kToUpperIMEID[] =
+ "_ext_ime_iafoklpfplgfnoimmaejoeondnjnlcfpToUpperIME";
+const char kAPIArgumentIMEID[] =
+ "_ext_ime_iafoklpfplgfnoimmaejoeondnjnlcfpAPIArgumentIME";
+const char kUnknownIMEID[] =
+ "_ext_ime_iafoklpfplgfnoimmaejoeondnjnlcfpUnknownIME";
+
+syncer::SyncData
+CreatePrefSyncData(const std::string& name, const base::Value& value) {
+ std::string serialized;
+ JSONStringValueSerializer json(&serialized);
+ json.Serialize(value);
+ sync_pb::EntitySpecifics specifics;
+ sync_pb::PreferenceSpecifics* pref = specifics.mutable_preference();
+ pref->set_name(name);
+ pref->set_value(serialized);
+ return syncer::SyncData::CreateRemoteData(
+ 1,
+ specifics,
+ base::Time(),
+ syncer::AttachmentIdList(),
+ syncer::AttachmentServiceProxyForTest::Create());
+}
+
+} // anonymous namespace
+
+namespace input_method {
+namespace {
+
+class MyMockInputMethodManager : public MockInputMethodManager {
public:
MyMockInputMethodManager(StringPrefMember* previous,
StringPrefMember* current)
: previous_(previous),
current_(current) {
+ input_method_extensions_.reset(new InputMethodDescriptors);
}
+
virtual ~MyMockInputMethodManager() {
}
@@ -37,48 +92,510 @@ class MyMockInputMethodManager : public input_method::MockInputMethodManager {
current_->SetValue(input_method_id);
}
+ virtual scoped_ptr<InputMethodDescriptors>
+ GetSupportedInputMethods() const OVERRIDE {
+ return whitelist_.GetSupportedInputMethods().Pass();
+ }
+
+ virtual void
+ GetInputMethodExtensions(InputMethodDescriptors* result) OVERRIDE {
+ *result = *input_method_extensions_;
+ }
+
+ virtual void AddInputMethodExtension(
+ const std::string& id, InputMethodEngineInterface* instance) OVERRIDE {
+ InputMethodDescriptor descriptor(
+ id, std::string(), std::string(), std::vector<std::string>(),
+ std::vector<std::string>(), false, GURL(), GURL());
+ input_method_extensions_->push_back(descriptor);
+ }
+
std::string last_input_method_id_;
private:
StringPrefMember* previous_;
StringPrefMember* current_;
+ scoped_ptr<InputMethodDescriptors> input_method_extensions_;
+ InputMethodWhitelist whitelist_;
};
} // anonymous namespace
+} // namespace input_method
+
+class PreferencesTest : public testing::Test {
+ public:
+ PreferencesTest() {}
+ virtual ~PreferencesTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ chromeos::FakeUserManager* user_manager = new chromeos::FakeUserManager();
+ user_manager_enabler_.reset(
+ new chromeos::ScopedUserManagerEnabler(user_manager));
+
+ const char test_user_email[] = "test_user@example.com";
+ test_user_ = user_manager->AddUser(test_user_email);
+ user_manager->LoginUser(test_user_email);
+ user_manager->SwitchActiveUser(test_user_email);
+
+ pref_service_.reset(new TestingPrefServiceSyncable);
+ Preferences::RegisterProfilePrefs(pref_service_->registry());
+ DownloadPrefs::RegisterProfilePrefs(pref_service_->registry());
+
+ // kSelectFileLastDirectory is registered for Profile. Here we register it
+ // for testing.
+ pref_service_->registry()->RegisterStringPref(
+ prefs::kSelectFileLastDirectory,
+ std::string(),
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+
+ previous_input_method_.Init(
+ prefs::kLanguagePreviousInputMethod, pref_service_.get());
+ previous_input_method_.SetValue("KeyboardA");
+ current_input_method_.Init(
+ prefs::kLanguageCurrentInputMethod, pref_service_.get());
+ current_input_method_.SetValue("KeyboardB");
+
+ mock_manager_ = new input_method::MyMockInputMethodManager(
+ &previous_input_method_, &current_input_method_);
+ input_method::InitializeForTesting(mock_manager_);
+ system::InputDeviceSettings::SetSettingsForTesting(
+ new system::FakeInputDeviceSettings());
+
+ prefs_.reset(new Preferences(mock_manager_));
+ }
+
+ virtual void TearDown() OVERRIDE {
+ input_method::Shutdown();
+ }
+
+ scoped_ptr<chromeos::ScopedUserManagerEnabler> user_manager_enabler_;
+ const User* test_user_;
+ scoped_ptr<TestingPrefServiceSyncable> pref_service_;
+ StringPrefMember previous_input_method_;
+ StringPrefMember current_input_method_;
+ input_method::MyMockInputMethodManager* mock_manager_;
+ scoped_ptr<Preferences> prefs_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PreferencesTest);
+};
+
+TEST_F(PreferencesTest, TestUpdatePrefOnBrowserScreenDetails) {
+ prefs_->Init(pref_service_.get(), test_user_);
+
+ // Confirm the current and previous input methods are unchanged.
+ EXPECT_EQ("KeyboardA", previous_input_method_.GetValue());
+ EXPECT_EQ("KeyboardB", current_input_method_.GetValue());
+ EXPECT_EQ("KeyboardB", mock_manager_->last_input_method_id_);
+}
+
+class InputMethodPreferencesTest : public PreferencesTest {
+ public:
+ InputMethodPreferencesTest() {}
+ virtual ~InputMethodPreferencesTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ PreferencesTest::SetUp();
+
+ // Initialize pref members.
+ preferred_languages_.Init(prefs::kLanguagePreferredLanguages,
+ pref_service_.get());
+ preferred_languages_syncable_.Init(
+ prefs::kLanguagePreferredLanguagesSyncable,
+ pref_service_.get());
+ preload_engines_.Init(prefs::kLanguagePreloadEngines, pref_service_.get());
+ preload_engines_syncable_.Init(prefs::kLanguagePreloadEnginesSyncable,
+ pref_service_.get());
+ enabled_extension_imes_.Init(prefs::kLanguageEnabledExtensionImes,
+ pref_service_.get());
+ enabled_extension_imes_syncable_.Init(
+ prefs::kLanguageEnabledExtensionImesSyncable, pref_service_.get());
+
+ // Initialize component and 3rd-party input method extensions.
+ InitComponentExtensionIMEManager();
+ mock_manager_->AddInputMethodExtension(kIdentityIMEID, NULL);
+ mock_manager_->AddInputMethodExtension(kToUpperIMEID, NULL);
+ mock_manager_->AddInputMethodExtension(kAPIArgumentIMEID, NULL);
+ }
+
+ void InitComponentExtensionIMEManager() {
+ // Set our custom IME list on the mock delegate.
+ input_method::MockComponentExtIMEManagerDelegate* mock_delegate =
+ new input_method::MockComponentExtIMEManagerDelegate();
+ mock_delegate->set_ime_list(CreateImeList());
+
+ // Pass the mock delegate to a new ComponentExtensionIMEManager.
+ scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate(mock_delegate);
+ scoped_ptr<ComponentExtensionIMEManager> component_extension_ime_manager(
+ new ComponentExtensionIMEManager);
+ component_extension_ime_manager->Initialize(delegate.Pass());
+
+ // Add the ComponentExtensionIMEManager to the mock InputMethodManager.
+ mock_manager_->SetComponentExtensionIMEManager(
+ component_extension_ime_manager.Pass());
+ }
+
+ std::vector<ComponentExtensionIME> CreateImeList() {
+ std::vector<ComponentExtensionIME> ime_list;
+
+ ComponentExtensionIME ext;
+ ext.id = extension_ime_util::kMozcExtensionId;
+ ext.description = "ext_description";
+ ext.path = base::FilePath("ext_file_path");
+
+ ComponentExtensionEngine ext_engine1;
+ ext_engine1.engine_id = "nacl_mozc_us";
+ ext_engine1.display_name = "ext_engine_1_display_name";
+ ext_engine1.language_codes.push_back("ja");
+ ext_engine1.layouts.push_back("us");
+ ext.engines.push_back(ext_engine1);
+
+ ComponentExtensionEngine ext_engine2;
+ ext_engine2.engine_id = "nacl_mozc_jp";
+ ext_engine2.display_name = "ext_engine_2_display_name";
+ ext_engine2.language_codes.push_back("ja");
+ ext_engine2.layouts.push_back("jp");
+ ext.engines.push_back(ext_engine2);
+
+ ime_list.push_back(ext);
+ return ime_list;
+ }
+
+ // Helper function to set local language and input values.
+ void SetLocalValues(const std::string& preferred_languages,
+ const std::string& preload_engines,
+ const std::string& enabled_extension_imes) {
+ preferred_languages_.SetValue(preferred_languages);
+ preload_engines_.SetValue(preload_engines);
+ enabled_extension_imes_.SetValue(enabled_extension_imes);
+ }
-TEST(PreferencesTest, TestUpdatePrefOnBrowserScreenDetails) {
- chromeos::FakeUserManager* user_manager = new chromeos::FakeUserManager();
- chromeos::ScopedUserManagerEnabler user_manager_enabler(user_manager);
- const char test_user_email[] = "test_user@example.com";
- const User* test_user = user_manager->AddUser(test_user_email);
- user_manager->LoginUser(test_user_email);
-
- TestingPrefServiceSyncable prefs;
- Preferences::RegisterProfilePrefs(prefs.registry());
- DownloadPrefs::RegisterProfilePrefs(prefs.registry());
- // kSelectFileLastDirectory is registered for Profile. Here we register it for
- // testing.
- prefs.registry()->RegisterStringPref(
- prefs::kSelectFileLastDirectory,
- std::string(),
- user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
-
- StringPrefMember previous;
- previous.Init(prefs::kLanguagePreviousInputMethod, &prefs);
- previous.SetValue("KeyboardA");
- StringPrefMember current;
- current.Init(prefs::kLanguageCurrentInputMethod, &prefs);
- current.SetValue("KeyboardB");
-
- MyMockInputMethodManager mock_manager(&previous, &current);
- Preferences testee(&mock_manager);
- testee.InitUserPrefsForTesting(&prefs, test_user);
- testee.SetInputMethodListForTesting();
-
- // Confirm they're unchanged.
- EXPECT_EQ("KeyboardA", previous.GetValue());
- EXPECT_EQ("KeyboardB", current.GetValue());
- EXPECT_EQ("KeyboardB", mock_manager.last_input_method_id_);
+ // Helper function to set global language and input values.
+ void SetGlobalValues(const std::string& preferred_languages,
+ const std::string& preload_engines,
+ const std::string& enabled_extension_imes) {
+ preferred_languages_syncable_.SetValue(preferred_languages);
+ preload_engines_syncable_.SetValue(preload_engines);
+ enabled_extension_imes_syncable_.SetValue(enabled_extension_imes);
+ }
+
+ // Helper function to check local language and input values.
+ void ExpectLocalValues(const std::string& preferred_languages,
+ const std::string& preload_engines,
+ const std::string& enabled_extension_imes) {
+ EXPECT_EQ(preferred_languages, preferred_languages_.GetValue());
+ EXPECT_EQ(preload_engines, preload_engines_.GetValue());
+ EXPECT_EQ(enabled_extension_imes, enabled_extension_imes_.GetValue());
+ }
+
+ // Helper function to check global language and input values.
+ void ExpectGlobalValues(const std::string& preferred_languages,
+ const std::string& preload_engines,
+ const std::string& enabled_extension_imes) {
+ EXPECT_EQ(preferred_languages, preferred_languages_syncable_.GetValue());
+ EXPECT_EQ(preload_engines, preload_engines_syncable_.GetValue());
+ EXPECT_EQ(enabled_extension_imes,
+ enabled_extension_imes_syncable_.GetValue());
+ }
+
+ // Translates engine IDs in a CSV string to input method IDs.
+ std::string ToInputMethodIds(std::string value) {
+ std::vector<std::string> tokens;
+ base::SplitString(value, ',', &tokens);
+ std::transform(tokens.begin(), tokens.end(), tokens.begin(),
+ &extension_ime_util::GetInputMethodIDByEngineID);
+ return JoinString(tokens, ',');
+ }
+
+ StringPrefMember preferred_languages_;
+ StringPrefMember preferred_languages_syncable_;
+ StringPrefMember preload_engines_;
+ StringPrefMember preload_engines_syncable_;
+ StringPrefMember enabled_extension_imes_;
+ StringPrefMember enabled_extension_imes_syncable_;
+ content::TestBrowserThreadBundle thread_bundle_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InputMethodPreferencesTest);
+};
+
+// Tests that the server values are added to the values chosen at OOBE.
+TEST_F(InputMethodPreferencesTest, TestOobeAndSync) {
+ scoped_ptr<input_method::InputMethodDescriptors> input_methods =
+ mock_manager_->GetSupportedInputMethods();
+
+ // Choose options at OOBE.
+ SetLocalValues("es",
+ ToInputMethodIds("xkb:us:altgr-intl:eng"),
+ std::string());
+ pref_service_->SetBoolean(prefs::kLanguageShouldMergeInputMethods, true);
+
+ // Initialize preferences.
+ prefs_->Init(pref_service_.get(), test_user_);
+
+ // Suppose we add an input method before syncing starts.
+ preload_engines_.SetValue(
+ ToInputMethodIds("xkb:us:altgr-intl:eng,xkb:us:intl:eng"));
+
+ // Create some values to come from the server.
+ syncer::SyncDataList sync_data_list;
+ sync_data_list.push_back(CreatePrefSyncData(
+ prefs::kLanguagePreferredLanguagesSyncable, base::StringValue("ru,fi")));
+ sync_data_list.push_back(CreatePrefSyncData(
+ prefs::kLanguagePreloadEnginesSyncable,
+ base::StringValue("xkb:se::swe")));
+ sync_data_list.push_back(CreatePrefSyncData(
+ prefs::kLanguageEnabledExtensionImesSyncable,
+ base::StringValue(kIdentityIMEID)));
+
+ // Sync for the first time.
+ syncer::SyncableService* sync =
+ pref_service_->GetSyncableService(syncer::PREFERENCES);
+ sync->MergeDataAndStartSyncing(syncer::PREFERENCES,
+ sync_data_list,
+ scoped_ptr<syncer::SyncChangeProcessor>(
+ new syncer::FakeSyncChangeProcessor),
+ scoped_ptr<syncer::SyncErrorFactory>(
+ new syncer::SyncErrorFactoryMock));
+ content::RunAllPendingInMessageLoop();
+
+ // Note that we expect the preload_engines to have been translated to input
+ // method IDs during the merge.
+ std::string expected_languages("es,ru,fi");
+ std::string expected_preload_engines(
+ "xkb:us:altgr-intl:eng,xkb:us:intl:eng,xkb:se::swe");
+ std::string expected_extensions(kIdentityIMEID);
+ {
+ SCOPED_TRACE("Server values should have merged into local values.");
+ ExpectLocalValues(
+ expected_languages,
+ ToInputMethodIds(expected_preload_engines),
+ expected_extensions);
+ ExpectGlobalValues(
+ expected_languages, expected_preload_engines, expected_extensions);
+ }
+
+ // Update the global values from the server again.
+ syncer::SyncChangeList change_list;
+ change_list.push_back(syncer::SyncChange(
+ FROM_HERE,
+ syncer::SyncChange::ACTION_UPDATE,
+ CreatePrefSyncData(
+ prefs::kLanguagePreferredLanguagesSyncable,
+ base::StringValue("de"))));
+ change_list.push_back(syncer::SyncChange(
+ FROM_HERE,
+ syncer::SyncChange::ACTION_UPDATE,
+ CreatePrefSyncData(
+ prefs::kLanguagePreloadEnginesSyncable,
+ base::StringValue(ToInputMethodIds("xkb:de::ger")))));
+ change_list.push_back(syncer::SyncChange(
+ FROM_HERE,
+ syncer::SyncChange::ACTION_UPDATE,
+ CreatePrefSyncData(
+ prefs::kLanguageEnabledExtensionImesSyncable,
+ base::StringValue(kToUpperIMEID))));
+ sync->ProcessSyncChanges(FROM_HERE, change_list);
+ content::RunAllPendingInMessageLoop();
+
+ {
+ SCOPED_TRACE("Local preferences should have remained the same.");
+ ExpectLocalValues(
+ expected_languages,
+ ToInputMethodIds(expected_preload_engines),
+ expected_extensions);
+ }
+ // Change local preferences.
+ SetLocalValues("ja", ToInputMethodIds("xkb:jp::jpn"), "ime2");
+ {
+ SCOPED_TRACE("Global preferences should have been updated.");
+ ExpectGlobalValues("ja", "xkb:jp::jpn", "ime2");
+ }
+}
+
+// Test that logging in after sync has completed changes nothing.
+TEST_F(InputMethodPreferencesTest, TestLogIn) {
+ // Set up existing preference values.
+ std::string languages("es");
+ std::string preload_engines(ToInputMethodIds("xkb:es::spa"));
+ std::string extensions(kIdentityIMEID);
+
+ SetLocalValues(languages, preload_engines, extensions);
+ SetGlobalValues(languages, preload_engines, extensions);
+ pref_service_->SetBoolean(prefs::kLanguageShouldMergeInputMethods, false);
+
+ // Initialize preferences.
+ prefs_->Init(pref_service_.get(), test_user_);
+
+ // Create some values to come from the server.
+ syncer::SyncDataList sync_data_list;
+ sync_data_list.push_back(CreatePrefSyncData(
+ prefs::kLanguagePreferredLanguages, base::StringValue("ru,fi")));
+ sync_data_list.push_back(CreatePrefSyncData(
+ prefs::kLanguagePreloadEngines,
+ base::StringValue(ToInputMethodIds("xkb:ru::rus"))));
+ sync_data_list.push_back(CreatePrefSyncData(
+ prefs::kLanguageEnabledExtensionImes, base::StringValue(kIdentityIMEID)));
+
+ // Sync.
+ syncer::SyncableService* sync =
+ pref_service_->GetSyncableService(syncer::PREFERENCES);
+ sync->MergeDataAndStartSyncing(syncer::PREFERENCES,
+ sync_data_list,
+ scoped_ptr<syncer::SyncChangeProcessor>(
+ new syncer::FakeSyncChangeProcessor),
+ scoped_ptr<syncer::SyncErrorFactory>(
+ new syncer::SyncErrorFactoryMock));
+ content::RunAllPendingInMessageLoop();
+ {
+ SCOPED_TRACE("Local preferences should have remained the same.");
+ ExpectLocalValues(languages, preload_engines, extensions);
+ }
+ // Change local preferences.
+ SetLocalValues("ja", ToInputMethodIds("xkb:jp::jpn"), kToUpperIMEID);
+ {
+ SCOPED_TRACE("Global preferences should have been updated.");
+ ExpectGlobalValues("ja", "xkb:jp::jpn", kToUpperIMEID);
+ }
+}
+
+// Tests that logging in with preferences from before a) XKB component
+// extensions and b) this IME syncing logic doesn't overwrite settings.
+TEST_F(InputMethodPreferencesTest, TestLogInLegacy) {
+ // Simulate existing local preferences from M-36.
+ SetLocalValues("es", "xkb:es::spa", kIdentityIMEID);
+
+ // Initialize preferences.
+ prefs_->Init(pref_service_.get(), test_user_);
+
+ // Sync. Since this is an existing profile, the local values shouldn't change.
+ syncer::SyncDataList sync_data_list;
+ sync_data_list.push_back(CreatePrefSyncData(
+ prefs::kLanguagePreferredLanguagesSyncable, base::StringValue("ru,fi")));
+ sync_data_list.push_back(CreatePrefSyncData(
+ prefs::kLanguagePreloadEnginesSyncable,
+ base::StringValue(ToInputMethodIds("xkb:ru::rus"))));
+ sync_data_list.push_back(CreatePrefSyncData(
+ prefs::kLanguageEnabledExtensionImesSyncable,
+ base::StringValue(kToUpperIMEID)));
+
+ syncer::SyncableService* sync =
+ pref_service_->GetSyncableService(syncer::PREFERENCES);
+ sync->MergeDataAndStartSyncing(syncer::PREFERENCES,
+ sync_data_list,
+ scoped_ptr<syncer::SyncChangeProcessor>(
+ new syncer::FakeSyncChangeProcessor),
+ scoped_ptr<syncer::SyncErrorFactory>(
+ new syncer::SyncErrorFactoryMock));
+ content::RunAllPendingInMessageLoop();
+ {
+ SCOPED_TRACE("Local preferences should have remained the same.");
+ ExpectLocalValues("es", "xkb:es::spa", kIdentityIMEID);
+ }
+ // Change local preferences.
+ SetLocalValues("ja", ToInputMethodIds("xkb:jp::jp"), kAPIArgumentIMEID);
+ {
+ SCOPED_TRACE("Global preferences should have been updated.");
+ ExpectGlobalValues("ja", "xkb:jp::jp", kAPIArgumentIMEID);
+ }
+}
+
+// Tests some edge cases: empty strings, lots of values, duplicates.
+TEST_F(InputMethodPreferencesTest, MergeStressTest) {
+ SetLocalValues("hr,lv,lt,es-419,he,el,da,ca,es,cs,bg",
+ ToInputMethodIds("xkb:es::spa,xkb:us::eng"),
+ std::string());
+ pref_service_->SetBoolean(prefs::kLanguageShouldMergeInputMethods, true);
+
+ // Initialize preferences.
+ prefs_->Init(pref_service_.get(), test_user_);
+
+ // Change input methods and languages before syncing starts.
+ std::string local_extensions =
+ kToUpperIMEID + std::string(",") +
+ kAPIArgumentIMEID + std::string(",") +
+ kIdentityIMEID;
+ SetLocalValues(
+ "en,es,ja,hr,lv,lt,es-419,he,el,da,ca,es,cs,bg,ar",
+ ToInputMethodIds("xkb:es::spa,xkb:us:dvorak,xkb:ua::ukr"),
+ local_extensions);
+
+ // Create some tricky values to come from the server.
+ syncer::SyncDataList sync_data_list;
+ sync_data_list.push_back(CreatePrefSyncData(
+ prefs::kLanguagePreferredLanguagesSyncable,
+ base::StringValue("ar,fi,es,de,ar")));
+ sync_data_list.push_back(CreatePrefSyncData(
+ prefs::kLanguagePreloadEnginesSyncable,
+ base::StringValue(
+ "nacl_mozc_us,xkb:ru::rus,xkb:ru::rus,xkb:es::spa,xkb:es::spa")));
+ sync_data_list.push_back(CreatePrefSyncData(
+ prefs::kLanguageEnabledExtensionImesSyncable,
+ base::StringValue(std::string())));
+
+ // Sync for the first time.
+ syncer::SyncableService* sync =
+ pref_service_->GetSyncableService(syncer::PREFERENCES);
+ sync->MergeDataAndStartSyncing(syncer::PREFERENCES,
+ sync_data_list,
+ scoped_ptr<syncer::SyncChangeProcessor>(
+ new syncer::FakeSyncChangeProcessor),
+ scoped_ptr<syncer::SyncErrorFactory>(
+ new syncer::SyncErrorFactoryMock));
+ content::RunAllPendingInMessageLoop();
+ {
+ SCOPED_TRACE("Server values should have merged with local values.");
+ ExpectLocalValues(
+ "en-US,es,ja,hr,lv,lt,es-419,he,el,da,ca,es,cs,bg,ar,fi,de",
+ ToInputMethodIds("xkb:es::spa,xkb:us:dvorak,xkb:ua::ukr,"
+ "nacl_mozc_us,xkb:ru::rus"),
+ local_extensions);
+ }
+}
+
+// Tests non-existent IDs.
+TEST_F(InputMethodPreferencesTest, MergeInvalidValues) {
+ SetLocalValues("es",
+ ToInputMethodIds("xkb:es::spa,xkb:us::eng"),
+ kIdentityIMEID);
+ pref_service_->SetBoolean(prefs::kLanguageShouldMergeInputMethods, true);
+
+ // Initialize preferences.
+ prefs_->Init(pref_service_.get(), test_user_);
+
+ // Create some valid and some non-existent IDs from the server.
+ std::string preload_engines(
+ "xkb:ru::rus,xkb:xy::xyz,"
+ "_comp_ime_nothisisnotactuallyanextensionidxkb:es::spa," +
+ ToInputMethodIds("xkb:jp::jpn"));
+ syncer::SyncDataList sync_data_list;
+ sync_data_list.push_back(CreatePrefSyncData(
+ prefs::kLanguagePreferredLanguagesSyncable,
+ base::StringValue("klingon,en")));
+ sync_data_list.push_back(CreatePrefSyncData(
+ prefs::kLanguagePreloadEnginesSyncable,
+ base::StringValue(preload_engines)));
+ sync_data_list.push_back(CreatePrefSyncData(
+ prefs::kLanguageEnabledExtensionImesSyncable,
+ base::StringValue(kUnknownIMEID)));
+
+ // Sync for the first time.
+ syncer::SyncableService* sync =
+ pref_service_->GetSyncableService(syncer::PREFERENCES);
+ sync->MergeDataAndStartSyncing(syncer::PREFERENCES,
+ sync_data_list,
+ scoped_ptr<syncer::SyncChangeProcessor>(
+ new syncer::FakeSyncChangeProcessor),
+ scoped_ptr<syncer::SyncErrorFactory>(
+ new syncer::SyncErrorFactoryMock));
+ content::RunAllPendingInMessageLoop();
+ {
+ SCOPED_TRACE("Only valid server values should have been merged in.");
+ ExpectLocalValues(
+ "es,en-US",
+ ToInputMethodIds("xkb:es::spa,xkb:us::eng,xkb:ru::rus,xkb:jp::jpn"),
+ kIdentityIMEID);
+ }
}
} // namespace chromeos

Powered by Google App Engine
This is Rietveld 408576698