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/path_service.h"
28 #include "base/prefs/pref_change_registrar.h"
29 #include "base/prefs/pref_service.h"
30 #include "base/run_loop.h"
31 #include "base/sequenced_task_runner.h"
32 #include "base/strings/string_number_conversions.h"
33 #include "base/strings/string_util.h"
34 #include "base/strings/stringprintf.h"
35 #include "base/strings/utf_string_conversions.h"
36 #include "base/synchronization/lock.h"
37 #include "base/thread_task_runner_handle.h"
38 #include "base/threading/sequenced_worker_pool.h"
39 #include "base/values.h"
40 #include "chrome/browser/browser_process.h"
41 #include "chrome/browser/chrome_notification_types.h"
42 #include "chrome/browser/chromeos/extensions/device_local_account_external_policy_loader.h"
43 #include "chrome/browser/chromeos/extensions/external_cache.h"
44 #include "chrome/browser/chromeos/input_method/input_method_util.h"
45 #include "chrome/browser/chromeos/login/existing_user_controller.h"
46 #include "chrome/browser/chromeos/login/screens/base_screen.h"
47 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
48 #include "chrome/browser/chromeos/login/session/user_session_manager_test_api.h"
49 #include "chrome/browser/chromeos/login/signin_specifics.h"
50 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
51 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
52 #include "chrome/browser/chromeos/login/ui/webui_login_view.h"
53 #include "chrome/browser/chromeos/login/users/avatar/user_image_manager.h"
54 #include "chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.h"
55 #include "chrome/browser/chromeos/login/users/avatar/user_image_manager_test_util.h"
56 #include "chrome/browser/chromeos/login/users/chrome_user_manager_impl.h"
57 #include "chrome/browser/chromeos/login/wizard_controller.h"
58 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
59 #include "chrome/browser/chromeos/policy/cloud_external_data_manager_base_test_util.h"
60 #include "chrome/browser/chromeos/policy/device_local_account.h"
61 #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
62 #include "chrome/browser/chromeos/policy/device_policy_builder.h"
63 #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
64 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
65 #include "chrome/browser/extensions/crx_installer.h"
66 #include "chrome/browser/extensions/extension_service.h"
67 #include "chrome/browser/extensions/updater/chromeos_extension_cache_delegate.h"
68 #include "chrome/browser/extensions/updater/extension_cache_impl.h"
69 #include "chrome/browser/extensions/updater/local_extension_cache.h"
70 #include "chrome/browser/lifetime/application_lifetime.h"
71 #include "chrome/browser/policy/profile_policy_connector.h"
72 #include "chrome/browser/policy/profile_policy_connector_factory.h"
73 #include "chrome/browser/policy/test/local_policy_test_server.h"
74 #include "chrome/browser/prefs/session_startup_pref.h"
75 #include "chrome/browser/profiles/profile.h"
76 #include "chrome/browser/profiles/profile_manager.h"
77 #include "chrome/browser/signin/signin_manager_factory.h"
78 #include "chrome/browser/ui/browser.h"
79 #include "chrome/browser/ui/browser_commands.h"
80 #include "chrome/browser/ui/browser_finder.h"
81 #include "chrome/browser/ui/browser_list.h"
82 #include "chrome/browser/ui/browser_list_observer.h"
83 #include "chrome/browser/ui/browser_window.h"
84 #include "chrome/browser/ui/extensions/app_launch_params.h"
85 #include "chrome/browser/ui/extensions/application_launch.h"
86 #include "chrome/browser/ui/host_desktop.h"
87 #include "chrome/browser/ui/tabs/tab_strip_model.h"
88 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
89 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
90 #include "chrome/common/chrome_paths.h"
91 #include "chrome/common/extensions/extension_constants.h"
92 #include "chrome/grit/chromium_strings.h"
93 #include "chrome/grit/generated_resources.h"
94 #include "chromeos/chromeos_paths.h"
95 #include "chromeos/chromeos_switches.h"
96 #include "chromeos/dbus/fake_session_manager_client.h"
97 #include "chromeos/login/auth/mock_auth_status_consumer.h"
98 #include "chromeos/login/auth/user_context.h"
99 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
100 #include "components/policy/core/common/cloud/cloud_policy_core.h"
101 #include "components/policy/core/common/cloud/cloud_policy_store.h"
102 #include "components/policy/core/common/cloud/policy_builder.h"
103 #include "components/policy/core/common/external_data_fetcher.h"
104 #include "components/policy/core/common/policy_map.h"
105 #include "components/policy/core/common/policy_namespace.h"
106 #include "components/policy/core/common/policy_service.h"
107 #include "components/policy/core/common/policy_switches.h"
108 #include "components/signin/core/browser/signin_manager.h"
109 #include "components/user_manager/user.h"
110 #include "components/user_manager/user_manager.h"
111 #include "components/user_manager/user_type.h"
112 #include "content/public/browser/browser_thread.h"
113 #include "content/public/browser/notification_details.h"
114 #include "content/public/browser/notification_service.h"
115 #include "content/public/browser/notification_source.h"
116 #include "content/public/browser/web_contents.h"
117 #include "content/public/browser/web_ui.h"
118 #include "content/public/test/browser_test_utils.h"
119 #include "content/public/test/test_utils.h"
120 #include "crypto/rsa_private_key.h"
121 #include "extensions/browser/app_window/app_window.h"
122 #include "extensions/browser/app_window/app_window_registry.h"
123 #include "extensions/browser/app_window/native_app_window.h"
124 #include "extensions/browser/extension_system.h"
125 #include "extensions/browser/install/crx_install_error.h"
126 #include "extensions/browser/management_policy.h"
127 #include "extensions/browser/notification_types.h"
128 #include "extensions/common/constants.h"
129 #include "extensions/common/extension.h"
130 #include "net/base/url_util.h"
131 #include "net/http/http_status_code.h"
132 #include "net/test/embedded_test_server/embedded_test_server.h"
133 #include "net/test/embedded_test_server/http_request.h"
134 #include "net/test/embedded_test_server/http_response.h"
135 #include "net/url_request/test_url_fetcher_factory.h"
136 #include "net/url_request/url_fetcher_delegate.h"
137 #include "net/url_request/url_request_status.h"
138 #include "policy/policy_constants.h"
139 #include "testing/gmock/include/gmock/gmock.h"
140 #include "third_party/icu/source/common/unicode/locid.h"
141 #include "ui/base/ime/chromeos/extension_ime_util.h"
142 #include "ui/base/ime/chromeos/input_method_descriptor.h"
143 #include "ui/base/ime/chromeos/input_method_manager.h"
144 #include "ui/base/l10n/l10n_util.h"
145 #include "ui/base/window_open_disposition.h"
146 #include "ui/gfx/image/image_skia.h"
147 #include "ui/views/widget/widget.h"
148 #include "url/gurl.h"
150 namespace em
= enterprise_management
;
152 using chromeos::LoginScreenContext
;
153 using testing::InvokeWithoutArgs
;
154 using testing::Return
;
161 const char kDomain
[] = "example.com";
162 const char kAccountId1
[] = "dla1@example.com";
163 const char kAccountId2
[] = "dla2@example.com";
164 const char kDisplayName1
[] = "display name 1";
165 const char kDisplayName2
[] = "display name 2";
166 const char* const kStartupURLs
[] = {
170 const char kExistentTermsOfServicePath
[] = "chromeos/enterprise/tos.txt";
171 const char kNonexistentTermsOfServicePath
[] = "chromeos/enterprise/tos404.txt";
172 const char kRelativeUpdateURL
[] = "/service/update2/crx";
173 const char kUpdateManifestHeader
[] =
174 "<?xml version='1.0' encoding='UTF-8'?>\n"
175 "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>\n";
176 const char kUpdateManifestTemplate
[] =
177 " <app appid='%s'>\n"
178 " <updatecheck codebase='%s' version='%s' />\n"
180 const char kUpdateManifestFooter
[] =
182 const char kHostedAppID
[] = "kbmnembihfiondgfjekmnmcbddelicoi";
183 const char kHostedAppCRXPath
[] = "extensions/hosted_app.crx";
184 const char kHostedAppVersion
[] = "1.0.0.0";
185 const char kGoodExtensionID
[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
186 const char kGoodExtensionCRXPath
[] = "extensions/good.crx";
187 const char kGoodExtensionVersion
[] = "1.0";
188 const char kPackagedAppCRXPath
[] = "extensions/platform_apps/app_window_2.crx";
189 const char kShowManagedStorageID
[] = "ongnjlefhnoajpbodoldndkbkdgfomlp";
190 const char kShowManagedStorageCRXPath
[] = "extensions/show_managed_storage.crx";
191 const char kShowManagedStorageVersion
[] = "1.0";
193 const char kExternalData
[] = "External data";
194 const char kExternalDataURL
[] = "http://localhost/external_data";
196 const char* const kSingleRecommendedLocale
[] = {
199 const char* const kRecommendedLocales1
[] = {
204 const char* const kRecommendedLocales2
[] = {
208 const char* const kInvalidRecommendedLocale
[] = {
211 const char kPublicSessionLocale
[] = "de";
212 const char kPublicSessionInputMethodIDTemplate
[] = "_comp_ime_%sxkb:de:neo:ger";
214 // The sequence token used by GetKeyboardLayoutsForLocale() for its background
216 const char kSequenceToken
[] = "chromeos_login_l10n_util";
218 // Helper that serves extension update manifests to Chrome.
219 class TestingUpdateManifestProvider
220 : public base::RefCountedThreadSafe
<TestingUpdateManifestProvider
> {
222 // Update manifests will be served at |relative_update_url|.
223 explicit TestingUpdateManifestProvider(
224 const std::string
& relative_update_url
);
226 // When an update manifest is requested for the given extension |id|, indicate
227 // that |version| of the extension can be downloaded at |crx_url|.
228 void AddUpdate(const std::string
& id
,
229 const std::string
& version
,
230 const GURL
& crx_url
);
232 // This method must be registered with the test's EmbeddedTestServer to start
233 // serving update manifests.
234 scoped_ptr
<net::test_server::HttpResponse
> HandleRequest(
235 const net::test_server::HttpRequest
& request
);
240 Update(const std::string
& version
, const GURL
& crx_url
);
246 typedef std::map
<std::string
, Update
> UpdateMap
;
248 ~TestingUpdateManifestProvider();
249 friend class RefCountedThreadSafe
<TestingUpdateManifestProvider
>;
251 // Protects other members against concurrent access from main thread and
252 // test server io thread.
255 std::string relative_update_url_
;
258 DISALLOW_COPY_AND_ASSIGN(TestingUpdateManifestProvider
);
261 // Helper that observes the dictionary |pref| in local state and waits until the
262 // value stored for |key| matches |expected_value|.
263 class DictionaryPrefValueWaiter
{
265 DictionaryPrefValueWaiter(const std::string
& pref
,
266 const std::string
& key
,
267 const std::string
& expected_value
);
268 ~DictionaryPrefValueWaiter();
273 void QuitLoopIfExpectedValueFound();
275 const std::string pref_
;
276 const std::string key_
;
277 const std::string expected_value_
;
279 base::RunLoop run_loop_
;
280 PrefChangeRegistrar pref_change_registrar_
;
282 DISALLOW_COPY_AND_ASSIGN(DictionaryPrefValueWaiter
);
285 TestingUpdateManifestProvider::Update::Update(const std::string
& version
,
291 TestingUpdateManifestProvider::Update::Update() {
294 TestingUpdateManifestProvider::TestingUpdateManifestProvider(
295 const std::string
& relative_update_url
)
296 : relative_update_url_(relative_update_url
) {
299 void TestingUpdateManifestProvider::AddUpdate(const std::string
& id
,
300 const std::string
& version
,
301 const GURL
& crx_url
) {
302 base::AutoLock
auto_lock(lock_
);
303 updates_
[id
] = Update(version
, crx_url
);
306 scoped_ptr
<net::test_server::HttpResponse
>
307 TestingUpdateManifestProvider::HandleRequest(
308 const net::test_server::HttpRequest
& request
) {
309 base::AutoLock
auto_lock(lock_
);
310 const GURL
url("http://localhost" + request
.relative_url
);
311 if (url
.path() != relative_update_url_
)
312 return scoped_ptr
<net::test_server::HttpResponse
>();
314 std::string content
= kUpdateManifestHeader
;
315 for (net::QueryIterator
it(url
); !it
.IsAtEnd(); it
.Advance()) {
316 if (it
.GetKey() != "x")
318 // Extract the extension id from the subquery. Since GetValueForKeyInQuery()
319 // expects a complete URL, dummy scheme and host must be prepended.
321 net::GetValueForKeyInQuery(GURL("http://dummy?" + it
.GetUnescapedValue()),
323 UpdateMap::const_iterator entry
= updates_
.find(id
);
324 if (entry
!= updates_
.end()) {
325 content
+= base::StringPrintf(kUpdateManifestTemplate
,
327 entry
->second
.crx_url
.spec().c_str(),
328 entry
->second
.version
.c_str());
331 content
+= kUpdateManifestFooter
;
332 scoped_ptr
<net::test_server::BasicHttpResponse
>
333 http_response(new net::test_server::BasicHttpResponse
);
334 http_response
->set_code(net::HTTP_OK
);
335 http_response
->set_content(content
);
336 http_response
->set_content_type("text/xml");
337 return http_response
.Pass();
340 TestingUpdateManifestProvider::~TestingUpdateManifestProvider() {
343 DictionaryPrefValueWaiter::DictionaryPrefValueWaiter(
344 const std::string
& pref
,
345 const std::string
& key
,
346 const std::string
& expected_value
)
349 expected_value_(expected_value
) {
350 pref_change_registrar_
.Init(g_browser_process
->local_state());
353 DictionaryPrefValueWaiter::~DictionaryPrefValueWaiter() {
356 void DictionaryPrefValueWaiter::Wait() {
357 pref_change_registrar_
.Add(
359 base::Bind(&DictionaryPrefValueWaiter::QuitLoopIfExpectedValueFound
,
360 base::Unretained(this)));
361 QuitLoopIfExpectedValueFound();
365 void DictionaryPrefValueWaiter::QuitLoopIfExpectedValueFound() {
366 const base::DictionaryValue
* pref
=
367 pref_change_registrar_
.prefs()->GetDictionary(pref_
.c_str());
369 std::string actual_value
;
370 if (pref
->GetStringWithoutPathExpansion(key_
, &actual_value
) &&
371 actual_value
== expected_value_
) {
376 bool DoesInstallSuccessReferToId(const std::string
& id
,
377 const content::NotificationSource
& source
,
378 const content::NotificationDetails
& details
) {
379 return content::Details
<const extensions::InstalledExtensionInfo
>(details
)->
380 extension
->id() == id
;
383 bool DoesInstallFailureReferToId(const std::string
& id
,
384 const content::NotificationSource
& source
,
385 const content::NotificationDetails
& details
) {
386 return content::Details
<const extensions::CrxInstallError
>(details
)
388 .find(base::UTF8ToUTF16(id
)) != base::string16::npos
;
391 scoped_ptr
<net::FakeURLFetcher
> RunCallbackAndReturnFakeURLFetcher(
392 scoped_refptr
<base::SequencedTaskRunner
> task_runner
,
393 const base::Closure
& callback
,
395 net::URLFetcherDelegate
* delegate
,
396 const std::string
& response_data
,
397 net::HttpStatusCode response_code
,
398 net::URLRequestStatus::Status status
) {
399 task_runner
->PostTask(FROM_HERE
, callback
);
400 return make_scoped_ptr(new net::FakeURLFetcher(
401 url
, delegate
, response_data
, response_code
, status
));
404 bool IsSessionStarted() {
405 return user_manager::UserManager::Get()->IsSessionStarted();
408 void PolicyChangedCallback(const base::Closure
& callback
,
409 const base::Value
* old_value
,
410 const base::Value
* new_value
) {
416 class DeviceLocalAccountTest
: public DevicePolicyCrosBrowserTest
,
417 public user_manager::UserManager::Observer
,
418 public chrome::BrowserListObserver
,
419 public extensions::AppWindowRegistry::Observer
{
421 DeviceLocalAccountTest()
422 : user_id_1_(GenerateDeviceLocalAccountUserId(
423 kAccountId1
, DeviceLocalAccount::TYPE_PUBLIC_SESSION
)),
424 user_id_2_(GenerateDeviceLocalAccountUserId(
425 kAccountId2
, DeviceLocalAccount::TYPE_PUBLIC_SESSION
)),
426 public_session_input_method_id_(base::StringPrintf(
427 kPublicSessionInputMethodIDTemplate
,
428 chromeos::extension_ime_util::kXkbExtensionId
)),
430 set_exit_when_last_browser_closes(false);
433 ~DeviceLocalAccountTest() override
{}
435 void SetUp() override
{
436 // Configure and start the test server.
437 scoped_ptr
<crypto::RSAPrivateKey
> signing_key(
438 PolicyBuilder::CreateTestSigningKey());
439 ASSERT_TRUE(test_server_
.SetSigningKeyAndSignature(
440 signing_key
.get(), PolicyBuilder::GetTestSigningKeySignature()));
442 test_server_
.RegisterClient(PolicyBuilder::kFakeToken
,
443 PolicyBuilder::kFakeDeviceId
);
444 ASSERT_TRUE(test_server_
.Start());
446 BrowserList::AddObserver(this);
448 DevicePolicyCrosBrowserTest::SetUp();
451 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
452 DevicePolicyCrosBrowserTest::SetUpCommandLine(command_line
);
453 command_line
->AppendSwitch(chromeos::switches::kLoginManager
);
454 command_line
->AppendSwitch(chromeos::switches::kForceLoginManagerInTests
);
455 command_line
->AppendSwitchASCII(chromeos::switches::kLoginProfile
, "user");
456 command_line
->AppendSwitchASCII(policy::switches::kDeviceManagementUrl
,
457 test_server_
.GetServiceURL().spec());
460 void SetUpInProcessBrowserTestFixture() override
{
461 DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
463 // Clear command-line arguments (but keep command-line switches) so the
464 // startup pages policy takes effect.
465 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
466 base::CommandLine::StringVector
argv(command_line
->argv());
467 argv
.erase(argv
.begin() + argv
.size() - command_line
->GetArgs().size(),
469 command_line
->InitFromArgv(argv
);
472 MarkAsEnterpriseOwned();
477 void SetUpOnMainThread() override
{
478 DevicePolicyCrosBrowserTest::SetUpOnMainThread();
480 initial_locale_
= g_browser_process
->GetApplicationLocale();
481 initial_language_
= l10n_util::GetLanguage(initial_locale_
);
483 content::WindowedNotificationObserver(
484 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
,
485 content::NotificationService::AllSources()).Wait();
487 chromeos::LoginDisplayHostImpl
* host
=
488 reinterpret_cast<chromeos::LoginDisplayHostImpl
*>(
489 chromeos::LoginDisplayHostImpl::default_host());
491 chromeos::WebUILoginView
* web_ui_login_view
= host
->GetWebUILoginView();
492 ASSERT_TRUE(web_ui_login_view
);
493 content::WebUI
* web_ui
= web_ui_login_view
->GetWebUI();
495 contents_
= web_ui
->GetWebContents();
496 ASSERT_TRUE(contents_
);
498 // Wait for the login UI to be ready.
499 chromeos::OobeUI
* oobe_ui
= host
->GetOobeUI();
500 ASSERT_TRUE(oobe_ui
);
501 base::RunLoop run_loop
;
502 const bool oobe_ui_ready
= oobe_ui
->IsJSReady(run_loop
.QuitClosure());
506 // The network selection screen changes the application locale on load and
507 // once again on blur. Wait for the screen to load and blur it so that any
508 // locale changes caused by this screen happen now and do not affect any
509 // subsequent parts of the test.
511 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
513 "var languageSelect = document.getElementById('language-select');"
514 "var blurAndReportSuccess = function() {"
515 " languageSelect.blur();"
516 " domAutomationController.send(true);"
518 "var screenLoading = document.getElementById('outer-container')"
519 " .classList.contains('down');"
520 "if (document.activeElement == languageSelect || !screenLoading)"
521 " blurAndReportSuccess();"
523 " languageSelect.addEventListener('focus', blurAndReportSuccess);",
526 // Skip to the login screen.
527 chromeos::WizardController
* wizard_controller
=
528 chromeos::WizardController::default_controller();
529 ASSERT_TRUE(wizard_controller
);
530 wizard_controller
->SkipToLoginForTesting(LoginScreenContext());
532 chromeos::test::UserSessionManagerTestApi
session_manager_test_api(
533 chromeos::UserSessionManager::GetInstance());
534 session_manager_test_api
.SetShouldObtainTokenHandleInTests(false);
537 void TearDownOnMainThread() override
{
538 BrowserList::RemoveObserver(this);
540 // This shuts down the login UI.
541 base::MessageLoop::current()->PostTask(FROM_HERE
,
542 base::Bind(&chrome::AttemptExit
));
543 base::RunLoop().RunUntilIdle();
546 void LocalStateChanged(user_manager::UserManager
* user_manager
) override
{
551 void OnBrowserRemoved(Browser
* browser
) override
{
556 void OnAppWindowAdded(extensions::AppWindow
* app_window
) override
{
561 void OnAppWindowRemoved(extensions::AppWindow
* app_window
) override
{
566 void InitializePolicy() {
567 device_policy()->policy_data().set_public_key_version(1);
568 em::ChromeDeviceSettingsProto
& proto(device_policy()->payload());
569 proto
.mutable_show_user_names()->set_show_user_names(true);
571 device_local_account_policy_
.policy_data().set_policy_type(
572 dm_protocol::kChromePublicAccountPolicyType
);
573 device_local_account_policy_
.policy_data().set_username(kAccountId1
);
574 device_local_account_policy_
.policy_data().set_settings_entity_id(
576 device_local_account_policy_
.policy_data().set_public_key_version(1);
577 device_local_account_policy_
.payload().mutable_userdisplayname()->set_value(
581 void BuildDeviceLocalAccountPolicy() {
582 device_local_account_policy_
.SetDefaultSigningKey();
583 device_local_account_policy_
.Build();
586 void UploadDeviceLocalAccountPolicy() {
587 BuildDeviceLocalAccountPolicy();
588 ASSERT_TRUE(test_server_
.UpdatePolicy(
589 dm_protocol::kChromePublicAccountPolicyType
, kAccountId1
,
590 device_local_account_policy_
.payload().SerializeAsString()));
593 void UploadAndInstallDeviceLocalAccountPolicy() {
594 UploadDeviceLocalAccountPolicy();
595 session_manager_client()->set_device_local_account_policy(
596 kAccountId1
, device_local_account_policy_
.GetBlob());
599 void SetRecommendedLocales(const char* const recommended_locales
[],
601 em::StringListPolicyProto
* session_locales_proto
=
602 device_local_account_policy_
.payload().mutable_sessionlocales();
603 session_locales_proto
->mutable_policy_options()->set_mode(
604 em::PolicyOptions_PolicyMode_RECOMMENDED
);
605 session_locales_proto
->mutable_value()->Clear();
606 for (size_t i
= 0; i
< array_size
; ++i
) {
607 session_locales_proto
->mutable_value()->add_entries(
608 recommended_locales
[i
]);
612 void AddPublicSessionToDevicePolicy(const std::string
& username
) {
613 em::ChromeDeviceSettingsProto
& proto(device_policy()->payload());
614 em::DeviceLocalAccountInfoProto
* account
=
615 proto
.mutable_device_local_accounts()->add_account();
616 account
->set_account_id(username
);
618 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION
);
619 RefreshDevicePolicy();
620 ASSERT_TRUE(test_server_
.UpdatePolicy(dm_protocol::kChromeDevicePolicyType
,
622 proto
.SerializeAsString()));
625 void EnableAutoLogin() {
626 em::ChromeDeviceSettingsProto
& proto(device_policy()->payload());
627 em::DeviceLocalAccountsProto
* device_local_accounts
=
628 proto
.mutable_device_local_accounts();
629 device_local_accounts
->set_auto_login_id(kAccountId1
);
630 device_local_accounts
->set_auto_login_delay(0);
631 RefreshDevicePolicy();
632 ASSERT_TRUE(test_server_
.UpdatePolicy(dm_protocol::kChromeDevicePolicyType
,
634 proto
.SerializeAsString()));
637 void CheckPublicSessionPresent(const std::string
& id
) {
638 const user_manager::User
* user
=
639 user_manager::UserManager::Get()->FindUser(id
);
641 EXPECT_EQ(id
, user
->email());
642 EXPECT_EQ(user_manager::USER_TYPE_PUBLIC_ACCOUNT
, user
->GetType());
645 base::FilePath
GetExtensionCacheDirectoryForAccountID(
646 const std::string
& account_id
) {
647 base::FilePath extension_cache_root_dir
;
648 if (!PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS
,
649 &extension_cache_root_dir
)) {
652 return extension_cache_root_dir
.Append(
653 base::HexEncode(account_id
.c_str(), account_id
.size()));
656 base::FilePath
GetCacheCRXFilePath(const std::string
& id
,
657 const std::string
& version
,
658 const base::FilePath
& path
) {
660 extensions::LocalExtensionCache::ExtensionFileName(id
, version
, ""));
663 base::FilePath
GetCacheCRXFile(const std::string
& account_id
,
664 const std::string
& id
,
665 const std::string
& version
) {
666 return GetCacheCRXFilePath(
667 id
, version
, GetExtensionCacheDirectoryForAccountID(account_id
));
670 // Returns a profile which can be used for testing.
671 Profile
* GetProfileForTest() {
672 // Any profile can be used here since this test does not test multi profile.
673 return ProfileManager::GetActiveUserProfile();
676 void WaitForDisplayName(const std::string
& user_id
,
677 const std::string
& expected_display_name
) {
678 DictionaryPrefValueWaiter("UserDisplayName",
680 expected_display_name
).Wait();
683 void WaitForPolicy() {
684 // Wait for the display name becoming available as that indicates
685 // device-local account policy is fully loaded, which is a prerequisite for
687 WaitForDisplayName(user_id_1_
, kDisplayName1
);
690 void ExpandPublicSessionPod(bool expect_advanced
) {
691 bool advanced
= false;
692 // Click on the pod to expand it.
693 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
697 " document.getElementById('pod-row').getPodWithUsername_('%s');"
699 "domAutomationController.send(pod.classList.contains('advanced'));",
702 // Verify that the pod expanded to its basic/advanced form, as expected.
703 EXPECT_EQ(expect_advanced
, advanced
);
705 // Verify that the construction of the pod's language list did not affect
706 // the current ICU locale.
707 EXPECT_EQ(initial_language_
, icu::Locale::getDefault().getLanguage());
710 // GetKeyboardLayoutsForLocale() posts a task to a background task runner.
711 // This method flushes that task runner and the current thread's message loop
712 // to ensure that GetKeyboardLayoutsForLocale() is finished.
713 void WaitForGetKeyboardLayoutsForLocaleToFinish() {
714 base::SequencedWorkerPool
* worker_pool
=
715 content::BrowserThread::GetBlockingPool();
716 scoped_refptr
<base::SequencedTaskRunner
> background_task_runner
=
717 worker_pool
->GetSequencedTaskRunner(
718 worker_pool
->GetNamedSequenceToken(kSequenceToken
));
719 base::RunLoop run_loop
;
720 background_task_runner
->PostTaskAndReply(FROM_HERE
,
721 base::Bind(&base::DoNothing
),
722 run_loop
.QuitClosure());
724 base::RunLoop().RunUntilIdle();
726 // Verify that the construction of the keyboard layout list did not affect
727 // the current ICU locale.
728 EXPECT_EQ(initial_language_
, icu::Locale::getDefault().getLanguage());
731 void StartLogin(const std::string
& locale
,
732 const std::string
& input_method
) {
733 // Start login into the device-local account.
734 chromeos::LoginDisplayHostImpl
* host
=
735 reinterpret_cast<chromeos::LoginDisplayHostImpl
*>(
736 chromeos::LoginDisplayHostImpl::default_host());
738 host
->StartSignInScreen(LoginScreenContext());
739 chromeos::ExistingUserController
* controller
=
740 chromeos::ExistingUserController::current_controller();
741 ASSERT_TRUE(controller
);
743 chromeos::UserContext
user_context(user_manager::USER_TYPE_PUBLIC_ACCOUNT
,
745 user_context
.SetPublicSessionLocale(locale
);
746 user_context
.SetPublicSessionInputMethod(input_method
);
747 controller
->Login(user_context
, chromeos::SigninSpecifics());
750 void WaitForSessionStart() {
751 if (IsSessionStarted())
753 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED
,
754 base::Bind(IsSessionStarted
)).Wait();
757 void VerifyKeyboardLayoutMatchesLocale() {
758 chromeos::input_method::InputMethodManager
* input_method_manager
=
759 chromeos::input_method::InputMethodManager::Get();
760 std::vector
<std::string
> layouts_from_locale
;
761 input_method_manager
->GetInputMethodUtil()->
762 GetInputMethodIdsFromLanguageCode(
763 g_browser_process
->GetApplicationLocale(),
764 chromeos::input_method::kKeyboardLayoutsOnly
,
765 &layouts_from_locale
);
766 ASSERT_FALSE(layouts_from_locale
.empty());
767 EXPECT_EQ(layouts_from_locale
.front(),
768 input_method_manager
->GetActiveIMEState()
769 ->GetCurrentInputMethod()
773 const std::string user_id_1_
;
774 const std::string user_id_2_
;
775 const std::string public_session_input_method_id_
;
777 std::string initial_locale_
;
778 std::string initial_language_
;
780 scoped_ptr
<base::RunLoop
> run_loop_
;
782 UserPolicyBuilder device_local_account_policy_
;
783 LocalPolicyTestServer test_server_
;
785 content::WebContents
* contents_
;
788 DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountTest
);
791 static bool IsKnownUser(const std::string
& account_id
) {
792 return user_manager::UserManager::Get()->IsKnownUser(account_id
);
795 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, LoginScreen
) {
796 AddPublicSessionToDevicePolicy(kAccountId1
);
797 AddPublicSessionToDevicePolicy(kAccountId2
);
799 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED
,
800 base::Bind(&IsKnownUser
, user_id_1_
))
802 EXPECT_TRUE(IsKnownUser(user_id_2_
));
804 CheckPublicSessionPresent(user_id_1_
);
805 CheckPublicSessionPresent(user_id_2_
);
808 // Flaky: http://crbug.com/512670.
809 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, DISABLED_DisplayName
) {
810 UploadAndInstallDeviceLocalAccountPolicy();
811 AddPublicSessionToDevicePolicy(kAccountId1
);
815 // Verify that the display name is shown in the UI.
816 const std::string get_compact_pod_display_name
= base::StringPrintf(
817 "domAutomationController.send(document.getElementById('pod-row')"
818 " .getPodWithUsername_('%s').nameElement.textContent);",
820 std::string display_name
;
821 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
823 get_compact_pod_display_name
,
825 EXPECT_EQ(kDisplayName1
, display_name
);
826 const std::string get_expanded_pod_display_name
= base::StringPrintf(
827 "domAutomationController.send(document.getElementById('pod-row')"
828 " .getPodWithUsername_('%s').querySelector('.expanded-pane-name')"
831 display_name
.clear();
832 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
834 get_expanded_pod_display_name
,
836 EXPECT_EQ(kDisplayName1
, display_name
);
838 // Click on the pod to expand it.
839 ASSERT_TRUE(content::ExecuteScript(
842 "document.getElementById('pod-row').getPodWithUsername_('%s')"
844 user_id_1_
.c_str())));
846 // Change the display name.
847 device_local_account_policy_
.payload().mutable_userdisplayname()->set_value(
849 UploadAndInstallDeviceLocalAccountPolicy();
850 policy::BrowserPolicyConnectorChromeOS
* connector
=
851 g_browser_process
->platform_part()->browser_policy_connector_chromeos();
852 DeviceLocalAccountPolicyBroker
* broker
=
853 connector
->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
856 broker
->core()->store()->Load();
857 WaitForDisplayName(user_id_1_
, kDisplayName2
);
859 // Verify that the new display name is shown in the UI.
860 display_name
.clear();
861 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
863 get_compact_pod_display_name
,
865 EXPECT_EQ(kDisplayName2
, display_name
);
866 display_name
.clear();
867 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
869 get_expanded_pod_display_name
,
871 EXPECT_EQ(kDisplayName2
, display_name
);
873 // Verify that the pod is still expanded. This indicates that the UI updated
874 // without reloading and losing state.
875 bool expanded
= false;
876 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
879 "domAutomationController.send(document.getElementById('pod-row')"
880 " .getPodWithUsername_('%s').expanded);",
883 EXPECT_TRUE(expanded
);
886 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, PolicyDownload
) {
887 UploadDeviceLocalAccountPolicy();
888 AddPublicSessionToDevicePolicy(kAccountId1
);
892 // Sanity check: The policy should be present now.
893 ASSERT_FALSE(session_manager_client()->device_local_account_policy(
894 kAccountId1
).empty());
897 static bool IsNotKnownUser(const std::string
& account_id
) {
898 return !IsKnownUser(account_id
);
901 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, AccountListChange
) {
902 AddPublicSessionToDevicePolicy(kAccountId1
);
903 AddPublicSessionToDevicePolicy(kAccountId2
);
905 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED
,
906 base::Bind(&IsKnownUser
, user_id_1_
))
908 EXPECT_TRUE(IsKnownUser(user_id_2_
));
910 // Update policy to remove kAccountId2.
911 em::ChromeDeviceSettingsProto
& proto(device_policy()->payload());
912 proto
.mutable_device_local_accounts()->clear_account();
913 AddPublicSessionToDevicePolicy(kAccountId1
);
915 em::ChromeDeviceSettingsProto policy
;
916 policy
.mutable_show_user_names()->set_show_user_names(true);
917 em::DeviceLocalAccountInfoProto
* account1
=
918 policy
.mutable_device_local_accounts()->add_account();
919 account1
->set_account_id(kAccountId1
);
921 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION
);
923 test_server_
.UpdatePolicy(dm_protocol::kChromeDevicePolicyType
, std::string(),
924 policy
.SerializeAsString());
925 g_browser_process
->policy_service()->RefreshPolicies(base::Closure());
927 // Make sure the second device-local account disappears.
928 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED
,
929 base::Bind(&IsNotKnownUser
, user_id_2_
))
933 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, StartSession
) {
934 // Specify startup pages.
935 device_local_account_policy_
.payload().mutable_restoreonstartup()->set_value(
936 SessionStartupPref::kPrefValueURLs
);
937 em::StringListPolicyProto
* startup_urls_proto
=
938 device_local_account_policy_
.payload().mutable_restoreonstartupurls();
939 for (size_t i
= 0; i
< arraysize(kStartupURLs
); ++i
)
940 startup_urls_proto
->mutable_value()->add_entries(kStartupURLs
[i
]);
941 UploadAndInstallDeviceLocalAccountPolicy();
942 AddPublicSessionToDevicePolicy(kAccountId1
);
946 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
947 WaitForSessionStart();
949 // Check that the startup pages specified in policy were opened.
950 BrowserList
* browser_list
=
951 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH
);
952 EXPECT_EQ(1U, browser_list
->size());
953 Browser
* browser
= browser_list
->get(0);
954 ASSERT_TRUE(browser
);
956 TabStripModel
* tabs
= browser
->tab_strip_model();
958 int expected_tab_count
= static_cast<int>(arraysize(kStartupURLs
));
959 EXPECT_EQ(expected_tab_count
, tabs
->count());
960 for (int i
= 0; i
< expected_tab_count
&& i
< tabs
->count(); ++i
) {
961 EXPECT_EQ(GURL(kStartupURLs
[i
]),
962 tabs
->GetWebContentsAt(i
)->GetVisibleURL());
965 // Verify that the session is not considered to be logged in with a GAIA
967 Profile
* profile
= GetProfileForTest();
968 ASSERT_TRUE(profile
);
970 SigninManagerFactory::GetForProfile(profile
)->IsAuthenticated());
973 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, FullscreenDisallowed
) {
974 UploadAndInstallDeviceLocalAccountPolicy();
975 AddPublicSessionToDevicePolicy(kAccountId1
);
979 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
980 WaitForSessionStart();
982 BrowserList
* browser_list
=
983 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH
);
984 EXPECT_EQ(1U, browser_list
->size());
985 Browser
* browser
= browser_list
->get(0);
986 ASSERT_TRUE(browser
);
987 BrowserWindow
* browser_window
= browser
->window();
988 ASSERT_TRUE(browser_window
);
990 // Verify that an attempt to enter fullscreen mode is denied.
991 EXPECT_FALSE(browser_window
->IsFullscreen());
992 chrome::ToggleFullscreenMode(browser
);
993 EXPECT_FALSE(browser_window
->IsFullscreen());
996 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, ExtensionsUncached
) {
997 // Make it possible to force-install a hosted app and an extension.
998 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
999 scoped_refptr
<TestingUpdateManifestProvider
> testing_update_manifest_provider(
1000 new TestingUpdateManifestProvider(kRelativeUpdateURL
));
1001 testing_update_manifest_provider
->AddUpdate(
1002 kHostedAppID
, kHostedAppVersion
,
1003 embedded_test_server()->GetURL(std::string("/") + kHostedAppCRXPath
));
1004 testing_update_manifest_provider
->AddUpdate(
1005 kGoodExtensionID
, kGoodExtensionVersion
,
1006 embedded_test_server()->GetURL(std::string("/") + kGoodExtensionCRXPath
));
1007 embedded_test_server()->RegisterRequestHandler(
1008 base::Bind(&TestingUpdateManifestProvider::HandleRequest
,
1009 testing_update_manifest_provider
));
1011 // Specify policy to force-install the hosted app and the extension.
1012 em::StringList
* forcelist
= device_local_account_policy_
.payload()
1013 .mutable_extensioninstallforcelist()->mutable_value();
1014 forcelist
->add_entries(base::StringPrintf(
1017 embedded_test_server()->GetURL(kRelativeUpdateURL
).spec().c_str()));
1018 forcelist
->add_entries(base::StringPrintf(
1021 embedded_test_server()->GetURL(kRelativeUpdateURL
).spec().c_str()));
1023 UploadAndInstallDeviceLocalAccountPolicy();
1024 AddPublicSessionToDevicePolicy(kAccountId1
);
1028 // Start listening for app/extension installation results.
1029 content::WindowedNotificationObserver
hosted_app_observer(
1030 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED
,
1031 base::Bind(DoesInstallSuccessReferToId
, kHostedAppID
));
1032 content::WindowedNotificationObserver
extension_observer(
1033 extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR
,
1034 base::Bind(DoesInstallFailureReferToId
, kGoodExtensionID
));
1036 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
1038 // Wait for the hosted app installation to succeed and the extension
1039 // installation to fail (because hosted apps are whitelisted for use in
1040 // device-local accounts and extensions are not).
1041 hosted_app_observer
.Wait();
1042 extension_observer
.Wait();
1044 // Verify that the hosted app was installed.
1045 Profile
* profile
= GetProfileForTest();
1046 ASSERT_TRUE(profile
);
1047 ExtensionService
* extension_service
=
1048 extensions::ExtensionSystem::Get(profile
)->extension_service();
1049 EXPECT_TRUE(extension_service
->GetExtensionById(kHostedAppID
, true));
1051 // Verify that the extension was not installed.
1052 EXPECT_FALSE(extension_service
->GetExtensionById(kGoodExtensionID
, true));
1054 // Verify that the app was downloaded to the account's extension cache.
1055 base::FilePath test_dir
;
1056 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_dir
));
1057 EXPECT_TRUE(ContentsEqual(
1058 GetCacheCRXFile(kAccountId1
, kHostedAppID
, kHostedAppVersion
),
1059 test_dir
.Append(kHostedAppCRXPath
)));
1061 // Verify that the extension was removed from the account's extension cache
1062 // after the installation failure.
1063 DeviceLocalAccountPolicyBroker
* broker
=
1064 g_browser_process
->platform_part()->browser_policy_connector_chromeos()->
1065 GetDeviceLocalAccountPolicyService()->GetBrokerForUser(user_id_1_
);
1066 ASSERT_TRUE(broker
);
1067 chromeos::ExternalCache
* cache
=
1068 broker
->extension_loader()->GetExternalCacheForTesting();
1070 EXPECT_FALSE(cache
->GetExtension(kGoodExtensionID
, NULL
, NULL
));
1073 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, ExtensionsCached
) {
1074 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
1076 // Pre-populate the device local account's extension cache with a hosted app
1077 // and an extension.
1078 EXPECT_TRUE(base::CreateDirectory(
1079 GetExtensionCacheDirectoryForAccountID(kAccountId1
)));
1080 base::FilePath test_dir
;
1081 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_dir
));
1082 const base::FilePath cached_hosted_app
=
1083 GetCacheCRXFile(kAccountId1
, kHostedAppID
, kHostedAppVersion
);
1084 EXPECT_TRUE(CopyFile(test_dir
.Append(kHostedAppCRXPath
),
1085 cached_hosted_app
));
1086 EXPECT_TRUE(CopyFile(
1087 test_dir
.Append(kGoodExtensionCRXPath
),
1088 GetCacheCRXFile(kAccountId1
, kGoodExtensionID
, kGoodExtensionVersion
)));
1090 // Specify policy to force-install the hosted app.
1091 em::StringList
* forcelist
= device_local_account_policy_
.payload()
1092 .mutable_extensioninstallforcelist()->mutable_value();
1093 forcelist
->add_entries(base::StringPrintf(
1096 embedded_test_server()->GetURL(kRelativeUpdateURL
).spec().c_str()));
1097 forcelist
->add_entries(base::StringPrintf(
1100 embedded_test_server()->GetURL(kRelativeUpdateURL
).spec().c_str()));
1102 UploadAndInstallDeviceLocalAccountPolicy();
1103 AddPublicSessionToDevicePolicy(kAccountId1
);
1107 // Start listening for app/extension installation results.
1108 content::WindowedNotificationObserver
hosted_app_observer(
1109 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED
,
1110 base::Bind(DoesInstallSuccessReferToId
, kHostedAppID
));
1111 content::WindowedNotificationObserver
extension_observer(
1112 extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR
,
1113 base::Bind(DoesInstallFailureReferToId
, kGoodExtensionID
));
1115 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
1117 // Wait for the hosted app installation to succeed and the extension
1118 // installation to fail.
1119 hosted_app_observer
.Wait();
1120 extension_observer
.Wait();
1122 // Verify that the hosted app was installed.
1123 Profile
* profile
= GetProfileForTest();
1124 ASSERT_TRUE(profile
);
1125 ExtensionService
* extension_service
=
1126 extensions::ExtensionSystem::Get(profile
)->extension_service();
1127 EXPECT_TRUE(extension_service
->GetExtensionById(kHostedAppID
, true));
1129 // Verify that the extension was not installed.
1130 EXPECT_FALSE(extension_service
->GetExtensionById(kGoodExtensionID
, true));
1132 // Verify that the app is still in the account's extension cache.
1133 EXPECT_TRUE(PathExists(cached_hosted_app
));
1135 // Verify that the extension was removed from the account's extension cache.
1136 DeviceLocalAccountPolicyBroker
* broker
=
1137 g_browser_process
->platform_part()->browser_policy_connector_chromeos()->
1138 GetDeviceLocalAccountPolicyService()->GetBrokerForUser(user_id_1_
);
1139 ASSERT_TRUE(broker
);
1140 chromeos::ExternalCache
* cache
=
1141 broker
->extension_loader()->GetExternalCacheForTesting();
1143 EXPECT_FALSE(cache
->GetExtension(kGoodExtensionID
, NULL
, NULL
));
1146 static void OnPutExtension(scoped_ptr
<base::RunLoop
>* run_loop
,
1147 const base::FilePath
& file_path
,
1148 bool file_ownership_passed
) {
1149 ASSERT_TRUE(*run_loop
);
1150 (*run_loop
)->Quit();
1153 static void OnExtensionCacheImplInitialized(
1154 scoped_ptr
<base::RunLoop
>* run_loop
) {
1155 ASSERT_TRUE(*run_loop
);
1156 (*run_loop
)->Quit();
1159 static void CreateFile(const base::FilePath
& file
,
1161 const base::Time
& timestamp
) {
1162 std::string
data(size
, 0);
1163 EXPECT_EQ(base::WriteFile(file
, data
.data(), data
.size()), int(size
));
1164 EXPECT_TRUE(base::TouchFile(file
, timestamp
, timestamp
));
1167 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, ExtensionCacheImplTest
) {
1168 // Make it possible to force-install a hosted app and an extension.
1169 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
1170 scoped_refptr
<TestingUpdateManifestProvider
> testing_update_manifest_provider(
1171 new TestingUpdateManifestProvider(kRelativeUpdateURL
));
1172 testing_update_manifest_provider
->AddUpdate(
1173 kHostedAppID
, kHostedAppVersion
,
1174 embedded_test_server()->GetURL(std::string("/") + kHostedAppCRXPath
));
1175 testing_update_manifest_provider
->AddUpdate(
1176 kGoodExtensionID
, kGoodExtensionVersion
,
1177 embedded_test_server()->GetURL(std::string("/") + kGoodExtensionCRXPath
));
1178 embedded_test_server()->RegisterRequestHandler(
1179 base::Bind(&TestingUpdateManifestProvider::HandleRequest
,
1180 testing_update_manifest_provider
));
1181 // Create and initialize local cache.
1182 base::ScopedTempDir cache_dir
;
1183 EXPECT_TRUE(cache_dir
.CreateUniqueTempDir());
1184 const base::FilePath impl_path
= cache_dir
.path();
1185 EXPECT_TRUE(base::CreateDirectory(impl_path
));
1186 CreateFile(impl_path
.Append(
1187 extensions::LocalExtensionCache::kCacheReadyFlagFileName
),
1188 0, base::Time::Now());
1189 extensions::ExtensionCacheImpl
cache_impl(make_scoped_ptr(
1190 new extensions::ChromeOSExtensionCacheDelegate(impl_path
)));
1191 scoped_ptr
<base::RunLoop
> run_loop
;
1192 run_loop
.reset(new base::RunLoop
);
1193 cache_impl
.Start(base::Bind(&OnExtensionCacheImplInitialized
, &run_loop
));
1196 // Put extension in the local cache.
1197 base::ScopedTempDir temp_dir
;
1198 EXPECT_TRUE(temp_dir
.CreateUniqueTempDir());
1199 const base::FilePath temp_path
= temp_dir
.path();
1200 EXPECT_TRUE(base::CreateDirectory(temp_path
));
1201 const base::FilePath temp_file
=
1202 GetCacheCRXFilePath(kGoodExtensionID
, kGoodExtensionVersion
, temp_path
);
1203 base::FilePath test_dir
;
1205 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_dir
));
1206 EXPECT_TRUE(CopyFile(test_dir
.Append(kGoodExtensionCRXPath
), temp_file
));
1207 cache_impl
.AllowCaching(kGoodExtensionID
);
1208 run_loop
.reset(new base::RunLoop
);
1209 cache_impl
.PutExtension(kGoodExtensionID
, hash
, temp_file
,
1210 kGoodExtensionVersion
,
1211 base::Bind(&OnPutExtension
, &run_loop
));
1214 // Verify that the extension file was added to the local cache.
1215 const base::FilePath local_file
=
1216 GetCacheCRXFilePath(kGoodExtensionID
, kGoodExtensionVersion
, impl_path
);
1217 EXPECT_TRUE(PathExists(local_file
));
1219 // Specify policy to force-install the hosted app and the extension.
1220 em::StringList
* forcelist
= device_local_account_policy_
.payload()
1221 .mutable_extensioninstallforcelist()->mutable_value();
1222 forcelist
->add_entries(base::StringPrintf(
1225 embedded_test_server()->GetURL(kRelativeUpdateURL
).spec().c_str()));
1226 forcelist
->add_entries(base::StringPrintf(
1229 embedded_test_server()->GetURL(kRelativeUpdateURL
).spec().c_str()));
1231 UploadAndInstallDeviceLocalAccountPolicy();
1232 AddPublicSessionToDevicePolicy(kAccountId1
);
1236 // Start listening for app/extension installation results.
1237 content::WindowedNotificationObserver
hosted_app_observer(
1238 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED
,
1239 base::Bind(DoesInstallSuccessReferToId
, kHostedAppID
));
1240 content::WindowedNotificationObserver
extension_observer(
1241 extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR
,
1242 base::Bind(DoesInstallFailureReferToId
, kGoodExtensionID
));
1244 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
1246 // Wait for the hosted app installation to succeed and the extension
1247 // installation to fail (because hosted apps are whitelisted for use in
1248 // device-local accounts and extensions are not).
1249 hosted_app_observer
.Wait();
1250 extension_observer
.Wait();
1252 // Verify that the extension was kept in the local cache.
1253 EXPECT_TRUE(cache_impl
.GetExtension(kGoodExtensionID
, hash
, NULL
, NULL
));
1255 // Verify that the extension file was kept in the local cache.
1256 EXPECT_TRUE(PathExists(local_file
));
1259 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, ExternalData
) {
1260 // user_manager::UserManager requests an external data fetch whenever
1261 // the key::kUserAvatarImage policy is set. Since this test wants to
1262 // verify that the underlying policy subsystem will start a fetch
1263 // without this request as well, the user_manager::UserManager must be
1264 // prevented from seeing the policy change.
1265 reinterpret_cast<chromeos::ChromeUserManagerImpl
*>(
1266 user_manager::UserManager::Get())->StopPolicyObserverForTesting();
1268 UploadDeviceLocalAccountPolicy();
1269 AddPublicSessionToDevicePolicy(kAccountId1
);
1273 // Start serving external data at |kExternalDataURL|.
1274 scoped_ptr
<base::RunLoop
> run_loop(new base::RunLoop
);
1275 scoped_ptr
<net::FakeURLFetcherFactory
> fetcher_factory(
1276 new net::FakeURLFetcherFactory(
1277 NULL
, base::Bind(&RunCallbackAndReturnFakeURLFetcher
,
1278 base::ThreadTaskRunnerHandle::Get(),
1279 run_loop
->QuitClosure())));
1280 fetcher_factory
->SetFakeResponse(GURL(kExternalDataURL
),
1283 net::URLRequestStatus::SUCCESS
);
1285 // Specify an external data reference for the key::kUserAvatarImage policy.
1286 scoped_ptr
<base::DictionaryValue
> metadata
=
1287 test::ConstructExternalDataReference(kExternalDataURL
, kExternalData
);
1289 base::JSONWriter::Write(*metadata
, &policy
);
1290 device_local_account_policy_
.payload().mutable_useravatarimage()->set_value(
1292 UploadAndInstallDeviceLocalAccountPolicy();
1293 policy::BrowserPolicyConnectorChromeOS
* connector
=
1294 g_browser_process
->platform_part()->browser_policy_connector_chromeos();
1295 DeviceLocalAccountPolicyBroker
* broker
=
1296 connector
->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
1298 ASSERT_TRUE(broker
);
1299 broker
->core()->store()->Load();
1301 // The external data should be fetched and cached automatically. Wait for this
1305 // Stop serving external data at |kExternalDataURL|.
1306 fetcher_factory
.reset();
1308 const PolicyMap::Entry
* policy_entry
=
1309 broker
->core()->store()->policy_map().Get(key::kUserAvatarImage
);
1310 ASSERT_TRUE(policy_entry
);
1311 ASSERT_TRUE(policy_entry
->external_data_fetcher
);
1313 // Retrieve the external data. Although the data is no longer being served at
1314 // |kExternalDataURL|, the retrieval should succeed because the data has been
1316 run_loop
.reset(new base::RunLoop
);
1317 scoped_ptr
<std::string
> fetched_external_data
;
1318 policy_entry
->external_data_fetcher
->Fetch(base::Bind(
1319 &test::ExternalDataFetchCallback
,
1320 &fetched_external_data
,
1321 run_loop
->QuitClosure()));
1324 ASSERT_TRUE(fetched_external_data
);
1325 EXPECT_EQ(kExternalData
, *fetched_external_data
);
1327 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
1328 WaitForSessionStart();
1330 // Verify that the external data reference has propagated to the device-local
1331 // account's ProfilePolicyConnector.
1332 ProfilePolicyConnector
* policy_connector
=
1333 ProfilePolicyConnectorFactory::GetForBrowserContext(GetProfileForTest());
1334 ASSERT_TRUE(policy_connector
);
1335 const PolicyMap
& policies
= policy_connector
->policy_service()->GetPolicies(
1336 PolicyNamespace(POLICY_DOMAIN_CHROME
, std::string()));
1337 policy_entry
= policies
.Get(key::kUserAvatarImage
);
1338 ASSERT_TRUE(policy_entry
);
1339 EXPECT_TRUE(base::Value::Equals(metadata
.get(), policy_entry
->value
));
1340 ASSERT_TRUE(policy_entry
->external_data_fetcher
);
1342 // Retrieve the external data via the ProfilePolicyConnector. The retrieval
1343 // should succeed because the data has been cached.
1344 run_loop
.reset(new base::RunLoop
);
1345 fetched_external_data
.reset();
1346 policy_entry
->external_data_fetcher
->Fetch(base::Bind(
1347 &test::ExternalDataFetchCallback
,
1348 &fetched_external_data
,
1349 run_loop
->QuitClosure()));
1352 ASSERT_TRUE(fetched_external_data
);
1353 EXPECT_EQ(kExternalData
, *fetched_external_data
);
1356 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, UserAvatarImage
) {
1357 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
1359 UploadDeviceLocalAccountPolicy();
1360 AddPublicSessionToDevicePolicy(kAccountId1
);
1364 base::FilePath test_dir
;
1365 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_dir
));
1366 std::string image_data
;
1367 ASSERT_TRUE(base::ReadFileToString(
1368 test_dir
.Append(chromeos::test::kUserAvatarImage1RelativePath
),
1372 base::JSONWriter::Write(
1373 *test::ConstructExternalDataReference(
1374 embedded_test_server()
1375 ->GetURL(std::string("/") +
1376 chromeos::test::kUserAvatarImage1RelativePath
)
1380 device_local_account_policy_
.payload().mutable_useravatarimage()->set_value(
1382 UploadAndInstallDeviceLocalAccountPolicy();
1383 policy::BrowserPolicyConnectorChromeOS
* connector
=
1384 g_browser_process
->platform_part()->browser_policy_connector_chromeos();
1385 DeviceLocalAccountPolicyBroker
* broker
=
1386 connector
->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
1388 ASSERT_TRUE(broker
);
1390 run_loop_
.reset(new base::RunLoop
);
1391 user_manager::UserManager::Get()->AddObserver(this);
1392 broker
->core()->store()->Load();
1394 user_manager::UserManager::Get()->RemoveObserver(this);
1396 scoped_ptr
<gfx::ImageSkia
> policy_image
= chromeos::test::ImageLoader(
1397 test_dir
.Append(chromeos::test::kUserAvatarImage1RelativePath
)).Load();
1398 ASSERT_TRUE(policy_image
);
1400 const user_manager::User
* user
=
1401 user_manager::UserManager::Get()->FindUser(user_id_1_
);
1404 base::FilePath user_data_dir
;
1405 ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA
, &user_data_dir
));
1406 const base::FilePath saved_image_path
=
1407 user_data_dir
.Append(user_id_1_
).AddExtension("jpg");
1409 EXPECT_FALSE(user
->HasDefaultImage());
1410 EXPECT_EQ(user_manager::User::USER_IMAGE_EXTERNAL
, user
->image_index());
1411 EXPECT_TRUE(chromeos::test::AreImagesEqual(*policy_image
, user
->GetImage()));
1412 const base::DictionaryValue
* images_pref
=
1413 g_browser_process
->local_state()->GetDictionary("user_image_info");
1414 ASSERT_TRUE(images_pref
);
1415 const base::DictionaryValue
* image_properties
;
1416 ASSERT_TRUE(images_pref
->GetDictionaryWithoutPathExpansion(
1418 &image_properties
));
1420 std::string image_path
;
1421 ASSERT_TRUE(image_properties
->GetInteger("index", &image_index
));
1422 ASSERT_TRUE(image_properties
->GetString("path", &image_path
));
1423 EXPECT_EQ(user_manager::User::USER_IMAGE_EXTERNAL
, image_index
);
1424 EXPECT_EQ(saved_image_path
.value(), image_path
);
1426 scoped_ptr
<gfx::ImageSkia
> saved_image
=
1427 chromeos::test::ImageLoader(saved_image_path
).Load();
1428 ASSERT_TRUE(saved_image
);
1430 // Check image dimensions. Images can't be compared since JPEG is lossy.
1431 EXPECT_EQ(policy_image
->width(), saved_image
->width());
1432 EXPECT_EQ(policy_image
->height(), saved_image
->height());
1435 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, LastWindowClosedLogoutReminder
) {
1436 UploadAndInstallDeviceLocalAccountPolicy();
1437 AddPublicSessionToDevicePolicy(kAccountId1
);
1441 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
1442 WaitForSessionStart();
1444 Profile
* profile
= GetProfileForTest();
1445 ASSERT_TRUE(profile
);
1446 extensions::AppWindowRegistry
* app_window_registry
=
1447 extensions::AppWindowRegistry::Get(profile
);
1448 app_window_registry
->AddObserver(this);
1450 // Verify that the logout confirmation dialog is not showing.
1451 ash::LogoutConfirmationController
* logout_confirmation_controller
=
1452 ash::Shell::GetInstance()->logout_confirmation_controller();
1453 ASSERT_TRUE(logout_confirmation_controller
);
1454 EXPECT_FALSE(logout_confirmation_controller
->dialog_for_testing());
1456 // Remove policy that allows only explicitly whitelisted apps to be installed
1457 // in a public session.
1458 extensions::ExtensionSystem
* extension_system
=
1459 extensions::ExtensionSystem::Get(profile
);
1460 ASSERT_TRUE(extension_system
);
1461 extension_system
->management_policy()->UnregisterAllProviders();
1463 // Install and a platform app.
1464 scoped_refptr
<extensions::CrxInstaller
> installer
=
1465 extensions::CrxInstaller::CreateSilent(
1466 extension_system
->extension_service());
1467 installer
->set_allow_silent_install(true);
1468 installer
->set_install_cause(extension_misc::INSTALL_CAUSE_USER_DOWNLOAD
);
1469 installer
->set_creation_flags(extensions::Extension::FROM_WEBSTORE
);
1470 content::WindowedNotificationObserver
app_install_observer(
1471 extensions::NOTIFICATION_CRX_INSTALLER_DONE
,
1472 content::NotificationService::AllSources());
1473 base::FilePath test_dir
;
1474 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_dir
));
1475 installer
->InstallCrx(test_dir
.Append(kPackagedAppCRXPath
));
1476 app_install_observer
.Wait();
1477 const extensions::Extension
* app
=
1478 content::Details
<const extensions::Extension
>(
1479 app_install_observer
.details()).ptr();
1481 // Start the platform app, causing it to open a window.
1482 run_loop_
.reset(new base::RunLoop
);
1483 OpenApplication(AppLaunchParams(profile
, app
,
1484 extensions::LAUNCH_CONTAINER_NONE
, NEW_WINDOW
,
1485 extensions::SOURCE_TEST
));
1487 EXPECT_EQ(1U, app_window_registry
->app_windows().size());
1489 // Close the only open browser window.
1490 BrowserList
* browser_list
=
1491 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH
);
1492 EXPECT_EQ(1U, browser_list
->size());
1493 Browser
* browser
= browser_list
->get(0);
1494 ASSERT_TRUE(browser
);
1495 BrowserWindow
* browser_window
= browser
->window();
1496 ASSERT_TRUE(browser_window
);
1497 run_loop_
.reset(new base::RunLoop
);
1498 browser_window
->Close();
1499 browser_window
= NULL
;
1502 EXPECT_TRUE(browser_list
->empty());
1504 // Verify that the logout confirmation dialog is not showing because an app
1505 // window is still open.
1506 EXPECT_FALSE(logout_confirmation_controller
->dialog_for_testing());
1508 // Open a browser window.
1509 Browser
* first_browser
= CreateBrowser(profile
);
1510 EXPECT_EQ(1U, browser_list
->size());
1512 // Close the app window.
1513 run_loop_
.reset(new base::RunLoop
);
1514 ASSERT_EQ(1U, app_window_registry
->app_windows().size());
1515 app_window_registry
->app_windows().front()->GetBaseWindow()->Close();
1517 EXPECT_TRUE(app_window_registry
->app_windows().empty());
1519 // Verify that the logout confirmation dialog is not showing because a browser
1520 // window is still open.
1521 EXPECT_FALSE(logout_confirmation_controller
->dialog_for_testing());
1523 // Open a second browser window.
1524 Browser
* second_browser
= CreateBrowser(profile
);
1525 EXPECT_EQ(2U, browser_list
->size());
1527 // Close the first browser window.
1528 browser_window
= first_browser
->window();
1529 ASSERT_TRUE(browser_window
);
1530 run_loop_
.reset(new base::RunLoop
);
1531 browser_window
->Close();
1532 browser_window
= NULL
;
1534 first_browser
= NULL
;
1535 EXPECT_EQ(1U, browser_list
->size());
1537 // Verify that the logout confirmation dialog is not showing because a browser
1538 // window is still open.
1539 EXPECT_FALSE(logout_confirmation_controller
->dialog_for_testing());
1541 // Close the second browser window.
1542 browser_window
= second_browser
->window();
1543 ASSERT_TRUE(browser_window
);
1544 run_loop_
.reset(new base::RunLoop
);
1545 browser_window
->Close();
1546 browser_window
= NULL
;
1548 second_browser
= NULL
;
1549 EXPECT_TRUE(browser_list
->empty());
1551 // Verify that the logout confirmation dialog is showing.
1552 ash::LogoutConfirmationDialog
* dialog
=
1553 logout_confirmation_controller
->dialog_for_testing();
1554 ASSERT_TRUE(dialog
);
1557 dialog
->GetWidget()->Close();
1559 base::RunLoop().RunUntilIdle();
1561 // Verify that the logout confirmation dialog is no longer showing.
1562 EXPECT_FALSE(logout_confirmation_controller
->dialog_for_testing());
1564 // Open a browser window.
1565 browser
= CreateBrowser(profile
);
1566 EXPECT_EQ(1U, browser_list
->size());
1568 // Close the browser window.
1569 browser_window
= browser
->window();
1570 ASSERT_TRUE(browser_window
);
1571 run_loop_
.reset(new base::RunLoop
);
1572 browser_window
->Close();
1573 browser_window
= NULL
;
1576 EXPECT_TRUE(browser_list
->empty());
1578 // Verify that the logout confirmation dialog is showing again.
1579 dialog
= logout_confirmation_controller
->dialog_for_testing();
1580 ASSERT_TRUE(dialog
);
1583 dialog
->GetWidget()->Close();
1585 base::RunLoop().RunUntilIdle();
1587 app_window_registry
->RemoveObserver(this);
1590 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, NoRecommendedLocaleNoSwitch
) {
1591 UploadAndInstallDeviceLocalAccountPolicy();
1592 AddPublicSessionToDevicePolicy(kAccountId1
);
1596 ExpandPublicSessionPod(false);
1598 // Click the enter button to start the session.
1599 ASSERT_TRUE(content::ExecuteScript(
1602 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1603 " .querySelector('.enter-button').click();",
1604 user_id_1_
.c_str())));
1606 WaitForSessionStart();
1608 // Verify that the locale has not changed and the first keyboard layout
1609 // applicable to the locale was chosen.
1610 EXPECT_EQ(initial_locale_
, g_browser_process
->GetApplicationLocale());
1611 EXPECT_EQ(initial_language_
, icu::Locale::getDefault().getLanguage());
1612 VerifyKeyboardLayoutMatchesLocale();
1615 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, NoRecommendedLocaleSwitch
) {
1616 UploadAndInstallDeviceLocalAccountPolicy();
1617 AddPublicSessionToDevicePolicy(kAccountId1
);
1621 ExpandPublicSessionPod(false);
1623 // Click the link that switches the pod to its advanced form. Verify that the
1624 // pod switches from basic to advanced.
1625 bool advanced
= false;
1626 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
1630 " document.getElementById('pod-row').getPodWithUsername_('%s');"
1631 "pod.querySelector('.language-and-input').click();"
1632 "domAutomationController.send(pod.classList.contains('advanced'));",
1633 user_id_1_
.c_str()),
1635 EXPECT_FALSE(advanced
);
1637 // Manually select a different locale.
1638 ASSERT_TRUE(content::ExecuteScript(
1641 "var languageSelect = document.getElementById('pod-row')"
1642 " .getPodWithUsername_('%s').querySelector('.language-select');"
1643 "languageSelect.value = '%s';"
1644 "var event = document.createEvent('HTMLEvents');"
1645 "event.initEvent('change', false, true);"
1646 "languageSelect.dispatchEvent(event);",
1648 kPublicSessionLocale
)));
1650 // The UI will have requested an updated list of keyboard layouts at this
1651 // point. Wait for the constructions of this list to finish.
1652 WaitForGetKeyboardLayoutsForLocaleToFinish();
1654 // Manually select a different keyboard layout and click the enter button to
1655 // start the session.
1656 ASSERT_TRUE(content::ExecuteScript(
1660 " document.getElementById('pod-row').getPodWithUsername_('%s');"
1661 "pod.querySelector('.keyboard-select').value = '%s';"
1662 "pod.querySelector('.enter-button').click();",
1664 public_session_input_method_id_
.c_str())));
1666 WaitForSessionStart();
1668 // Verify that the locale and keyboard layout have been applied.
1669 EXPECT_EQ(kPublicSessionLocale
, g_browser_process
->GetApplicationLocale());
1670 EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale
),
1671 icu::Locale::getDefault().getLanguage());
1672 EXPECT_EQ(public_session_input_method_id_
,
1673 chromeos::input_method::InputMethodManager::Get()
1674 ->GetActiveIMEState()
1675 ->GetCurrentInputMethod()
1679 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, OneRecommendedLocale
) {
1680 // Specify a recommended locale.
1681 SetRecommendedLocales(kSingleRecommendedLocale
,
1682 arraysize(kSingleRecommendedLocale
));
1683 UploadAndInstallDeviceLocalAccountPolicy();
1684 AddPublicSessionToDevicePolicy(kAccountId1
);
1688 ExpandPublicSessionPod(false);
1690 // Click the enter button to start the session.
1691 ASSERT_TRUE(content::ExecuteScript(
1694 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1695 " .querySelector('.enter-button').click();",
1696 user_id_1_
.c_str())));
1698 WaitForSessionStart();
1700 // Verify that the recommended locale has been applied and the first keyboard
1701 // layout applicable to the locale was chosen.
1702 EXPECT_EQ(kSingleRecommendedLocale
[0],
1703 g_browser_process
->GetApplicationLocale());
1704 EXPECT_EQ(l10n_util::GetLanguage(kSingleRecommendedLocale
[0]),
1705 icu::Locale::getDefault().getLanguage());
1706 VerifyKeyboardLayoutMatchesLocale();
1709 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, MultipleRecommendedLocales
) {
1710 // Specify recommended locales.
1711 SetRecommendedLocales(kRecommendedLocales1
, arraysize(kRecommendedLocales1
));
1712 UploadAndInstallDeviceLocalAccountPolicy();
1713 AddPublicSessionToDevicePolicy(kAccountId1
);
1714 AddPublicSessionToDevicePolicy(kAccountId2
);
1718 ExpandPublicSessionPod(true);
1720 // Verify that the pod shows a list of locales beginning with the recommended
1721 // ones, followed by others.
1722 const std::string get_locale_list
= base::StringPrintf(
1723 "var languageSelect = document.getElementById('pod-row')"
1724 " .getPodWithUsername_('%s').querySelector('.language-select');"
1726 "for (var i = 0; i < languageSelect.length; ++i)"
1727 " locales.push(languageSelect.options[i].value);"
1728 "domAutomationController.send(JSON.stringify(locales));",
1729 user_id_1_
.c_str());
1731 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_
,
1734 scoped_ptr
<base::Value
> value_ptr
= base::JSONReader::Read(json
);
1735 const base::ListValue
* locales
= NULL
;
1736 ASSERT_TRUE(value_ptr
);
1737 ASSERT_TRUE(value_ptr
->GetAsList(&locales
));
1738 EXPECT_LT(arraysize(kRecommendedLocales1
), locales
->GetSize());
1740 // Verify that the list starts with the recommended locales, in correct order.
1741 for (size_t i
= 0; i
< arraysize(kRecommendedLocales1
); ++i
) {
1743 EXPECT_TRUE(locales
->GetString(i
, &locale
));
1744 EXPECT_EQ(kRecommendedLocales1
[i
], locale
);
1747 // Verify that the recommended locales do not appear again in the remainder of
1749 std::set
<std::string
> recommended_locales
;
1750 for (size_t i
= 0; i
< arraysize(kRecommendedLocales1
); ++i
)
1751 recommended_locales
.insert(kRecommendedLocales1
[i
]);
1752 for (size_t i
= arraysize(kRecommendedLocales1
); i
< locales
->GetSize();
1755 EXPECT_TRUE(locales
->GetString(i
, &locale
));
1756 EXPECT_EQ(recommended_locales
.end(), recommended_locales
.find(locale
));
1759 // Verify that the first recommended locale is selected.
1760 const std::string get_selected_locale
=
1762 "domAutomationController.send(document.getElementById('pod-row')"
1763 " .getPodWithUsername_('%s').querySelector('.language-select')"
1765 user_id_1_
.c_str());
1766 std::string selected_locale
;
1767 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_
,
1768 get_selected_locale
,
1770 EXPECT_EQ(kRecommendedLocales1
[0], selected_locale
);
1772 // Change the list of recommended locales.
1773 SetRecommendedLocales(kRecommendedLocales2
, arraysize(kRecommendedLocales2
));
1775 // Also change the display name as it is easy to ensure that policy has been
1776 // updated by waiting for a display name change.
1777 device_local_account_policy_
.payload().mutable_userdisplayname()->set_value(
1779 UploadAndInstallDeviceLocalAccountPolicy();
1780 policy::BrowserPolicyConnectorChromeOS
* connector
=
1781 g_browser_process
->platform_part()->browser_policy_connector_chromeos();
1782 DeviceLocalAccountPolicyBroker
* broker
=
1783 connector
->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
1785 ASSERT_TRUE(broker
);
1786 broker
->core()->store()->Load();
1787 WaitForDisplayName(user_id_1_
, kDisplayName2
);
1789 // Verify that the new list of locales is shown in the UI.
1790 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_
,
1793 value_ptr
.reset(base::JSONReader::DeprecatedRead(json
));
1795 ASSERT_TRUE(value_ptr
);
1796 ASSERT_TRUE(value_ptr
->GetAsList(&locales
));
1797 EXPECT_LT(arraysize(kRecommendedLocales2
), locales
->GetSize());
1798 for (size_t i
= 0; i
< arraysize(kRecommendedLocales2
); ++i
) {
1800 EXPECT_TRUE(locales
->GetString(i
, &locale
));
1801 EXPECT_EQ(kRecommendedLocales2
[i
], locale
);
1804 // Verify that the first new recommended locale is selected.
1805 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_
,
1806 get_selected_locale
,
1808 EXPECT_EQ(kRecommendedLocales2
[0], selected_locale
);
1810 // Manually select a different locale.
1811 ASSERT_TRUE(content::ExecuteScript(
1814 "var languageSelect = document.getElementById('pod-row')"
1815 " .getPodWithUsername_('%s').querySelector('.language-select');"
1816 "languageSelect.value = '%s';"
1817 "var event = document.createEvent('HTMLEvents');"
1818 "event.initEvent('change', false, true);"
1819 "languageSelect.dispatchEvent(event);",
1821 kPublicSessionLocale
)));
1823 // Change the list of recommended locales.
1824 SetRecommendedLocales(kRecommendedLocales2
, arraysize(kRecommendedLocales2
));
1825 device_local_account_policy_
.payload().mutable_userdisplayname()->set_value(
1827 UploadAndInstallDeviceLocalAccountPolicy();
1828 broker
->core()->store()->Load();
1829 WaitForDisplayName(user_id_1_
, kDisplayName1
);
1831 // Verify that the manually selected locale is still selected.
1832 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_
,
1833 get_selected_locale
,
1835 EXPECT_EQ(kPublicSessionLocale
, selected_locale
);
1837 // The UI will request an updated list of keyboard layouts at this point. Wait
1838 // for the constructions of this list to finish.
1839 WaitForGetKeyboardLayoutsForLocaleToFinish();
1841 // Manually select a different keyboard layout.
1842 ASSERT_TRUE(content::ExecuteScript(
1845 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1846 " .querySelector('.keyboard-select').value = '%s';",
1848 public_session_input_method_id_
.c_str())));
1850 // Click on a different pod, causing focus to shift away and the pod to
1852 ASSERT_TRUE(content::ExecuteScript(
1855 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1857 user_id_2_
.c_str())));
1859 // Click on the pod again, causing it to expand again. Verify that the pod has
1860 // kept all its state (the advanced form is being shown, the manually selected
1861 // locale and keyboard layout are selected).
1862 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1866 " document.getElementById('pod-row').getPodWithUsername_('%s');"
1869 "state.advanced = pod.classList.contains('advanced');"
1870 "state.locale = pod.querySelector('.language-select').value;"
1871 "state.keyboardLayout = pod.querySelector('.keyboard-select').value;"
1872 "console.log(JSON.stringify(state));"
1873 "domAutomationController.send(JSON.stringify(state));",
1874 user_id_1_
.c_str()),
1877 value_ptr
.reset(base::JSONReader::DeprecatedRead(json
));
1878 const base::DictionaryValue
* state
= NULL
;
1879 ASSERT_TRUE(value_ptr
);
1880 ASSERT_TRUE(value_ptr
->GetAsDictionary(&state
));
1881 bool advanced
= false;
1882 EXPECT_TRUE(state
->GetBoolean("advanced", &advanced
));
1883 EXPECT_TRUE(advanced
);
1884 EXPECT_TRUE(state
->GetString("locale", &selected_locale
));
1885 EXPECT_EQ(kPublicSessionLocale
, selected_locale
);
1886 std::string selected_keyboard_layout
;
1887 EXPECT_TRUE(state
->GetString("keyboardLayout", &selected_keyboard_layout
));
1888 EXPECT_EQ(public_session_input_method_id_
, selected_keyboard_layout
);
1890 // Click the enter button to start the session.
1891 ASSERT_TRUE(content::ExecuteScript(
1894 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1895 " .querySelector('.enter-button').click();",
1896 user_id_1_
.c_str())));
1898 WaitForSessionStart();
1900 // Verify that the locale and keyboard layout have been applied.
1901 EXPECT_EQ(kPublicSessionLocale
, g_browser_process
->GetApplicationLocale());
1902 EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale
),
1903 icu::Locale::getDefault().getLanguage());
1904 EXPECT_EQ(public_session_input_method_id_
,
1905 chromeos::input_method::InputMethodManager::Get()
1906 ->GetActiveIMEState()
1907 ->GetCurrentInputMethod()
1911 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, InvalidRecommendedLocale
) {
1912 // Specify an invalid recommended locale.
1913 SetRecommendedLocales(kInvalidRecommendedLocale
,
1914 arraysize(kInvalidRecommendedLocale
));
1915 UploadAndInstallDeviceLocalAccountPolicy();
1916 AddPublicSessionToDevicePolicy(kAccountId1
);
1920 // Click on the pod to expand it. Verify that the pod expands to its basic
1921 // form as there is only one recommended locale.
1922 bool advanced
= false;
1923 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
1927 " document.getElementById('pod-row').getPodWithUsername_('%s');"
1929 "domAutomationController.send(pod.classList.contains('advanced'));",
1930 user_id_1_
.c_str()),
1932 EXPECT_FALSE(advanced
);
1933 EXPECT_EQ(l10n_util::GetLanguage(initial_locale_
),
1934 icu::Locale::getDefault().getLanguage());
1936 // Click the enter button to start the session.
1937 ASSERT_TRUE(content::ExecuteScript(
1940 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1941 " .querySelector('.enter-button').click();",
1942 user_id_1_
.c_str())));
1944 WaitForSessionStart();
1946 // Verify that since the recommended locale was invalid, the locale has not
1947 // changed and the first keyboard layout applicable to the locale was chosen.
1948 EXPECT_EQ(initial_locale_
, g_browser_process
->GetApplicationLocale());
1949 EXPECT_EQ(l10n_util::GetLanguage(initial_locale_
),
1950 icu::Locale::getDefault().getLanguage());
1951 VerifyKeyboardLayoutMatchesLocale();
1954 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
,
1955 AutoLoginWithoutRecommendedLocales
) {
1956 UploadAndInstallDeviceLocalAccountPolicy();
1957 AddPublicSessionToDevicePolicy(kAccountId1
);
1962 WaitForSessionStart();
1964 // Verify that the locale has not changed and the first keyboard layout
1965 // applicable to the locale was chosen.
1966 EXPECT_EQ(initial_locale_
, g_browser_process
->GetApplicationLocale());
1967 EXPECT_EQ(initial_language_
, icu::Locale::getDefault().getLanguage());
1968 VerifyKeyboardLayoutMatchesLocale();
1971 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
,
1972 AutoLoginWithRecommendedLocales
) {
1973 // Specify recommended locales.
1974 SetRecommendedLocales(kRecommendedLocales1
, arraysize(kRecommendedLocales1
));
1975 UploadAndInstallDeviceLocalAccountPolicy();
1976 AddPublicSessionToDevicePolicy(kAccountId1
);
1981 WaitForSessionStart();
1983 // Verify that the first recommended locale has been applied and the first
1984 // keyboard layout applicable to the locale was chosen.
1985 EXPECT_EQ(kRecommendedLocales1
[0], g_browser_process
->GetApplicationLocale());
1986 EXPECT_EQ(l10n_util::GetLanguage(kRecommendedLocales1
[0]),
1987 icu::Locale::getDefault().getLanguage());
1988 VerifyKeyboardLayoutMatchesLocale();
1991 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, TermsOfServiceWithLocaleSwitch
) {
1992 // Specify Terms of Service URL.
1993 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
1994 device_local_account_policy_
.payload().mutable_termsofserviceurl()->set_value(
1995 embedded_test_server()->GetURL(
1996 std::string("/") + kExistentTermsOfServicePath
).spec());
1997 UploadAndInstallDeviceLocalAccountPolicy();
1998 AddPublicSessionToDevicePolicy(kAccountId1
);
2002 // Select a different locale.
2003 ASSERT_TRUE(content::ExecuteScript(
2006 "var languageSelect = document.getElementById('pod-row')"
2007 " .getPodWithUsername_('%s').querySelector('.language-select');"
2008 "languageSelect.value = '%s';"
2009 "var event = document.createEvent('HTMLEvents');"
2010 "event.initEvent('change', false, true);"
2011 "languageSelect.dispatchEvent(event);",
2013 kPublicSessionLocale
)));
2015 // The UI will have requested an updated list of keyboard layouts at this
2016 // point. Wait for the constructions of this list to finish.
2017 WaitForGetKeyboardLayoutsForLocaleToFinish();
2019 // Set up an observer that will quit the message loop when login has succeeded
2020 // and the first wizard screen, if any, is being shown.
2021 base::RunLoop login_wait_run_loop
;
2022 chromeos::MockAuthStatusConsumer login_status_consumer
;
2023 EXPECT_CALL(login_status_consumer
, OnAuthSuccess(_
)).Times(1).WillOnce(
2024 InvokeWithoutArgs(&login_wait_run_loop
, &base::RunLoop::Quit
));
2025 chromeos::ExistingUserController
* controller
=
2026 chromeos::ExistingUserController::current_controller();
2027 ASSERT_TRUE(controller
);
2028 controller
->set_login_status_consumer(&login_status_consumer
);
2030 // Manually select a different keyboard layout and click the enter button to
2031 // start the session.
2032 ASSERT_TRUE(content::ExecuteScript(
2036 " document.getElementById('pod-row').getPodWithUsername_('%s');"
2037 "pod.querySelector('.keyboard-select').value = '%s';"
2038 "pod.querySelector('.enter-button').click();",
2040 public_session_input_method_id_
.c_str())));
2042 // Spin the loop until the login observer fires. Then, unregister the
2044 login_wait_run_loop
.Run();
2045 controller
->set_login_status_consumer(NULL
);
2047 // Verify that the Terms of Service screen is being shown.
2048 chromeos::WizardController
* wizard_controller
=
2049 chromeos::WizardController::default_controller();
2050 ASSERT_TRUE(wizard_controller
);
2051 ASSERT_TRUE(wizard_controller
->current_screen());
2052 EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName
,
2053 wizard_controller
->current_screen()->GetName());
2055 // Wait for the Terms of Service to finish downloading.
2057 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(contents_
,
2058 "var screenElement = document.getElementById('terms-of-service');"
2059 "function SendReplyIfDownloadDone() {"
2060 " if (screenElement.classList.contains('tos-loading'))"
2062 " domAutomationController.send(true);"
2063 " observer.disconnect();"
2066 "var observer = new MutationObserver(SendReplyIfDownloadDone);"
2067 "if (!SendReplyIfDownloadDone()) {"
2068 " var options = { attributes: true, attributeFilter: [ 'class' ] };"
2069 " observer.observe(screenElement, options);"
2073 // Verify that the locale and keyboard layout have been applied.
2074 EXPECT_EQ(kPublicSessionLocale
, g_browser_process
->GetApplicationLocale());
2075 EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale
),
2076 icu::Locale::getDefault().getLanguage());
2077 EXPECT_EQ(public_session_input_method_id_
,
2078 chromeos::input_method::InputMethodManager::Get()
2079 ->GetActiveIMEState()
2080 ->GetCurrentInputMethod()
2083 // Wait for 'tos-accept-button' to become enabled.
2085 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
2087 "var screenElement = document.getElementById('tos-accept-button');"
2088 "function SendReplyIfAcceptEnabled() {"
2089 " if ($('tos-accept-button').disabled)"
2091 " domAutomationController.send(true);"
2092 " observer.disconnect();"
2095 "var observer = new MutationObserver(SendReplyIfAcceptEnabled);"
2096 "if (!SendReplyIfAcceptEnabled()) {"
2097 " var options = { attributes: true };"
2098 " observer.observe(screenElement, options);"
2102 // Click the accept button.
2103 ASSERT_TRUE(content::ExecuteScript(contents_
,
2104 "$('tos-accept-button').click();"));
2106 WaitForSessionStart();
2108 // Verify that the locale and keyboard layout are still in force.
2109 EXPECT_EQ(kPublicSessionLocale
, g_browser_process
->GetApplicationLocale());
2110 EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale
),
2111 icu::Locale::getDefault().getLanguage());
2112 EXPECT_EQ(public_session_input_method_id_
,
2113 chromeos::input_method::InputMethodManager::Get()
2114 ->GetActiveIMEState()
2115 ->GetCurrentInputMethod()
2119 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest
, PolicyForExtensions
) {
2120 // Set up a test update server for the Show Managed Storage app.
2121 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
2122 scoped_refptr
<TestingUpdateManifestProvider
> testing_update_manifest_provider(
2123 new TestingUpdateManifestProvider(kRelativeUpdateURL
));
2124 testing_update_manifest_provider
->AddUpdate(
2125 kShowManagedStorageID
, kShowManagedStorageVersion
,
2126 embedded_test_server()->GetURL(std::string("/") +
2127 kShowManagedStorageCRXPath
));
2128 embedded_test_server()->RegisterRequestHandler(
2129 base::Bind(&TestingUpdateManifestProvider::HandleRequest
,
2130 testing_update_manifest_provider
));
2132 // Force-install the Show Managed Storage app. This app can be installed in
2133 // public sessions because it's whitelisted for testing purposes.
2134 em::StringList
* forcelist
= device_local_account_policy_
.payload()
2135 .mutable_extensioninstallforcelist()->mutable_value();
2136 forcelist
->add_entries(base::StringPrintf(
2138 kShowManagedStorageID
,
2139 embedded_test_server()->GetURL(kRelativeUpdateURL
).spec().c_str()));
2141 // Set a policy for the app at the policy testserver.
2142 // Note that the policy for the device-local account will be fetched before
2143 // the session is started, so the policy for the app must be installed before
2144 // the first device policy fetch.
2145 ASSERT_TRUE(test_server_
.UpdatePolicyData(
2146 dm_protocol::kChromeExtensionPolicyType
, kShowManagedStorageID
,
2149 " \"Value\": \"policy test value one\""
2153 // Install and refresh the device policy now. This will also fetch the initial
2154 // user policy for the device-local account now.
2155 UploadAndInstallDeviceLocalAccountPolicy();
2156 AddPublicSessionToDevicePolicy(kAccountId1
);
2159 // Observe the app installation after login.
2160 content::WindowedNotificationObserver
extension_observer(
2161 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED
,
2162 base::Bind(DoesInstallSuccessReferToId
, kShowManagedStorageID
));
2163 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
2164 WaitForSessionStart();
2165 extension_observer
.Wait();
2167 // Verify that the app was installed.
2168 Profile
* profile
= GetProfileForTest();
2169 ASSERT_TRUE(profile
);
2170 ExtensionService
* extension_service
=
2171 extensions::ExtensionSystem::Get(profile
)->extension_service();
2172 EXPECT_TRUE(extension_service
->GetExtensionById(kShowManagedStorageID
, true));
2174 // Wait for the app policy if it hasn't been fetched yet.
2175 ProfilePolicyConnector
* connector
=
2176 ProfilePolicyConnectorFactory::GetForBrowserContext(profile
);
2177 ASSERT_TRUE(connector
);
2178 PolicyService
* policy_service
= connector
->policy_service();
2179 ASSERT_TRUE(policy_service
);
2180 const PolicyNamespace
ns(POLICY_DOMAIN_EXTENSIONS
, kShowManagedStorageID
);
2181 if (policy_service
->GetPolicies(ns
).empty()) {
2182 PolicyChangeRegistrar
policy_registrar(policy_service
, ns
);
2183 base::RunLoop run_loop
;
2184 policy_registrar
.Observe(
2185 "string", base::Bind(&PolicyChangedCallback
, run_loop
.QuitClosure()));
2189 // Verify that the app policy was set.
2190 base::StringValue
expected_value("policy test value one");
2191 EXPECT_TRUE(base::Value::Equals(
2193 policy_service
->GetPolicies(ns
).GetValue("string")));
2195 // Now update the policy at the server.
2196 ASSERT_TRUE(test_server_
.UpdatePolicyData(
2197 dm_protocol::kChromeExtensionPolicyType
, kShowManagedStorageID
,
2200 " \"Value\": \"policy test value two\""
2204 // And issue a policy refresh.
2206 PolicyChangeRegistrar
policy_registrar(policy_service
, ns
);
2207 base::RunLoop run_loop
;
2208 policy_registrar
.Observe(
2209 "string", base::Bind(&PolicyChangedCallback
, run_loop
.QuitClosure()));
2210 policy_service
->RefreshPolicies(base::Closure());
2214 // Verify that the app policy was updated.
2215 base::StringValue
expected_new_value("policy test value two");
2216 EXPECT_TRUE(base::Value::Equals(
2217 &expected_new_value
,
2218 policy_service
->GetPolicies(ns
).GetValue("string")));
2221 class TermsOfServiceDownloadTest
: public DeviceLocalAccountTest
,
2222 public testing::WithParamInterface
<bool> {
2225 IN_PROC_BROWSER_TEST_P(TermsOfServiceDownloadTest
, TermsOfServiceScreen
) {
2226 // Specify Terms of Service URL.
2227 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
2228 device_local_account_policy_
.payload().mutable_termsofserviceurl()->set_value(
2229 embedded_test_server()->GetURL(
2231 (GetParam() ? kExistentTermsOfServicePath
2232 : kNonexistentTermsOfServicePath
)).spec());
2233 UploadAndInstallDeviceLocalAccountPolicy();
2234 AddPublicSessionToDevicePolicy(kAccountId1
);
2238 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
2240 // Set up an observer that will quit the message loop when login has succeeded
2241 // and the first wizard screen, if any, is being shown.
2242 base::RunLoop login_wait_run_loop
;
2243 chromeos::MockAuthStatusConsumer login_status_consumer
;
2244 EXPECT_CALL(login_status_consumer
, OnAuthSuccess(_
)).Times(1).WillOnce(
2245 InvokeWithoutArgs(&login_wait_run_loop
, &base::RunLoop::Quit
));
2247 // Spin the loop until the observer fires. Then, unregister the observer.
2248 chromeos::ExistingUserController
* controller
=
2249 chromeos::ExistingUserController::current_controller();
2250 ASSERT_TRUE(controller
);
2251 controller
->set_login_status_consumer(&login_status_consumer
);
2252 login_wait_run_loop
.Run();
2253 controller
->set_login_status_consumer(NULL
);
2255 // Verify that the Terms of Service screen is being shown.
2256 chromeos::WizardController
* wizard_controller
=
2257 chromeos::WizardController::default_controller();
2258 ASSERT_TRUE(wizard_controller
);
2259 ASSERT_TRUE(wizard_controller
->current_screen());
2260 EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName
,
2261 wizard_controller
->current_screen()->GetName());
2263 // Wait for the Terms of Service to finish downloading, then get the status of
2264 // the screen's UI elements.
2266 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_
,
2267 "var screenElement = document.getElementById('terms-of-service');"
2268 "function SendReplyIfDownloadDone() {"
2269 " if (screenElement.classList.contains('tos-loading'))"
2272 " status.heading = document.getElementById('tos-heading').textContent;"
2273 " status.subheading ="
2274 " document.getElementById('tos-subheading').textContent;"
2275 " status.contentHeading ="
2276 " document.getElementById('tos-content-heading').textContent;"
2278 " document.getElementById('tos-content-main').textContent;"
2279 " status.error = screenElement.classList.contains('error');"
2280 " status.acceptEnabled ="
2281 " !document.getElementById('tos-accept-button').disabled;"
2282 " domAutomationController.send(JSON.stringify(status));"
2283 " observer.disconnect();"
2286 "var observer = new MutationObserver(SendReplyIfDownloadDone);"
2287 "if (!SendReplyIfDownloadDone()) {"
2288 " var options = { attributes: true, attributeFilter: [ 'class' ] };"
2289 " observer.observe(screenElement, options);"
2292 scoped_ptr
<base::Value
> value_ptr
= base::JSONReader::Read(json
);
2293 const base::DictionaryValue
* status
= NULL
;
2294 ASSERT_TRUE(value_ptr
);
2295 ASSERT_TRUE(value_ptr
->GetAsDictionary(&status
));
2296 std::string heading
;
2297 EXPECT_TRUE(status
->GetString("heading", &heading
));
2298 std::string subheading
;
2299 EXPECT_TRUE(status
->GetString("subheading", &subheading
));
2300 std::string content_heading
;
2301 EXPECT_TRUE(status
->GetString("contentHeading", &content_heading
));
2302 std::string content
;
2303 EXPECT_TRUE(status
->GetString("content", &content
));
2305 EXPECT_TRUE(status
->GetBoolean("error", &error
));
2306 bool accept_enabled
;
2307 EXPECT_TRUE(status
->GetBoolean("acceptEnabled", &accept_enabled
));
2309 // Verify that the screen's headings have been set correctly.
2311 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_HEADING
,
2312 base::UTF8ToUTF16(kDomain
)),
2315 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_SUBHEADING
,
2316 base::UTF8ToUTF16(kDomain
)),
2319 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_CONTENT_HEADING
,
2320 base::UTF8ToUTF16(kDomain
)),
2324 // The Terms of Service URL was invalid. Verify that the screen is showing
2325 // an error and the accept button is disabled.
2327 EXPECT_FALSE(accept_enabled
);
2331 // The Terms of Service URL was valid. Verify that the screen is showing the
2332 // downloaded Terms of Service and the accept button is enabled.
2333 base::FilePath test_dir
;
2334 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_dir
));
2335 std::string terms_of_service
;
2336 ASSERT_TRUE(base::ReadFileToString(
2337 test_dir
.Append(kExistentTermsOfServicePath
), &terms_of_service
));
2338 EXPECT_EQ(terms_of_service
, content
);
2339 EXPECT_FALSE(error
);
2340 EXPECT_TRUE(accept_enabled
);
2342 // Click the accept button.
2343 ASSERT_TRUE(content::ExecuteScript(contents_
,
2344 "$('tos-accept-button').click();"));
2346 WaitForSessionStart();
2349 INSTANTIATE_TEST_CASE_P(TermsOfServiceDownloadTestInstance
,
2350 TermsOfServiceDownloadTest
, testing::Bool());
2352 } // namespace policy