1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/preferences.h"
7 #include "base/json/json_string_value_serializer.h"
8 #include "base/prefs/pref_member.h"
9 #include "base/strings/string_split.h"
10 #include "base/strings/string_util.h"
11 #include "chrome/browser/chromeos/input_method/input_method_configuration.h"
12 #include "chrome/browser/chromeos/input_method/mock_input_method_manager.h"
13 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
14 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
15 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
16 #include "chrome/browser/chromeos/system/fake_input_device_settings.h"
17 #include "chrome/common/chrome_constants.h"
18 #include "chrome/common/pref_names.h"
19 #include "chrome/test/base/testing_browser_process.h"
20 #include "chrome/test/base/testing_pref_service_syncable.h"
21 #include "chrome/test/base/testing_profile.h"
22 #include "chrome/test/base/testing_profile_manager.h"
23 #include "content/public/test/test_browser_thread_bundle.h"
24 #include "content/public/test/test_utils.h"
25 #include "sync/api/attachments/attachment_id.h"
26 #include "sync/api/fake_sync_change_processor.h"
27 #include "sync/api/sync_change.h"
28 #include "sync/api/sync_data.h"
29 #include "sync/api/sync_error_factory.h"
30 #include "sync/api/sync_error_factory_mock.h"
31 #include "sync/api/syncable_service.h"
32 #include "sync/internal_api/public/attachments/attachment_service_proxy_for_test.h"
33 #include "sync/protocol/preference_specifics.pb.h"
34 #include "sync/protocol/sync.pb.h"
35 #include "testing/gtest/include/gtest/gtest.h"
36 #include "ui/base/ime/chromeos/extension_ime_util.h"
37 #include "ui/base/ime/chromeos/input_method_whitelist.h"
38 #include "ui/base/ime/chromeos/mock_component_extension_ime_manager_delegate.h"
44 const char kIdentityIMEID
[] =
45 "_ext_ime_iafoklpfplgfnoimmaejoeondnjnlcfpIdentityIME";
46 const char kToUpperIMEID
[] =
47 "_ext_ime_iafoklpfplgfnoimmaejoeondnjnlcfpToUpperIME";
48 const char kAPIArgumentIMEID
[] =
49 "_ext_ime_iafoklpfplgfnoimmaejoeondnjnlcfpAPIArgumentIME";
50 const char kUnknownIMEID
[] =
51 "_ext_ime_iafoklpfplgfnoimmaejoeondnjnlcfpUnknownIME";
54 CreatePrefSyncData(const std::string
& name
, const base::Value
& value
) {
55 std::string serialized
;
56 JSONStringValueSerializer
json(&serialized
);
57 json
.Serialize(value
);
58 sync_pb::EntitySpecifics specifics
;
59 sync_pb::PreferenceSpecifics
* pref
= specifics
.mutable_preference();
61 pref
->set_value(serialized
);
62 return syncer::SyncData::CreateRemoteData(
66 syncer::AttachmentIdList(),
67 syncer::AttachmentServiceProxyForTest::Create());
70 } // anonymous namespace
72 namespace input_method
{
75 class MyMockInputMethodManager
: public MockInputMethodManager
{
77 class State
: public MockInputMethodManager::State
{
79 explicit State(MyMockInputMethodManager
* manager
)
80 : MockInputMethodManager::State(manager
), manager_(manager
) {
81 input_method_extensions_
.reset(new InputMethodDescriptors
);
84 void ChangeInputMethod(const std::string
& input_method_id
,
85 bool show_message
) override
{
86 manager_
->last_input_method_id_
= input_method_id
;
87 // Do the same thing as BrowserStateMonitor::UpdateUserPreferences.
88 const std::string current_input_method_on_pref
=
89 manager_
->current_
->GetValue();
90 if (current_input_method_on_pref
== input_method_id
)
92 manager_
->previous_
->SetValue(current_input_method_on_pref
);
93 manager_
->current_
->SetValue(input_method_id
);
96 void GetInputMethodExtensions(InputMethodDescriptors
* result
) override
{
97 *result
= *input_method_extensions_
;
100 void AddInputMethodExtension(
101 const std::string
& id
,
102 const InputMethodDescriptors
& descriptors
,
103 InputMethodEngineInterface
* instance
) override
{
104 InputMethodDescriptor
descriptor(
105 id
, std::string(), std::string(), std::vector
<std::string
>(),
106 std::vector
<std::string
>(), false, GURL(), GURL());
107 input_method_extensions_
->push_back(descriptor
);
114 MyMockInputMethodManager
* const manager_
;
115 scoped_ptr
<InputMethodDescriptors
> input_method_extensions_
;
118 MyMockInputMethodManager(StringPrefMember
* previous
,
119 StringPrefMember
* current
)
120 : previous_(previous
),
122 state_
= new State(this);
125 ~MyMockInputMethodManager() override
{}
127 scoped_ptr
<InputMethodDescriptors
> GetSupportedInputMethods() const override
{
128 return whitelist_
.GetSupportedInputMethods().Pass();
131 std::string last_input_method_id_
;
134 StringPrefMember
* previous_
;
135 StringPrefMember
* current_
;
136 InputMethodWhitelist whitelist_
;
139 } // anonymous namespace
140 } // namespace input_method
142 class PreferencesTest
: public testing::Test
{
145 ~PreferencesTest() override
{}
147 void SetUp() override
{
148 profile_manager_
.reset(
149 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
150 ASSERT_TRUE(profile_manager_
->SetUp());
152 chromeos::FakeChromeUserManager
* user_manager
=
153 new chromeos::FakeChromeUserManager();
154 user_manager_enabler_
.reset(
155 new chromeos::ScopedUserManagerEnabler(user_manager
));
157 const char test_user_email
[] = "test_user@example.com";
158 test_user_
= user_manager
->AddUser(test_user_email
);
159 user_manager
->LoginUser(test_user_email
);
160 user_manager
->SwitchActiveUser(test_user_email
);
162 test_profile_
= profile_manager_
->CreateTestingProfile(
163 chrome::kInitialProfile
);
164 pref_service_
= test_profile_
->GetTestingPrefService();
166 previous_input_method_
.Init(
167 prefs::kLanguagePreviousInputMethod
, pref_service_
);
168 previous_input_method_
.SetValue("KeyboardA");
169 current_input_method_
.Init(
170 prefs::kLanguageCurrentInputMethod
, pref_service_
);
171 current_input_method_
.SetValue("KeyboardB");
173 mock_manager_
= new input_method::MyMockInputMethodManager(
174 &previous_input_method_
, ¤t_input_method_
);
175 input_method::InitializeForTesting(mock_manager_
);
176 system::InputDeviceSettings::SetSettingsForTesting(
177 new system::FakeInputDeviceSettings());
179 prefs_
.reset(new Preferences(mock_manager_
));
182 void TearDown() override
{
183 input_method::Shutdown();
184 // UserSessionManager doesn't listen to profile destruction, so make sure
185 // the default IME state isn't still cached in case test_profile_ is
186 // given the same address in the next test.
187 UserSessionManager::GetInstance()->RemoveProfileForTesting(test_profile_
);
190 void InitPreferences() {
191 prefs_
->InitUserPrefsForTesting(
192 pref_service_
, test_user_
, mock_manager_
->GetActiveIMEState());
193 prefs_
->SetInputMethodListForTesting();
196 content::TestBrowserThreadBundle thread_bundle_
;
197 scoped_ptr
<TestingProfileManager
> profile_manager_
;
198 scoped_ptr
<chromeos::ScopedUserManagerEnabler
> user_manager_enabler_
;
199 scoped_ptr
<Preferences
> prefs_
;
200 StringPrefMember previous_input_method_
;
201 StringPrefMember current_input_method_
;
204 const user_manager::User
* test_user_
;
205 TestingProfile
* test_profile_
;
206 TestingPrefServiceSyncable
* pref_service_
;
207 input_method::MyMockInputMethodManager
* mock_manager_
;
210 DISALLOW_COPY_AND_ASSIGN(PreferencesTest
);
213 TEST_F(PreferencesTest
, TestUpdatePrefOnBrowserScreenDetails
) {
216 // Confirm the current and previous input methods are unchanged.
217 EXPECT_EQ("KeyboardA", previous_input_method_
.GetValue());
218 EXPECT_EQ("KeyboardB", current_input_method_
.GetValue());
219 EXPECT_EQ("KeyboardB", mock_manager_
->last_input_method_id_
);
222 class InputMethodPreferencesTest
: public PreferencesTest
{
224 InputMethodPreferencesTest() {}
225 ~InputMethodPreferencesTest() override
{}
227 void SetUp() override
{
228 PreferencesTest::SetUp();
230 // Initialize pref members.
231 preferred_languages_
.Init(prefs::kLanguagePreferredLanguages
,
233 preferred_languages_syncable_
.Init(
234 prefs::kLanguagePreferredLanguagesSyncable
,
236 preload_engines_
.Init(prefs::kLanguagePreloadEngines
, pref_service_
);
237 preload_engines_syncable_
.Init(prefs::kLanguagePreloadEnginesSyncable
,
239 enabled_extension_imes_
.Init(prefs::kLanguageEnabledExtensionImes
,
241 enabled_extension_imes_syncable_
.Init(
242 prefs::kLanguageEnabledExtensionImesSyncable
, pref_service_
);
244 // Initialize component and 3rd-party input method extensions.
245 InitComponentExtensionIMEManager();
246 input_method::InputMethodDescriptors descriptors
;
247 mock_manager_
->GetActiveIMEState()->AddInputMethodExtension(
251 mock_manager_
->GetActiveIMEState()->AddInputMethodExtension(
255 mock_manager_
->GetActiveIMEState()->AddInputMethodExtension(
261 void InitComponentExtensionIMEManager() {
262 // Set our custom IME list on the mock delegate.
263 input_method::MockComponentExtIMEManagerDelegate
* mock_delegate
=
264 new input_method::MockComponentExtIMEManagerDelegate();
265 mock_delegate
->set_ime_list(CreateImeList());
267 // Pass the mock delegate to a new ComponentExtensionIMEManager.
268 scoped_ptr
<ComponentExtensionIMEManagerDelegate
> delegate(mock_delegate
);
269 scoped_ptr
<ComponentExtensionIMEManager
> component_extension_ime_manager(
270 new ComponentExtensionIMEManager
);
271 component_extension_ime_manager
->Initialize(delegate
.Pass());
273 // Add the ComponentExtensionIMEManager to the mock InputMethodManager.
274 mock_manager_
->SetComponentExtensionIMEManager(
275 component_extension_ime_manager
.Pass());
278 std::vector
<ComponentExtensionIME
> CreateImeList() {
279 std::vector
<ComponentExtensionIME
> ime_list
;
281 ComponentExtensionIME ext
;
282 ext
.id
= extension_ime_util::kMozcExtensionId
;
283 ext
.description
= "ext_description";
284 ext
.path
= base::FilePath("ext_file_path");
286 ComponentExtensionEngine ext_engine1
;
287 ext_engine1
.engine_id
= "nacl_mozc_us";
288 ext_engine1
.display_name
= "ext_engine_1_display_name";
289 ext_engine1
.language_codes
.push_back("ja");
290 ext_engine1
.layouts
.push_back("us");
291 ext
.engines
.push_back(ext_engine1
);
293 ComponentExtensionEngine ext_engine2
;
294 ext_engine2
.engine_id
= "nacl_mozc_jp";
295 ext_engine2
.display_name
= "ext_engine_2_display_name";
296 ext_engine2
.language_codes
.push_back("ja");
297 ext_engine2
.layouts
.push_back("jp");
298 ext
.engines
.push_back(ext_engine2
);
300 ime_list
.push_back(ext
);
304 // Helper function to set local language and input values.
305 void SetLocalValues(const std::string
& preferred_languages
,
306 const std::string
& preload_engines
,
307 const std::string
& enabled_extension_imes
) {
308 preferred_languages_
.SetValue(preferred_languages
);
309 preload_engines_
.SetValue(preload_engines
);
310 enabled_extension_imes_
.SetValue(enabled_extension_imes
);
313 // Helper function to set global language and input values.
314 void SetGlobalValues(const std::string
& preferred_languages
,
315 const std::string
& preload_engines
,
316 const std::string
& enabled_extension_imes
) {
317 preferred_languages_syncable_
.SetValue(preferred_languages
);
318 preload_engines_syncable_
.SetValue(preload_engines
);
319 enabled_extension_imes_syncable_
.SetValue(enabled_extension_imes
);
322 // Helper function to check local language and input values.
323 void ExpectLocalValues(const std::string
& preferred_languages
,
324 const std::string
& preload_engines
,
325 const std::string
& enabled_extension_imes
) {
326 EXPECT_EQ(preferred_languages
, preferred_languages_
.GetValue());
327 EXPECT_EQ(preload_engines
, preload_engines_
.GetValue());
328 EXPECT_EQ(enabled_extension_imes
, enabled_extension_imes_
.GetValue());
331 // Helper function to check global language and input values.
332 void ExpectGlobalValues(const std::string
& preferred_languages
,
333 const std::string
& preload_engines
,
334 const std::string
& enabled_extension_imes
) {
335 EXPECT_EQ(preferred_languages
, preferred_languages_syncable_
.GetValue());
336 EXPECT_EQ(preload_engines
, preload_engines_syncable_
.GetValue());
337 EXPECT_EQ(enabled_extension_imes
,
338 enabled_extension_imes_syncable_
.GetValue());
341 // Translates engine IDs in a CSV string to input method IDs.
342 std::string
ToInputMethodIds(std::string value
) {
343 std::vector
<std::string
> tokens
= base::SplitString(
344 value
, ",", base::TRIM_WHITESPACE
, base::SPLIT_WANT_ALL
);
345 std::transform(tokens
.begin(), tokens
.end(), tokens
.begin(),
346 &extension_ime_util::GetInputMethodIDByEngineID
);
347 return base::JoinString(tokens
, ",");
350 StringPrefMember preferred_languages_
;
351 StringPrefMember preferred_languages_syncable_
;
352 StringPrefMember preload_engines_
;
353 StringPrefMember preload_engines_syncable_
;
354 StringPrefMember enabled_extension_imes_
;
355 StringPrefMember enabled_extension_imes_syncable_
;
358 DISALLOW_COPY_AND_ASSIGN(InputMethodPreferencesTest
);
361 // Tests that the server values are added to the values chosen at OOBE.
362 TEST_F(InputMethodPreferencesTest
, TestOobeAndSync
) {
363 // Choose options at OOBE.
364 pref_service_
->SetBoolean(
365 prefs::kLanguageShouldMergeInputMethods
, true);
367 ToInputMethodIds("xkb:us:altgr-intl:eng"),
371 // Suppose we add an input method before syncing starts.
372 preload_engines_
.SetValue(
373 ToInputMethodIds("xkb:us:altgr-intl:eng,xkb:us:intl:eng"));
375 // Create some values to come from the server.
376 syncer::SyncDataList sync_data_list
;
377 sync_data_list
.push_back(CreatePrefSyncData(
378 prefs::kLanguagePreferredLanguagesSyncable
, base::StringValue("ru,fi")));
379 sync_data_list
.push_back(CreatePrefSyncData(
380 prefs::kLanguagePreloadEnginesSyncable
,
381 base::StringValue("xkb:se::swe")));
382 sync_data_list
.push_back(CreatePrefSyncData(
383 prefs::kLanguageEnabledExtensionImesSyncable
,
384 base::StringValue(kIdentityIMEID
)));
386 // Sync for the first time.
387 syncer::SyncableService
* sync
=
388 pref_service_
->GetSyncableService(
389 syncer::PREFERENCES
);
390 sync
->MergeDataAndStartSyncing(syncer::PREFERENCES
,
392 scoped_ptr
<syncer::SyncChangeProcessor
>(
393 new syncer::FakeSyncChangeProcessor
),
394 scoped_ptr
<syncer::SyncErrorFactory
>(
395 new syncer::SyncErrorFactoryMock
));
396 content::RunAllBlockingPoolTasksUntilIdle();
398 // Note that we expect the preload_engines to have been translated to input
399 // method IDs during the merge.
400 std::string
expected_languages("es,ru,fi");
401 std::string
expected_preload_engines(
402 "xkb:us:altgr-intl:eng,xkb:us:intl:eng,xkb:se::swe");
403 std::string
expected_extensions(kIdentityIMEID
);
405 SCOPED_TRACE("Server values should have merged into local values.");
408 ToInputMethodIds(expected_preload_engines
),
409 expected_extensions
);
412 SCOPED_TRACE("Server values should have been updated to local values.");
414 expected_languages
, expected_preload_engines
, expected_extensions
);
417 // Update the global values from the server again.
418 syncer::SyncChangeList change_list
;
419 change_list
.push_back(syncer::SyncChange(
421 syncer::SyncChange::ACTION_UPDATE
,
423 prefs::kLanguagePreferredLanguagesSyncable
,
424 base::StringValue("de"))));
425 change_list
.push_back(syncer::SyncChange(
427 syncer::SyncChange::ACTION_UPDATE
,
429 prefs::kLanguagePreloadEnginesSyncable
,
430 base::StringValue(ToInputMethodIds("xkb:de::ger")))));
431 change_list
.push_back(syncer::SyncChange(
433 syncer::SyncChange::ACTION_UPDATE
,
435 prefs::kLanguageEnabledExtensionImesSyncable
,
436 base::StringValue(kToUpperIMEID
))));
437 sync
->ProcessSyncChanges(FROM_HERE
, change_list
);
438 content::RunAllBlockingPoolTasksUntilIdle();
441 SCOPED_TRACE("Local preferences should have remained the same.");
444 ToInputMethodIds(expected_preload_engines
),
445 expected_extensions
);
447 // Change local preferences.
448 SetLocalValues("ja", ToInputMethodIds("xkb:jp::jpn"), "ime2");
450 SCOPED_TRACE("Global preferences should have been updated.");
451 ExpectGlobalValues("ja", "xkb:jp::jpn", "ime2");
453 content::RunAllBlockingPoolTasksUntilIdle();
456 // Tests that logging in after sync has completed changes nothing.
457 TEST_F(InputMethodPreferencesTest
, TestLogIn
) {
458 // Set up existing preference values.
459 std::string
languages("es");
460 std::string
preload_engines(ToInputMethodIds("xkb:es::spa"));
461 std::string
extensions(kIdentityIMEID
);
463 SetLocalValues(languages
, preload_engines
, extensions
);
464 SetGlobalValues(languages
, preload_engines
, extensions
);
465 pref_service_
->SetBoolean(
466 prefs::kLanguageShouldMergeInputMethods
, false);
469 // Create some values to come from the server.
470 syncer::SyncDataList sync_data_list
;
471 sync_data_list
.push_back(CreatePrefSyncData(
472 prefs::kLanguagePreferredLanguages
, base::StringValue("ru,fi")));
473 sync_data_list
.push_back(CreatePrefSyncData(
474 prefs::kLanguagePreloadEngines
,
475 base::StringValue(ToInputMethodIds("xkb:ru::rus"))));
476 sync_data_list
.push_back(CreatePrefSyncData(
477 prefs::kLanguageEnabledExtensionImes
, base::StringValue(kIdentityIMEID
)));
480 syncer::SyncableService
* sync
=
481 pref_service_
->GetSyncableService(
482 syncer::PREFERENCES
);
483 sync
->MergeDataAndStartSyncing(syncer::PREFERENCES
,
485 scoped_ptr
<syncer::SyncChangeProcessor
>(
486 new syncer::FakeSyncChangeProcessor
),
487 scoped_ptr
<syncer::SyncErrorFactory
>(
488 new syncer::SyncErrorFactoryMock
));
489 content::RunAllBlockingPoolTasksUntilIdle();
491 SCOPED_TRACE("Local preferences should have remained the same.");
492 ExpectLocalValues(languages
, preload_engines
, extensions
);
494 // Change local preferences.
495 SetLocalValues("ja", ToInputMethodIds("xkb:jp::jpn"), kToUpperIMEID
);
496 content::RunAllBlockingPoolTasksUntilIdle();
498 SCOPED_TRACE("Global preferences should have been updated.");
499 ExpectGlobalValues("ja", "xkb:jp::jpn", kToUpperIMEID
);
503 // Tests that logging in with preferences from before a) XKB component
504 // extensions and b) the IME syncing logic doesn't overwrite settings.
505 TEST_F(InputMethodPreferencesTest
, TestLogInLegacy
) {
506 // Simulate existing local preferences from M-36.
507 SetLocalValues("es", "xkb:es::spa", kIdentityIMEID
);
510 // Sync. Since this is an existing profile, the local values shouldn't change.
511 syncer::SyncDataList sync_data_list
;
512 sync_data_list
.push_back(CreatePrefSyncData(
513 prefs::kLanguagePreferredLanguagesSyncable
, base::StringValue("ru,fi")));
514 sync_data_list
.push_back(CreatePrefSyncData(
515 prefs::kLanguagePreloadEnginesSyncable
,
516 base::StringValue(ToInputMethodIds("xkb:ru::rus"))));
517 sync_data_list
.push_back(CreatePrefSyncData(
518 prefs::kLanguageEnabledExtensionImesSyncable
,
519 base::StringValue(kToUpperIMEID
)));
521 syncer::SyncableService
* sync
=
522 pref_service_
->GetSyncableService(
523 syncer::PREFERENCES
);
524 sync
->MergeDataAndStartSyncing(syncer::PREFERENCES
,
526 scoped_ptr
<syncer::SyncChangeProcessor
>(
527 new syncer::FakeSyncChangeProcessor
),
528 scoped_ptr
<syncer::SyncErrorFactory
>(
529 new syncer::SyncErrorFactoryMock
));
530 content::RunAllBlockingPoolTasksUntilIdle();
532 SCOPED_TRACE("Local preferences should have remained the same.");
533 ExpectLocalValues("es", "xkb:es::spa", kIdentityIMEID
);
536 SCOPED_TRACE("Global preferences should have remained the same.");
537 ExpectGlobalValues("ru,fi", ToInputMethodIds("xkb:ru::rus"), kToUpperIMEID
);
539 // Change local preferences.
540 SetLocalValues("ja", ToInputMethodIds("xkb:jp::jp"), kAPIArgumentIMEID
);
542 SCOPED_TRACE("Global preferences should have been updated.");
543 ExpectGlobalValues("ja", "xkb:jp::jp", kAPIArgumentIMEID
);
547 // Tests some edge cases: empty strings, lots of values, duplicates.
548 TEST_F(InputMethodPreferencesTest
, MergeStressTest
) {
549 SetLocalValues("hr,lv,lt,es-419,he,el,da,ca,es,cs,bg",
550 ToInputMethodIds("xkb:es::spa,xkb:us::eng"),
552 pref_service_
->SetBoolean(
553 prefs::kLanguageShouldMergeInputMethods
, true);
556 // Change input methods and languages before syncing starts.
557 std::string local_extensions
=
558 kToUpperIMEID
+ std::string(",") +
559 kAPIArgumentIMEID
+ std::string(",") +
562 "en,es,ja,hr,lv,lt,es-419,he,el,da,ca,es,cs,bg,ar",
563 ToInputMethodIds("xkb:es::spa,xkb:us:dvorak,xkb:ua::ukr"),
566 // Create some tricky values to come from the server.
567 syncer::SyncDataList sync_data_list
;
568 sync_data_list
.push_back(CreatePrefSyncData(
569 prefs::kLanguagePreferredLanguagesSyncable
,
570 base::StringValue("ar,fi,es,de,ar")));
571 sync_data_list
.push_back(CreatePrefSyncData(
572 prefs::kLanguagePreloadEnginesSyncable
,
574 "nacl_mozc_us,xkb:ru::rus,xkb:ru::rus,xkb:es::spa,xkb:es::spa")));
575 sync_data_list
.push_back(CreatePrefSyncData(
576 prefs::kLanguageEnabledExtensionImesSyncable
,
577 base::StringValue(std::string())));
579 // Sync for the first time.
580 syncer::SyncableService
* sync
=
581 pref_service_
->GetSyncableService(
582 syncer::PREFERENCES
);
583 sync
->MergeDataAndStartSyncing(syncer::PREFERENCES
,
585 scoped_ptr
<syncer::SyncChangeProcessor
>(
586 new syncer::FakeSyncChangeProcessor
),
587 scoped_ptr
<syncer::SyncErrorFactory
>(
588 new syncer::SyncErrorFactoryMock
));
589 content::RunAllBlockingPoolTasksUntilIdle();
591 SCOPED_TRACE("Server values should have merged into local values.");
593 "en,es,ja,hr,lv,lt,es-419,he,el,da,ca,es,cs,bg,ar,fi,de",
594 ToInputMethodIds("xkb:es::spa,xkb:us:dvorak,xkb:ua::ukr,"
595 "nacl_mozc_us,xkb:ru::rus"),
599 SCOPED_TRACE("Server values should have incorporated local values.");
601 "en,es,ja,hr,lv,lt,es-419,he,el,da,ca,es,cs,bg,ar,fi,de",
602 "xkb:es::spa,xkb:us:dvorak,xkb:ua::ukr,nacl_mozc_us,xkb:ru::rus",
607 // Tests non-existent IDs.
608 TEST_F(InputMethodPreferencesTest
, MergeInvalidValues
) {
610 ToInputMethodIds("xkb:es::spa,xkb:us::eng"),
612 pref_service_
->SetBoolean(
613 prefs::kLanguageShouldMergeInputMethods
, true);
616 // Create some valid and some non-existent IDs from the server.
617 std::string
preload_engines(
618 "xkb:ru::rus,xkb:xy::xyz,"
619 "_comp_ime_nothisisnotactuallyanextensionidxkb:es::spa," +
620 ToInputMethodIds("xkb:jp::jpn"));
621 syncer::SyncDataList sync_data_list
;
622 sync_data_list
.push_back(CreatePrefSyncData(
623 prefs::kLanguagePreferredLanguagesSyncable
,
624 base::StringValue("klingon,en-US")));
625 sync_data_list
.push_back(CreatePrefSyncData(
626 prefs::kLanguagePreloadEnginesSyncable
,
627 base::StringValue(preload_engines
)));
628 sync_data_list
.push_back(CreatePrefSyncData(
629 prefs::kLanguageEnabledExtensionImesSyncable
,
630 base::StringValue(kUnknownIMEID
)));
632 // Sync for the first time.
633 syncer::SyncableService
* sync
=
634 pref_service_
->GetSyncableService(
635 syncer::PREFERENCES
);
636 sync
->MergeDataAndStartSyncing(syncer::PREFERENCES
,
638 scoped_ptr
<syncer::SyncChangeProcessor
>(
639 new syncer::FakeSyncChangeProcessor
),
640 scoped_ptr
<syncer::SyncErrorFactory
>(
641 new syncer::SyncErrorFactoryMock
));
642 content::RunAllBlockingPoolTasksUntilIdle();
644 SCOPED_TRACE("Only valid server values should have been merged in.");
647 ToInputMethodIds("xkb:es::spa,xkb:us::eng,xkb:ru::rus,xkb:jp::jpn"),
652 // Tests that we merge input methods even if syncing has started before
653 // initialization of Preferences.
654 TEST_F(InputMethodPreferencesTest
, MergeAfterSyncing
) {
656 ToInputMethodIds("xkb:es::spa,xkb:us::eng"),
658 pref_service_
->SetBoolean(
659 prefs::kLanguageShouldMergeInputMethods
, true);
661 // Create some valid and some non-existent IDs from the server.
662 std::string
preload_engines(
663 "xkb:ru::rus,xkb:xy::xyz," + ToInputMethodIds("xkb:jp::jpn"));
664 syncer::SyncDataList sync_data_list
;
665 sync_data_list
.push_back(CreatePrefSyncData(
666 prefs::kLanguagePreferredLanguagesSyncable
,
667 base::StringValue("en-US")));
668 sync_data_list
.push_back(CreatePrefSyncData(
669 prefs::kLanguagePreloadEnginesSyncable
,
670 base::StringValue(preload_engines
)));
671 sync_data_list
.push_back(CreatePrefSyncData(
672 prefs::kLanguageEnabledExtensionImesSyncable
,
673 base::StringValue(kUnknownIMEID
)));
675 // Sync for the first time.
676 syncer::SyncableService
* sync
=
677 pref_service_
->GetSyncableService(
678 syncer::PREFERENCES
);
679 sync
->MergeDataAndStartSyncing(syncer::PREFERENCES
,
681 scoped_ptr
<syncer::SyncChangeProcessor
>(
682 new syncer::FakeSyncChangeProcessor
),
683 scoped_ptr
<syncer::SyncErrorFactory
>(
684 new syncer::SyncErrorFactoryMock
));
685 content::RunAllBlockingPoolTasksUntilIdle();
687 content::RunAllBlockingPoolTasksUntilIdle();
690 SCOPED_TRACE("Local values should have been merged on initialization.");
693 ToInputMethodIds("xkb:es::spa,xkb:us::eng,xkb:ru::rus,xkb:jp::jpn"),
698 "Syncable values should have added local values on initialization.");
701 "xkb:es::spa,xkb:us::eng,xkb:ru::rus,xkb:xy::xyz," +
702 ToInputMethodIds("xkb:jp::jpn"),
703 std::string(kIdentityIMEID
) + "," + kUnknownIMEID
);
707 } // namespace chromeos