OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/preferences.h" | 5 #include "chrome/browser/chromeos/preferences.h" |
6 | 6 |
7 #include "base/json/json_string_value_serializer.h" | |
8 #include "base/prefs/pref_member.h" | 7 #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" | 8 #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_user_manager.h" | 9 #include "chrome/browser/chromeos/login/users/fake_user_manager.h" |
15 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h" | 10 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h" |
16 #include "chrome/browser/chromeos/system/fake_input_device_settings.h" | 11 #include "chrome/browser/download/download_prefs.h" |
17 #include "chrome/common/chrome_constants.h" | |
18 #include "chrome/common/pref_names.h" | 12 #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" | 13 #include "chrome/test/base/testing_pref_service_syncable.h" |
21 #include "chrome/test/base/testing_profile.h" | 14 #include "components/pref_registry/pref_registry_syncable.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" | 15 #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" | |
39 #include "url/gurl.h" | |
40 | 16 |
41 namespace chromeos { | 17 namespace chromeos { |
42 namespace { | 18 namespace { |
43 | 19 |
44 const char kIdentityIMEID[] = | 20 class MyMockInputMethodManager : public input_method::MockInputMethodManager { |
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"; | |
52 | |
53 syncer::SyncData | |
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(); | |
60 pref->set_name(name); | |
61 pref->set_value(serialized); | |
62 return syncer::SyncData::CreateRemoteData( | |
63 1, | |
64 specifics, | |
65 base::Time(), | |
66 syncer::AttachmentIdList(), | |
67 syncer::AttachmentServiceProxyForTest::Create()); | |
68 } | |
69 | |
70 } // anonymous namespace | |
71 | |
72 namespace input_method { | |
73 namespace { | |
74 | |
75 class MyMockInputMethodManager : public MockInputMethodManager { | |
76 public: | 21 public: |
77 class State : public MockInputMethodManager::State { | 22 class State : public MockInputMethodManager::State { |
78 public: | 23 public: |
79 explicit State(MyMockInputMethodManager* manager) | 24 explicit State(MyMockInputMethodManager* manager) |
80 : MockInputMethodManager::State(manager), manager_(manager) { | 25 : MockInputMethodManager::State(manager), manager_(manager) {}; |
81 input_method_extensions_.reset(new InputMethodDescriptors); | |
82 } | |
83 | 26 |
84 virtual void ChangeInputMethod(const std::string& input_method_id, | 27 virtual void ChangeInputMethod(const std::string& input_method_id, |
85 bool show_message) override { | 28 bool show_message) override { |
86 manager_->last_input_method_id_ = input_method_id; | 29 manager_->last_input_method_id_ = input_method_id; |
87 // Do the same thing as BrowserStateMonitor::UpdateUserPreferences. | 30 // Do the same thing as BrowserStateMonitor::UpdateUserPreferences. |
88 const std::string current_input_method_on_pref = | 31 const std::string current_input_method_on_pref = |
89 manager_->current_->GetValue(); | 32 manager_->current_->GetValue(); |
90 if (current_input_method_on_pref == input_method_id) | 33 if (current_input_method_on_pref == input_method_id) |
91 return; | 34 return; |
92 manager_->previous_->SetValue(current_input_method_on_pref); | 35 manager_->previous_->SetValue(current_input_method_on_pref); |
93 manager_->current_->SetValue(input_method_id); | 36 manager_->current_->SetValue(input_method_id); |
94 } | 37 } |
95 | 38 |
96 virtual void | |
97 GetInputMethodExtensions(InputMethodDescriptors* result) override { | |
98 *result = *input_method_extensions_; | |
99 } | |
100 | |
101 virtual void AddInputMethodExtension( | |
102 const std::string& id, | |
103 const InputMethodDescriptors& descriptors, | |
104 InputMethodEngineInterface* instance) override { | |
105 InputMethodDescriptor descriptor( | |
106 id, std::string(), std::string(), std::vector<std::string>(), | |
107 std::vector<std::string>(), false, GURL(), GURL()); | |
108 input_method_extensions_->push_back(descriptor); | |
109 } | |
110 | |
111 protected: | 39 protected: |
112 virtual ~State() {}; | 40 virtual ~State() {}; |
113 | 41 |
114 private: | 42 private: |
115 MyMockInputMethodManager* const manager_; | 43 MyMockInputMethodManager* const manager_; |
116 scoped_ptr<InputMethodDescriptors> input_method_extensions_; | |
117 }; | 44 }; |
118 | 45 |
119 MyMockInputMethodManager(StringPrefMember* previous, | 46 MyMockInputMethodManager(StringPrefMember* previous, |
120 StringPrefMember* current) | 47 StringPrefMember* current) |
121 : previous_(previous), | 48 : previous_(previous), |
122 current_(current) { | 49 current_(current) { |
123 state_ = new State(this); | 50 state_ = new State(this); |
124 } | 51 } |
125 | 52 |
126 virtual ~MyMockInputMethodManager() {} | 53 virtual ~MyMockInputMethodManager() {} |
127 | 54 |
128 virtual scoped_ptr<InputMethodDescriptors> | |
129 GetSupportedInputMethods() const override { | |
130 return whitelist_.GetSupportedInputMethods().Pass(); | |
131 } | |
132 | |
133 std::string last_input_method_id_; | 55 std::string last_input_method_id_; |
134 | 56 |
135 private: | 57 private: |
136 StringPrefMember* previous_; | 58 StringPrefMember* previous_; |
137 StringPrefMember* current_; | 59 StringPrefMember* current_; |
138 InputMethodWhitelist whitelist_; | |
139 }; | 60 }; |
140 | 61 |
141 } // anonymous namespace | 62 } // anonymous namespace |
142 } // namespace input_method | |
143 | 63 |
144 class PreferencesTest : public testing::Test { | 64 TEST(PreferencesTest, TestUpdatePrefOnBrowserScreenDetails) { |
145 public: | 65 chromeos::FakeUserManager* user_manager = new chromeos::FakeUserManager(); |
146 PreferencesTest() {} | 66 chromeos::ScopedUserManagerEnabler user_manager_enabler(user_manager); |
147 virtual ~PreferencesTest() {} | 67 const char test_user_email[] = "test_user@example.com"; |
| 68 const user_manager::User* test_user = user_manager->AddUser(test_user_email); |
| 69 user_manager->LoginUser(test_user_email); |
148 | 70 |
149 virtual void SetUp() override { | 71 TestingPrefServiceSyncable prefs; |
150 profile_manager_.reset( | 72 Preferences::RegisterProfilePrefs(prefs.registry()); |
151 new TestingProfileManager(TestingBrowserProcess::GetGlobal())); | 73 DownloadPrefs::RegisterProfilePrefs(prefs.registry()); |
152 ASSERT_TRUE(profile_manager_->SetUp()); | 74 // kSelectFileLastDirectory is registered for Profile. Here we register it for |
| 75 // testing. |
| 76 prefs.registry()->RegisterStringPref( |
| 77 prefs::kSelectFileLastDirectory, |
| 78 std::string(), |
| 79 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
153 | 80 |
154 chromeos::FakeUserManager* user_manager = new chromeos::FakeUserManager(); | 81 StringPrefMember previous; |
155 user_manager_enabler_.reset( | 82 previous.Init(prefs::kLanguagePreviousInputMethod, &prefs); |
156 new chromeos::ScopedUserManagerEnabler(user_manager)); | 83 previous.SetValue("KeyboardA"); |
| 84 StringPrefMember current; |
| 85 current.Init(prefs::kLanguageCurrentInputMethod, &prefs); |
| 86 current.SetValue("KeyboardB"); |
157 | 87 |
158 const char test_user_email[] = "test_user@example.com"; | 88 MyMockInputMethodManager mock_manager(&previous, ¤t); |
159 test_user_ = user_manager->AddUser(test_user_email); | 89 Preferences testee(&mock_manager); |
160 user_manager->LoginUser(test_user_email); | 90 testee.InitUserPrefsForTesting( |
161 user_manager->SwitchActiveUser(test_user_email); | 91 &prefs, test_user, mock_manager.GetActiveIMEState()); |
| 92 testee.SetInputMethodListForTesting(); |
162 | 93 |
163 test_profile_ = profile_manager_->CreateTestingProfile( | 94 // Confirm they're unchanged. |
164 chrome::kInitialProfile); | 95 EXPECT_EQ("KeyboardA", previous.GetValue()); |
165 pref_service_ = test_profile_->GetTestingPrefService(); | 96 EXPECT_EQ("KeyboardB", current.GetValue()); |
166 | 97 EXPECT_EQ("KeyboardB", mock_manager.last_input_method_id_); |
167 previous_input_method_.Init( | |
168 prefs::kLanguagePreviousInputMethod, pref_service_); | |
169 previous_input_method_.SetValue("KeyboardA"); | |
170 current_input_method_.Init( | |
171 prefs::kLanguageCurrentInputMethod, pref_service_); | |
172 current_input_method_.SetValue("KeyboardB"); | |
173 | |
174 mock_manager_ = new input_method::MyMockInputMethodManager( | |
175 &previous_input_method_, ¤t_input_method_); | |
176 input_method::InitializeForTesting(mock_manager_); | |
177 system::InputDeviceSettings::SetSettingsForTesting( | |
178 new system::FakeInputDeviceSettings()); | |
179 | |
180 prefs_.reset(new Preferences(mock_manager_)); | |
181 } | |
182 | |
183 virtual void TearDown() override { | |
184 input_method::Shutdown(); | |
185 // UserSessionManager doesn't listen to profile destruction, so make sure | |
186 // the default IME state isn't still cached in case test_profile_ is | |
187 // given the same address in the next test. | |
188 UserSessionManager::GetInstance()->RemoveProfileForTesting(test_profile_); | |
189 } | |
190 | |
191 void InitPreferences() { | |
192 prefs_->InitUserPrefsForTesting( | |
193 pref_service_, test_user_, mock_manager_->GetActiveIMEState()); | |
194 prefs_->SetInputMethodListForTesting(); | |
195 } | |
196 | |
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_; | |
202 | |
203 // Not owned. | |
204 const user_manager::User* test_user_; | |
205 TestingProfile* test_profile_; | |
206 TestingPrefServiceSyncable* pref_service_; | |
207 input_method::MyMockInputMethodManager* mock_manager_; | |
208 | |
209 private: | |
210 DISALLOW_COPY_AND_ASSIGN(PreferencesTest); | |
211 }; | |
212 | |
213 TEST_F(PreferencesTest, TestUpdatePrefOnBrowserScreenDetails) { | |
214 InitPreferences(); | |
215 | |
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_); | |
220 } | |
221 | |
222 class InputMethodPreferencesTest : public PreferencesTest { | |
223 public: | |
224 InputMethodPreferencesTest() {} | |
225 virtual ~InputMethodPreferencesTest() {} | |
226 | |
227 virtual void SetUp() override { | |
228 PreferencesTest::SetUp(); | |
229 | |
230 // Initialize pref members. | |
231 preferred_languages_.Init(prefs::kLanguagePreferredLanguages, | |
232 pref_service_); | |
233 preferred_languages_syncable_.Init( | |
234 prefs::kLanguagePreferredLanguagesSyncable, | |
235 pref_service_); | |
236 preload_engines_.Init(prefs::kLanguagePreloadEngines, pref_service_); | |
237 preload_engines_syncable_.Init(prefs::kLanguagePreloadEnginesSyncable, | |
238 pref_service_); | |
239 enabled_extension_imes_.Init(prefs::kLanguageEnabledExtensionImes, | |
240 pref_service_); | |
241 enabled_extension_imes_syncable_.Init( | |
242 prefs::kLanguageEnabledExtensionImesSyncable, pref_service_); | |
243 | |
244 // Initialize component and 3rd-party input method extensions. | |
245 InitComponentExtensionIMEManager(); | |
246 input_method::InputMethodDescriptors descriptors; | |
247 mock_manager_->GetActiveIMEState()->AddInputMethodExtension( | |
248 kIdentityIMEID, | |
249 descriptors, | |
250 NULL); | |
251 mock_manager_->GetActiveIMEState()->AddInputMethodExtension( | |
252 kToUpperIMEID, | |
253 descriptors, | |
254 NULL); | |
255 mock_manager_->GetActiveIMEState()->AddInputMethodExtension( | |
256 kAPIArgumentIMEID, | |
257 descriptors, | |
258 NULL); | |
259 } | |
260 | |
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()); | |
266 | |
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()); | |
272 | |
273 // Add the ComponentExtensionIMEManager to the mock InputMethodManager. | |
274 mock_manager_->SetComponentExtensionIMEManager( | |
275 component_extension_ime_manager.Pass()); | |
276 } | |
277 | |
278 std::vector<ComponentExtensionIME> CreateImeList() { | |
279 std::vector<ComponentExtensionIME> ime_list; | |
280 | |
281 ComponentExtensionIME ext; | |
282 ext.id = extension_ime_util::kMozcExtensionId; | |
283 ext.description = "ext_description"; | |
284 ext.path = base::FilePath("ext_file_path"); | |
285 | |
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); | |
292 | |
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); | |
299 | |
300 ime_list.push_back(ext); | |
301 return ime_list; | |
302 } | |
303 | |
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); | |
311 } | |
312 | |
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); | |
320 } | |
321 | |
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()); | |
329 } | |
330 | |
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()); | |
339 } | |
340 | |
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; | |
344 base::SplitString(value, ',', &tokens); | |
345 std::transform(tokens.begin(), tokens.end(), tokens.begin(), | |
346 &extension_ime_util::GetInputMethodIDByEngineID); | |
347 return JoinString(tokens, ','); | |
348 } | |
349 | |
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_; | |
356 content::TestBrowserThreadBundle thread_bundle_; | |
357 | |
358 private: | |
359 DISALLOW_COPY_AND_ASSIGN(InputMethodPreferencesTest); | |
360 }; | |
361 | |
362 // Tests that the server values are added to the values chosen at OOBE. | |
363 TEST_F(InputMethodPreferencesTest, TestOobeAndSync) { | |
364 // Choose options at OOBE. | |
365 pref_service_->SetBoolean( | |
366 prefs::kLanguageShouldMergeInputMethods, true); | |
367 SetLocalValues("es", | |
368 ToInputMethodIds("xkb:us:altgr-intl:eng"), | |
369 std::string()); | |
370 InitPreferences(); | |
371 | |
372 // Suppose we add an input method before syncing starts. | |
373 preload_engines_.SetValue( | |
374 ToInputMethodIds("xkb:us:altgr-intl:eng,xkb:us:intl:eng")); | |
375 | |
376 // Create some values to come from the server. | |
377 syncer::SyncDataList sync_data_list; | |
378 sync_data_list.push_back(CreatePrefSyncData( | |
379 prefs::kLanguagePreferredLanguagesSyncable, base::StringValue("ru,fi"))); | |
380 sync_data_list.push_back(CreatePrefSyncData( | |
381 prefs::kLanguagePreloadEnginesSyncable, | |
382 base::StringValue("xkb:se::swe"))); | |
383 sync_data_list.push_back(CreatePrefSyncData( | |
384 prefs::kLanguageEnabledExtensionImesSyncable, | |
385 base::StringValue(kIdentityIMEID))); | |
386 | |
387 // Sync for the first time. | |
388 syncer::SyncableService* sync = | |
389 pref_service_->GetSyncableService( | |
390 syncer::PREFERENCES); | |
391 sync->MergeDataAndStartSyncing(syncer::PREFERENCES, | |
392 sync_data_list, | |
393 scoped_ptr<syncer::SyncChangeProcessor>( | |
394 new syncer::FakeSyncChangeProcessor), | |
395 scoped_ptr<syncer::SyncErrorFactory>( | |
396 new syncer::SyncErrorFactoryMock)); | |
397 content::RunAllBlockingPoolTasksUntilIdle(); | |
398 | |
399 // Note that we expect the preload_engines to have been translated to input | |
400 // method IDs during the merge. | |
401 std::string expected_languages("es,ru,fi"); | |
402 std::string expected_preload_engines( | |
403 "xkb:us:altgr-intl:eng,xkb:us:intl:eng,xkb:se::swe"); | |
404 std::string expected_extensions(kIdentityIMEID); | |
405 { | |
406 SCOPED_TRACE("Server values should have merged into local values."); | |
407 ExpectLocalValues( | |
408 expected_languages, | |
409 ToInputMethodIds(expected_preload_engines), | |
410 expected_extensions); | |
411 } | |
412 { | |
413 SCOPED_TRACE("Server values should have been updated to local values."); | |
414 ExpectGlobalValues( | |
415 expected_languages, expected_preload_engines, expected_extensions); | |
416 } | |
417 | |
418 // Update the global values from the server again. | |
419 syncer::SyncChangeList change_list; | |
420 change_list.push_back(syncer::SyncChange( | |
421 FROM_HERE, | |
422 syncer::SyncChange::ACTION_UPDATE, | |
423 CreatePrefSyncData( | |
424 prefs::kLanguagePreferredLanguagesSyncable, | |
425 base::StringValue("de")))); | |
426 change_list.push_back(syncer::SyncChange( | |
427 FROM_HERE, | |
428 syncer::SyncChange::ACTION_UPDATE, | |
429 CreatePrefSyncData( | |
430 prefs::kLanguagePreloadEnginesSyncable, | |
431 base::StringValue(ToInputMethodIds("xkb:de::ger"))))); | |
432 change_list.push_back(syncer::SyncChange( | |
433 FROM_HERE, | |
434 syncer::SyncChange::ACTION_UPDATE, | |
435 CreatePrefSyncData( | |
436 prefs::kLanguageEnabledExtensionImesSyncable, | |
437 base::StringValue(kToUpperIMEID)))); | |
438 sync->ProcessSyncChanges(FROM_HERE, change_list); | |
439 content::RunAllBlockingPoolTasksUntilIdle(); | |
440 | |
441 { | |
442 SCOPED_TRACE("Local preferences should have remained the same."); | |
443 ExpectLocalValues( | |
444 expected_languages, | |
445 ToInputMethodIds(expected_preload_engines), | |
446 expected_extensions); | |
447 } | |
448 // Change local preferences. | |
449 SetLocalValues("ja", ToInputMethodIds("xkb:jp::jpn"), "ime2"); | |
450 { | |
451 SCOPED_TRACE("Global preferences should have been updated."); | |
452 ExpectGlobalValues("ja", "xkb:jp::jpn", "ime2"); | |
453 } | |
454 content::RunAllBlockingPoolTasksUntilIdle(); | |
455 } | |
456 | |
457 // Tests that logging in after sync has completed changes nothing. | |
458 TEST_F(InputMethodPreferencesTest, TestLogIn) { | |
459 // Set up existing preference values. | |
460 std::string languages("es"); | |
461 std::string preload_engines(ToInputMethodIds("xkb:es::spa")); | |
462 std::string extensions(kIdentityIMEID); | |
463 | |
464 SetLocalValues(languages, preload_engines, extensions); | |
465 SetGlobalValues(languages, preload_engines, extensions); | |
466 pref_service_->SetBoolean( | |
467 prefs::kLanguageShouldMergeInputMethods, false); | |
468 InitPreferences(); | |
469 | |
470 // Create some values to come from the server. | |
471 syncer::SyncDataList sync_data_list; | |
472 sync_data_list.push_back(CreatePrefSyncData( | |
473 prefs::kLanguagePreferredLanguages, base::StringValue("ru,fi"))); | |
474 sync_data_list.push_back(CreatePrefSyncData( | |
475 prefs::kLanguagePreloadEngines, | |
476 base::StringValue(ToInputMethodIds("xkb:ru::rus")))); | |
477 sync_data_list.push_back(CreatePrefSyncData( | |
478 prefs::kLanguageEnabledExtensionImes, base::StringValue(kIdentityIMEID))); | |
479 | |
480 // Sync. | |
481 syncer::SyncableService* sync = | |
482 pref_service_->GetSyncableService( | |
483 syncer::PREFERENCES); | |
484 sync->MergeDataAndStartSyncing(syncer::PREFERENCES, | |
485 sync_data_list, | |
486 scoped_ptr<syncer::SyncChangeProcessor>( | |
487 new syncer::FakeSyncChangeProcessor), | |
488 scoped_ptr<syncer::SyncErrorFactory>( | |
489 new syncer::SyncErrorFactoryMock)); | |
490 content::RunAllBlockingPoolTasksUntilIdle(); | |
491 { | |
492 SCOPED_TRACE("Local preferences should have remained the same."); | |
493 ExpectLocalValues(languages, preload_engines, extensions); | |
494 } | |
495 // Change local preferences. | |
496 SetLocalValues("ja", ToInputMethodIds("xkb:jp::jpn"), kToUpperIMEID); | |
497 content::RunAllBlockingPoolTasksUntilIdle(); | |
498 { | |
499 SCOPED_TRACE("Global preferences should have been updated."); | |
500 ExpectGlobalValues("ja", "xkb:jp::jpn", kToUpperIMEID); | |
501 } | |
502 } | |
503 | |
504 // Tests that logging in with preferences from before a) XKB component | |
505 // extensions and b) the IME syncing logic doesn't overwrite settings. | |
506 TEST_F(InputMethodPreferencesTest, TestLogInLegacy) { | |
507 // Simulate existing local preferences from M-36. | |
508 SetLocalValues("es", "xkb:es::spa", kIdentityIMEID); | |
509 InitPreferences(); | |
510 | |
511 // Sync. Since this is an existing profile, the local values shouldn't change. | |
512 syncer::SyncDataList sync_data_list; | |
513 sync_data_list.push_back(CreatePrefSyncData( | |
514 prefs::kLanguagePreferredLanguagesSyncable, base::StringValue("ru,fi"))); | |
515 sync_data_list.push_back(CreatePrefSyncData( | |
516 prefs::kLanguagePreloadEnginesSyncable, | |
517 base::StringValue(ToInputMethodIds("xkb:ru::rus")))); | |
518 sync_data_list.push_back(CreatePrefSyncData( | |
519 prefs::kLanguageEnabledExtensionImesSyncable, | |
520 base::StringValue(kToUpperIMEID))); | |
521 | |
522 syncer::SyncableService* sync = | |
523 pref_service_->GetSyncableService( | |
524 syncer::PREFERENCES); | |
525 sync->MergeDataAndStartSyncing(syncer::PREFERENCES, | |
526 sync_data_list, | |
527 scoped_ptr<syncer::SyncChangeProcessor>( | |
528 new syncer::FakeSyncChangeProcessor), | |
529 scoped_ptr<syncer::SyncErrorFactory>( | |
530 new syncer::SyncErrorFactoryMock)); | |
531 content::RunAllBlockingPoolTasksUntilIdle(); | |
532 { | |
533 SCOPED_TRACE("Local preferences should have remained the same."); | |
534 ExpectLocalValues("es", "xkb:es::spa", kIdentityIMEID); | |
535 } | |
536 { | |
537 SCOPED_TRACE("Global preferences should have remained the same."); | |
538 ExpectGlobalValues("ru,fi", ToInputMethodIds("xkb:ru::rus"), kToUpperIMEID); | |
539 } | |
540 // Change local preferences. | |
541 SetLocalValues("ja", ToInputMethodIds("xkb:jp::jp"), kAPIArgumentIMEID); | |
542 { | |
543 SCOPED_TRACE("Global preferences should have been updated."); | |
544 ExpectGlobalValues("ja", "xkb:jp::jp", kAPIArgumentIMEID); | |
545 } | |
546 } | |
547 | |
548 // Tests some edge cases: empty strings, lots of values, duplicates. | |
549 TEST_F(InputMethodPreferencesTest, MergeStressTest) { | |
550 SetLocalValues("hr,lv,lt,es-419,he,el,da,ca,es,cs,bg", | |
551 ToInputMethodIds("xkb:es::spa,xkb:us::eng"), | |
552 std::string()); | |
553 pref_service_->SetBoolean( | |
554 prefs::kLanguageShouldMergeInputMethods, true); | |
555 InitPreferences(); | |
556 | |
557 // Change input methods and languages before syncing starts. | |
558 std::string local_extensions = | |
559 kToUpperIMEID + std::string(",") + | |
560 kAPIArgumentIMEID + std::string(",") + | |
561 kIdentityIMEID; | |
562 SetLocalValues( | |
563 "en,es,ja,hr,lv,lt,es-419,he,el,da,ca,es,cs,bg,ar", | |
564 ToInputMethodIds("xkb:es::spa,xkb:us:dvorak,xkb:ua::ukr"), | |
565 local_extensions); | |
566 | |
567 // Create some tricky values to come from the server. | |
568 syncer::SyncDataList sync_data_list; | |
569 sync_data_list.push_back(CreatePrefSyncData( | |
570 prefs::kLanguagePreferredLanguagesSyncable, | |
571 base::StringValue("ar,fi,es,de,ar"))); | |
572 sync_data_list.push_back(CreatePrefSyncData( | |
573 prefs::kLanguagePreloadEnginesSyncable, | |
574 base::StringValue( | |
575 "nacl_mozc_us,xkb:ru::rus,xkb:ru::rus,xkb:es::spa,xkb:es::spa"))); | |
576 sync_data_list.push_back(CreatePrefSyncData( | |
577 prefs::kLanguageEnabledExtensionImesSyncable, | |
578 base::StringValue(std::string()))); | |
579 | |
580 // Sync for the first time. | |
581 syncer::SyncableService* sync = | |
582 pref_service_->GetSyncableService( | |
583 syncer::PREFERENCES); | |
584 sync->MergeDataAndStartSyncing(syncer::PREFERENCES, | |
585 sync_data_list, | |
586 scoped_ptr<syncer::SyncChangeProcessor>( | |
587 new syncer::FakeSyncChangeProcessor), | |
588 scoped_ptr<syncer::SyncErrorFactory>( | |
589 new syncer::SyncErrorFactoryMock)); | |
590 content::RunAllBlockingPoolTasksUntilIdle(); | |
591 { | |
592 SCOPED_TRACE("Server values should have merged into local values."); | |
593 ExpectLocalValues( | |
594 "en,es,ja,hr,lv,lt,es-419,he,el,da,ca,es,cs,bg,ar,fi,de", | |
595 ToInputMethodIds("xkb:es::spa,xkb:us:dvorak,xkb:ua::ukr," | |
596 "nacl_mozc_us,xkb:ru::rus"), | |
597 local_extensions); | |
598 } | |
599 { | |
600 SCOPED_TRACE("Server values should have incorporated local values."); | |
601 ExpectGlobalValues( | |
602 "en,es,ja,hr,lv,lt,es-419,he,el,da,ca,es,cs,bg,ar,fi,de", | |
603 "xkb:es::spa,xkb:us:dvorak,xkb:ua::ukr,nacl_mozc_us,xkb:ru::rus", | |
604 local_extensions); | |
605 } | |
606 } | |
607 | |
608 // Tests non-existent IDs. | |
609 TEST_F(InputMethodPreferencesTest, MergeInvalidValues) { | |
610 SetLocalValues("es", | |
611 ToInputMethodIds("xkb:es::spa,xkb:us::eng"), | |
612 kIdentityIMEID); | |
613 pref_service_->SetBoolean( | |
614 prefs::kLanguageShouldMergeInputMethods, true); | |
615 InitPreferences(); | |
616 | |
617 // Create some valid and some non-existent IDs from the server. | |
618 std::string preload_engines( | |
619 "xkb:ru::rus,xkb:xy::xyz," | |
620 "_comp_ime_nothisisnotactuallyanextensionidxkb:es::spa," + | |
621 ToInputMethodIds("xkb:jp::jpn")); | |
622 syncer::SyncDataList sync_data_list; | |
623 sync_data_list.push_back(CreatePrefSyncData( | |
624 prefs::kLanguagePreferredLanguagesSyncable, | |
625 base::StringValue("klingon,en-US"))); | |
626 sync_data_list.push_back(CreatePrefSyncData( | |
627 prefs::kLanguagePreloadEnginesSyncable, | |
628 base::StringValue(preload_engines))); | |
629 sync_data_list.push_back(CreatePrefSyncData( | |
630 prefs::kLanguageEnabledExtensionImesSyncable, | |
631 base::StringValue(kUnknownIMEID))); | |
632 | |
633 // Sync for the first time. | |
634 syncer::SyncableService* sync = | |
635 pref_service_->GetSyncableService( | |
636 syncer::PREFERENCES); | |
637 sync->MergeDataAndStartSyncing(syncer::PREFERENCES, | |
638 sync_data_list, | |
639 scoped_ptr<syncer::SyncChangeProcessor>( | |
640 new syncer::FakeSyncChangeProcessor), | |
641 scoped_ptr<syncer::SyncErrorFactory>( | |
642 new syncer::SyncErrorFactoryMock)); | |
643 content::RunAllBlockingPoolTasksUntilIdle(); | |
644 { | |
645 SCOPED_TRACE("Only valid server values should have been merged in."); | |
646 ExpectLocalValues( | |
647 "es,en-US", | |
648 ToInputMethodIds("xkb:es::spa,xkb:us::eng,xkb:ru::rus,xkb:jp::jpn"), | |
649 kIdentityIMEID); | |
650 } | |
651 } | |
652 | |
653 // Tests that we merge input methods even if syncing has started before | |
654 // initialization of Preferences. | |
655 TEST_F(InputMethodPreferencesTest, MergeAfterSyncing) { | |
656 SetLocalValues("es", | |
657 ToInputMethodIds("xkb:es::spa,xkb:us::eng"), | |
658 kIdentityIMEID); | |
659 pref_service_->SetBoolean( | |
660 prefs::kLanguageShouldMergeInputMethods, true); | |
661 | |
662 // Create some valid and some non-existent IDs from the server. | |
663 std::string preload_engines( | |
664 "xkb:ru::rus,xkb:xy::xyz," + ToInputMethodIds("xkb:jp::jpn")); | |
665 syncer::SyncDataList sync_data_list; | |
666 sync_data_list.push_back(CreatePrefSyncData( | |
667 prefs::kLanguagePreferredLanguagesSyncable, | |
668 base::StringValue("en-US"))); | |
669 sync_data_list.push_back(CreatePrefSyncData( | |
670 prefs::kLanguagePreloadEnginesSyncable, | |
671 base::StringValue(preload_engines))); | |
672 sync_data_list.push_back(CreatePrefSyncData( | |
673 prefs::kLanguageEnabledExtensionImesSyncable, | |
674 base::StringValue(kUnknownIMEID))); | |
675 | |
676 // Sync for the first time. | |
677 syncer::SyncableService* sync = | |
678 pref_service_->GetSyncableService( | |
679 syncer::PREFERENCES); | |
680 sync->MergeDataAndStartSyncing(syncer::PREFERENCES, | |
681 sync_data_list, | |
682 scoped_ptr<syncer::SyncChangeProcessor>( | |
683 new syncer::FakeSyncChangeProcessor), | |
684 scoped_ptr<syncer::SyncErrorFactory>( | |
685 new syncer::SyncErrorFactoryMock)); | |
686 content::RunAllBlockingPoolTasksUntilIdle(); | |
687 InitPreferences(); | |
688 content::RunAllBlockingPoolTasksUntilIdle(); | |
689 | |
690 { | |
691 SCOPED_TRACE("Local values should have been merged on initialization."); | |
692 ExpectLocalValues( | |
693 "es,en-US", | |
694 ToInputMethodIds("xkb:es::spa,xkb:us::eng,xkb:ru::rus,xkb:jp::jpn"), | |
695 kIdentityIMEID); | |
696 } | |
697 { | |
698 SCOPED_TRACE( | |
699 "Syncable values should have added local values on initialization."); | |
700 ExpectGlobalValues( | |
701 "es,en-US", | |
702 "xkb:es::spa,xkb:us::eng,xkb:ru::rus,xkb:xy::xyz," + | |
703 ToInputMethodIds("xkb:jp::jpn"), | |
704 std::string(kIdentityIMEID) + "," + kUnknownIMEID); | |
705 } | |
706 } | 98 } |
707 | 99 |
708 } // namespace chromeos | 100 } // namespace chromeos |
OLD | NEW |