1 // Copyright (c) 2013 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.
10 #include "ash/shell.h"
11 #include "ash/system/chromeos/session/logout_confirmation_controller.h"
12 #include "ash/system/chromeos/session/logout_confirmation_dialog.h"
13 #include "base/basictypes.h"
14 #include "base/bind.h"
15 #include "base/bind_helpers.h"
16 #include "base/callback.h"
17 #include "base/command_line.h"
18 #include "base/files/file_path.h"
19 #include "base/files/file_util.h"
20 #include "base/json/json_reader.h"
21 #include "base/json/json_writer.h"
22 #include "base/location.h"
23 #include "base/macros.h"
24 #include "base/memory/ref_counted.h"
25 #include "base/memory/scoped_ptr.h"
26 #include "base/message_loop/message_loop.h"
27 #include "base/message_loop/message_loop_proxy.h"
28 #include "base/path_service.h"
29 #include "base/prefs/pref_change_registrar.h"
30 #include "base/prefs/pref_service.h"
31 #include "base/run_loop.h"
32 #include "base/sequenced_task_runner.h"
33 #include "base/strings/string_number_conversions.h"
34 #include "base/strings/string_util.h"
35 #include "base/strings/stringprintf.h"
36 #include "base/strings/utf_string_conversions.h"
37 #include "base/threading/sequenced_worker_pool.h"
38 #include "base/values.h"
39 #include "chrome/browser/browser_process.h"
40 #include "chrome/browser/chrome_notification_types.h"
41 #include "chrome/browser/chromeos/extensions/device_local_account_external_policy_loader.h"
42 #include "chrome/browser/chromeos/extensions/external_cache.h"
43 #include "chrome/browser/chromeos/input_method/input_method_util.h"
44 #include "chrome/browser/chromeos/login/existing_user_controller.h"
45 #include "chrome/browser/chromeos/login/screens/base_screen.h"
46 #include "chrome/browser/chromeos/login/signin_specifics.h"
47 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
48 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
49 #include "chrome/browser/chromeos/login/ui/webui_login_view.h"
50 #include "chrome/browser/chromeos/login/users/avatar/user_image_manager.h"
51 #include "chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.h"
52 #include "chrome/browser/chromeos/login/users/avatar/user_image_manager_test_util.h"
53 #include "chrome/browser/chromeos/login/users/chrome_user_manager_impl.h"
54 #include "chrome/browser/chromeos/login/wizard_controller.h"
55 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
56 #include "chrome/browser/chromeos/policy/cloud_external_data_manager_base_test_util.h"
57 #include "chrome/browser/chromeos/policy/device_local_account.h"
58 #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
59 #include "chrome/browser/chromeos/policy/device_policy_builder.h"
60 #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
61 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
62 #include "chrome/browser/extensions/crx_installer.h"
63 #include "chrome/browser/extensions/extension_service.h"
64 #include "chrome/browser/extensions/updater/extension_cache_impl.h"
65 #include "chrome/browser/lifetime/application_lifetime.h"
66 #include "chrome/browser/policy/profile_policy_connector.h"
67 #include "chrome/browser/policy/profile_policy_connector_factory.h"
68 #include "chrome/browser/policy/test/local_policy_test_server.h"
69 #include "chrome/browser/prefs/session_startup_pref.h"
70 #include "chrome/browser/profiles/profile.h"
71 #include "chrome/browser/profiles/profile_manager.h"
72 #include "chrome/browser/signin/signin_manager_factory.h"
73 #include "chrome/browser/ui/browser.h"
74 #include "chrome/browser/ui/browser_commands.h"
75 #include "chrome/browser/ui/browser_finder.h"
76 #include "chrome/browser/ui/browser_list.h"
77 #include "chrome/browser/ui/browser_list_observer.h"
78 #include "chrome/browser/ui/browser_window.h"
79 #include "chrome/browser/ui/extensions/app_launch_params.h"
80 #include "chrome/browser/ui/extensions/application_launch.h"
81 #include "chrome/browser/ui/host_desktop.h"
82 #include "chrome/browser/ui/tabs/tab_strip_model.h"
83 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
84 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
85 #include "chrome/common/chrome_paths.h"
86 #include "chrome/common/extensions/extension_constants.h"
87 #include "chrome/grit/chromium_strings.h"
88 #include "chrome/grit/generated_resources.h"
89 #include "chromeos/chromeos_paths.h"
90 #include "chromeos/chromeos_switches.h"
91 #include "chromeos/dbus/fake_session_manager_client.h"
92 #include "chromeos/login/auth/mock_auth_status_consumer.h"
93 #include "chromeos/login/auth/user_context.h"
94 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
95 #include "components/policy/core/common/cloud/cloud_policy_core.h"
96 #include "components/policy/core/common/cloud/cloud_policy_store.h"
97 #include "components/policy/core/common/cloud/policy_builder.h"
98 #include "components/policy/core/common/external_data_fetcher.h"
99 #include "components/policy/core/common/policy_map.h"
100 #include "components/policy/core/common/policy_namespace.h"
101 #include "components/policy/core/common/policy_service.h"
102 #include "components/policy/core/common/policy_switches.h"
103 #include "components/signin/core/browser/signin_manager.h"
104 #include "components/user_manager/user.h"
105 #include "components/user_manager/user_manager.h"
106 #include "components/user_manager/user_type.h"
107 #include "content/public/browser/browser_thread.h"
108 #include "content/public/browser/notification_details.h"
109 #include "content/public/browser/notification_service.h"
110 #include "content/public/browser/notification_source.h"
111 #include "content/public/browser/web_contents.h"
112 #include "content/public/browser/web_ui.h"
113 #include "content/public/test/browser_test_utils.h"
114 #include "content/public/test/test_utils.h"
115 #include "crypto/rsa_private_key.h"
116 #include "extensions/browser/app_window/app_window.h"
117 #include "extensions/browser/app_window/app_window_registry.h"
118 #include "extensions/browser/app_window/native_app_window.h"
119 #include "extensions/browser/extension_system.h"
120 #include "extensions/browser/install/crx_installer_error.h"
121 #include "extensions/browser/management_policy.h"
122 #include "extensions/browser/notification_types.h"
123 #include "extensions/common/constants.h"
124 #include "extensions/common/extension.h"
125 #include "net/base/url_util.h"
126 #include "net/http/http_status_code.h"
127 #include "net/test/embedded_test_server/embedded_test_server.h"
128 #include "net/test/embedded_test_server/http_request.h"
129 #include "net/test/embedded_test_server/http_response.h"
130 #include "net/url_request/test_url_fetcher_factory.h"
131 #include "net/url_request/url_fetcher_delegate.h"
132 #include "net/url_request/url_request_status.h"
133 #include "policy/policy_constants.h"
134 #include "testing/gmock/include/gmock/gmock.h"
135 #include "third_party/icu/source/common/unicode/locid.h"
136 #include "ui/base/ime/chromeos/extension_ime_util.h"
137 #include "ui/base/ime/chromeos/input_method_descriptor.h"
138 #include "ui/base/ime/chromeos/input_method_manager.h"
139 #include "ui/base/l10n/l10n_util.h"
140 #include "ui/base/window_open_disposition.h"
141 #include "ui/gfx/image/image_skia.h"
142 #include "ui/views/widget/widget.h"
143 #include "url/gurl.h"
145 namespace em
= enterprise_management
;
147 using chromeos::LoginScreenContext
;
148 using testing::InvokeWithoutArgs
;
149 using testing::Return
;
156 const char kDomain
[] = "example.com";
157 const char kAccountId1
[] = "dla1@example.com";
158 const char kAccountId2
[] = "dla2@example.com";
159 const char kDisplayName1
[] = "display name 1";
160 const char kDisplayName2
[] = "display name 2";
161 const char* const kStartupURLs
[] = {
165 const char kExistentTermsOfServicePath
[] = "chromeos/enterprise/tos.txt";
166 const char kNonexistentTermsOfServicePath
[] = "chromeos/enterprise/tos404.txt";
167 const char kRelativeUpdateURL
[] = "/service/update2/crx";
168 const char kUpdateManifestHeader
[] =
169 "<?xml version='1.0' encoding='UTF-8'?>\n"
170 "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>\n";
171 const char kUpdateManifestTemplate
[] =
172 " <app appid='%s'>\n"
173 " <updatecheck codebase='%s' version='%s' />\n"
175 const char kUpdateManifestFooter
[] =
177 const char kHostedAppID
[] = "kbmnembihfiondgfjekmnmcbddelicoi";
178 const char kHostedAppCRXPath
[] = "extensions/hosted_app.crx";
179 const char kHostedAppVersion
[] = "1.0.0.0";
180 const char kGoodExtensionID
[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
181 const char kGoodExtensionCRXPath
[] = "extensions/good.crx";
182 const char kGoodExtensionVersion
[] = "1.0";
183 const char kPackagedAppCRXPath
[] = "extensions/platform_apps/app_window_2.crx";
184 const char kShowManagedStorageID
[] = "ongnjlefhnoajpbodoldndkbkdgfomlp";
185 const char kShowManagedStorageCRXPath
[] = "extensions/show_managed_storage.crx";
186 const char kShowManagedStorageVersion
[] = "1.0";
188 const char kExternalData
[] = "External data";
189 const char kExternalDataURL
[] = "http://localhost/external_data";
191 const char* const kSingleRecommendedLocale
[] = {
194 const char* const kRecommendedLocales1
[] = {
199 const char* const kRecommendedLocales2
[] = {
203 const char* const kInvalidRecommendedLocale
[] = {
206 const char kPublicSessionLocale
[] = "de";
207 const char kPublicSessionInputMethodIDTemplate
[] = "_comp_ime_%sxkb:de:neo:ger";
209 // The sequence token used by GetKeyboardLayoutsForLocale() for its background
211 const char kSequenceToken
[] = "chromeos_login_l10n_util";
213 // Helper that serves extension update manifests to Chrome.
214 class TestingUpdateManifestProvider
{
216 // Update manifests will be served at |relative_update_url|.
217 explicit TestingUpdateManifestProvider(
218 const std::string
& relative_update_url
);
219 ~TestingUpdateManifestProvider();
221 // When an update manifest is requested for the given extension |id|, indicate
222 // that |version| of the extension can be downloaded at |crx_url|.
223 void AddUpdate(const std::string
& id
,
224 const std::string
& version
,
225 const GURL
& crx_url
);
227 // This method must be registered with the test's EmbeddedTestServer to start
228 // serving update manifests.
229 scoped_ptr
<net::test_server::HttpResponse
> HandleRequest(
230 const net::test_server::HttpRequest
& request
);
235 Update(const std::string
& version
, const GURL
& crx_url
);
241 typedef std::map
<std::string
, Update
> UpdateMap
;
244 const std::string relative_update_url_
;
246 DISALLOW_COPY_AND_ASSIGN(TestingUpdateManifestProvider
);
249 // Helper that observes the dictionary |pref| in local state and waits until the
250 // value stored for |key| matches |expected_value|.
251 class DictionaryPrefValueWaiter
{
253 DictionaryPrefValueWaiter(const std::string
& pref
,
254 const std::string
& key
,
255 const std::string
& expected_value
);
256 ~DictionaryPrefValueWaiter();
261 void QuitLoopIfExpectedValueFound();
263 const std::string pref_
;
264 const std::string key_
;
265 const std::string expected_value_
;
267 base::RunLoop run_loop_
;
268 PrefChangeRegistrar pref_change_registrar_
;
270 DISALLOW_COPY_AND_ASSIGN(DictionaryPrefValueWaiter
);
273 TestingUpdateManifestProvider::Update::Update(const std::string
& version
,
279 TestingUpdateManifestProvider::Update::Update() {
282 TestingUpdateManifestProvider::TestingUpdateManifestProvider(
283 const std::string
& relative_update_url
)
284 : relative_update_url_(relative_update_url
) {
287 TestingUpdateManifestProvider::~TestingUpdateManifestProvider() {
290 void TestingUpdateManifestProvider::AddUpdate(const std::string
& id
,
291 const std::string
& version
,
292 const GURL
& crx_url
) {
293 updates_
[id
] = Update(version
, crx_url
);
296 scoped_ptr
<net::test_server::HttpResponse
>
297 TestingUpdateManifestProvider::HandleRequest(
298 const net::test_server::HttpRequest
& request
) {
299 const GURL
url("http://localhost" + request
.relative_url
);
300 if (url
.path() != relative_update_url_
)
301 return scoped_ptr
<net::test_server::HttpResponse
>();
303 std::string content
= kUpdateManifestHeader
;
304 for (net::QueryIterator
it(url
); !it
.IsAtEnd(); it
.Advance()) {
305 if (it
.GetKey() != "x")
307 // Extract the extension id from the subquery. Since GetValueForKeyInQuery()
308 // expects a complete URL, dummy scheme and host must be prepended.
310 net::GetValueForKeyInQuery(GURL("http://dummy?" + it
.GetUnescapedValue()),
312 UpdateMap::const_iterator entry
= updates_
.find(id
);
313 if (entry
!= updates_
.end()) {
314 content
+= base::StringPrintf(kUpdateManifestTemplate
,
316 entry
->second
.crx_url
.spec().c_str(),
317 entry
->second
.version
.c_str());
320 content
+= kUpdateManifestFooter
;
321 scoped_ptr
<net::test_server::BasicHttpResponse
>
322 http_response(new net::test_server::BasicHttpResponse
);
323 http_response
->set_code(net::HTTP_OK
);
324 http_response
->set_content(content
);
325 http_response
->set_content_type("text/xml");
326 return http_response
.Pass();
329 DictionaryPrefValueWaiter::DictionaryPrefValueWaiter(
330 const std::string
& pref
,
331 const std::string
& key
,
332 const std::string
& expected_value
)
335 expected_value_(expected_value
) {
336 pref_change_registrar_
.Init(g_browser_process
->local_state());
339 DictionaryPrefValueWaiter::~DictionaryPrefValueWaiter() {
342 void DictionaryPrefValueWaiter::Wait() {
343 pref_change_registrar_
.Add(
345 base::Bind(&DictionaryPrefValueWaiter::QuitLoopIfExpectedValueFound
,
346 base::Unretained(this)));
347 QuitLoopIfExpectedValueFound();
351 void DictionaryPrefValueWaiter::QuitLoopIfExpectedValueFound() {
352 const base::DictionaryValue
* pref
=
353 pref_change_registrar_
.prefs()->GetDictionary(pref_
.c_str());
355 std::string actual_value
;
356 if (pref
->GetStringWithoutPathExpansion(key_
, &actual_value
) &&
357 actual_value
== expected_value_
) {
362 bool DoesInstallSuccessReferToId(const std::string
& id
,
363 const content::NotificationSource
& source
,
364 const content::NotificationDetails
& details
) {
365 return content::Details
<const extensions::InstalledExtensionInfo
>(details
)->
366 extension
->id() == id
;
369 bool DoesInstallFailureReferToId(const std::string
& id
,
370 const content::NotificationSource
& source
,
371 const content::NotificationDetails
& details
) {
372 return content::Details
<const extensions::CrxInstallerError
>(details
)->
373 message().find(base::UTF8ToUTF16(id
)) != base::string16::npos
;
376 scoped_ptr
<net::FakeURLFetcher
> RunCallbackAndReturnFakeURLFetcher(
377 scoped_refptr
<base::SequencedTaskRunner
> task_runner
,
378 const base::Closure
& callback
,
380 net::URLFetcherDelegate
* delegate
,
381 const std::string
& response_data
,
382 net::HttpStatusCode response_code
,
383 net::URLRequestStatus::Status status
) {
384 task_runner
->PostTask(FROM_HERE
, callback
);
385 return make_scoped_ptr(new net::FakeURLFetcher(
386 url
, delegate
, response_data
, response_code
, status
));
389 bool IsSessionStarted() {
390 return user_manager::UserManager::Get()->IsSessionStarted();
393 void PolicyChangedCallback(const base::Closure
& callback
,
394 const base::Value
* old_value
,
395 const base::Value
* new_value
) {
401 class DeviceLocalAccountTest
: public DevicePolicyCrosBrowserTest
,
402 public user_manager::UserManager::Observer
,
403 public chrome::BrowserListObserver
,
404 public extensions::AppWindowRegistry::Observer
{
406 DeviceLocalAccountTest()
407 : user_id_1_(GenerateDeviceLocalAccountUserId(
408 kAccountId1
, DeviceLocalAccount::TYPE_PUBLIC_SESSION
)),
409 user_id_2_(GenerateDeviceLocalAccountUserId(
410 kAccountId2
, DeviceLocalAccount::TYPE_PUBLIC_SESSION
)),
411 public_session_input_method_id_(base::StringPrintf(
412 kPublicSessionInputMethodIDTemplate
,
413 chromeos::extension_ime_util::kXkbExtensionId
)),
415 set_exit_when_last_browser_closes(false);
418 ~DeviceLocalAccountTest() override
{}
420 void SetUp() override
{
421 // Configure and start the test server.
422 scoped_ptr
<crypto::RSAPrivateKey
> signing_key(
423 PolicyBuilder::CreateTestSigningKey());
424 ASSERT_TRUE(test_server_
.SetSigningKeyAndSignature(
425 signing_key
.get(), PolicyBuilder::GetTestSigningKeySignature()));
427 test_server_
.RegisterClient(PolicyBuilder::kFakeToken
,
428 PolicyBuilder::kFakeDeviceId
);
429 ASSERT_TRUE(test_server_
.Start());
431 BrowserList::AddObserver(this);
433 DevicePolicyCrosBrowserTest::SetUp();
436 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
437 DevicePolicyCrosBrowserTest::SetUpCommandLine(command_line
);
438 command_line
->AppendSwitch(chromeos::switches::kLoginManager
);
439 command_line
->AppendSwitch(chromeos::switches::kForceLoginManagerInTests
);
440 command_line
->AppendSwitchASCII(chromeos::switches::kLoginProfile
, "user");
441 command_line
->AppendSwitchASCII(policy::switches::kDeviceManagementUrl
,
442 test_server_
.GetServiceURL().spec());
445 void SetUpInProcessBrowserTestFixture() override
{
446 DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
448 // Clear command-line arguments (but keep command-line switches) so the
449 // startup pages policy takes effect.
450 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
451 base::CommandLine::StringVector
argv(command_line
->argv());
452 argv
.erase(argv
.begin() + argv
.size() - command_line
->GetArgs().size(),
454 command_line
->InitFromArgv(argv
);
457 MarkAsEnterpriseOwned();
462 void SetUpOnMainThread() override
{
463 DevicePolicyCrosBrowserTest::SetUpOnMainThread();
465 initial_locale_
= g_browser_process
->GetApplicationLocale();
466 initial_language_
= l10n_util::GetLanguage(initial_locale_
);
468 content::WindowedNotificationObserver(
469 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
,
470 content::NotificationService::AllSources()).Wait();
472 chromeos::LoginDisplayHostImpl
* host
=
473 reinterpret_cast<chromeos::LoginDisplayHostImpl
*>(
474 chromeos::LoginDisplayHostImpl::default_host());
476 chromeos::WebUILoginView
* web_ui_login_view
= host
->GetWebUILoginView();
477 ASSERT_TRUE(web_ui_login_view
);
478 content::WebUI
* web_ui
= web_ui_login_view
->GetWebUI();
480 contents_
= web_ui
->GetWebContents();
481 ASSERT_TRUE(contents_
);
483 // Wait for the login UI to be ready.
484 chromeos::OobeUI
* oobe_ui
= host
->GetOobeUI();
485 ASSERT_TRUE(oobe_ui
);
486 base::RunLoop run_loop
;
487 const bool oobe_ui_ready
= oobe_ui
->IsJSReady(run_loop
.QuitClosure());
491 // The network selection screen changes the application locale on load and
492 // once again on blur. Wait for the screen to load and blur it so that any
493 // locale changes caused by this screen happen now and do not affect any
494 // subsequent parts of the test.
496 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
498 "var languageSelect = document.getElementById('language-select');"
499 "var blurAndReportSuccess = function() {"
500 " languageSelect.blur();"
501 " domAutomationController.send(true);"
503 "var screenLoading = document.getElementById('outer-container')"
504 " .classList.contains('down');"
505 "if (document.activeElement == languageSelect || !screenLoading)"
506 " blurAndReportSuccess();"
508 " languageSelect.addEventListener('focus', blurAndReportSuccess);",
511 // Skip to the login screen.
512 chromeos::WizardController
* wizard_controller
=
513 chromeos::WizardController::default_controller();
514 ASSERT_TRUE(wizard_controller
);
515 wizard_controller
->SkipToLoginForTesting(LoginScreenContext());
518 void TearDownOnMainThread() override
{
519 BrowserList::RemoveObserver(this);
521 // This shuts down the login UI.
522 base::MessageLoop::current()->PostTask(FROM_HERE
,
523 base::Bind(&chrome::AttemptExit
));
524 base::RunLoop().RunUntilIdle();
527 void LocalStateChanged(user_manager::UserManager
* user_manager
) override
{
532 void OnBrowserRemoved(Browser
* browser
) override
{
537 void OnAppWindowAdded(extensions::AppWindow
* app_window
) override
{
542 void OnAppWindowRemoved(extensions::AppWindow
* app_window
) override
{
547 void InitializePolicy() {
548 device_policy()->policy_data().set_public_key_version(1);
549 em::ChromeDeviceSettingsProto
& proto(device_policy()->payload());
550 proto
.mutable_show_user_names()->set_show_user_names(true);
552 device_local_account_policy_
.policy_data().set_policy_type(
553 dm_protocol::kChromePublicAccountPolicyType
);
554 device_local_account_policy_
.policy_data().set_username(kAccountId1
);
555 device_local_account_policy_
.policy_data().set_settings_entity_id(
557 device_local_account_policy_
.policy_data().set_public_key_version(1);
558 device_local_account_policy_
.payload().mutable_userdisplayname()->set_value(
562 void BuildDeviceLocalAccountPolicy() {
563 device_local_account_policy_
.SetDefaultSigningKey();
564 device_local_account_policy_
.Build();
567 void UploadDeviceLocalAccountPolicy() {
568 BuildDeviceLocalAccountPolicy();
569 ASSERT_TRUE(test_server_
.UpdatePolicy(
570 dm_protocol::kChromePublicAccountPolicyType
, kAccountId1
,
571 device_local_account_policy_
.payload().SerializeAsString()));
574 void UploadAndInstallDeviceLocalAccountPolicy() {
575 UploadDeviceLocalAccountPolicy();
576 session_manager_client()->set_device_local_account_policy(
577 kAccountId1
, device_local_account_policy_
.GetBlob());
580 void SetRecommendedLocales(const char* const recommended_locales
[],
582 em::StringListPolicyProto
* session_locales_proto
=
583 device_local_account_policy_
.payload().mutable_sessionlocales();
584 session_locales_proto
->mutable_policy_options()->set_mode(
585 em::PolicyOptions_PolicyMode_RECOMMENDED
);
586 session_locales_proto
->mutable_value()->Clear();
587 for (size_t i
= 0; i
< array_size
; ++i
) {
588 session_locales_proto
->mutable_value()->add_entries(
589 recommended_locales
[i
]);
593 void AddPublicSessionToDevicePolicy(const std::string
& username
) {
594 em::ChromeDeviceSettingsProto
& proto(device_policy()->payload());
595 em::DeviceLocalAccountInfoProto
* account
=
596 proto
.mutable_device_local_accounts()->add_account();
597 account
->set_account_id(username
);
599 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION
);
600 RefreshDevicePolicy();
601 ASSERT_TRUE(test_server_
.UpdatePolicy(dm_protocol::kChromeDevicePolicyType
,
603 proto
.SerializeAsString()));
606 void EnableAutoLogin() {
607 em::ChromeDeviceSettingsProto
& proto(device_policy()->payload());
608 em::DeviceLocalAccountsProto
* device_local_accounts
=
609 proto
.mutable_device_local_accounts();
610 device_local_accounts
->set_auto_login_id(kAccountId1
);
611 device_local_accounts
->set_auto_login_delay(0);
612 RefreshDevicePolicy();
613 ASSERT_TRUE(test_server_
.UpdatePolicy(dm_protocol::kChromeDevicePolicyType
,
615 proto
.SerializeAsString()));
618 void CheckPublicSessionPresent(const std::string
& id
) {
619 const user_manager::User
* user
=
620 user_manager::UserManager::Get()->FindUser(id
);
622 EXPECT_EQ(id
, user
->email());
623 EXPECT_EQ(user_manager::USER_TYPE_PUBLIC_ACCOUNT
, user
->GetType());
626 base::FilePath
GetExtensionCacheDirectoryForAccountID(
627 const std::string
& account_id
) {
628 base::FilePath extension_cache_root_dir
;
629 if (!PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS
,
630 &extension_cache_root_dir
)) {
633 return extension_cache_root_dir
.Append(
634 base::HexEncode(account_id
.c_str(), account_id
.size()));
637 base::FilePath
GetCacheCRXFilePath(const std::string
& account_id
,
638 const std::string
& id
,
639 const std::string
& version
,
640 const base::FilePath
& path
) {
642 base::StringPrintf("%s-%s.crx", id
.c_str(), version
.c_str()));
645 base::FilePath
GetCacheCRXFile(const std::string
& account_id
,
646 const std::string
& id
,
647 const std::string
& version
) {
648 return GetCacheCRXFilePath(
649 account_id
, id
, version
,
650 GetExtensionCacheDirectoryForAccountID(account_id
));
653 // Returns a profile which can be used for testing.
654 Profile
* GetProfileForTest() {
655 // Any profile can be used here since this test does not test multi profile.
656 return ProfileManager::GetActiveUserProfile();
659 void WaitForDisplayName(const std::string
& user_id
,
660 const std::string
& expected_display_name
) {
661 DictionaryPrefValueWaiter("UserDisplayName",
663 expected_display_name
).Wait();
666 void WaitForPolicy() {
667 // Wait for the display name becoming available as that indicates
668 // device-local account policy is fully loaded, which is a prerequisite for
670 WaitForDisplayName(user_id_1_
, kDisplayName1
);
673 void ExpandPublicSessionPod(bool expect_advanced
) {
674 bool advanced
= false;
675 // Click on the pod to expand it.
676 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
680 " document.getElementById('pod-row').getPodWithUsername_('%s');"
682 "domAutomationController.send(pod.classList.contains('advanced'));",
685 // Verify that the pod expanded to its basic/advanced form, as expected.
686 EXPECT_EQ(expect_advanced
, advanced
);
688 // Verify that the construction of the pod's language list did not affect
689 // the current ICU locale.
690 EXPECT_EQ(initial_language_
, icu::Locale::getDefault().getLanguage());
693 // GetKeyboardLayoutsForLocale() posts a task to a background task runner.
694 // This method flushes that task runner and the current thread's message loop
695 // to ensure that GetKeyboardLayoutsForLocale() is finished.
696 void WaitForGetKeyboardLayoutsForLocaleToFinish() {
697 base::SequencedWorkerPool
* worker_pool
=
698 content::BrowserThread::GetBlockingPool();
699 scoped_refptr
<base::SequencedTaskRunner
> background_task_runner
=
700 worker_pool
->GetSequencedTaskRunner(
701 worker_pool
->GetNamedSequenceToken(kSequenceToken
));
702 base::RunLoop run_loop
;
703 background_task_runner
->PostTaskAndReply(FROM_HERE
,
704 base::Bind(&base::DoNothing
),
705 run_loop
.QuitClosure());
707 base::RunLoop().RunUntilIdle();
709 // Verify that the construction of the keyboard layout list did not affect
710 // the current ICU locale.
711 EXPECT_EQ(initial_language_
, icu::Locale::getDefault().getLanguage());
714 void StartLogin(const std::string
& locale
,
715 const std::string
& input_method
) {
716 // Start login into the device-local account.
717 chromeos::LoginDisplayHostImpl
* host
=
718 reinterpret_cast<chromeos::LoginDisplayHostImpl
*>(
719 chromeos::LoginDisplayHostImpl::default_host());
721 host
->StartSignInScreen(LoginScreenContext());
722 chromeos::ExistingUserController
* controller
=
723 chromeos::ExistingUserController::current_controller();
724 ASSERT_TRUE(controller
);
726 chromeos::UserContext
user_context(user_manager::USER_TYPE_PUBLIC_ACCOUNT
,
728 user_context
.SetPublicSessionLocale(locale
);
729 user_context
.SetPublicSessionInputMethod(input_method
);
730 controller
->Login(user_context
, chromeos::SigninSpecifics());
733 void WaitForSessionStart() {
734 if (IsSessionStarted())
736 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED
,
737 base::Bind(IsSessionStarted
)).Wait();
740 void VerifyKeyboardLayoutMatchesLocale() {
741 chromeos::input_method::InputMethodManager
* input_method_manager
=
742 chromeos::input_method::InputMethodManager::Get();
743 std::vector
<std::string
> layouts_from_locale
;
744 input_method_manager
->GetInputMethodUtil()->
745 GetInputMethodIdsFromLanguageCode(
746 g_browser_process
->GetApplicationLocale(),
747 chromeos::input_method::kKeyboardLayoutsOnly
,
748 &layouts_from_locale
);
749 ASSERT_FALSE(layouts_from_locale
.empty());
750 EXPECT_EQ(layouts_from_locale
.front(),
751 input_method_manager
->GetActiveIMEState()
752 ->GetCurrentInputMethod()
756 const std::string user_id_1_
;
757 const std::string user_id_2_
;
758 const std::string public_session_input_method_id_
;
760 std::string initial_locale_
;
761 std::string initial_language_
;
763 scoped_ptr
<base::RunLoop
> run_loop_
;
765 UserPolicyBuilder device_local_account_policy_
;
766 LocalPolicyTestServer test_server_
;
768 content::WebContents
* contents_
;
771 DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountTest
);
774 static bool IsKnownUser(const std::string
& account_id
) {
775 return user_manager::UserManager::Get()->IsKnownUser(account_id
);
778 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, LoginScreen
) {
779 AddPublicSessionToDevicePolicy(kAccountId1
);
780 AddPublicSessionToDevicePolicy(kAccountId2
);
782 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED
,
783 base::Bind(&IsKnownUser
, user_id_1_
))
785 EXPECT_TRUE(IsKnownUser(user_id_2_
));
787 CheckPublicSessionPresent(user_id_1_
);
788 CheckPublicSessionPresent(user_id_2_
);
791 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, DisplayName
) {
792 UploadAndInstallDeviceLocalAccountPolicy();
793 AddPublicSessionToDevicePolicy(kAccountId1
);
797 // Verify that the display name is shown in the UI.
798 const std::string get_compact_pod_display_name
= base::StringPrintf(
799 "domAutomationController.send(document.getElementById('pod-row')"
800 " .getPodWithUsername_('%s').nameElement.textContent);",
802 std::string display_name
;
803 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
805 get_compact_pod_display_name
,
807 EXPECT_EQ(kDisplayName1
, display_name
);
808 const std::string get_expanded_pod_display_name
= base::StringPrintf(
809 "domAutomationController.send(document.getElementById('pod-row')"
810 " .getPodWithUsername_('%s').querySelector('.expanded-pane-name')"
813 display_name
.clear();
814 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
816 get_expanded_pod_display_name
,
818 EXPECT_EQ(kDisplayName1
, display_name
);
820 // Click on the pod to expand it.
821 ASSERT_TRUE(content::ExecuteScript(
824 "document.getElementById('pod-row').getPodWithUsername_('%s')"
826 user_id_1_
.c_str())));
828 // Change the display name.
829 device_local_account_policy_
.payload().mutable_userdisplayname()->set_value(
831 UploadAndInstallDeviceLocalAccountPolicy();
832 policy::BrowserPolicyConnectorChromeOS
* connector
=
833 g_browser_process
->platform_part()->browser_policy_connector_chromeos();
834 DeviceLocalAccountPolicyBroker
* broker
=
835 connector
->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
838 broker
->core()->store()->Load();
839 WaitForDisplayName(user_id_1_
, kDisplayName2
);
841 // Verify that the new display name is shown in the UI.
842 display_name
.clear();
843 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
845 get_compact_pod_display_name
,
847 EXPECT_EQ(kDisplayName2
, display_name
);
848 display_name
.clear();
849 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
851 get_expanded_pod_display_name
,
853 EXPECT_EQ(kDisplayName2
, display_name
);
855 // Verify that the pod is still expanded. This indicates that the UI updated
856 // without reloading and losing state.
857 bool expanded
= false;
858 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
861 "domAutomationController.send(document.getElementById('pod-row')"
862 " .getPodWithUsername_('%s').expanded);",
865 EXPECT_TRUE(expanded
);
868 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, PolicyDownload
) {
869 UploadDeviceLocalAccountPolicy();
870 AddPublicSessionToDevicePolicy(kAccountId1
);
874 // Sanity check: The policy should be present now.
875 ASSERT_FALSE(session_manager_client()->device_local_account_policy(
876 kAccountId1
).empty());
879 static bool IsNotKnownUser(const std::string
& account_id
) {
880 return !IsKnownUser(account_id
);
883 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, AccountListChange
) {
884 AddPublicSessionToDevicePolicy(kAccountId1
);
885 AddPublicSessionToDevicePolicy(kAccountId2
);
887 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED
,
888 base::Bind(&IsKnownUser
, user_id_1_
))
890 EXPECT_TRUE(IsKnownUser(user_id_2_
));
892 // Update policy to remove kAccountId2.
893 em::ChromeDeviceSettingsProto
& proto(device_policy()->payload());
894 proto
.mutable_device_local_accounts()->clear_account();
895 AddPublicSessionToDevicePolicy(kAccountId1
);
897 em::ChromeDeviceSettingsProto policy
;
898 policy
.mutable_show_user_names()->set_show_user_names(true);
899 em::DeviceLocalAccountInfoProto
* account1
=
900 policy
.mutable_device_local_accounts()->add_account();
901 account1
->set_account_id(kAccountId1
);
903 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION
);
905 test_server_
.UpdatePolicy(dm_protocol::kChromeDevicePolicyType
, std::string(),
906 policy
.SerializeAsString());
907 g_browser_process
->policy_service()->RefreshPolicies(base::Closure());
909 // Make sure the second device-local account disappears.
910 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED
,
911 base::Bind(&IsNotKnownUser
, user_id_2_
))
915 // Test fails under MSan, http://crbug.com/446950
916 #if defined(MEMORY_SANITIZER)
917 #define MAYBE_StartSession DISABLED_StartSession
919 #define MAYBE_StartSession StartSession
922 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, MAYBE_StartSession
) {
923 // Specify startup pages.
924 device_local_account_policy_
.payload().mutable_restoreonstartup()->set_value(
925 SessionStartupPref::kPrefValueURLs
);
926 em::StringListPolicyProto
* startup_urls_proto
=
927 device_local_account_policy_
.payload().mutable_restoreonstartupurls();
928 for (size_t i
= 0; i
< arraysize(kStartupURLs
); ++i
)
929 startup_urls_proto
->mutable_value()->add_entries(kStartupURLs
[i
]);
930 UploadAndInstallDeviceLocalAccountPolicy();
931 AddPublicSessionToDevicePolicy(kAccountId1
);
935 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
936 WaitForSessionStart();
938 // Check that the startup pages specified in policy were opened.
939 BrowserList
* browser_list
=
940 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH
);
941 EXPECT_EQ(1U, browser_list
->size());
942 Browser
* browser
= browser_list
->get(0);
943 ASSERT_TRUE(browser
);
945 TabStripModel
* tabs
= browser
->tab_strip_model();
947 int expected_tab_count
= static_cast<int>(arraysize(kStartupURLs
));
948 EXPECT_EQ(expected_tab_count
, tabs
->count());
949 for (int i
= 0; i
< expected_tab_count
&& i
< tabs
->count(); ++i
) {
950 EXPECT_EQ(GURL(kStartupURLs
[i
]),
951 tabs
->GetWebContentsAt(i
)->GetVisibleURL());
954 // Verify that the session is not considered to be logged in with a GAIA
956 Profile
* profile
= GetProfileForTest();
957 ASSERT_TRUE(profile
);
959 SigninManagerFactory::GetForProfile(profile
)->IsAuthenticated());
962 // Test fails under MSan, http://crbug.com/446950
963 #if defined(MEMORY_SANITIZER)
964 #define MAYBE_FullscreenDisallowed DISABLED_FullscreenDisallowed
966 #define MAYBE_FullscreenDisallowed FullscreenDisallowed
969 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, MAYBE_FullscreenDisallowed
) {
970 UploadAndInstallDeviceLocalAccountPolicy();
971 AddPublicSessionToDevicePolicy(kAccountId1
);
975 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
976 WaitForSessionStart();
978 BrowserList
* browser_list
=
979 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH
);
980 EXPECT_EQ(1U, browser_list
->size());
981 Browser
* browser
= browser_list
->get(0);
982 ASSERT_TRUE(browser
);
983 BrowserWindow
* browser_window
= browser
->window();
984 ASSERT_TRUE(browser_window
);
986 // Verify that an attempt to enter fullscreen mode is denied.
987 EXPECT_FALSE(browser_window
->IsFullscreen());
988 chrome::ToggleFullscreenMode(browser
);
989 EXPECT_FALSE(browser_window
->IsFullscreen());
992 // Test fails under MSan, http://crbug.com/446950
993 #if defined(MEMORY_SANITIZER)
994 #define MAYBE_ExtensionsUncached DISABLED_ExtensionsUncached
996 #define MAYBE_ExtensionsUncached ExtensionsUncached
999 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, MAYBE_ExtensionsUncached
) {
1000 // Make it possible to force-install a hosted app and an extension.
1001 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
1002 TestingUpdateManifestProvider
testing_update_manifest_provider(
1003 kRelativeUpdateURL
);
1004 testing_update_manifest_provider
.AddUpdate(
1007 embedded_test_server()->GetURL(std::string("/") + kHostedAppCRXPath
));
1008 testing_update_manifest_provider
.AddUpdate(
1010 kGoodExtensionVersion
,
1011 embedded_test_server()->GetURL(std::string("/") + kGoodExtensionCRXPath
));
1012 embedded_test_server()->RegisterRequestHandler(
1013 base::Bind(&TestingUpdateManifestProvider::HandleRequest
,
1014 base::Unretained(&testing_update_manifest_provider
)));
1016 // Specify policy to force-install the hosted app and the extension.
1017 em::StringList
* forcelist
= device_local_account_policy_
.payload()
1018 .mutable_extensioninstallforcelist()->mutable_value();
1019 forcelist
->add_entries(base::StringPrintf(
1022 embedded_test_server()->GetURL(kRelativeUpdateURL
).spec().c_str()));
1023 forcelist
->add_entries(base::StringPrintf(
1026 embedded_test_server()->GetURL(kRelativeUpdateURL
).spec().c_str()));
1028 UploadAndInstallDeviceLocalAccountPolicy();
1029 AddPublicSessionToDevicePolicy(kAccountId1
);
1033 // Start listening for app/extension installation results.
1034 content::WindowedNotificationObserver
hosted_app_observer(
1035 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED
,
1036 base::Bind(DoesInstallSuccessReferToId
, kHostedAppID
));
1037 content::WindowedNotificationObserver
extension_observer(
1038 extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR
,
1039 base::Bind(DoesInstallFailureReferToId
, kGoodExtensionID
));
1041 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
1043 // Wait for the hosted app installation to succeed and the extension
1044 // installation to fail (because hosted apps are whitelisted for use in
1045 // device-local accounts and extensions are not).
1046 hosted_app_observer
.Wait();
1047 extension_observer
.Wait();
1049 // Verify that the hosted app was installed.
1050 Profile
* profile
= GetProfileForTest();
1051 ASSERT_TRUE(profile
);
1052 ExtensionService
* extension_service
=
1053 extensions::ExtensionSystem::Get(profile
)->extension_service();
1054 EXPECT_TRUE(extension_service
->GetExtensionById(kHostedAppID
, true));
1056 // Verify that the extension was not installed.
1057 EXPECT_FALSE(extension_service
->GetExtensionById(kGoodExtensionID
, true));
1059 // Verify that the app was downloaded to the account's extension cache.
1060 base::FilePath test_dir
;
1061 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_dir
));
1062 EXPECT_TRUE(ContentsEqual(
1063 GetCacheCRXFile(kAccountId1
, kHostedAppID
, kHostedAppVersion
),
1064 test_dir
.Append(kHostedAppCRXPath
)));
1066 // Verify that the extension was removed from the account's extension cache
1067 // after the installation failure.
1068 DeviceLocalAccountPolicyBroker
* broker
=
1069 g_browser_process
->platform_part()->browser_policy_connector_chromeos()->
1070 GetDeviceLocalAccountPolicyService()->GetBrokerForUser(user_id_1_
);
1071 ASSERT_TRUE(broker
);
1072 chromeos::ExternalCache
* cache
=
1073 broker
->extension_loader()->GetExternalCacheForTesting();
1075 EXPECT_FALSE(cache
->GetExtension(kGoodExtensionID
, NULL
, NULL
));
1078 // Test fails under MSan, http://crbug.com/446950
1079 #if defined(MEMORY_SANITIZER)
1080 #define MAYBE_ExtensionsCached DISABLED_ExtensionsCached
1082 #define MAYBE_ExtensionsCached ExtensionsCached
1085 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, MAYBE_ExtensionsCached
) {
1086 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
1088 // Pre-populate the device local account's extension cache with a hosted app
1089 // and an extension.
1090 EXPECT_TRUE(base::CreateDirectory(
1091 GetExtensionCacheDirectoryForAccountID(kAccountId1
)));
1092 base::FilePath test_dir
;
1093 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_dir
));
1094 const base::FilePath cached_hosted_app
=
1095 GetCacheCRXFile(kAccountId1
, kHostedAppID
, kHostedAppVersion
);
1096 EXPECT_TRUE(CopyFile(test_dir
.Append(kHostedAppCRXPath
),
1097 cached_hosted_app
));
1098 EXPECT_TRUE(CopyFile(
1099 test_dir
.Append(kGoodExtensionCRXPath
),
1100 GetCacheCRXFile(kAccountId1
, kGoodExtensionID
, kGoodExtensionVersion
)));
1102 // Specify policy to force-install the hosted app.
1103 em::StringList
* forcelist
= device_local_account_policy_
.payload()
1104 .mutable_extensioninstallforcelist()->mutable_value();
1105 forcelist
->add_entries(base::StringPrintf(
1108 embedded_test_server()->GetURL(kRelativeUpdateURL
).spec().c_str()));
1109 forcelist
->add_entries(base::StringPrintf(
1112 embedded_test_server()->GetURL(kRelativeUpdateURL
).spec().c_str()));
1114 UploadAndInstallDeviceLocalAccountPolicy();
1115 AddPublicSessionToDevicePolicy(kAccountId1
);
1119 // Start listening for app/extension installation results.
1120 content::WindowedNotificationObserver
hosted_app_observer(
1121 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED
,
1122 base::Bind(DoesInstallSuccessReferToId
, kHostedAppID
));
1123 content::WindowedNotificationObserver
extension_observer(
1124 extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR
,
1125 base::Bind(DoesInstallFailureReferToId
, kGoodExtensionID
));
1127 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
1129 // Wait for the hosted app installation to succeed and the extension
1130 // installation to fail.
1131 hosted_app_observer
.Wait();
1132 extension_observer
.Wait();
1134 // Verify that the hosted app was installed.
1135 Profile
* profile
= GetProfileForTest();
1136 ASSERT_TRUE(profile
);
1137 ExtensionService
* extension_service
=
1138 extensions::ExtensionSystem::Get(profile
)->extension_service();
1139 EXPECT_TRUE(extension_service
->GetExtensionById(kHostedAppID
, true));
1141 // Verify that the extension was not installed.
1142 EXPECT_FALSE(extension_service
->GetExtensionById(kGoodExtensionID
, true));
1144 // Verify that the app is still in the account's extension cache.
1145 EXPECT_TRUE(PathExists(cached_hosted_app
));
1147 // Verify that the extension was removed from the account's extension cache.
1148 DeviceLocalAccountPolicyBroker
* broker
=
1149 g_browser_process
->platform_part()->browser_policy_connector_chromeos()->
1150 GetDeviceLocalAccountPolicyService()->GetBrokerForUser(user_id_1_
);
1151 ASSERT_TRUE(broker
);
1152 chromeos::ExternalCache
* cache
=
1153 broker
->extension_loader()->GetExternalCacheForTesting();
1155 EXPECT_FALSE(cache
->GetExtension(kGoodExtensionID
, NULL
, NULL
));
1158 static void OnPutExtension(scoped_ptr
<base::RunLoop
>* run_loop
,
1159 const base::FilePath
& file_path
,
1160 bool file_ownership_passed
) {
1161 ASSERT_TRUE(*run_loop
);
1162 (*run_loop
)->Quit();
1165 static void OnExtensionCacheImplInitialized(
1166 scoped_ptr
<base::RunLoop
>* run_loop
) {
1167 ASSERT_TRUE(*run_loop
);
1168 (*run_loop
)->Quit();
1171 static void CreateFile(const base::FilePath
& file
,
1173 const base::Time
& timestamp
) {
1174 std::string
data(size
, 0);
1175 EXPECT_EQ(base::WriteFile(file
, data
.data(), data
.size()), int(size
));
1176 EXPECT_TRUE(base::TouchFile(file
, timestamp
, timestamp
));
1179 // Test fails under MSan, http://crbug.com/446950
1180 #if defined(MEMORY_SANITIZER)
1181 #define MAYBE_ExtensionCacheImplTest DISABLED_ExtensionCacheImplTest
1183 #define MAYBE_ExtensionCacheImplTest ExtensionCacheImplTest
1186 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, MAYBE_ExtensionCacheImplTest
) {
1187 // Make it possible to force-install a hosted app and an extension.
1188 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
1189 TestingUpdateManifestProvider
testing_update_manifest_provider(
1190 kRelativeUpdateURL
);
1191 testing_update_manifest_provider
.AddUpdate(
1194 embedded_test_server()->GetURL(std::string("/") + kHostedAppCRXPath
));
1195 testing_update_manifest_provider
.AddUpdate(
1197 kGoodExtensionVersion
,
1198 embedded_test_server()->GetURL(std::string("/") + kGoodExtensionCRXPath
));
1199 embedded_test_server()->RegisterRequestHandler(
1200 base::Bind(&TestingUpdateManifestProvider::HandleRequest
,
1201 base::Unretained(&testing_update_manifest_provider
)));
1203 // Create and initialize local cache.
1204 base::ScopedTempDir cache_dir
;
1205 EXPECT_TRUE(cache_dir
.CreateUniqueTempDir());
1206 const base::FilePath impl_path
= cache_dir
.path();
1207 EXPECT_TRUE(base::CreateDirectory(impl_path
));
1208 CreateFile(impl_path
.Append(
1209 extensions::LocalExtensionCache::kCacheReadyFlagFileName
),
1210 0, base::Time::Now());
1211 extensions::ExtensionCacheImpl
cache_impl(impl_path
);
1212 scoped_ptr
<base::RunLoop
> run_loop
;
1213 run_loop
.reset(new base::RunLoop
);
1214 cache_impl
.Start(base::Bind(&OnExtensionCacheImplInitialized
, &run_loop
));
1217 // Put extension in the local cache.
1218 base::ScopedTempDir temp_dir
;
1219 EXPECT_TRUE(temp_dir
.CreateUniqueTempDir());
1220 const base::FilePath temp_path
= temp_dir
.path();
1221 EXPECT_TRUE(base::CreateDirectory(temp_path
));
1222 const base::FilePath temp_file
= GetCacheCRXFilePath(
1223 kAccountId1
, kGoodExtensionID
, kGoodExtensionVersion
, temp_path
);
1224 base::FilePath test_dir
;
1225 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_dir
));
1226 EXPECT_TRUE(CopyFile(test_dir
.Append(kGoodExtensionCRXPath
), temp_file
));
1227 cache_impl
.AllowCaching(kGoodExtensionID
);
1228 run_loop
.reset(new base::RunLoop
);
1229 cache_impl
.PutExtension(kGoodExtensionID
, temp_file
, kGoodExtensionVersion
,
1230 base::Bind(&OnPutExtension
, &run_loop
));
1233 // Verify that the extension file was added to the local cache.
1234 const base::FilePath local_file
= GetCacheCRXFilePath(
1235 kAccountId1
, kGoodExtensionID
, kGoodExtensionVersion
, impl_path
);
1236 EXPECT_TRUE(PathExists(local_file
));
1238 // Specify policy to force-install the hosted app and the extension.
1239 em::StringList
* forcelist
= device_local_account_policy_
.payload()
1240 .mutable_extensioninstallforcelist()->mutable_value();
1241 forcelist
->add_entries(base::StringPrintf(
1244 embedded_test_server()->GetURL(kRelativeUpdateURL
).spec().c_str()));
1245 forcelist
->add_entries(base::StringPrintf(
1248 embedded_test_server()->GetURL(kRelativeUpdateURL
).spec().c_str()));
1250 UploadAndInstallDeviceLocalAccountPolicy();
1251 AddPublicSessionToDevicePolicy(kAccountId1
);
1255 // Start listening for app/extension installation results.
1256 content::WindowedNotificationObserver
hosted_app_observer(
1257 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED
,
1258 base::Bind(DoesInstallSuccessReferToId
, kHostedAppID
));
1259 content::WindowedNotificationObserver
extension_observer(
1260 extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR
,
1261 base::Bind(DoesInstallFailureReferToId
, kGoodExtensionID
));
1263 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
1265 // Wait for the hosted app installation to succeed and the extension
1266 // installation to fail (because hosted apps are whitelisted for use in
1267 // device-local accounts and extensions are not).
1268 hosted_app_observer
.Wait();
1269 extension_observer
.Wait();
1271 // Verify that the extension was kept in the local cache.
1272 EXPECT_TRUE(cache_impl
.GetExtension(kGoodExtensionID
, NULL
, NULL
));
1274 // Verify that the extension file was kept in the local cache.
1275 EXPECT_TRUE(PathExists(local_file
));
1278 // Test fails under MSan, http://crbug.com/446950
1279 #if defined(MEMORY_SANITIZER)
1280 #define MAYBE_ExternalData DISABLED_ExternalData
1282 #define MAYBE_ExternalData ExternalData
1285 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, MAYBE_ExternalData
) {
1286 // user_manager::UserManager requests an external data fetch whenever
1287 // the key::kUserAvatarImage policy is set. Since this test wants to
1288 // verify that the underlying policy subsystem will start a fetch
1289 // without this request as well, the user_manager::UserManager must be
1290 // prevented from seeing the policy change.
1291 reinterpret_cast<chromeos::ChromeUserManagerImpl
*>(
1292 user_manager::UserManager::Get())->StopPolicyObserverForTesting();
1294 UploadDeviceLocalAccountPolicy();
1295 AddPublicSessionToDevicePolicy(kAccountId1
);
1299 // Start serving external data at |kExternalDataURL|.
1300 scoped_ptr
<base::RunLoop
> run_loop(new base::RunLoop
);
1301 scoped_ptr
<net::FakeURLFetcherFactory
> fetcher_factory(
1302 new net::FakeURLFetcherFactory(
1304 base::Bind(&RunCallbackAndReturnFakeURLFetcher
,
1305 base::MessageLoopProxy::current(),
1306 run_loop
->QuitClosure())));
1307 fetcher_factory
->SetFakeResponse(GURL(kExternalDataURL
),
1310 net::URLRequestStatus::SUCCESS
);
1312 // Specify an external data reference for the key::kUserAvatarImage policy.
1313 scoped_ptr
<base::DictionaryValue
> metadata
=
1314 test::ConstructExternalDataReference(kExternalDataURL
, kExternalData
);
1316 base::JSONWriter::Write(metadata
.get(), &policy
);
1317 device_local_account_policy_
.payload().mutable_useravatarimage()->set_value(
1319 UploadAndInstallDeviceLocalAccountPolicy();
1320 policy::BrowserPolicyConnectorChromeOS
* connector
=
1321 g_browser_process
->platform_part()->browser_policy_connector_chromeos();
1322 DeviceLocalAccountPolicyBroker
* broker
=
1323 connector
->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
1325 ASSERT_TRUE(broker
);
1326 broker
->core()->store()->Load();
1328 // The external data should be fetched and cached automatically. Wait for this
1332 // Stop serving external data at |kExternalDataURL|.
1333 fetcher_factory
.reset();
1335 const PolicyMap::Entry
* policy_entry
=
1336 broker
->core()->store()->policy_map().Get(key::kUserAvatarImage
);
1337 ASSERT_TRUE(policy_entry
);
1338 ASSERT_TRUE(policy_entry
->external_data_fetcher
);
1340 // Retrieve the external data. Although the data is no longer being served at
1341 // |kExternalDataURL|, the retrieval should succeed because the data has been
1343 run_loop
.reset(new base::RunLoop
);
1344 scoped_ptr
<std::string
> fetched_external_data
;
1345 policy_entry
->external_data_fetcher
->Fetch(base::Bind(
1346 &test::ExternalDataFetchCallback
,
1347 &fetched_external_data
,
1348 run_loop
->QuitClosure()));
1351 ASSERT_TRUE(fetched_external_data
);
1352 EXPECT_EQ(kExternalData
, *fetched_external_data
);
1354 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
1355 WaitForSessionStart();
1357 // Verify that the external data reference has propagated to the device-local
1358 // account's ProfilePolicyConnector.
1359 ProfilePolicyConnector
* policy_connector
=
1360 ProfilePolicyConnectorFactory::GetForProfile(GetProfileForTest());
1361 ASSERT_TRUE(policy_connector
);
1362 const PolicyMap
& policies
= policy_connector
->policy_service()->GetPolicies(
1363 PolicyNamespace(POLICY_DOMAIN_CHROME
, std::string()));
1364 policy_entry
= policies
.Get(key::kUserAvatarImage
);
1365 ASSERT_TRUE(policy_entry
);
1366 EXPECT_TRUE(base::Value::Equals(metadata
.get(), policy_entry
->value
));
1367 ASSERT_TRUE(policy_entry
->external_data_fetcher
);
1369 // Retrieve the external data via the ProfilePolicyConnector. The retrieval
1370 // should succeed because the data has been cached.
1371 run_loop
.reset(new base::RunLoop
);
1372 fetched_external_data
.reset();
1373 policy_entry
->external_data_fetcher
->Fetch(base::Bind(
1374 &test::ExternalDataFetchCallback
,
1375 &fetched_external_data
,
1376 run_loop
->QuitClosure()));
1379 ASSERT_TRUE(fetched_external_data
);
1380 EXPECT_EQ(kExternalData
, *fetched_external_data
);
1383 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, UserAvatarImage
) {
1384 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
1386 UploadDeviceLocalAccountPolicy();
1387 AddPublicSessionToDevicePolicy(kAccountId1
);
1391 base::FilePath test_dir
;
1392 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_dir
));
1393 std::string image_data
;
1394 ASSERT_TRUE(base::ReadFileToString(
1395 test_dir
.Append(chromeos::test::kUserAvatarImage1RelativePath
),
1399 base::JSONWriter::Write(test::ConstructExternalDataReference(
1400 embedded_test_server()->GetURL(std::string("/") +
1401 chromeos::test::kUserAvatarImage1RelativePath
).spec(),
1404 device_local_account_policy_
.payload().mutable_useravatarimage()->set_value(
1406 UploadAndInstallDeviceLocalAccountPolicy();
1407 policy::BrowserPolicyConnectorChromeOS
* connector
=
1408 g_browser_process
->platform_part()->browser_policy_connector_chromeos();
1409 DeviceLocalAccountPolicyBroker
* broker
=
1410 connector
->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
1412 ASSERT_TRUE(broker
);
1414 run_loop_
.reset(new base::RunLoop
);
1415 user_manager::UserManager::Get()->AddObserver(this);
1416 broker
->core()->store()->Load();
1418 user_manager::UserManager::Get()->RemoveObserver(this);
1420 scoped_ptr
<gfx::ImageSkia
> policy_image
= chromeos::test::ImageLoader(
1421 test_dir
.Append(chromeos::test::kUserAvatarImage1RelativePath
)).Load();
1422 ASSERT_TRUE(policy_image
);
1424 const user_manager::User
* user
=
1425 user_manager::UserManager::Get()->FindUser(user_id_1_
);
1428 base::FilePath user_data_dir
;
1429 ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA
, &user_data_dir
));
1430 const base::FilePath saved_image_path
=
1431 user_data_dir
.Append(user_id_1_
).AddExtension("jpg");
1433 EXPECT_FALSE(user
->HasDefaultImage());
1434 EXPECT_EQ(user_manager::User::USER_IMAGE_EXTERNAL
, user
->image_index());
1435 EXPECT_TRUE(chromeos::test::AreImagesEqual(*policy_image
, user
->GetImage()));
1436 const base::DictionaryValue
* images_pref
=
1437 g_browser_process
->local_state()->GetDictionary("user_image_info");
1438 ASSERT_TRUE(images_pref
);
1439 const base::DictionaryValue
* image_properties
;
1440 ASSERT_TRUE(images_pref
->GetDictionaryWithoutPathExpansion(
1442 &image_properties
));
1444 std::string image_path
;
1445 ASSERT_TRUE(image_properties
->GetInteger("index", &image_index
));
1446 ASSERT_TRUE(image_properties
->GetString("path", &image_path
));
1447 EXPECT_EQ(user_manager::User::USER_IMAGE_EXTERNAL
, image_index
);
1448 EXPECT_EQ(saved_image_path
.value(), image_path
);
1450 scoped_ptr
<gfx::ImageSkia
> saved_image
=
1451 chromeos::test::ImageLoader(saved_image_path
).Load();
1452 ASSERT_TRUE(saved_image
);
1454 // Check image dimensions. Images can't be compared since JPEG is lossy.
1455 EXPECT_EQ(policy_image
->width(), saved_image
->width());
1456 EXPECT_EQ(policy_image
->height(), saved_image
->height());
1459 // Test fails under MSan, http://crbug.com/446950
1460 #if defined(MEMORY_SANITIZER)
1461 #define MAYBE_LastWindowClosedLogoutReminder \
1462 DISABLED_LastWindowClosedLogoutReminder
1464 #define MAYBE_LastWindowClosedLogoutReminder LastWindowClosedLogoutReminder
1467 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
,
1468 MAYBE_LastWindowClosedLogoutReminder
) {
1469 UploadAndInstallDeviceLocalAccountPolicy();
1470 AddPublicSessionToDevicePolicy(kAccountId1
);
1474 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
1475 WaitForSessionStart();
1477 Profile
* profile
= GetProfileForTest();
1478 ASSERT_TRUE(profile
);
1479 extensions::AppWindowRegistry
* app_window_registry
=
1480 extensions::AppWindowRegistry::Get(profile
);
1481 app_window_registry
->AddObserver(this);
1483 // Verify that the logout confirmation dialog is not showing.
1484 ash::LogoutConfirmationController
* logout_confirmation_controller
=
1485 ash::Shell::GetInstance()->logout_confirmation_controller();
1486 ASSERT_TRUE(logout_confirmation_controller
);
1487 EXPECT_FALSE(logout_confirmation_controller
->dialog_for_testing());
1489 // Remove policy that allows only explicitly whitelisted apps to be installed
1490 // in a public session.
1491 extensions::ExtensionSystem
* extension_system
=
1492 extensions::ExtensionSystem::Get(profile
);
1493 ASSERT_TRUE(extension_system
);
1494 extension_system
->management_policy()->UnregisterAllProviders();
1496 // Install and a platform app.
1497 scoped_refptr
<extensions::CrxInstaller
> installer
=
1498 extensions::CrxInstaller::CreateSilent(
1499 extension_system
->extension_service());
1500 installer
->set_allow_silent_install(true);
1501 installer
->set_install_cause(extension_misc::INSTALL_CAUSE_USER_DOWNLOAD
);
1502 installer
->set_creation_flags(extensions::Extension::FROM_WEBSTORE
);
1503 content::WindowedNotificationObserver
app_install_observer(
1504 extensions::NOTIFICATION_CRX_INSTALLER_DONE
,
1505 content::NotificationService::AllSources());
1506 base::FilePath test_dir
;
1507 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_dir
));
1508 installer
->InstallCrx(test_dir
.Append(kPackagedAppCRXPath
));
1509 app_install_observer
.Wait();
1510 const extensions::Extension
* app
=
1511 content::Details
<const extensions::Extension
>(
1512 app_install_observer
.details()).ptr();
1514 // Start the platform app, causing it to open a window.
1515 run_loop_
.reset(new base::RunLoop
);
1516 OpenApplication(AppLaunchParams(profile
, app
,
1517 extensions::LAUNCH_CONTAINER_NONE
, NEW_WINDOW
,
1518 extensions::SOURCE_TEST
));
1520 EXPECT_EQ(1U, app_window_registry
->app_windows().size());
1522 // Close the only open browser window.
1523 BrowserList
* browser_list
=
1524 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH
);
1525 EXPECT_EQ(1U, browser_list
->size());
1526 Browser
* browser
= browser_list
->get(0);
1527 ASSERT_TRUE(browser
);
1528 BrowserWindow
* browser_window
= browser
->window();
1529 ASSERT_TRUE(browser_window
);
1530 run_loop_
.reset(new base::RunLoop
);
1531 browser_window
->Close();
1532 browser_window
= NULL
;
1535 EXPECT_TRUE(browser_list
->empty());
1537 // Verify that the logout confirmation dialog is not showing because an app
1538 // window is still open.
1539 EXPECT_FALSE(logout_confirmation_controller
->dialog_for_testing());
1541 // Open a browser window.
1542 Browser
* first_browser
= CreateBrowser(profile
);
1543 EXPECT_EQ(1U, browser_list
->size());
1545 // Close the app window.
1546 run_loop_
.reset(new base::RunLoop
);
1547 ASSERT_EQ(1U, app_window_registry
->app_windows().size());
1548 app_window_registry
->app_windows().front()->GetBaseWindow()->Close();
1550 EXPECT_TRUE(app_window_registry
->app_windows().empty());
1552 // Verify that the logout confirmation dialog is not showing because a browser
1553 // window is still open.
1554 EXPECT_FALSE(logout_confirmation_controller
->dialog_for_testing());
1556 // Open a second browser window.
1557 Browser
* second_browser
= CreateBrowser(profile
);
1558 EXPECT_EQ(2U, browser_list
->size());
1560 // Close the first browser window.
1561 browser_window
= first_browser
->window();
1562 ASSERT_TRUE(browser_window
);
1563 run_loop_
.reset(new base::RunLoop
);
1564 browser_window
->Close();
1565 browser_window
= NULL
;
1567 first_browser
= NULL
;
1568 EXPECT_EQ(1U, browser_list
->size());
1570 // Verify that the logout confirmation dialog is not showing because a browser
1571 // window is still open.
1572 EXPECT_FALSE(logout_confirmation_controller
->dialog_for_testing());
1574 // Close the second browser window.
1575 browser_window
= second_browser
->window();
1576 ASSERT_TRUE(browser_window
);
1577 run_loop_
.reset(new base::RunLoop
);
1578 browser_window
->Close();
1579 browser_window
= NULL
;
1581 second_browser
= NULL
;
1582 EXPECT_TRUE(browser_list
->empty());
1584 // Verify that the logout confirmation dialog is showing.
1585 ash::LogoutConfirmationDialog
* dialog
=
1586 logout_confirmation_controller
->dialog_for_testing();
1587 ASSERT_TRUE(dialog
);
1590 dialog
->GetWidget()->Close();
1592 base::RunLoop().RunUntilIdle();
1594 // Verify that the logout confirmation dialog is no longer showing.
1595 EXPECT_FALSE(logout_confirmation_controller
->dialog_for_testing());
1597 // Open a browser window.
1598 browser
= CreateBrowser(profile
);
1599 EXPECT_EQ(1U, browser_list
->size());
1601 // Close the browser window.
1602 browser_window
= browser
->window();
1603 ASSERT_TRUE(browser_window
);
1604 run_loop_
.reset(new base::RunLoop
);
1605 browser_window
->Close();
1606 browser_window
= NULL
;
1609 EXPECT_TRUE(browser_list
->empty());
1611 // Verify that the logout confirmation dialog is showing again.
1612 dialog
= logout_confirmation_controller
->dialog_for_testing();
1613 ASSERT_TRUE(dialog
);
1616 dialog
->GetWidget()->Close();
1618 base::RunLoop().RunUntilIdle();
1620 app_window_registry
->RemoveObserver(this);
1623 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, NoRecommendedLocaleNoSwitch
) {
1624 UploadAndInstallDeviceLocalAccountPolicy();
1625 AddPublicSessionToDevicePolicy(kAccountId1
);
1629 ExpandPublicSessionPod(false);
1631 // Click the enter button to start the session.
1632 ASSERT_TRUE(content::ExecuteScript(
1635 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1636 " .querySelector('.enter-button').click();",
1637 user_id_1_
.c_str())));
1639 WaitForSessionStart();
1641 // Verify that the locale has not changed and the first keyboard layout
1642 // applicable to the locale was chosen.
1643 EXPECT_EQ(initial_locale_
, g_browser_process
->GetApplicationLocale());
1644 EXPECT_EQ(initial_language_
, icu::Locale::getDefault().getLanguage());
1645 VerifyKeyboardLayoutMatchesLocale();
1648 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, NoRecommendedLocaleSwitch
) {
1649 UploadAndInstallDeviceLocalAccountPolicy();
1650 AddPublicSessionToDevicePolicy(kAccountId1
);
1654 ExpandPublicSessionPod(false);
1656 // Click the link that switches the pod to its advanced form. Verify that the
1657 // pod switches from basic to advanced.
1658 bool advanced
= false;
1659 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
1663 " document.getElementById('pod-row').getPodWithUsername_('%s');"
1664 "pod.querySelector('.language-and-input').click();"
1665 "domAutomationController.send(pod.classList.contains('advanced'));",
1666 user_id_1_
.c_str()),
1668 EXPECT_FALSE(advanced
);
1670 // Manually select a different locale.
1671 ASSERT_TRUE(content::ExecuteScript(
1674 "var languageSelect = document.getElementById('pod-row')"
1675 " .getPodWithUsername_('%s').querySelector('.language-select');"
1676 "languageSelect.value = '%s';"
1677 "var event = document.createEvent('HTMLEvents');"
1678 "event.initEvent('change', false, true);"
1679 "languageSelect.dispatchEvent(event);",
1681 kPublicSessionLocale
)));
1683 // The UI will have requested an updated list of keyboard layouts at this
1684 // point. Wait for the constructions of this list to finish.
1685 WaitForGetKeyboardLayoutsForLocaleToFinish();
1687 // Manually select a different keyboard layout and click the enter button to
1688 // start the session.
1689 ASSERT_TRUE(content::ExecuteScript(
1693 " document.getElementById('pod-row').getPodWithUsername_('%s');"
1694 "pod.querySelector('.keyboard-select').value = '%s';"
1695 "pod.querySelector('.enter-button').click();",
1697 public_session_input_method_id_
.c_str())));
1699 WaitForSessionStart();
1701 // Verify that the locale and keyboard layout have been applied.
1702 EXPECT_EQ(kPublicSessionLocale
, g_browser_process
->GetApplicationLocale());
1703 EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale
),
1704 icu::Locale::getDefault().getLanguage());
1705 EXPECT_EQ(public_session_input_method_id_
,
1706 chromeos::input_method::InputMethodManager::Get()
1707 ->GetActiveIMEState()
1708 ->GetCurrentInputMethod()
1712 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, OneRecommendedLocale
) {
1713 // Specify a recommended locale.
1714 SetRecommendedLocales(kSingleRecommendedLocale
,
1715 arraysize(kSingleRecommendedLocale
));
1716 UploadAndInstallDeviceLocalAccountPolicy();
1717 AddPublicSessionToDevicePolicy(kAccountId1
);
1721 ExpandPublicSessionPod(false);
1723 // Click the enter button to start the session.
1724 ASSERT_TRUE(content::ExecuteScript(
1727 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1728 " .querySelector('.enter-button').click();",
1729 user_id_1_
.c_str())));
1731 WaitForSessionStart();
1733 // Verify that the recommended locale has been applied and the first keyboard
1734 // layout applicable to the locale was chosen.
1735 EXPECT_EQ(kSingleRecommendedLocale
[0],
1736 g_browser_process
->GetApplicationLocale());
1737 EXPECT_EQ(l10n_util::GetLanguage(kSingleRecommendedLocale
[0]),
1738 icu::Locale::getDefault().getLanguage());
1739 VerifyKeyboardLayoutMatchesLocale();
1742 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, MultipleRecommendedLocales
) {
1743 // Specify recommended locales.
1744 SetRecommendedLocales(kRecommendedLocales1
, arraysize(kRecommendedLocales1
));
1745 UploadAndInstallDeviceLocalAccountPolicy();
1746 AddPublicSessionToDevicePolicy(kAccountId1
);
1747 AddPublicSessionToDevicePolicy(kAccountId2
);
1751 ExpandPublicSessionPod(true);
1753 // Verify that the pod shows a list of locales beginning with the recommended
1754 // ones, followed by others.
1755 const std::string get_locale_list
= base::StringPrintf(
1756 "var languageSelect = document.getElementById('pod-row')"
1757 " .getPodWithUsername_('%s').querySelector('.language-select');"
1759 "for (var i = 0; i < languageSelect.length; ++i)"
1760 " locales.push(languageSelect.options[i].value);"
1761 "domAutomationController.send(JSON.stringify(locales));",
1762 user_id_1_
.c_str());
1764 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_
,
1767 scoped_ptr
<base::Value
> value_ptr(base::JSONReader::Read(json
));
1768 const base::ListValue
* locales
= NULL
;
1769 ASSERT_TRUE(value_ptr
);
1770 ASSERT_TRUE(value_ptr
->GetAsList(&locales
));
1771 EXPECT_LT(arraysize(kRecommendedLocales1
), locales
->GetSize());
1773 // Verify that the list starts with the recommended locales, in correct order.
1774 for (size_t i
= 0; i
< arraysize(kRecommendedLocales1
); ++i
) {
1776 EXPECT_TRUE(locales
->GetString(i
, &locale
));
1777 EXPECT_EQ(kRecommendedLocales1
[i
], locale
);
1780 // Verify that the recommended locales do not appear again in the remainder of
1782 std::set
<std::string
> recommended_locales
;
1783 for (size_t i
= 0; i
< arraysize(kRecommendedLocales1
); ++i
)
1784 recommended_locales
.insert(kRecommendedLocales1
[i
]);
1785 for (size_t i
= arraysize(kRecommendedLocales1
); i
< locales
->GetSize();
1788 EXPECT_TRUE(locales
->GetString(i
, &locale
));
1789 EXPECT_EQ(recommended_locales
.end(), recommended_locales
.find(locale
));
1792 // Verify that the first recommended locale is selected.
1793 const std::string get_selected_locale
=
1795 "domAutomationController.send(document.getElementById('pod-row')"
1796 " .getPodWithUsername_('%s').querySelector('.language-select')"
1798 user_id_1_
.c_str());
1799 std::string selected_locale
;
1800 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_
,
1801 get_selected_locale
,
1803 EXPECT_EQ(kRecommendedLocales1
[0], selected_locale
);
1805 // Change the list of recommended locales.
1806 SetRecommendedLocales(kRecommendedLocales2
, arraysize(kRecommendedLocales2
));
1808 // Also change the display name as it is easy to ensure that policy has been
1809 // updated by waiting for a display name change.
1810 device_local_account_policy_
.payload().mutable_userdisplayname()->set_value(
1812 UploadAndInstallDeviceLocalAccountPolicy();
1813 policy::BrowserPolicyConnectorChromeOS
* connector
=
1814 g_browser_process
->platform_part()->browser_policy_connector_chromeos();
1815 DeviceLocalAccountPolicyBroker
* broker
=
1816 connector
->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
1818 ASSERT_TRUE(broker
);
1819 broker
->core()->store()->Load();
1820 WaitForDisplayName(user_id_1_
, kDisplayName2
);
1822 // Verify that the new list of locales is shown in the UI.
1823 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_
,
1826 value_ptr
.reset(base::JSONReader::Read(json
));
1828 ASSERT_TRUE(value_ptr
);
1829 ASSERT_TRUE(value_ptr
->GetAsList(&locales
));
1830 EXPECT_LT(arraysize(kRecommendedLocales2
), locales
->GetSize());
1831 for (size_t i
= 0; i
< arraysize(kRecommendedLocales2
); ++i
) {
1833 EXPECT_TRUE(locales
->GetString(i
, &locale
));
1834 EXPECT_EQ(kRecommendedLocales2
[i
], locale
);
1837 // Verify that the first new recommended locale is selected.
1838 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_
,
1839 get_selected_locale
,
1841 EXPECT_EQ(kRecommendedLocales2
[0], selected_locale
);
1843 // Manually select a different locale.
1844 ASSERT_TRUE(content::ExecuteScript(
1847 "var languageSelect = document.getElementById('pod-row')"
1848 " .getPodWithUsername_('%s').querySelector('.language-select');"
1849 "languageSelect.value = '%s';"
1850 "var event = document.createEvent('HTMLEvents');"
1851 "event.initEvent('change', false, true);"
1852 "languageSelect.dispatchEvent(event);",
1854 kPublicSessionLocale
)));
1856 // Change the list of recommended locales.
1857 SetRecommendedLocales(kRecommendedLocales2
, arraysize(kRecommendedLocales2
));
1858 device_local_account_policy_
.payload().mutable_userdisplayname()->set_value(
1860 UploadAndInstallDeviceLocalAccountPolicy();
1861 broker
->core()->store()->Load();
1862 WaitForDisplayName(user_id_1_
, kDisplayName1
);
1864 // Verify that the manually selected locale is still selected.
1865 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_
,
1866 get_selected_locale
,
1868 EXPECT_EQ(kPublicSessionLocale
, selected_locale
);
1870 // The UI will request an updated list of keyboard layouts at this point. Wait
1871 // for the constructions of this list to finish.
1872 WaitForGetKeyboardLayoutsForLocaleToFinish();
1874 // Manually select a different keyboard layout.
1875 ASSERT_TRUE(content::ExecuteScript(
1878 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1879 " .querySelector('.keyboard-select').value = '%s';",
1881 public_session_input_method_id_
.c_str())));
1883 // Click on a different pod, causing focus to shift away and the pod to
1885 ASSERT_TRUE(content::ExecuteScript(
1888 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1890 user_id_2_
.c_str())));
1892 // Click on the pod again, causing it to expand again. Verify that the pod has
1893 // kept all its state (the advanced form is being shown, the manually selected
1894 // locale and keyboard layout are selected).
1895 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1899 " document.getElementById('pod-row').getPodWithUsername_('%s');"
1902 "state.advanced = pod.classList.contains('advanced');"
1903 "state.locale = pod.querySelector('.language-select').value;"
1904 "state.keyboardLayout = pod.querySelector('.keyboard-select').value;"
1905 "console.log(JSON.stringify(state));"
1906 "domAutomationController.send(JSON.stringify(state));",
1907 user_id_1_
.c_str()),
1910 value_ptr
.reset(base::JSONReader::Read(json
));
1911 const base::DictionaryValue
* state
= NULL
;
1912 ASSERT_TRUE(value_ptr
);
1913 ASSERT_TRUE(value_ptr
->GetAsDictionary(&state
));
1914 bool advanced
= false;
1915 EXPECT_TRUE(state
->GetBoolean("advanced", &advanced
));
1916 EXPECT_TRUE(advanced
);
1917 EXPECT_TRUE(state
->GetString("locale", &selected_locale
));
1918 EXPECT_EQ(kPublicSessionLocale
, selected_locale
);
1919 std::string selected_keyboard_layout
;
1920 EXPECT_TRUE(state
->GetString("keyboardLayout", &selected_keyboard_layout
));
1921 EXPECT_EQ(public_session_input_method_id_
, selected_keyboard_layout
);
1923 // Click the enter button to start the session.
1924 ASSERT_TRUE(content::ExecuteScript(
1927 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1928 " .querySelector('.enter-button').click();",
1929 user_id_1_
.c_str())));
1931 WaitForSessionStart();
1933 // Verify that the locale and keyboard layout have been applied.
1934 EXPECT_EQ(kPublicSessionLocale
, g_browser_process
->GetApplicationLocale());
1935 EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale
),
1936 icu::Locale::getDefault().getLanguage());
1937 EXPECT_EQ(public_session_input_method_id_
,
1938 chromeos::input_method::InputMethodManager::Get()
1939 ->GetActiveIMEState()
1940 ->GetCurrentInputMethod()
1944 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, InvalidRecommendedLocale
) {
1945 // Specify an invalid recommended locale.
1946 SetRecommendedLocales(kInvalidRecommendedLocale
,
1947 arraysize(kInvalidRecommendedLocale
));
1948 UploadAndInstallDeviceLocalAccountPolicy();
1949 AddPublicSessionToDevicePolicy(kAccountId1
);
1953 // Click on the pod to expand it. Verify that the pod expands to its basic
1954 // form as there is only one recommended locale.
1955 bool advanced
= false;
1956 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
1960 " document.getElementById('pod-row').getPodWithUsername_('%s');"
1962 "domAutomationController.send(pod.classList.contains('advanced'));",
1963 user_id_1_
.c_str()),
1965 EXPECT_FALSE(advanced
);
1966 EXPECT_EQ(l10n_util::GetLanguage(initial_locale_
),
1967 icu::Locale::getDefault().getLanguage());
1969 // Click the enter button to start the session.
1970 ASSERT_TRUE(content::ExecuteScript(
1973 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1974 " .querySelector('.enter-button').click();",
1975 user_id_1_
.c_str())));
1977 WaitForSessionStart();
1979 // Verify that since the recommended locale was invalid, the locale has not
1980 // changed and the first keyboard layout applicable to the locale was chosen.
1981 EXPECT_EQ(initial_locale_
, g_browser_process
->GetApplicationLocale());
1982 EXPECT_EQ(l10n_util::GetLanguage(initial_locale_
),
1983 icu::Locale::getDefault().getLanguage());
1984 VerifyKeyboardLayoutMatchesLocale();
1987 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
,
1988 AutoLoginWithoutRecommendedLocales
) {
1989 UploadAndInstallDeviceLocalAccountPolicy();
1990 AddPublicSessionToDevicePolicy(kAccountId1
);
1995 WaitForSessionStart();
1997 // Verify that the locale has not changed and the first keyboard layout
1998 // applicable to the locale was chosen.
1999 EXPECT_EQ(initial_locale_
, g_browser_process
->GetApplicationLocale());
2000 EXPECT_EQ(initial_language_
, icu::Locale::getDefault().getLanguage());
2001 VerifyKeyboardLayoutMatchesLocale();
2004 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
,
2005 AutoLoginWithRecommendedLocales
) {
2006 // Specify recommended locales.
2007 SetRecommendedLocales(kRecommendedLocales1
, arraysize(kRecommendedLocales1
));
2008 UploadAndInstallDeviceLocalAccountPolicy();
2009 AddPublicSessionToDevicePolicy(kAccountId1
);
2014 WaitForSessionStart();
2016 // Verify that the first recommended locale has been applied and the first
2017 // keyboard layout applicable to the locale was chosen.
2018 EXPECT_EQ(kRecommendedLocales1
[0], g_browser_process
->GetApplicationLocale());
2019 EXPECT_EQ(l10n_util::GetLanguage(kRecommendedLocales1
[0]),
2020 icu::Locale::getDefault().getLanguage());
2021 VerifyKeyboardLayoutMatchesLocale();
2024 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, TermsOfServiceWithLocaleSwitch
) {
2025 // Specify Terms of Service URL.
2026 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
2027 device_local_account_policy_
.payload().mutable_termsofserviceurl()->set_value(
2028 embedded_test_server()->GetURL(
2029 std::string("/") + kExistentTermsOfServicePath
).spec());
2030 UploadAndInstallDeviceLocalAccountPolicy();
2031 AddPublicSessionToDevicePolicy(kAccountId1
);
2035 // Select a different locale.
2036 ASSERT_TRUE(content::ExecuteScript(
2039 "var languageSelect = document.getElementById('pod-row')"
2040 " .getPodWithUsername_('%s').querySelector('.language-select');"
2041 "languageSelect.value = '%s';"
2042 "var event = document.createEvent('HTMLEvents');"
2043 "event.initEvent('change', false, true);"
2044 "languageSelect.dispatchEvent(event);",
2046 kPublicSessionLocale
)));
2048 // The UI will have requested an updated list of keyboard layouts at this
2049 // point. Wait for the constructions of this list to finish.
2050 WaitForGetKeyboardLayoutsForLocaleToFinish();
2052 // Set up an observer that will quit the message loop when login has succeeded
2053 // and the first wizard screen, if any, is being shown.
2054 base::RunLoop login_wait_run_loop
;
2055 chromeos::MockAuthStatusConsumer login_status_consumer
;
2056 EXPECT_CALL(login_status_consumer
, OnAuthSuccess(_
)).Times(1).WillOnce(
2057 InvokeWithoutArgs(&login_wait_run_loop
, &base::RunLoop::Quit
));
2058 chromeos::ExistingUserController
* controller
=
2059 chromeos::ExistingUserController::current_controller();
2060 ASSERT_TRUE(controller
);
2061 controller
->set_login_status_consumer(&login_status_consumer
);
2063 // Manually select a different keyboard layout and click the enter button to
2064 // start the session.
2065 ASSERT_TRUE(content::ExecuteScript(
2069 " document.getElementById('pod-row').getPodWithUsername_('%s');"
2070 "pod.querySelector('.keyboard-select').value = '%s';"
2071 "pod.querySelector('.enter-button').click();",
2073 public_session_input_method_id_
.c_str())));
2075 // Spin the loop until the login observer fires. Then, unregister the
2077 login_wait_run_loop
.Run();
2078 controller
->set_login_status_consumer(NULL
);
2080 // Verify that the Terms of Service screen is being shown.
2081 chromeos::WizardController
* wizard_controller
=
2082 chromeos::WizardController::default_controller();
2083 ASSERT_TRUE(wizard_controller
);
2084 ASSERT_TRUE(wizard_controller
->current_screen());
2085 EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName
,
2086 wizard_controller
->current_screen()->GetName());
2088 // Wait for the Terms of Service to finish downloading.
2090 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(contents_
,
2091 "var screenElement = document.getElementById('terms-of-service');"
2092 "function SendReplyIfDownloadDone() {"
2093 " if (screenElement.classList.contains('tos-loading'))"
2095 " domAutomationController.send(true);"
2096 " observer.disconnect();"
2099 "var observer = new MutationObserver(SendReplyIfDownloadDone);"
2100 "if (!SendReplyIfDownloadDone()) {"
2101 " var options = { attributes: true, attributeFilter: [ 'class' ] };"
2102 " observer.observe(screenElement, options);"
2106 // Verify that the locale and keyboard layout have been applied.
2107 EXPECT_EQ(kPublicSessionLocale
, g_browser_process
->GetApplicationLocale());
2108 EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale
),
2109 icu::Locale::getDefault().getLanguage());
2110 EXPECT_EQ(public_session_input_method_id_
,
2111 chromeos::input_method::InputMethodManager::Get()
2112 ->GetActiveIMEState()
2113 ->GetCurrentInputMethod()
2116 // Wait for 'tos-accept-button' to become enabled.
2118 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
2120 "var screenElement = document.getElementById('tos-accept-button');"
2121 "function SendReplyIfAcceptEnabled() {"
2122 " if ($('tos-accept-button').disabled)"
2124 " domAutomationController.send(true);"
2125 " observer.disconnect();"
2128 "var observer = new MutationObserver(SendReplyIfAcceptEnabled);"
2129 "if (!SendReplyIfAcceptEnabled()) {"
2130 " var options = { attributes: true };"
2131 " observer.observe(screenElement, options);"
2135 // Click the accept button.
2136 ASSERT_TRUE(content::ExecuteScript(contents_
,
2137 "$('tos-accept-button').click();"));
2139 WaitForSessionStart();
2141 // Verify that the locale and keyboard layout are still in force.
2142 EXPECT_EQ(kPublicSessionLocale
, g_browser_process
->GetApplicationLocale());
2143 EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale
),
2144 icu::Locale::getDefault().getLanguage());
2145 EXPECT_EQ(public_session_input_method_id_
,
2146 chromeos::input_method::InputMethodManager::Get()
2147 ->GetActiveIMEState()
2148 ->GetCurrentInputMethod()
2152 // Test fails under MSan, http://crbug.com/446950
2153 #if defined(MEMORY_SANITIZER)
2154 #define MAYBE_PolicyForExtensions DISABLED_PolicyForExtensions
2156 #define MAYBE_PolicyForExtensions PolicyForExtensions
2159 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, MAYBE_PolicyForExtensions
) {
2160 // Set up a test update server for the Show Managed Storage app.
2161 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
2162 TestingUpdateManifestProvider
testing_update_manifest_provider(
2163 kRelativeUpdateURL
);
2164 testing_update_manifest_provider
.AddUpdate(
2165 kShowManagedStorageID
,
2166 kShowManagedStorageVersion
,
2167 embedded_test_server()->GetURL(std::string("/") +
2168 kShowManagedStorageCRXPath
));
2169 embedded_test_server()->RegisterRequestHandler(
2170 base::Bind(&TestingUpdateManifestProvider::HandleRequest
,
2171 base::Unretained(&testing_update_manifest_provider
)));
2173 // Force-install the Show Managed Storage app. This app can be installed in
2174 // public sessions because it's whitelisted for testing purposes.
2175 em::StringList
* forcelist
= device_local_account_policy_
.payload()
2176 .mutable_extensioninstallforcelist()->mutable_value();
2177 forcelist
->add_entries(base::StringPrintf(
2179 kShowManagedStorageID
,
2180 embedded_test_server()->GetURL(kRelativeUpdateURL
).spec().c_str()));
2182 // Set a policy for the app at the policy testserver.
2183 // Note that the policy for the device-local account will be fetched before
2184 // the session is started, so the policy for the app must be installed before
2185 // the first device policy fetch.
2186 ASSERT_TRUE(test_server_
.UpdatePolicyData(
2187 dm_protocol::kChromeExtensionPolicyType
, kShowManagedStorageID
,
2190 " \"Value\": \"policy test value one\""
2194 // Install and refresh the device policy now. This will also fetch the initial
2195 // user policy for the device-local account now.
2196 UploadAndInstallDeviceLocalAccountPolicy();
2197 AddPublicSessionToDevicePolicy(kAccountId1
);
2200 // Observe the app installation after login.
2201 content::WindowedNotificationObserver
extension_observer(
2202 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED
,
2203 base::Bind(DoesInstallSuccessReferToId
, kShowManagedStorageID
));
2204 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
2205 WaitForSessionStart();
2206 extension_observer
.Wait();
2208 // Verify that the app was installed.
2209 Profile
* profile
= GetProfileForTest();
2210 ASSERT_TRUE(profile
);
2211 ExtensionService
* extension_service
=
2212 extensions::ExtensionSystem::Get(profile
)->extension_service();
2213 EXPECT_TRUE(extension_service
->GetExtensionById(kShowManagedStorageID
, true));
2215 // Wait for the app policy if it hasn't been fetched yet.
2216 ProfilePolicyConnector
* connector
=
2217 ProfilePolicyConnectorFactory::GetForProfile(profile
);
2218 ASSERT_TRUE(connector
);
2219 PolicyService
* policy_service
= connector
->policy_service();
2220 ASSERT_TRUE(policy_service
);
2221 const PolicyNamespace
ns(POLICY_DOMAIN_EXTENSIONS
, kShowManagedStorageID
);
2222 if (policy_service
->GetPolicies(ns
).empty()) {
2223 PolicyChangeRegistrar
policy_registrar(policy_service
, ns
);
2224 base::RunLoop run_loop
;
2225 policy_registrar
.Observe(
2226 "string", base::Bind(&PolicyChangedCallback
, run_loop
.QuitClosure()));
2230 // Verify that the app policy was set.
2231 base::StringValue
expected_value("policy test value one");
2232 EXPECT_TRUE(base::Value::Equals(
2234 policy_service
->GetPolicies(ns
).GetValue("string")));
2236 // Now update the policy at the server.
2237 ASSERT_TRUE(test_server_
.UpdatePolicyData(
2238 dm_protocol::kChromeExtensionPolicyType
, kShowManagedStorageID
,
2241 " \"Value\": \"policy test value two\""
2245 // And issue a policy refresh.
2247 PolicyChangeRegistrar
policy_registrar(policy_service
, ns
);
2248 base::RunLoop run_loop
;
2249 policy_registrar
.Observe(
2250 "string", base::Bind(&PolicyChangedCallback
, run_loop
.QuitClosure()));
2251 policy_service
->RefreshPolicies(base::Closure());
2255 // Verify that the app policy was updated.
2256 base::StringValue
expected_new_value("policy test value two");
2257 EXPECT_TRUE(base::Value::Equals(
2258 &expected_new_value
,
2259 policy_service
->GetPolicies(ns
).GetValue("string")));
2262 class TermsOfServiceDownloadTest
: public DeviceLocalAccountTest
,
2263 public testing::WithParamInterface
<bool> {
2266 // Test fails under MSan, http://crbug.com/446950
2267 #if defined(MEMORY_SANITIZER)
2268 #define MAYBE_TermsOfServiceScreen DISABLED_TermsOfServiceScreen
2270 #define MAYBE_TermsOfServiceScreen TermsOfServiceScreen
2273 IN_PROC_BROWSER_TEST_P(TermsOfServiceDownloadTest
, MAYBE_TermsOfServiceScreen
) {
2274 // Specify Terms of Service URL.
2275 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
2276 device_local_account_policy_
.payload().mutable_termsofserviceurl()->set_value(
2277 embedded_test_server()->GetURL(
2279 (GetParam() ? kExistentTermsOfServicePath
2280 : kNonexistentTermsOfServicePath
)).spec());
2281 UploadAndInstallDeviceLocalAccountPolicy();
2282 AddPublicSessionToDevicePolicy(kAccountId1
);
2286 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
2288 // Set up an observer that will quit the message loop when login has succeeded
2289 // and the first wizard screen, if any, is being shown.
2290 base::RunLoop login_wait_run_loop
;
2291 chromeos::MockAuthStatusConsumer login_status_consumer
;
2292 EXPECT_CALL(login_status_consumer
, OnAuthSuccess(_
)).Times(1).WillOnce(
2293 InvokeWithoutArgs(&login_wait_run_loop
, &base::RunLoop::Quit
));
2295 // Spin the loop until the observer fires. Then, unregister the observer.
2296 chromeos::ExistingUserController
* controller
=
2297 chromeos::ExistingUserController::current_controller();
2298 ASSERT_TRUE(controller
);
2299 controller
->set_login_status_consumer(&login_status_consumer
);
2300 login_wait_run_loop
.Run();
2301 controller
->set_login_status_consumer(NULL
);
2303 // Verify that the Terms of Service screen is being shown.
2304 chromeos::WizardController
* wizard_controller
=
2305 chromeos::WizardController::default_controller();
2306 ASSERT_TRUE(wizard_controller
);
2307 ASSERT_TRUE(wizard_controller
->current_screen());
2308 EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName
,
2309 wizard_controller
->current_screen()->GetName());
2311 // Wait for the Terms of Service to finish downloading, then get the status of
2312 // the screen's UI elements.
2314 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_
,
2315 "var screenElement = document.getElementById('terms-of-service');"
2316 "function SendReplyIfDownloadDone() {"
2317 " if (screenElement.classList.contains('tos-loading'))"
2320 " status.heading = document.getElementById('tos-heading').textContent;"
2321 " status.subheading ="
2322 " document.getElementById('tos-subheading').textContent;"
2323 " status.contentHeading ="
2324 " document.getElementById('tos-content-heading').textContent;"
2326 " document.getElementById('tos-content-main').textContent;"
2327 " status.error = screenElement.classList.contains('error');"
2328 " status.acceptEnabled ="
2329 " !document.getElementById('tos-accept-button').disabled;"
2330 " domAutomationController.send(JSON.stringify(status));"
2331 " observer.disconnect();"
2334 "var observer = new MutationObserver(SendReplyIfDownloadDone);"
2335 "if (!SendReplyIfDownloadDone()) {"
2336 " var options = { attributes: true, attributeFilter: [ 'class' ] };"
2337 " observer.observe(screenElement, options);"
2340 scoped_ptr
<base::Value
> value_ptr(base::JSONReader::Read(json
));
2341 const base::DictionaryValue
* status
= NULL
;
2342 ASSERT_TRUE(value_ptr
);
2343 ASSERT_TRUE(value_ptr
->GetAsDictionary(&status
));
2344 std::string heading
;
2345 EXPECT_TRUE(status
->GetString("heading", &heading
));
2346 std::string subheading
;
2347 EXPECT_TRUE(status
->GetString("subheading", &subheading
));
2348 std::string content_heading
;
2349 EXPECT_TRUE(status
->GetString("contentHeading", &content_heading
));
2350 std::string content
;
2351 EXPECT_TRUE(status
->GetString("content", &content
));
2353 EXPECT_TRUE(status
->GetBoolean("error", &error
));
2354 bool accept_enabled
;
2355 EXPECT_TRUE(status
->GetBoolean("acceptEnabled", &accept_enabled
));
2357 // Verify that the screen's headings have been set correctly.
2359 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_HEADING
,
2360 base::UTF8ToUTF16(kDomain
)),
2363 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_SUBHEADING
,
2364 base::UTF8ToUTF16(kDomain
)),
2367 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_CONTENT_HEADING
,
2368 base::UTF8ToUTF16(kDomain
)),
2372 // The Terms of Service URL was invalid. Verify that the screen is showing
2373 // an error and the accept button is disabled.
2375 EXPECT_FALSE(accept_enabled
);
2379 // The Terms of Service URL was valid. Verify that the screen is showing the
2380 // downloaded Terms of Service and the accept button is enabled.
2381 base::FilePath test_dir
;
2382 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_dir
));
2383 std::string terms_of_service
;
2384 ASSERT_TRUE(base::ReadFileToString(
2385 test_dir
.Append(kExistentTermsOfServicePath
), &terms_of_service
));
2386 EXPECT_EQ(terms_of_service
, content
);
2387 EXPECT_FALSE(error
);
2388 EXPECT_TRUE(accept_enabled
);
2390 // Click the accept button.
2391 ASSERT_TRUE(content::ExecuteScript(contents_
,
2392 "$('tos-accept-button').click();"));
2394 WaitForSessionStart();
2397 INSTANTIATE_TEST_CASE_P(TermsOfServiceDownloadTestInstance
,
2398 TermsOfServiceDownloadTest
, testing::Bool());
2400 } // namespace policy