| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "base/message_loop/message_loop.h" | 5 #include "base/message_loop/message_loop.h" |
| 6 #include "base/prefs/pref_service.h" | 6 #include "base/prefs/pref_service.h" |
| 7 #include "base/strings/stringprintf.h" | 7 #include "base/strings/stringprintf.h" |
| 8 #include "base/task_runner.h" | 8 #include "base/task_runner.h" |
| 9 #include "chrome/browser/browser_process.h" | 9 #include "chrome/browser/browser_process.h" |
| 10 #include "chrome/browser/chrome_notification_types.h" | 10 #include "chrome/browser/chrome_notification_types.h" |
| 11 #include "chrome/browser/chromeos/customization_document.h" | 11 #include "chrome/browser/chromeos/customization_document.h" |
| 12 #include "chrome/browser/chromeos/input_method/input_method_util.h" | 12 #include "chrome/browser/chromeos/input_method/input_method_util.h" |
| 13 #include "chrome/browser/chromeos/login/login_manager_test.h" | |
| 14 #include "chrome/browser/chromeos/login/login_wizard.h" | 13 #include "chrome/browser/chromeos/login/login_wizard.h" |
| 15 #include "chrome/browser/chromeos/login/test/js_checker.h" | 14 #include "chrome/browser/chromeos/login/test/js_checker.h" |
| 16 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h" | 15 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h" |
| 17 #include "chrome/common/pref_names.h" | 16 #include "chrome/common/pref_names.h" |
| 18 #include "chrome/test/base/in_process_browser_test.h" | 17 #include "chrome/test/base/in_process_browser_test.h" |
| 19 #include "chromeos/ime/extension_ime_util.h" | 18 #include "chromeos/ime/extension_ime_util.h" |
| 20 #include "chromeos/ime/input_method_manager.h" | 19 #include "chromeos/ime/input_method_manager.h" |
| 21 #include "chromeos/ime/input_method_whitelist.h" | 20 #include "chromeos/ime/input_method_whitelist.h" |
| 22 #include "chromeos/system/statistics_provider.h" | 21 #include "chromeos/system/statistics_provider.h" |
| 23 #include "content/public/browser/notification_service.h" | 22 #include "content/public/browser/notification_service.h" |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 | 82 |
| 84 virtual void Shutdown() override { | 83 virtual void Shutdown() override { |
| 85 } | 84 } |
| 86 | 85 |
| 87 std::string initial_locale_; | 86 std::string initial_locale_; |
| 88 std::string keyboard_layout_; | 87 std::string keyboard_layout_; |
| 89 }; | 88 }; |
| 90 | 89 |
| 91 } // namespace system | 90 } // namespace system |
| 92 | 91 |
| 93 struct LocalizationTestParams { | 92 class OobeLocalizationTest : public InProcessBrowserTest { |
| 94 const char* initial_locale; | |
| 95 const char* keyboard_layout; | |
| 96 const char* expected_locale; | |
| 97 const char* expected_keyboard_layout; | |
| 98 const char* expected_keyboard_select_control; | |
| 99 } const oobe_localization_test_parameters[] = { | |
| 100 // ------------------ Non-Latin setup | |
| 101 // For a non-Latin keyboard layout like Russian, we expect to see the US | |
| 102 // keyboard. | |
| 103 {"ru", "xkb:ru::rus", "ru", kUSLayout, "xkb:us::eng"}, | |
| 104 {"ru", "xkb:us::eng,xkb:ru::rus", "ru", kUSLayout, "xkb:us::eng"}, | |
| 105 | |
| 106 // IMEs do not load at OOBE, so we just expect to see the (Latin) Japanese | |
| 107 // keyboard. | |
| 108 {"ja", "xkb:jp::jpn", "ja", "xkb:jp::jpn", "xkb:jp::jpn,[xkb:us::eng]"}, | |
| 109 | |
| 110 // We don't use the Icelandic locale but the Icelandic keyboard layout | |
| 111 // should still be selected when specified as the default. | |
| 112 {"en-US", | |
| 113 "xkb:is::ice", | |
| 114 "en-US", | |
| 115 "xkb:is::ice", | |
| 116 "xkb:is::ice,[xkb:us::eng,xkb:us:intl:eng,xkb:us:altgr-intl:eng," | |
| 117 "xkb:us:dvorak:eng,xkb:us:colemak:eng]"}, | |
| 118 // ------------------ Full Latin setup | |
| 119 // French Swiss keyboard. | |
| 120 {"fr", | |
| 121 "xkb:ch:fr:fra", | |
| 122 "fr", | |
| 123 "xkb:ch:fr:fra", | |
| 124 "xkb:ch:fr:fra,[xkb:fr::fra,xkb:be::fra,xkb:ca::fra," | |
| 125 "xkb:ca:multix:fra,xkb:us::eng]"}, | |
| 126 | |
| 127 // German Swiss keyboard. | |
| 128 {"de", | |
| 129 "xkb:ch::ger", | |
| 130 "de", | |
| 131 "xkb:ch::ger", | |
| 132 "xkb:ch::ger,[xkb:de::ger,xkb:de:neo:ger,xkb:be::ger,xkb:us::eng]"}, | |
| 133 | |
| 134 // NetworkScreenMultipleLocales | |
| 135 {"es,en-US,nl", | |
| 136 "xkb:be::nld", | |
| 137 "es,en-US,nl", | |
| 138 "xkb:be::nld", | |
| 139 "xkb:be::nld,[xkb:es::spa,xkb:latam::spa,xkb:us::eng]"}, | |
| 140 | |
| 141 {"ru,de", "xkb:ru::rus", "ru,de", kUSLayout, "xkb:us::eng"}, | |
| 142 | |
| 143 // ------------------ Regional Locales | |
| 144 // Syntetic example to test correct merging of different locales. | |
| 145 {"fr-CH,it-CH,de-CH", | |
| 146 "xkb:fr::fra,xkb:it::ita,xkb:de::ger", | |
| 147 "fr-CH,it-CH,de-CH", | |
| 148 "xkb:fr::fra", | |
| 149 "xkb:fr::fra,xkb:it::ita,xkb:de::ger,[xkb:be::fra,xkb:ca::fra," | |
| 150 "xkb:ch:fr:fra,xkb:ca:multix:fra,xkb:us::eng]"}, | |
| 151 | |
| 152 // Another syntetic example. Check that british keyboard is available. | |
| 153 {"en-AU", | |
| 154 "xkb:us::eng", | |
| 155 "en-AU", | |
| 156 "xkb:us::eng", | |
| 157 "xkb:us::eng,[xkb:gb:extd:eng,xkb:gb:dvorak:eng]"}, | |
| 158 }; | |
| 159 | |
| 160 class OobeLocalizationTest | |
| 161 : public LoginManagerTest, | |
| 162 public testing::WithParamInterface<const LocalizationTestParams*> { | |
| 163 public: | 93 public: |
| 164 OobeLocalizationTest(); | 94 OobeLocalizationTest(); |
| 165 virtual ~OobeLocalizationTest(); | 95 virtual ~OobeLocalizationTest(); |
| 166 | 96 |
| 167 // Verifies that the comma-separated |values| corresponds with the first | 97 // Verifies that the comma-separated |values| corresponds with the first |
| 168 // values in |select_id|, optionally checking for an options group label after | 98 // values in |select_id|, optionally checking for an options group label after |
| 169 // the first set of options. | 99 // the first set of options. |
| 170 bool VerifyInitialOptions(const char* select_id, | 100 bool VerifyInitialOptions(const char* select_id, |
| 171 const char* values, | 101 const char* values, |
| 172 bool check_separator); | 102 bool check_separator); |
| 173 | 103 |
| 174 // Verifies that |value| exists in |select_id|. | 104 // Verifies that |value| exists in |select_id|. |
| 175 bool VerifyOptionExists(const char* select_id, const char* value); | 105 bool VerifyOptionExists(const char* select_id, const char* value); |
| 176 | 106 |
| 177 // Dumps OOBE select control (language or keyboard) to string. | 107 // Dumps OOBE select control (language or keyboard) to string. |
| 178 std::string DumpOptions(const char* select_id); | 108 std::string DumpOptions(const char* select_id); |
| 179 | 109 |
| 180 protected: | 110 protected: |
| 181 // Runs the test for the given locale and keyboard layout. | 111 // Runs the test for the given locale and keyboard layout. |
| 182 void RunLocalizationTest(); | 112 void RunLocalizationTest(const std::string& initial_locale, |
| 183 | 113 const std::string& keyboard_layout, |
| 184 void WaitUntilJSIsReady() { | 114 const std::string& expected_locale, |
| 185 LoginDisplayHostImpl* host = static_cast<LoginDisplayHostImpl*>( | 115 const std::string& expected_keyboard_layout, |
| 186 LoginDisplayHostImpl::default_host()); | 116 const std::string& expected_keyboard_select_control); |
| 187 if (!host) | |
| 188 return; | |
| 189 chromeos::OobeUI* oobe_ui = host->GetOobeUI(); | |
| 190 if (!oobe_ui) | |
| 191 return; | |
| 192 base::RunLoop run_loop; | |
| 193 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure()); | |
| 194 if (!oobe_ui_ready) | |
| 195 run_loop.Run(); | |
| 196 } | |
| 197 | 117 |
| 198 private: | 118 private: |
| 199 scoped_ptr<system::FakeStatisticsProvider> statistics_provider_; | 119 scoped_ptr<system::FakeStatisticsProvider> statistics_provider_; |
| 200 test::JSChecker checker; | 120 test::JSChecker checker; |
| 201 | 121 |
| 202 DISALLOW_COPY_AND_ASSIGN(OobeLocalizationTest); | 122 DISALLOW_COPY_AND_ASSIGN(OobeLocalizationTest); |
| 203 }; | 123 }; |
| 204 | 124 |
| 205 OobeLocalizationTest::OobeLocalizationTest() : LoginManagerTest(false) { | 125 OobeLocalizationTest::OobeLocalizationTest() { |
| 206 statistics_provider_.reset(new system::FakeStatisticsProvider()); | 126 statistics_provider_.reset(new system::FakeStatisticsProvider()); |
| 207 // Set the instance returned by GetInstance() for testing. | 127 // Set the instance returned by GetInstance() for testing. |
| 208 system::StatisticsProvider::SetTestProvider(statistics_provider_.get()); | 128 system::StatisticsProvider::SetTestProvider(statistics_provider_.get()); |
| 209 | |
| 210 statistics_provider_->set_locale(GetParam()->initial_locale); | |
| 211 statistics_provider_->set_keyboard_layout(GetParam()->keyboard_layout); | |
| 212 } | 129 } |
| 213 | 130 |
| 214 OobeLocalizationTest::~OobeLocalizationTest() { | 131 OobeLocalizationTest::~OobeLocalizationTest() { |
| 215 system::StatisticsProvider::SetTestProvider(NULL); | 132 system::StatisticsProvider::SetTestProvider(NULL); |
| 216 } | 133 } |
| 217 | 134 |
| 218 bool OobeLocalizationTest::VerifyInitialOptions(const char* select_id, | 135 bool OobeLocalizationTest::VerifyInitialOptions(const char* select_id, |
| 219 const char* values, | 136 const char* values, |
| 220 bool check_separator) { | 137 bool check_separator) { |
| 221 const std::string expression = base::StringPrintf( | 138 const std::string expression = base::StringPrintf( |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 std::string repl_old = "xkb:"; | 229 std::string repl_old = "xkb:"; |
| 313 std::string repl_new = | 230 std::string repl_new = |
| 314 extension_ime_util::GetInputMethodIDByEngineID("xkb:"); | 231 extension_ime_util::GetInputMethodIDByEngineID("xkb:"); |
| 315 while ((pos = result.find(repl_old, pos)) != std::string::npos) { | 232 while ((pos = result.find(repl_old, pos)) != std::string::npos) { |
| 316 result.replace(pos, repl_old.length(), repl_new); | 233 result.replace(pos, repl_old.length(), repl_new); |
| 317 pos += repl_new.length(); | 234 pos += repl_new.length(); |
| 318 } | 235 } |
| 319 return result; | 236 return result; |
| 320 } | 237 } |
| 321 | 238 |
| 322 void OobeLocalizationTest::RunLocalizationTest() { | 239 void OobeLocalizationTest::RunLocalizationTest( |
| 323 const std::string initial_locale(GetParam()->initial_locale); | 240 const std::string& initial_locale, |
| 324 const std::string keyboard_layout(GetParam()->keyboard_layout); | 241 const std::string& keyboard_layout, |
| 325 const std::string expected_locale(GetParam()->expected_locale); | 242 const std::string& expected_locale, |
| 326 const std::string expected_keyboard_layout( | 243 const std::string& expected_keyboard_layout, |
| 327 GetParam()->expected_keyboard_layout); | 244 const std::string& expected_keyboard_select_control) { |
| 328 const std::string expected_keyboard_select_control( | 245 statistics_provider_->set_locale(initial_locale); |
| 329 GetParam()->expected_keyboard_select_control); | 246 statistics_provider_->set_keyboard_layout(keyboard_layout); |
| 247 |
| 248 // Initialize StartupCustomizationDocument with fake statistics provider. |
| 249 StartupCustomizationDocument::GetInstance()->Init( |
| 250 statistics_provider_.get()); |
| 251 |
| 252 g_browser_process->local_state()->SetString( |
| 253 prefs::kHardwareKeyboardLayout, keyboard_layout); |
| 254 |
| 255 input_method::InputMethodManager::Get() |
| 256 ->GetInputMethodUtil() |
| 257 ->InitXkbInputMethodsForTesting(); |
| 330 | 258 |
| 331 const std::string expected_keyboard_select = | 259 const std::string expected_keyboard_select = |
| 332 TranslateXKB2Extension(expected_keyboard_select_control); | 260 TranslateXKB2Extension(expected_keyboard_select_control); |
| 333 | 261 |
| 334 WaitUntilJSIsReady(); | 262 // Bring up the OOBE network screen. |
| 335 | 263 chromeos::ShowLoginWizard(chromeos::WizardController::kNetworkScreenName); |
| 336 const std::string first_language = | 264 content::WindowedNotificationObserver( |
| 337 expected_locale.substr(0, expected_locale.find(',')); | 265 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, |
| 338 bool done = false; | 266 content::NotificationService::AllSources()).Wait(); |
| 339 const std::string waiting_script = base::StringPrintf( | |
| 340 "var screenElement = document.getElementById('language-select');" | |
| 341 "function SendReplyIfAcceptEnabled() {" | |
| 342 " if ($('language-select').value != '%s')" | |
| 343 " return false;" | |
| 344 " domAutomationController.send(true);" | |
| 345 " observer.disconnect();" | |
| 346 " return true;" | |
| 347 "}" | |
| 348 "var observer = new MutationObserver(SendReplyIfAcceptEnabled);" | |
| 349 "if (!SendReplyIfAcceptEnabled()) {" | |
| 350 " var options = { attributes: true };" | |
| 351 " observer.observe(screenElement, options);" | |
| 352 "}", | |
| 353 first_language.c_str()); | |
| 354 | |
| 355 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( | |
| 356 static_cast<chromeos::LoginDisplayHostImpl*>( | |
| 357 chromeos::LoginDisplayHostImpl::default_host()) | |
| 358 ->GetOobeUI() | |
| 359 ->web_ui() | |
| 360 ->GetWebContents(), | |
| 361 waiting_script, | |
| 362 &done)); | |
| 363 | 267 |
| 364 checker.set_web_contents(static_cast<chromeos::LoginDisplayHostImpl*>( | 268 checker.set_web_contents(static_cast<chromeos::LoginDisplayHostImpl*>( |
| 365 chromeos::LoginDisplayHostImpl::default_host())-> | 269 chromeos::LoginDisplayHostImpl::default_host())-> |
| 366 GetOobeUI()->web_ui()->GetWebContents()); | 270 GetOobeUI()->web_ui()->GetWebContents()); |
| 367 | 271 |
| 368 if (!VerifyInitialOptions(kLocaleSelect, expected_locale.c_str(), true)) { | 272 if (!VerifyInitialOptions(kLocaleSelect, expected_locale.c_str(), true)) { |
| 369 LOG(ERROR) << "Actual value of " << kLocaleSelect << ":\n" | 273 LOG(ERROR) << "Actual value of " << kLocaleSelect << ":\n" |
| 370 << DumpOptions(kLocaleSelect); | 274 << DumpOptions(kLocaleSelect); |
| 371 } | 275 } |
| 372 if (!VerifyInitialOptions( | 276 if (!VerifyInitialOptions( |
| (...skipping 18 matching lines...) Expand all Loading... |
| 391 | 295 |
| 392 // Shut down the display host. | 296 // Shut down the display host. |
| 393 chromeos::LoginDisplayHostImpl::default_host()->Finalize(); | 297 chromeos::LoginDisplayHostImpl::default_host()->Finalize(); |
| 394 base::MessageLoopForUI::current()->RunUntilIdle(); | 298 base::MessageLoopForUI::current()->RunUntilIdle(); |
| 395 | 299 |
| 396 // Clear the locale pref so the statistics provider is pinged next time. | 300 // Clear the locale pref so the statistics provider is pinged next time. |
| 397 g_browser_process->local_state()->SetString(prefs::kApplicationLocale, | 301 g_browser_process->local_state()->SetString(prefs::kApplicationLocale, |
| 398 std::string()); | 302 std::string()); |
| 399 } | 303 } |
| 400 | 304 |
| 401 IN_PROC_BROWSER_TEST_P(OobeLocalizationTest, LocalizationTest) { | 305 IN_PROC_BROWSER_TEST_F(OobeLocalizationTest, NetworkScreenNonLatin) { |
| 402 RunLocalizationTest(); | 306 // For a non-Latin keyboard layout like Russian, we expect to see the US |
| 307 // keyboard. |
| 308 RunLocalizationTest("ru", "xkb:ru::rus", |
| 309 "ru", kUSLayout, |
| 310 "xkb:us::eng"); |
| 311 |
| 312 RunLocalizationTest("ru", "xkb:us::eng,xkb:ru::rus", |
| 313 "ru", kUSLayout, |
| 314 "xkb:us::eng"); |
| 315 |
| 316 // IMEs do not load at OOBE, so we just expect to see the (Latin) Japanese |
| 317 // keyboard. |
| 318 RunLocalizationTest("ja", "xkb:jp::jpn", |
| 319 "ja", "xkb:jp::jpn", |
| 320 "xkb:jp::jpn,[xkb:us::eng]"); |
| 403 } | 321 } |
| 404 | 322 |
| 405 INSTANTIATE_TEST_CASE_P( | 323 IN_PROC_BROWSER_TEST_F(OobeLocalizationTest, NetworkScreenKeyboardLayout) { |
| 406 StructSequence, | 324 // We don't use the Icelandic locale but the Icelandic keyboard layout |
| 407 OobeLocalizationTest, | 325 // should still be selected when specified as the default. |
| 408 testing::Range(&oobe_localization_test_parameters[0], | 326 RunLocalizationTest("en-US", "xkb:is::ice", |
| 409 &oobe_localization_test_parameters[arraysize( | 327 "en-US", "xkb:is::ice", |
| 410 oobe_localization_test_parameters)])); | 328 "xkb:is::ice,[" |
| 329 "xkb:us::eng,xkb:us:intl:eng,xkb:us:altgr-intl:eng," |
| 330 "xkb:us:dvorak:eng,xkb:us:colemak:eng]"); |
| 331 } |
| 332 |
| 333 IN_PROC_BROWSER_TEST_F(OobeLocalizationTest, NetworkScreenFullLatin) { |
| 334 // French Swiss keyboard. |
| 335 RunLocalizationTest("fr", "xkb:ch:fr:fra", |
| 336 "fr", "xkb:ch:fr:fra", |
| 337 "xkb:ch:fr:fra,[" |
| 338 "xkb:fr::fra,xkb:be::fra,xkb:ca::fra," |
| 339 "xkb:ca:multix:fra,xkb:us::eng]"); |
| 340 |
| 341 // German Swiss keyboard. |
| 342 RunLocalizationTest("de", "xkb:ch::ger", |
| 343 "de", "xkb:ch::ger", |
| 344 "xkb:ch::ger,[" |
| 345 "xkb:de::ger,xkb:de:neo:ger,xkb:be::ger,xkb:us::eng" |
| 346 "]"); |
| 347 } |
| 348 |
| 349 IN_PROC_BROWSER_TEST_F(OobeLocalizationTest, NetworkScreenMultipleLocales) { |
| 350 RunLocalizationTest("es,en-US,nl", "xkb:be::nld", |
| 351 "es,en-US,nl", "xkb:be::nld", |
| 352 "xkb:be::nld,[xkb:es::spa,xkb:latam::spa,xkb:us::eng]"); |
| 353 |
| 354 RunLocalizationTest("ru,de", "xkb:ru::rus", |
| 355 "ru,de", kUSLayout, |
| 356 "xkb:us::eng"); |
| 357 } |
| 358 |
| 359 IN_PROC_BROWSER_TEST_F(OobeLocalizationTest, NetworkScreenRegionalLocales) { |
| 360 // Syntetic example to test correct merging of different locales. |
| 361 RunLocalizationTest("fr-CH,it-CH,de-CH", |
| 362 "xkb:fr::fra,xkb:it::ita,xkb:de::ger", |
| 363 "fr-CH,it-CH,de-CH", |
| 364 "xkb:fr::fra", |
| 365 "xkb:fr::fra,xkb:it::ita,xkb:de::ger,[" |
| 366 "xkb:be::fra,xkb:ca::fra,xkb:ch:fr:fra," |
| 367 "xkb:ca:multix:fra,xkb:us::eng" |
| 368 "]"); |
| 369 // Another syntetic example. Check that british keyboard is available. |
| 370 RunLocalizationTest("en-AU", |
| 371 "xkb:us::eng", |
| 372 "en-AU", |
| 373 "xkb:us::eng", |
| 374 "xkb:us::eng,[xkb:gb:extd:eng,xkb:gb:dvorak:eng]"); |
| 375 } |
| 376 |
| 411 } // namespace chromeos | 377 } // namespace chromeos |
| OLD | NEW |