Switch global error menu icon to vectorized MD asset
[chromium-blink-merge.git] / chrome / browser / chromeos / policy / device_local_account_browsertest.cc
blob673390b8396ef140b3691248b0b52c7663cdf8b0
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.
5 #include <map>
6 #include <set>
7 #include <string>
8 #include <vector>
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;
155 using testing::_;
157 namespace policy {
159 namespace {
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[] = {
167 "chrome://policy",
168 "chrome://about",
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"
179 " </app>\n";
180 const char kUpdateManifestFooter[] =
181 "</gupdate>\n";
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[] = {
197 "el",
199 const char* const kRecommendedLocales1[] = {
200 "pl",
201 "et",
202 "en-US",
204 const char* const kRecommendedLocales2[] = {
205 "fr",
206 "nl",
208 const char* const kInvalidRecommendedLocale[] = {
209 "xx",
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
215 // tasks.
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> {
221 public:
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);
237 private:
238 struct Update {
239 public:
240 Update(const std::string& version, const GURL& crx_url);
241 Update();
243 std::string version;
244 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.
253 base::Lock lock_;
255 std::string relative_update_url_;
256 UpdateMap updates_;
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 {
264 public:
265 DictionaryPrefValueWaiter(const std::string& pref,
266 const std::string& key,
267 const std::string& expected_value);
268 ~DictionaryPrefValueWaiter();
270 void Wait();
272 private:
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,
286 const GURL& crx_url)
287 : version(version),
288 crx_url(crx_url) {
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")
317 continue;
318 // Extract the extension id from the subquery. Since GetValueForKeyInQuery()
319 // expects a complete URL, dummy scheme and host must be prepended.
320 std::string id;
321 net::GetValueForKeyInQuery(GURL("http://dummy?" + it.GetUnescapedValue()),
322 "id", &id);
323 UpdateMap::const_iterator entry = updates_.find(id);
324 if (entry != updates_.end()) {
325 content += base::StringPrintf(kUpdateManifestTemplate,
326 id.c_str(),
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)
347 : pref_(pref),
348 key_(key),
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(
358 pref_.c_str(),
359 base::Bind(&DictionaryPrefValueWaiter::QuitLoopIfExpectedValueFound,
360 base::Unretained(this)));
361 QuitLoopIfExpectedValueFound();
362 run_loop_.Run();
365 void DictionaryPrefValueWaiter::QuitLoopIfExpectedValueFound() {
366 const base::DictionaryValue* pref =
367 pref_change_registrar_.prefs()->GetDictionary(pref_.c_str());
368 ASSERT_TRUE(pref);
369 std::string actual_value;
370 if (pref->GetStringWithoutPathExpansion(key_, &actual_value) &&
371 actual_value == expected_value_) {
372 run_loop_.Quit();
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)
387 ->message()
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,
394 const GURL& url,
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) {
411 callback.Run();
414 } // namespace
416 class DeviceLocalAccountTest : public DevicePolicyCrosBrowserTest,
417 public user_manager::UserManager::Observer,
418 public chrome::BrowserListObserver,
419 public extensions::AppWindowRegistry::Observer {
420 protected:
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)),
429 contents_(NULL) {
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()));
441 signing_key.reset();
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(),
468 argv.end());
469 command_line->InitFromArgv(argv);
471 InstallOwnerKey();
472 MarkAsEnterpriseOwned();
474 InitializePolicy();
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());
490 ASSERT_TRUE(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();
494 ASSERT_TRUE(web_ui);
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());
503 if (!oobe_ui_ready)
504 run_loop.Run();
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.
510 bool done = false;
511 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
512 contents_,
513 "var languageSelect = document.getElementById('language-select');"
514 "var blurAndReportSuccess = function() {"
515 " languageSelect.blur();"
516 " domAutomationController.send(true);"
517 "};"
518 "var screenLoading = document.getElementById('outer-container')"
519 " .classList.contains('down');"
520 "if (document.activeElement == languageSelect || !screenLoading)"
521 " blurAndReportSuccess();"
522 "else"
523 " languageSelect.addEventListener('focus', blurAndReportSuccess);",
524 &done));
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 {
547 if (run_loop_)
548 run_loop_->Quit();
551 void OnBrowserRemoved(Browser* browser) override {
552 if (run_loop_)
553 run_loop_->Quit();
556 void OnAppWindowAdded(extensions::AppWindow* app_window) override {
557 if (run_loop_)
558 run_loop_->Quit();
561 void OnAppWindowRemoved(extensions::AppWindow* app_window) override {
562 if (run_loop_)
563 run_loop_->Quit();
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(
575 kAccountId1);
576 device_local_account_policy_.policy_data().set_public_key_version(1);
577 device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
578 kDisplayName1);
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[],
600 size_t array_size) {
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);
617 account->set_type(
618 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
619 RefreshDevicePolicy();
620 ASSERT_TRUE(test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType,
621 std::string(),
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,
633 std::string(),
634 proto.SerializeAsString()));
637 void CheckPublicSessionPresent(const std::string& id) {
638 const user_manager::User* user =
639 user_manager::UserManager::Get()->FindUser(id);
640 ASSERT_TRUE(user);
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)) {
650 ADD_FAILURE();
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) {
659 return path.Append(
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",
679 user_id,
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
686 // successful login.
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(
694 contents_,
695 base::StringPrintf(
696 "var pod ="
697 " document.getElementById('pod-row').getPodWithUsername_('%s');"
698 "pod.click();"
699 "domAutomationController.send(pod.classList.contains('advanced'));",
700 user_id_1_.c_str()),
701 &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());
723 run_loop.Run();
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());
737 ASSERT_TRUE(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,
744 user_id_1_);
745 user_context.SetPublicSessionLocale(locale);
746 user_context.SetPublicSessionInputMethod(input_method);
747 controller->Login(user_context, chromeos::SigninSpecifics());
750 void WaitForSessionStart() {
751 if (IsSessionStarted())
752 return;
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()
770 .id());
773 void RunWithRecommendedLocale(const char* const locales[],
774 size_t locales_size) {
775 SetRecommendedLocales(locales, locales_size);
776 UploadAndInstallDeviceLocalAccountPolicy();
777 AddPublicSessionToDevicePolicy(kAccountId1);
778 EnableAutoLogin();
780 WaitForPolicy();
782 WaitForSessionStart();
784 EXPECT_EQ(locales[0], g_browser_process->GetApplicationLocale());
785 EXPECT_EQ(l10n_util::GetLanguage(locales[0]),
786 icu::Locale::getDefault().getLanguage());
787 VerifyKeyboardLayoutMatchesLocale();
790 const std::string user_id_1_;
791 const std::string user_id_2_;
792 const std::string public_session_input_method_id_;
794 std::string initial_locale_;
795 std::string initial_language_;
797 scoped_ptr<base::RunLoop> run_loop_;
799 UserPolicyBuilder device_local_account_policy_;
800 LocalPolicyTestServer test_server_;
802 content::WebContents* contents_;
804 private:
805 DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountTest);
808 static bool IsKnownUser(const std::string& account_id) {
809 return user_manager::UserManager::Get()->IsKnownUser(account_id);
812 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LoginScreen) {
813 AddPublicSessionToDevicePolicy(kAccountId1);
814 AddPublicSessionToDevicePolicy(kAccountId2);
816 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
817 base::Bind(&IsKnownUser, user_id_1_))
818 .Wait();
819 EXPECT_TRUE(IsKnownUser(user_id_2_));
821 CheckPublicSessionPresent(user_id_1_);
822 CheckPublicSessionPresent(user_id_2_);
825 // Flaky: http://crbug.com/512670.
826 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DISABLED_DisplayName) {
827 UploadAndInstallDeviceLocalAccountPolicy();
828 AddPublicSessionToDevicePolicy(kAccountId1);
830 WaitForPolicy();
832 // Verify that the display name is shown in the UI.
833 const std::string get_compact_pod_display_name = base::StringPrintf(
834 "domAutomationController.send(document.getElementById('pod-row')"
835 " .getPodWithUsername_('%s').nameElement.textContent);",
836 user_id_1_.c_str());
837 std::string display_name;
838 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
839 contents_,
840 get_compact_pod_display_name,
841 &display_name));
842 EXPECT_EQ(kDisplayName1, display_name);
843 const std::string get_expanded_pod_display_name = base::StringPrintf(
844 "domAutomationController.send(document.getElementById('pod-row')"
845 " .getPodWithUsername_('%s').querySelector('.expanded-pane-name')"
846 " .textContent);",
847 user_id_1_.c_str());
848 display_name.clear();
849 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
850 contents_,
851 get_expanded_pod_display_name,
852 &display_name));
853 EXPECT_EQ(kDisplayName1, display_name);
855 // Click on the pod to expand it.
856 ASSERT_TRUE(content::ExecuteScript(
857 contents_,
858 base::StringPrintf(
859 "document.getElementById('pod-row').getPodWithUsername_('%s')"
860 " .click();",
861 user_id_1_.c_str())));
863 // Change the display name.
864 device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
865 kDisplayName2);
866 UploadAndInstallDeviceLocalAccountPolicy();
867 policy::BrowserPolicyConnectorChromeOS* connector =
868 g_browser_process->platform_part()->browser_policy_connector_chromeos();
869 DeviceLocalAccountPolicyBroker* broker =
870 connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
871 user_id_1_);
872 ASSERT_TRUE(broker);
873 broker->core()->store()->Load();
874 WaitForDisplayName(user_id_1_, kDisplayName2);
876 // Verify that the new display name is shown in the UI.
877 display_name.clear();
878 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
879 contents_,
880 get_compact_pod_display_name,
881 &display_name));
882 EXPECT_EQ(kDisplayName2, display_name);
883 display_name.clear();
884 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
885 contents_,
886 get_expanded_pod_display_name,
887 &display_name));
888 EXPECT_EQ(kDisplayName2, display_name);
890 // Verify that the pod is still expanded. This indicates that the UI updated
891 // without reloading and losing state.
892 bool expanded = false;
893 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
894 contents_,
895 base::StringPrintf(
896 "domAutomationController.send(document.getElementById('pod-row')"
897 " .getPodWithUsername_('%s').expanded);",
898 user_id_1_.c_str()),
899 &expanded));
900 EXPECT_TRUE(expanded);
903 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyDownload) {
904 UploadDeviceLocalAccountPolicy();
905 AddPublicSessionToDevicePolicy(kAccountId1);
907 WaitForPolicy();
909 // Sanity check: The policy should be present now.
910 ASSERT_FALSE(session_manager_client()->device_local_account_policy(
911 kAccountId1).empty());
914 static bool IsNotKnownUser(const std::string& account_id) {
915 return !IsKnownUser(account_id);
918 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, AccountListChange) {
919 AddPublicSessionToDevicePolicy(kAccountId1);
920 AddPublicSessionToDevicePolicy(kAccountId2);
922 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
923 base::Bind(&IsKnownUser, user_id_1_))
924 .Wait();
925 EXPECT_TRUE(IsKnownUser(user_id_2_));
927 // Update policy to remove kAccountId2.
928 em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
929 proto.mutable_device_local_accounts()->clear_account();
930 AddPublicSessionToDevicePolicy(kAccountId1);
932 em::ChromeDeviceSettingsProto policy;
933 policy.mutable_show_user_names()->set_show_user_names(true);
934 em::DeviceLocalAccountInfoProto* account1 =
935 policy.mutable_device_local_accounts()->add_account();
936 account1->set_account_id(kAccountId1);
937 account1->set_type(
938 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
940 test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType, std::string(),
941 policy.SerializeAsString());
942 g_browser_process->policy_service()->RefreshPolicies(base::Closure());
944 // Make sure the second device-local account disappears.
945 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
946 base::Bind(&IsNotKnownUser, user_id_2_))
947 .Wait();
950 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, StartSession) {
951 // Specify startup pages.
952 device_local_account_policy_.payload().mutable_restoreonstartup()->set_value(
953 SessionStartupPref::kPrefValueURLs);
954 em::StringListPolicyProto* startup_urls_proto =
955 device_local_account_policy_.payload().mutable_restoreonstartupurls();
956 for (size_t i = 0; i < arraysize(kStartupURLs); ++i)
957 startup_urls_proto->mutable_value()->add_entries(kStartupURLs[i]);
958 UploadAndInstallDeviceLocalAccountPolicy();
959 AddPublicSessionToDevicePolicy(kAccountId1);
961 WaitForPolicy();
963 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
964 WaitForSessionStart();
966 // Check that the startup pages specified in policy were opened.
967 BrowserList* browser_list =
968 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
969 EXPECT_EQ(1U, browser_list->size());
970 Browser* browser = browser_list->get(0);
971 ASSERT_TRUE(browser);
973 TabStripModel* tabs = browser->tab_strip_model();
974 ASSERT_TRUE(tabs);
975 int expected_tab_count = static_cast<int>(arraysize(kStartupURLs));
976 EXPECT_EQ(expected_tab_count, tabs->count());
977 for (int i = 0; i < expected_tab_count && i < tabs->count(); ++i) {
978 EXPECT_EQ(GURL(kStartupURLs[i]),
979 tabs->GetWebContentsAt(i)->GetVisibleURL());
982 // Verify that the session is not considered to be logged in with a GAIA
983 // account.
984 Profile* profile = GetProfileForTest();
985 ASSERT_TRUE(profile);
986 EXPECT_FALSE(
987 SigninManagerFactory::GetForProfile(profile)->IsAuthenticated());
990 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, FullscreenDisallowed) {
991 UploadAndInstallDeviceLocalAccountPolicy();
992 AddPublicSessionToDevicePolicy(kAccountId1);
994 WaitForPolicy();
996 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
997 WaitForSessionStart();
999 BrowserList* browser_list =
1000 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
1001 EXPECT_EQ(1U, browser_list->size());
1002 Browser* browser = browser_list->get(0);
1003 ASSERT_TRUE(browser);
1004 BrowserWindow* browser_window = browser->window();
1005 ASSERT_TRUE(browser_window);
1007 // Verify that an attempt to enter fullscreen mode is denied.
1008 EXPECT_FALSE(browser_window->IsFullscreen());
1009 chrome::ToggleFullscreenMode(browser);
1010 EXPECT_FALSE(browser_window->IsFullscreen());
1013 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExtensionsUncached) {
1014 // Make it possible to force-install a hosted app and an extension.
1015 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
1016 scoped_refptr<TestingUpdateManifestProvider> testing_update_manifest_provider(
1017 new TestingUpdateManifestProvider(kRelativeUpdateURL));
1018 testing_update_manifest_provider->AddUpdate(
1019 kHostedAppID, kHostedAppVersion,
1020 embedded_test_server()->GetURL(std::string("/") + kHostedAppCRXPath));
1021 testing_update_manifest_provider->AddUpdate(
1022 kGoodExtensionID, kGoodExtensionVersion,
1023 embedded_test_server()->GetURL(std::string("/") + kGoodExtensionCRXPath));
1024 embedded_test_server()->RegisterRequestHandler(
1025 base::Bind(&TestingUpdateManifestProvider::HandleRequest,
1026 testing_update_manifest_provider));
1028 // Specify policy to force-install the hosted app and the extension.
1029 em::StringList* forcelist = device_local_account_policy_.payload()
1030 .mutable_extensioninstallforcelist()->mutable_value();
1031 forcelist->add_entries(base::StringPrintf(
1032 "%s;%s",
1033 kHostedAppID,
1034 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
1035 forcelist->add_entries(base::StringPrintf(
1036 "%s;%s",
1037 kGoodExtensionID,
1038 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
1040 UploadAndInstallDeviceLocalAccountPolicy();
1041 AddPublicSessionToDevicePolicy(kAccountId1);
1043 WaitForPolicy();
1045 // Start listening for app/extension installation results.
1046 content::WindowedNotificationObserver hosted_app_observer(
1047 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
1048 base::Bind(DoesInstallSuccessReferToId, kHostedAppID));
1049 content::WindowedNotificationObserver extension_observer(
1050 extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR,
1051 base::Bind(DoesInstallFailureReferToId, kGoodExtensionID));
1053 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
1055 // Wait for the hosted app installation to succeed and the extension
1056 // installation to fail (because hosted apps are whitelisted for use in
1057 // device-local accounts and extensions are not).
1058 hosted_app_observer.Wait();
1059 extension_observer.Wait();
1061 // Verify that the hosted app was installed.
1062 Profile* profile = GetProfileForTest();
1063 ASSERT_TRUE(profile);
1064 ExtensionService* extension_service =
1065 extensions::ExtensionSystem::Get(profile)->extension_service();
1066 EXPECT_TRUE(extension_service->GetExtensionById(kHostedAppID, true));
1068 // Verify that the extension was not installed.
1069 EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true));
1071 // Verify that the app was downloaded to the account's extension cache.
1072 base::FilePath test_dir;
1073 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
1074 EXPECT_TRUE(ContentsEqual(
1075 GetCacheCRXFile(kAccountId1, kHostedAppID, kHostedAppVersion),
1076 test_dir.Append(kHostedAppCRXPath)));
1078 // Verify that the extension was removed from the account's extension cache
1079 // after the installation failure.
1080 DeviceLocalAccountPolicyBroker* broker =
1081 g_browser_process->platform_part()->browser_policy_connector_chromeos()->
1082 GetDeviceLocalAccountPolicyService()->GetBrokerForUser(user_id_1_);
1083 ASSERT_TRUE(broker);
1084 chromeos::ExternalCache* cache =
1085 broker->extension_loader()->GetExternalCacheForTesting();
1086 ASSERT_TRUE(cache);
1087 EXPECT_FALSE(cache->GetExtension(kGoodExtensionID, NULL, NULL));
1090 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExtensionsCached) {
1091 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
1093 // Pre-populate the device local account's extension cache with a hosted app
1094 // and an extension.
1095 EXPECT_TRUE(base::CreateDirectory(
1096 GetExtensionCacheDirectoryForAccountID(kAccountId1)));
1097 base::FilePath test_dir;
1098 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
1099 const base::FilePath cached_hosted_app =
1100 GetCacheCRXFile(kAccountId1, kHostedAppID, kHostedAppVersion);
1101 EXPECT_TRUE(CopyFile(test_dir.Append(kHostedAppCRXPath),
1102 cached_hosted_app));
1103 EXPECT_TRUE(CopyFile(
1104 test_dir.Append(kGoodExtensionCRXPath),
1105 GetCacheCRXFile(kAccountId1, kGoodExtensionID, kGoodExtensionVersion)));
1107 // Specify policy to force-install the hosted app.
1108 em::StringList* forcelist = device_local_account_policy_.payload()
1109 .mutable_extensioninstallforcelist()->mutable_value();
1110 forcelist->add_entries(base::StringPrintf(
1111 "%s;%s",
1112 kHostedAppID,
1113 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
1114 forcelist->add_entries(base::StringPrintf(
1115 "%s;%s",
1116 kGoodExtensionID,
1117 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
1119 UploadAndInstallDeviceLocalAccountPolicy();
1120 AddPublicSessionToDevicePolicy(kAccountId1);
1122 WaitForPolicy();
1124 // Start listening for app/extension installation results.
1125 content::WindowedNotificationObserver hosted_app_observer(
1126 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
1127 base::Bind(DoesInstallSuccessReferToId, kHostedAppID));
1128 content::WindowedNotificationObserver extension_observer(
1129 extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR,
1130 base::Bind(DoesInstallFailureReferToId, kGoodExtensionID));
1132 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
1134 // Wait for the hosted app installation to succeed and the extension
1135 // installation to fail.
1136 hosted_app_observer.Wait();
1137 extension_observer.Wait();
1139 // Verify that the hosted app was installed.
1140 Profile* profile = GetProfileForTest();
1141 ASSERT_TRUE(profile);
1142 ExtensionService* extension_service =
1143 extensions::ExtensionSystem::Get(profile)->extension_service();
1144 EXPECT_TRUE(extension_service->GetExtensionById(kHostedAppID, true));
1146 // Verify that the extension was not installed.
1147 EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true));
1149 // Verify that the app is still in the account's extension cache.
1150 EXPECT_TRUE(PathExists(cached_hosted_app));
1152 // Verify that the extension was removed from the account's extension cache.
1153 DeviceLocalAccountPolicyBroker* broker =
1154 g_browser_process->platform_part()->browser_policy_connector_chromeos()->
1155 GetDeviceLocalAccountPolicyService()->GetBrokerForUser(user_id_1_);
1156 ASSERT_TRUE(broker);
1157 chromeos::ExternalCache* cache =
1158 broker->extension_loader()->GetExternalCacheForTesting();
1159 ASSERT_TRUE(cache);
1160 EXPECT_FALSE(cache->GetExtension(kGoodExtensionID, NULL, NULL));
1163 static void OnPutExtension(scoped_ptr<base::RunLoop>* run_loop,
1164 const base::FilePath& file_path,
1165 bool file_ownership_passed) {
1166 ASSERT_TRUE(*run_loop);
1167 (*run_loop)->Quit();
1170 static void OnExtensionCacheImplInitialized(
1171 scoped_ptr<base::RunLoop>* run_loop) {
1172 ASSERT_TRUE(*run_loop);
1173 (*run_loop)->Quit();
1176 static void CreateFile(const base::FilePath& file,
1177 size_t size,
1178 const base::Time& timestamp) {
1179 std::string data(size, 0);
1180 EXPECT_EQ(base::WriteFile(file, data.data(), data.size()), int(size));
1181 EXPECT_TRUE(base::TouchFile(file, timestamp, timestamp));
1184 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExtensionCacheImplTest) {
1185 // Make it possible to force-install a hosted app and an extension.
1186 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
1187 scoped_refptr<TestingUpdateManifestProvider> testing_update_manifest_provider(
1188 new TestingUpdateManifestProvider(kRelativeUpdateURL));
1189 testing_update_manifest_provider->AddUpdate(
1190 kHostedAppID, kHostedAppVersion,
1191 embedded_test_server()->GetURL(std::string("/") + kHostedAppCRXPath));
1192 testing_update_manifest_provider->AddUpdate(
1193 kGoodExtensionID, kGoodExtensionVersion,
1194 embedded_test_server()->GetURL(std::string("/") + kGoodExtensionCRXPath));
1195 embedded_test_server()->RegisterRequestHandler(
1196 base::Bind(&TestingUpdateManifestProvider::HandleRequest,
1197 testing_update_manifest_provider));
1198 // Create and initialize local cache.
1199 base::ScopedTempDir cache_dir;
1200 EXPECT_TRUE(cache_dir.CreateUniqueTempDir());
1201 const base::FilePath impl_path = cache_dir.path();
1202 EXPECT_TRUE(base::CreateDirectory(impl_path));
1203 CreateFile(impl_path.Append(
1204 extensions::LocalExtensionCache::kCacheReadyFlagFileName),
1205 0, base::Time::Now());
1206 extensions::ExtensionCacheImpl cache_impl(make_scoped_ptr(
1207 new extensions::ChromeOSExtensionCacheDelegate(impl_path)));
1208 scoped_ptr<base::RunLoop> run_loop;
1209 run_loop.reset(new base::RunLoop);
1210 cache_impl.Start(base::Bind(&OnExtensionCacheImplInitialized, &run_loop));
1211 run_loop->Run();
1213 // Put extension in the local cache.
1214 base::ScopedTempDir temp_dir;
1215 EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
1216 const base::FilePath temp_path = temp_dir.path();
1217 EXPECT_TRUE(base::CreateDirectory(temp_path));
1218 const base::FilePath temp_file =
1219 GetCacheCRXFilePath(kGoodExtensionID, kGoodExtensionVersion, temp_path);
1220 base::FilePath test_dir;
1221 std::string hash;
1222 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
1223 EXPECT_TRUE(CopyFile(test_dir.Append(kGoodExtensionCRXPath), temp_file));
1224 cache_impl.AllowCaching(kGoodExtensionID);
1225 run_loop.reset(new base::RunLoop);
1226 cache_impl.PutExtension(kGoodExtensionID, hash, temp_file,
1227 kGoodExtensionVersion,
1228 base::Bind(&OnPutExtension, &run_loop));
1229 run_loop->Run();
1231 // Verify that the extension file was added to the local cache.
1232 const base::FilePath local_file =
1233 GetCacheCRXFilePath(kGoodExtensionID, kGoodExtensionVersion, impl_path);
1234 EXPECT_TRUE(PathExists(local_file));
1236 // Specify policy to force-install the hosted app and the extension.
1237 em::StringList* forcelist = device_local_account_policy_.payload()
1238 .mutable_extensioninstallforcelist()->mutable_value();
1239 forcelist->add_entries(base::StringPrintf(
1240 "%s;%s",
1241 kHostedAppID,
1242 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
1243 forcelist->add_entries(base::StringPrintf(
1244 "%s;%s",
1245 kGoodExtensionID,
1246 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
1248 UploadAndInstallDeviceLocalAccountPolicy();
1249 AddPublicSessionToDevicePolicy(kAccountId1);
1251 WaitForPolicy();
1253 // Start listening for app/extension installation results.
1254 content::WindowedNotificationObserver hosted_app_observer(
1255 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
1256 base::Bind(DoesInstallSuccessReferToId, kHostedAppID));
1257 content::WindowedNotificationObserver extension_observer(
1258 extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR,
1259 base::Bind(DoesInstallFailureReferToId, kGoodExtensionID));
1261 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
1263 // Wait for the hosted app installation to succeed and the extension
1264 // installation to fail (because hosted apps are whitelisted for use in
1265 // device-local accounts and extensions are not).
1266 hosted_app_observer.Wait();
1267 extension_observer.Wait();
1269 // Verify that the extension was kept in the local cache.
1270 EXPECT_TRUE(cache_impl.GetExtension(kGoodExtensionID, hash, NULL, NULL));
1272 // Verify that the extension file was kept in the local cache.
1273 EXPECT_TRUE(PathExists(local_file));
1276 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExternalData) {
1277 // user_manager::UserManager requests an external data fetch whenever
1278 // the key::kUserAvatarImage policy is set. Since this test wants to
1279 // verify that the underlying policy subsystem will start a fetch
1280 // without this request as well, the user_manager::UserManager must be
1281 // prevented from seeing the policy change.
1282 reinterpret_cast<chromeos::ChromeUserManagerImpl*>(
1283 user_manager::UserManager::Get())->StopPolicyObserverForTesting();
1285 UploadDeviceLocalAccountPolicy();
1286 AddPublicSessionToDevicePolicy(kAccountId1);
1288 WaitForPolicy();
1290 // Start serving external data at |kExternalDataURL|.
1291 scoped_ptr<base::RunLoop> run_loop(new base::RunLoop);
1292 scoped_ptr<net::FakeURLFetcherFactory> fetcher_factory(
1293 new net::FakeURLFetcherFactory(
1294 NULL, base::Bind(&RunCallbackAndReturnFakeURLFetcher,
1295 base::ThreadTaskRunnerHandle::Get(),
1296 run_loop->QuitClosure())));
1297 fetcher_factory->SetFakeResponse(GURL(kExternalDataURL),
1298 kExternalData,
1299 net::HTTP_OK,
1300 net::URLRequestStatus::SUCCESS);
1302 // Specify an external data reference for the key::kUserAvatarImage policy.
1303 scoped_ptr<base::DictionaryValue> metadata =
1304 test::ConstructExternalDataReference(kExternalDataURL, kExternalData);
1305 std::string policy;
1306 base::JSONWriter::Write(*metadata, &policy);
1307 device_local_account_policy_.payload().mutable_useravatarimage()->set_value(
1308 policy);
1309 UploadAndInstallDeviceLocalAccountPolicy();
1310 policy::BrowserPolicyConnectorChromeOS* connector =
1311 g_browser_process->platform_part()->browser_policy_connector_chromeos();
1312 DeviceLocalAccountPolicyBroker* broker =
1313 connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
1314 user_id_1_);
1315 ASSERT_TRUE(broker);
1316 broker->core()->store()->Load();
1318 // The external data should be fetched and cached automatically. Wait for this
1319 // fetch.
1320 run_loop->Run();
1322 // Stop serving external data at |kExternalDataURL|.
1323 fetcher_factory.reset();
1325 const PolicyMap::Entry* policy_entry =
1326 broker->core()->store()->policy_map().Get(key::kUserAvatarImage);
1327 ASSERT_TRUE(policy_entry);
1328 ASSERT_TRUE(policy_entry->external_data_fetcher);
1330 // Retrieve the external data. Although the data is no longer being served at
1331 // |kExternalDataURL|, the retrieval should succeed because the data has been
1332 // cached.
1333 run_loop.reset(new base::RunLoop);
1334 scoped_ptr<std::string> fetched_external_data;
1335 policy_entry->external_data_fetcher->Fetch(base::Bind(
1336 &test::ExternalDataFetchCallback,
1337 &fetched_external_data,
1338 run_loop->QuitClosure()));
1339 run_loop->Run();
1341 ASSERT_TRUE(fetched_external_data);
1342 EXPECT_EQ(kExternalData, *fetched_external_data);
1344 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
1345 WaitForSessionStart();
1347 // Verify that the external data reference has propagated to the device-local
1348 // account's ProfilePolicyConnector.
1349 ProfilePolicyConnector* policy_connector =
1350 ProfilePolicyConnectorFactory::GetForBrowserContext(GetProfileForTest());
1351 ASSERT_TRUE(policy_connector);
1352 const PolicyMap& policies = policy_connector->policy_service()->GetPolicies(
1353 PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
1354 policy_entry = policies.Get(key::kUserAvatarImage);
1355 ASSERT_TRUE(policy_entry);
1356 EXPECT_TRUE(base::Value::Equals(metadata.get(), policy_entry->value));
1357 ASSERT_TRUE(policy_entry->external_data_fetcher);
1359 // Retrieve the external data via the ProfilePolicyConnector. The retrieval
1360 // should succeed because the data has been cached.
1361 run_loop.reset(new base::RunLoop);
1362 fetched_external_data.reset();
1363 policy_entry->external_data_fetcher->Fetch(base::Bind(
1364 &test::ExternalDataFetchCallback,
1365 &fetched_external_data,
1366 run_loop->QuitClosure()));
1367 run_loop->Run();
1369 ASSERT_TRUE(fetched_external_data);
1370 EXPECT_EQ(kExternalData, *fetched_external_data);
1373 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, UserAvatarImage) {
1374 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
1376 UploadDeviceLocalAccountPolicy();
1377 AddPublicSessionToDevicePolicy(kAccountId1);
1379 WaitForPolicy();
1381 base::FilePath test_dir;
1382 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
1383 std::string image_data;
1384 ASSERT_TRUE(base::ReadFileToString(
1385 test_dir.Append(chromeos::test::kUserAvatarImage1RelativePath),
1386 &image_data));
1388 std::string policy;
1389 base::JSONWriter::Write(
1390 *test::ConstructExternalDataReference(
1391 embedded_test_server()
1392 ->GetURL(std::string("/") +
1393 chromeos::test::kUserAvatarImage1RelativePath)
1394 .spec(),
1395 image_data),
1396 &policy);
1397 device_local_account_policy_.payload().mutable_useravatarimage()->set_value(
1398 policy);
1399 UploadAndInstallDeviceLocalAccountPolicy();
1400 policy::BrowserPolicyConnectorChromeOS* connector =
1401 g_browser_process->platform_part()->browser_policy_connector_chromeos();
1402 DeviceLocalAccountPolicyBroker* broker =
1403 connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
1404 user_id_1_);
1405 ASSERT_TRUE(broker);
1407 run_loop_.reset(new base::RunLoop);
1408 user_manager::UserManager::Get()->AddObserver(this);
1409 broker->core()->store()->Load();
1410 run_loop_->Run();
1411 user_manager::UserManager::Get()->RemoveObserver(this);
1413 scoped_ptr<gfx::ImageSkia> policy_image = chromeos::test::ImageLoader(
1414 test_dir.Append(chromeos::test::kUserAvatarImage1RelativePath)).Load();
1415 ASSERT_TRUE(policy_image);
1417 const user_manager::User* user =
1418 user_manager::UserManager::Get()->FindUser(user_id_1_);
1419 ASSERT_TRUE(user);
1421 base::FilePath user_data_dir;
1422 ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
1423 const base::FilePath saved_image_path =
1424 user_data_dir.Append(user_id_1_).AddExtension("jpg");
1426 EXPECT_FALSE(user->HasDefaultImage());
1427 EXPECT_EQ(user_manager::User::USER_IMAGE_EXTERNAL, user->image_index());
1428 EXPECT_TRUE(chromeos::test::AreImagesEqual(*policy_image, user->GetImage()));
1429 const base::DictionaryValue* images_pref =
1430 g_browser_process->local_state()->GetDictionary("user_image_info");
1431 ASSERT_TRUE(images_pref);
1432 const base::DictionaryValue* image_properties;
1433 ASSERT_TRUE(images_pref->GetDictionaryWithoutPathExpansion(
1434 user_id_1_,
1435 &image_properties));
1436 int image_index;
1437 std::string image_path;
1438 ASSERT_TRUE(image_properties->GetInteger("index", &image_index));
1439 ASSERT_TRUE(image_properties->GetString("path", &image_path));
1440 EXPECT_EQ(user_manager::User::USER_IMAGE_EXTERNAL, image_index);
1441 EXPECT_EQ(saved_image_path.value(), image_path);
1443 scoped_ptr<gfx::ImageSkia> saved_image =
1444 chromeos::test::ImageLoader(saved_image_path).Load();
1445 ASSERT_TRUE(saved_image);
1447 // Check image dimensions. Images can't be compared since JPEG is lossy.
1448 EXPECT_EQ(policy_image->width(), saved_image->width());
1449 EXPECT_EQ(policy_image->height(), saved_image->height());
1452 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LastWindowClosedLogoutReminder) {
1453 UploadAndInstallDeviceLocalAccountPolicy();
1454 AddPublicSessionToDevicePolicy(kAccountId1);
1456 WaitForPolicy();
1458 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
1459 WaitForSessionStart();
1461 Profile* profile = GetProfileForTest();
1462 ASSERT_TRUE(profile);
1463 extensions::AppWindowRegistry* app_window_registry =
1464 extensions::AppWindowRegistry::Get(profile);
1465 app_window_registry->AddObserver(this);
1467 // Verify that the logout confirmation dialog is not showing.
1468 ash::LogoutConfirmationController* logout_confirmation_controller =
1469 ash::Shell::GetInstance()->logout_confirmation_controller();
1470 ASSERT_TRUE(logout_confirmation_controller);
1471 EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());
1473 // Remove policy that allows only explicitly whitelisted apps to be installed
1474 // in a public session.
1475 extensions::ExtensionSystem* extension_system =
1476 extensions::ExtensionSystem::Get(profile);
1477 ASSERT_TRUE(extension_system);
1478 extension_system->management_policy()->UnregisterAllProviders();
1480 // Install and a platform app.
1481 scoped_refptr<extensions::CrxInstaller> installer =
1482 extensions::CrxInstaller::CreateSilent(
1483 extension_system->extension_service());
1484 installer->set_allow_silent_install(true);
1485 installer->set_install_cause(extension_misc::INSTALL_CAUSE_USER_DOWNLOAD);
1486 installer->set_creation_flags(extensions::Extension::FROM_WEBSTORE);
1487 content::WindowedNotificationObserver app_install_observer(
1488 extensions::NOTIFICATION_CRX_INSTALLER_DONE,
1489 content::NotificationService::AllSources());
1490 base::FilePath test_dir;
1491 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
1492 installer->InstallCrx(test_dir.Append(kPackagedAppCRXPath));
1493 app_install_observer.Wait();
1494 const extensions::Extension* app =
1495 content::Details<const extensions::Extension>(
1496 app_install_observer.details()).ptr();
1498 // Start the platform app, causing it to open a window.
1499 run_loop_.reset(new base::RunLoop);
1500 OpenApplication(AppLaunchParams(profile, app,
1501 extensions::LAUNCH_CONTAINER_NONE, NEW_WINDOW,
1502 extensions::SOURCE_TEST));
1503 run_loop_->Run();
1504 EXPECT_EQ(1U, app_window_registry->app_windows().size());
1506 // Close the only open browser window.
1507 BrowserList* browser_list =
1508 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
1509 EXPECT_EQ(1U, browser_list->size());
1510 Browser* browser = browser_list->get(0);
1511 ASSERT_TRUE(browser);
1512 BrowserWindow* browser_window = browser->window();
1513 ASSERT_TRUE(browser_window);
1514 run_loop_.reset(new base::RunLoop);
1515 browser_window->Close();
1516 browser_window = NULL;
1517 run_loop_->Run();
1518 browser = NULL;
1519 EXPECT_TRUE(browser_list->empty());
1521 // Verify that the logout confirmation dialog is not showing because an app
1522 // window is still open.
1523 EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());
1525 // Open a browser window.
1526 Browser* first_browser = CreateBrowser(profile);
1527 EXPECT_EQ(1U, browser_list->size());
1529 // Close the app window.
1530 run_loop_.reset(new base::RunLoop);
1531 ASSERT_EQ(1U, app_window_registry->app_windows().size());
1532 app_window_registry->app_windows().front()->GetBaseWindow()->Close();
1533 run_loop_->Run();
1534 EXPECT_TRUE(app_window_registry->app_windows().empty());
1536 // Verify that the logout confirmation dialog is not showing because a browser
1537 // window is still open.
1538 EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());
1540 // Open a second browser window.
1541 Browser* second_browser = CreateBrowser(profile);
1542 EXPECT_EQ(2U, browser_list->size());
1544 // Close the first browser window.
1545 browser_window = first_browser->window();
1546 ASSERT_TRUE(browser_window);
1547 run_loop_.reset(new base::RunLoop);
1548 browser_window->Close();
1549 browser_window = NULL;
1550 run_loop_->Run();
1551 first_browser = NULL;
1552 EXPECT_EQ(1U, browser_list->size());
1554 // Verify that the logout confirmation dialog is not showing because a browser
1555 // window is still open.
1556 EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());
1558 // Close the second browser window.
1559 browser_window = second_browser->window();
1560 ASSERT_TRUE(browser_window);
1561 run_loop_.reset(new base::RunLoop);
1562 browser_window->Close();
1563 browser_window = NULL;
1564 run_loop_->Run();
1565 second_browser = NULL;
1566 EXPECT_TRUE(browser_list->empty());
1568 // Verify that the logout confirmation dialog is showing.
1569 ash::LogoutConfirmationDialog* dialog =
1570 logout_confirmation_controller->dialog_for_testing();
1571 ASSERT_TRUE(dialog);
1573 // Deny the logout.
1574 dialog->GetWidget()->Close();
1575 dialog = NULL;
1576 base::RunLoop().RunUntilIdle();
1578 // Verify that the logout confirmation dialog is no longer showing.
1579 EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());
1581 // Open a browser window.
1582 browser = CreateBrowser(profile);
1583 EXPECT_EQ(1U, browser_list->size());
1585 // Close the browser window.
1586 browser_window = browser->window();
1587 ASSERT_TRUE(browser_window);
1588 run_loop_.reset(new base::RunLoop);
1589 browser_window->Close();
1590 browser_window = NULL;
1591 run_loop_->Run();
1592 browser = NULL;
1593 EXPECT_TRUE(browser_list->empty());
1595 // Verify that the logout confirmation dialog is showing again.
1596 dialog = logout_confirmation_controller->dialog_for_testing();
1597 ASSERT_TRUE(dialog);
1599 // Deny the logout.
1600 dialog->GetWidget()->Close();
1601 dialog = NULL;
1602 base::RunLoop().RunUntilIdle();
1604 app_window_registry->RemoveObserver(this);
1607 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, NoRecommendedLocaleNoSwitch) {
1608 UploadAndInstallDeviceLocalAccountPolicy();
1609 AddPublicSessionToDevicePolicy(kAccountId1);
1611 WaitForPolicy();
1613 ExpandPublicSessionPod(false);
1615 // Click the enter button to start the session.
1616 ASSERT_TRUE(content::ExecuteScript(
1617 contents_,
1618 base::StringPrintf(
1619 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1620 " .querySelector('.enter-button').click();",
1621 user_id_1_.c_str())));
1623 WaitForSessionStart();
1625 // Verify that the locale has not changed and the first keyboard layout
1626 // applicable to the locale was chosen.
1627 EXPECT_EQ(initial_locale_, g_browser_process->GetApplicationLocale());
1628 EXPECT_EQ(initial_language_, icu::Locale::getDefault().getLanguage());
1629 VerifyKeyboardLayoutMatchesLocale();
1632 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, NoRecommendedLocaleSwitch) {
1633 UploadAndInstallDeviceLocalAccountPolicy();
1634 AddPublicSessionToDevicePolicy(kAccountId1);
1636 WaitForPolicy();
1638 ExpandPublicSessionPod(false);
1640 // Click the link that switches the pod to its advanced form. Verify that the
1641 // pod switches from basic to advanced.
1642 bool advanced = false;
1643 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
1644 contents_,
1645 base::StringPrintf(
1646 "var pod ="
1647 " document.getElementById('pod-row').getPodWithUsername_('%s');"
1648 "pod.querySelector('.language-and-input').click();"
1649 "domAutomationController.send(pod.classList.contains('advanced'));",
1650 user_id_1_.c_str()),
1651 &advanced));
1652 EXPECT_FALSE(advanced);
1654 // Manually select a different locale.
1655 ASSERT_TRUE(content::ExecuteScript(
1656 contents_,
1657 base::StringPrintf(
1658 "var languageSelect = document.getElementById('pod-row')"
1659 " .getPodWithUsername_('%s').querySelector('.language-select');"
1660 "languageSelect.value = '%s';"
1661 "var event = document.createEvent('HTMLEvents');"
1662 "event.initEvent('change', false, true);"
1663 "languageSelect.dispatchEvent(event);",
1664 user_id_1_.c_str(),
1665 kPublicSessionLocale)));
1667 // The UI will have requested an updated list of keyboard layouts at this
1668 // point. Wait for the constructions of this list to finish.
1669 WaitForGetKeyboardLayoutsForLocaleToFinish();
1671 // Manually select a different keyboard layout and click the enter button to
1672 // start the session.
1673 ASSERT_TRUE(content::ExecuteScript(
1674 contents_,
1675 base::StringPrintf(
1676 "var pod ="
1677 " document.getElementById('pod-row').getPodWithUsername_('%s');"
1678 "pod.querySelector('.keyboard-select').value = '%s';"
1679 "pod.querySelector('.enter-button').click();",
1680 user_id_1_.c_str(),
1681 public_session_input_method_id_.c_str())));
1683 WaitForSessionStart();
1685 // Verify that the locale and keyboard layout have been applied.
1686 EXPECT_EQ(kPublicSessionLocale, g_browser_process->GetApplicationLocale());
1687 EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale),
1688 icu::Locale::getDefault().getLanguage());
1689 EXPECT_EQ(public_session_input_method_id_,
1690 chromeos::input_method::InputMethodManager::Get()
1691 ->GetActiveIMEState()
1692 ->GetCurrentInputMethod()
1693 .id());
1696 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, OneRecommendedLocale) {
1697 // Specify a recommended locale.
1698 SetRecommendedLocales(kSingleRecommendedLocale,
1699 arraysize(kSingleRecommendedLocale));
1700 UploadAndInstallDeviceLocalAccountPolicy();
1701 AddPublicSessionToDevicePolicy(kAccountId1);
1703 WaitForPolicy();
1705 ExpandPublicSessionPod(false);
1707 // Click the enter button to start the session.
1708 ASSERT_TRUE(content::ExecuteScript(
1709 contents_,
1710 base::StringPrintf(
1711 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1712 " .querySelector('.enter-button').click();",
1713 user_id_1_.c_str())));
1715 WaitForSessionStart();
1717 // Verify that the recommended locale has been applied and the first keyboard
1718 // layout applicable to the locale was chosen.
1719 EXPECT_EQ(kSingleRecommendedLocale[0],
1720 g_browser_process->GetApplicationLocale());
1721 EXPECT_EQ(l10n_util::GetLanguage(kSingleRecommendedLocale[0]),
1722 icu::Locale::getDefault().getLanguage());
1723 VerifyKeyboardLayoutMatchesLocale();
1726 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, MultipleRecommendedLocales) {
1727 // Specify recommended locales.
1728 SetRecommendedLocales(kRecommendedLocales1, arraysize(kRecommendedLocales1));
1729 UploadAndInstallDeviceLocalAccountPolicy();
1730 AddPublicSessionToDevicePolicy(kAccountId1);
1731 AddPublicSessionToDevicePolicy(kAccountId2);
1733 WaitForPolicy();
1735 ExpandPublicSessionPod(true);
1737 // Verify that the pod shows a list of locales beginning with the recommended
1738 // ones, followed by others.
1739 const std::string get_locale_list = base::StringPrintf(
1740 "var languageSelect = document.getElementById('pod-row')"
1741 " .getPodWithUsername_('%s').querySelector('.language-select');"
1742 "var locales = [];"
1743 "for (var i = 0; i < languageSelect.length; ++i)"
1744 " locales.push(languageSelect.options[i].value);"
1745 "domAutomationController.send(JSON.stringify(locales));",
1746 user_id_1_.c_str());
1747 std::string json;
1748 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
1749 get_locale_list,
1750 &json));
1751 scoped_ptr<base::Value> value_ptr = base::JSONReader::Read(json);
1752 const base::ListValue* locales = NULL;
1753 ASSERT_TRUE(value_ptr);
1754 ASSERT_TRUE(value_ptr->GetAsList(&locales));
1755 EXPECT_LT(arraysize(kRecommendedLocales1), locales->GetSize());
1757 // Verify that the list starts with the recommended locales, in correct order.
1758 for (size_t i = 0; i < arraysize(kRecommendedLocales1); ++i) {
1759 std::string locale;
1760 EXPECT_TRUE(locales->GetString(i, &locale));
1761 EXPECT_EQ(kRecommendedLocales1[i], locale);
1764 // Verify that the recommended locales do not appear again in the remainder of
1765 // the list.
1766 std::set<std::string> recommended_locales;
1767 for (size_t i = 0; i < arraysize(kRecommendedLocales1); ++i)
1768 recommended_locales.insert(kRecommendedLocales1[i]);
1769 for (size_t i = arraysize(kRecommendedLocales1); i < locales->GetSize();
1770 ++i) {
1771 std::string locale;
1772 EXPECT_TRUE(locales->GetString(i, &locale));
1773 EXPECT_EQ(recommended_locales.end(), recommended_locales.find(locale));
1776 // Verify that the first recommended locale is selected.
1777 const std::string get_selected_locale =
1778 base::StringPrintf(
1779 "domAutomationController.send(document.getElementById('pod-row')"
1780 " .getPodWithUsername_('%s').querySelector('.language-select')"
1781 " .value);",
1782 user_id_1_.c_str());
1783 std::string selected_locale;
1784 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
1785 get_selected_locale,
1786 &selected_locale));
1787 EXPECT_EQ(kRecommendedLocales1[0], selected_locale);
1789 // Change the list of recommended locales.
1790 SetRecommendedLocales(kRecommendedLocales2, arraysize(kRecommendedLocales2));
1792 // Also change the display name as it is easy to ensure that policy has been
1793 // updated by waiting for a display name change.
1794 device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
1795 kDisplayName2);
1796 UploadAndInstallDeviceLocalAccountPolicy();
1797 policy::BrowserPolicyConnectorChromeOS* connector =
1798 g_browser_process->platform_part()->browser_policy_connector_chromeos();
1799 DeviceLocalAccountPolicyBroker* broker =
1800 connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
1801 user_id_1_);
1802 ASSERT_TRUE(broker);
1803 broker->core()->store()->Load();
1804 WaitForDisplayName(user_id_1_, kDisplayName2);
1806 // Verify that the new list of locales is shown in the UI.
1807 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
1808 get_locale_list,
1809 &json));
1810 value_ptr.reset(base::JSONReader::DeprecatedRead(json));
1811 locales = NULL;
1812 ASSERT_TRUE(value_ptr);
1813 ASSERT_TRUE(value_ptr->GetAsList(&locales));
1814 EXPECT_LT(arraysize(kRecommendedLocales2), locales->GetSize());
1815 for (size_t i = 0; i < arraysize(kRecommendedLocales2); ++i) {
1816 std::string locale;
1817 EXPECT_TRUE(locales->GetString(i, &locale));
1818 EXPECT_EQ(kRecommendedLocales2[i], locale);
1821 // Verify that the first new recommended locale is selected.
1822 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
1823 get_selected_locale,
1824 &selected_locale));
1825 EXPECT_EQ(kRecommendedLocales2[0], selected_locale);
1827 // Manually select a different locale.
1828 ASSERT_TRUE(content::ExecuteScript(
1829 contents_,
1830 base::StringPrintf(
1831 "var languageSelect = document.getElementById('pod-row')"
1832 " .getPodWithUsername_('%s').querySelector('.language-select');"
1833 "languageSelect.value = '%s';"
1834 "var event = document.createEvent('HTMLEvents');"
1835 "event.initEvent('change', false, true);"
1836 "languageSelect.dispatchEvent(event);",
1837 user_id_1_.c_str(),
1838 kPublicSessionLocale)));
1840 // Change the list of recommended locales.
1841 SetRecommendedLocales(kRecommendedLocales2, arraysize(kRecommendedLocales2));
1842 device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
1843 kDisplayName1);
1844 UploadAndInstallDeviceLocalAccountPolicy();
1845 broker->core()->store()->Load();
1846 WaitForDisplayName(user_id_1_, kDisplayName1);
1848 // Verify that the manually selected locale is still selected.
1849 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
1850 get_selected_locale,
1851 &selected_locale));
1852 EXPECT_EQ(kPublicSessionLocale, selected_locale);
1854 // The UI will request an updated list of keyboard layouts at this point. Wait
1855 // for the constructions of this list to finish.
1856 WaitForGetKeyboardLayoutsForLocaleToFinish();
1858 // Manually select a different keyboard layout.
1859 ASSERT_TRUE(content::ExecuteScript(
1860 contents_,
1861 base::StringPrintf(
1862 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1863 " .querySelector('.keyboard-select').value = '%s';",
1864 user_id_1_.c_str(),
1865 public_session_input_method_id_.c_str())));
1867 // Click on a different pod, causing focus to shift away and the pod to
1868 // contract.
1869 ASSERT_TRUE(content::ExecuteScript(
1870 contents_,
1871 base::StringPrintf(
1872 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1873 " .click();",
1874 user_id_2_.c_str())));
1876 // Click on the pod again, causing it to expand again. Verify that the pod has
1877 // kept all its state (the advanced form is being shown, the manually selected
1878 // locale and keyboard layout are selected).
1879 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1880 contents_,
1881 base::StringPrintf(
1882 "var pod ="
1883 " document.getElementById('pod-row').getPodWithUsername_('%s');"
1884 "pod.click();"
1885 "var state = {};"
1886 "state.advanced = pod.classList.contains('advanced');"
1887 "state.locale = pod.querySelector('.language-select').value;"
1888 "state.keyboardLayout = pod.querySelector('.keyboard-select').value;"
1889 "console.log(JSON.stringify(state));"
1890 "domAutomationController.send(JSON.stringify(state));",
1891 user_id_1_.c_str()),
1892 &json));
1893 LOG(ERROR) << json;
1894 value_ptr.reset(base::JSONReader::DeprecatedRead(json));
1895 const base::DictionaryValue* state = NULL;
1896 ASSERT_TRUE(value_ptr);
1897 ASSERT_TRUE(value_ptr->GetAsDictionary(&state));
1898 bool advanced = false;
1899 EXPECT_TRUE(state->GetBoolean("advanced", &advanced));
1900 EXPECT_TRUE(advanced);
1901 EXPECT_TRUE(state->GetString("locale", &selected_locale));
1902 EXPECT_EQ(kPublicSessionLocale, selected_locale);
1903 std::string selected_keyboard_layout;
1904 EXPECT_TRUE(state->GetString("keyboardLayout", &selected_keyboard_layout));
1905 EXPECT_EQ(public_session_input_method_id_, selected_keyboard_layout);
1907 // Click the enter button to start the session.
1908 ASSERT_TRUE(content::ExecuteScript(
1909 contents_,
1910 base::StringPrintf(
1911 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1912 " .querySelector('.enter-button').click();",
1913 user_id_1_.c_str())));
1915 WaitForSessionStart();
1917 // Verify that the locale and keyboard layout have been applied.
1918 EXPECT_EQ(kPublicSessionLocale, g_browser_process->GetApplicationLocale());
1919 EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale),
1920 icu::Locale::getDefault().getLanguage());
1921 EXPECT_EQ(public_session_input_method_id_,
1922 chromeos::input_method::InputMethodManager::Get()
1923 ->GetActiveIMEState()
1924 ->GetCurrentInputMethod()
1925 .id());
1928 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, InvalidRecommendedLocale) {
1929 // Specify an invalid recommended locale.
1930 SetRecommendedLocales(kInvalidRecommendedLocale,
1931 arraysize(kInvalidRecommendedLocale));
1932 UploadAndInstallDeviceLocalAccountPolicy();
1933 AddPublicSessionToDevicePolicy(kAccountId1);
1935 WaitForPolicy();
1937 // Click on the pod to expand it. Verify that the pod expands to its basic
1938 // form as there is only one recommended locale.
1939 bool advanced = false;
1940 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
1941 contents_,
1942 base::StringPrintf(
1943 "var pod ="
1944 " document.getElementById('pod-row').getPodWithUsername_('%s');"
1945 "pod.click();"
1946 "domAutomationController.send(pod.classList.contains('advanced'));",
1947 user_id_1_.c_str()),
1948 &advanced));
1949 EXPECT_FALSE(advanced);
1950 EXPECT_EQ(l10n_util::GetLanguage(initial_locale_),
1951 icu::Locale::getDefault().getLanguage());
1953 // Click the enter button to start the session.
1954 ASSERT_TRUE(content::ExecuteScript(
1955 contents_,
1956 base::StringPrintf(
1957 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1958 " .querySelector('.enter-button').click();",
1959 user_id_1_.c_str())));
1961 WaitForSessionStart();
1963 // Verify that since the recommended locale was invalid, the locale has not
1964 // changed and the first keyboard layout applicable to the locale was chosen.
1965 EXPECT_EQ(initial_locale_, g_browser_process->GetApplicationLocale());
1966 EXPECT_EQ(l10n_util::GetLanguage(initial_locale_),
1967 icu::Locale::getDefault().getLanguage());
1968 VerifyKeyboardLayoutMatchesLocale();
1971 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LocaleWithIME) {
1972 // Specify a locale that has real IMEs in addition to a keyboard layout one.
1973 const char* const kSingleLocaleWithIME[] = {"ja"};
1974 RunWithRecommendedLocale(kSingleLocaleWithIME,
1975 arraysize(kSingleLocaleWithIME));
1977 EXPECT_GT(chromeos::input_method::InputMethodManager::Get()
1978 ->GetActiveIMEState()
1979 ->GetNumActiveInputMethods(),
1980 1u);
1983 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LocaleWithNoIME) {
1984 // Specify a locale that has only keyboard layout.
1985 const char* const kSingleLocaleWithNoIME[] = {"de"};
1986 RunWithRecommendedLocale(kSingleLocaleWithNoIME,
1987 arraysize(kSingleLocaleWithNoIME));
1989 EXPECT_EQ(1u, chromeos::input_method::InputMethodManager::Get()
1990 ->GetActiveIMEState()
1991 ->GetNumActiveInputMethods());
1994 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest,
1995 AutoLoginWithoutRecommendedLocales) {
1996 UploadAndInstallDeviceLocalAccountPolicy();
1997 AddPublicSessionToDevicePolicy(kAccountId1);
1998 EnableAutoLogin();
2000 WaitForPolicy();
2002 WaitForSessionStart();
2004 // Verify that the locale has not changed and the first keyboard layout
2005 // applicable to the locale was chosen.
2006 EXPECT_EQ(initial_locale_, g_browser_process->GetApplicationLocale());
2007 EXPECT_EQ(initial_language_, icu::Locale::getDefault().getLanguage());
2008 VerifyKeyboardLayoutMatchesLocale();
2011 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest,
2012 AutoLoginWithRecommendedLocales) {
2013 // Specify recommended locales.
2014 SetRecommendedLocales(kRecommendedLocales1, arraysize(kRecommendedLocales1));
2015 UploadAndInstallDeviceLocalAccountPolicy();
2016 AddPublicSessionToDevicePolicy(kAccountId1);
2017 EnableAutoLogin();
2019 WaitForPolicy();
2021 WaitForSessionStart();
2023 // Verify that the first recommended locale has been applied and the first
2024 // keyboard layout applicable to the locale was chosen.
2025 EXPECT_EQ(kRecommendedLocales1[0], g_browser_process->GetApplicationLocale());
2026 EXPECT_EQ(l10n_util::GetLanguage(kRecommendedLocales1[0]),
2027 icu::Locale::getDefault().getLanguage());
2028 VerifyKeyboardLayoutMatchesLocale();
2031 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, TermsOfServiceWithLocaleSwitch) {
2032 // Specify Terms of Service URL.
2033 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
2034 device_local_account_policy_.payload().mutable_termsofserviceurl()->set_value(
2035 embedded_test_server()->GetURL(
2036 std::string("/") + kExistentTermsOfServicePath).spec());
2037 UploadAndInstallDeviceLocalAccountPolicy();
2038 AddPublicSessionToDevicePolicy(kAccountId1);
2040 WaitForPolicy();
2042 // Select a different locale.
2043 ASSERT_TRUE(content::ExecuteScript(
2044 contents_,
2045 base::StringPrintf(
2046 "var languageSelect = document.getElementById('pod-row')"
2047 " .getPodWithUsername_('%s').querySelector('.language-select');"
2048 "languageSelect.value = '%s';"
2049 "var event = document.createEvent('HTMLEvents');"
2050 "event.initEvent('change', false, true);"
2051 "languageSelect.dispatchEvent(event);",
2052 user_id_1_.c_str(),
2053 kPublicSessionLocale)));
2055 // The UI will have requested an updated list of keyboard layouts at this
2056 // point. Wait for the constructions of this list to finish.
2057 WaitForGetKeyboardLayoutsForLocaleToFinish();
2059 // Set up an observer that will quit the message loop when login has succeeded
2060 // and the first wizard screen, if any, is being shown.
2061 base::RunLoop login_wait_run_loop;
2062 chromeos::MockAuthStatusConsumer login_status_consumer;
2063 EXPECT_CALL(login_status_consumer, OnAuthSuccess(_)).Times(1).WillOnce(
2064 InvokeWithoutArgs(&login_wait_run_loop, &base::RunLoop::Quit));
2065 chromeos::ExistingUserController* controller =
2066 chromeos::ExistingUserController::current_controller();
2067 ASSERT_TRUE(controller);
2068 controller->set_login_status_consumer(&login_status_consumer);
2070 // Manually select a different keyboard layout and click the enter button to
2071 // start the session.
2072 ASSERT_TRUE(content::ExecuteScript(
2073 contents_,
2074 base::StringPrintf(
2075 "var pod ="
2076 " document.getElementById('pod-row').getPodWithUsername_('%s');"
2077 "pod.querySelector('.keyboard-select').value = '%s';"
2078 "pod.querySelector('.enter-button').click();",
2079 user_id_1_.c_str(),
2080 public_session_input_method_id_.c_str())));
2082 // Spin the loop until the login observer fires. Then, unregister the
2083 // observer.
2084 login_wait_run_loop.Run();
2085 controller->set_login_status_consumer(NULL);
2087 // Verify that the Terms of Service screen is being shown.
2088 chromeos::WizardController* wizard_controller =
2089 chromeos::WizardController::default_controller();
2090 ASSERT_TRUE(wizard_controller);
2091 ASSERT_TRUE(wizard_controller->current_screen());
2092 EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName,
2093 wizard_controller->current_screen()->GetName());
2095 // Wait for the Terms of Service to finish downloading.
2096 bool done = false;
2097 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(contents_,
2098 "var screenElement = document.getElementById('terms-of-service');"
2099 "function SendReplyIfDownloadDone() {"
2100 " if (screenElement.classList.contains('tos-loading'))"
2101 " return false;"
2102 " domAutomationController.send(true);"
2103 " observer.disconnect();"
2104 " return true;"
2106 "var observer = new MutationObserver(SendReplyIfDownloadDone);"
2107 "if (!SendReplyIfDownloadDone()) {"
2108 " var options = { attributes: true, attributeFilter: [ 'class' ] };"
2109 " observer.observe(screenElement, options);"
2110 "}",
2111 &done));
2113 // Verify that the locale and keyboard layout have been applied.
2114 EXPECT_EQ(kPublicSessionLocale, g_browser_process->GetApplicationLocale());
2115 EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale),
2116 icu::Locale::getDefault().getLanguage());
2117 EXPECT_EQ(public_session_input_method_id_,
2118 chromeos::input_method::InputMethodManager::Get()
2119 ->GetActiveIMEState()
2120 ->GetCurrentInputMethod()
2121 .id());
2123 // Wait for 'tos-accept-button' to become enabled.
2124 done = false;
2125 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
2126 contents_,
2127 "var screenElement = document.getElementById('tos-accept-button');"
2128 "function SendReplyIfAcceptEnabled() {"
2129 " if ($('tos-accept-button').disabled)"
2130 " return false;"
2131 " domAutomationController.send(true);"
2132 " observer.disconnect();"
2133 " return true;"
2135 "var observer = new MutationObserver(SendReplyIfAcceptEnabled);"
2136 "if (!SendReplyIfAcceptEnabled()) {"
2137 " var options = { attributes: true };"
2138 " observer.observe(screenElement, options);"
2139 "}",
2140 &done));
2142 // Click the accept button.
2143 ASSERT_TRUE(content::ExecuteScript(contents_,
2144 "$('tos-accept-button').click();"));
2146 WaitForSessionStart();
2148 // Verify that the locale and keyboard layout are still in force.
2149 EXPECT_EQ(kPublicSessionLocale, g_browser_process->GetApplicationLocale());
2150 EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale),
2151 icu::Locale::getDefault().getLanguage());
2152 EXPECT_EQ(public_session_input_method_id_,
2153 chromeos::input_method::InputMethodManager::Get()
2154 ->GetActiveIMEState()
2155 ->GetCurrentInputMethod()
2156 .id());
2159 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyForExtensions) {
2160 // Set up a test update server for the Show Managed Storage app.
2161 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
2162 scoped_refptr<TestingUpdateManifestProvider> testing_update_manifest_provider(
2163 new TestingUpdateManifestProvider(kRelativeUpdateURL));
2164 testing_update_manifest_provider->AddUpdate(
2165 kShowManagedStorageID, kShowManagedStorageVersion,
2166 embedded_test_server()->GetURL(std::string("/") +
2167 kShowManagedStorageCRXPath));
2168 embedded_test_server()->RegisterRequestHandler(
2169 base::Bind(&TestingUpdateManifestProvider::HandleRequest,
2170 testing_update_manifest_provider));
2172 // Force-install the Show Managed Storage app. This app can be installed in
2173 // public sessions because it's whitelisted for testing purposes.
2174 em::StringList* forcelist = device_local_account_policy_.payload()
2175 .mutable_extensioninstallforcelist()->mutable_value();
2176 forcelist->add_entries(base::StringPrintf(
2177 "%s;%s",
2178 kShowManagedStorageID,
2179 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
2181 // Set a policy for the app at the policy testserver.
2182 // Note that the policy for the device-local account will be fetched before
2183 // the session is started, so the policy for the app must be installed before
2184 // the first device policy fetch.
2185 ASSERT_TRUE(test_server_.UpdatePolicyData(
2186 dm_protocol::kChromeExtensionPolicyType, kShowManagedStorageID,
2188 " \"string\": {"
2189 " \"Value\": \"policy test value one\""
2190 " }"
2191 "}"));
2193 // Install and refresh the device policy now. This will also fetch the initial
2194 // user policy for the device-local account now.
2195 UploadAndInstallDeviceLocalAccountPolicy();
2196 AddPublicSessionToDevicePolicy(kAccountId1);
2197 WaitForPolicy();
2199 // Observe the app installation after login.
2200 content::WindowedNotificationObserver extension_observer(
2201 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
2202 base::Bind(DoesInstallSuccessReferToId, kShowManagedStorageID));
2203 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
2204 WaitForSessionStart();
2205 extension_observer.Wait();
2207 // Verify that the app was installed.
2208 Profile* profile = GetProfileForTest();
2209 ASSERT_TRUE(profile);
2210 ExtensionService* extension_service =
2211 extensions::ExtensionSystem::Get(profile)->extension_service();
2212 EXPECT_TRUE(extension_service->GetExtensionById(kShowManagedStorageID, true));
2214 // Wait for the app policy if it hasn't been fetched yet.
2215 ProfilePolicyConnector* connector =
2216 ProfilePolicyConnectorFactory::GetForBrowserContext(profile);
2217 ASSERT_TRUE(connector);
2218 PolicyService* policy_service = connector->policy_service();
2219 ASSERT_TRUE(policy_service);
2220 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, kShowManagedStorageID);
2221 if (policy_service->GetPolicies(ns).empty()) {
2222 PolicyChangeRegistrar policy_registrar(policy_service, ns);
2223 base::RunLoop run_loop;
2224 policy_registrar.Observe(
2225 "string", base::Bind(&PolicyChangedCallback, run_loop.QuitClosure()));
2226 run_loop.Run();
2229 // Verify that the app policy was set.
2230 base::StringValue expected_value("policy test value one");
2231 EXPECT_TRUE(base::Value::Equals(
2232 &expected_value,
2233 policy_service->GetPolicies(ns).GetValue("string")));
2235 // Now update the policy at the server.
2236 ASSERT_TRUE(test_server_.UpdatePolicyData(
2237 dm_protocol::kChromeExtensionPolicyType, kShowManagedStorageID,
2239 " \"string\": {"
2240 " \"Value\": \"policy test value two\""
2241 " }"
2242 "}"));
2244 // And issue a policy refresh.
2246 PolicyChangeRegistrar policy_registrar(policy_service, ns);
2247 base::RunLoop run_loop;
2248 policy_registrar.Observe(
2249 "string", base::Bind(&PolicyChangedCallback, run_loop.QuitClosure()));
2250 policy_service->RefreshPolicies(base::Closure());
2251 run_loop.Run();
2254 // Verify that the app policy was updated.
2255 base::StringValue expected_new_value("policy test value two");
2256 EXPECT_TRUE(base::Value::Equals(
2257 &expected_new_value,
2258 policy_service->GetPolicies(ns).GetValue("string")));
2261 class TermsOfServiceDownloadTest : public DeviceLocalAccountTest,
2262 public testing::WithParamInterface<bool> {
2265 IN_PROC_BROWSER_TEST_P(TermsOfServiceDownloadTest, TermsOfServiceScreen) {
2266 // Specify Terms of Service URL.
2267 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
2268 device_local_account_policy_.payload().mutable_termsofserviceurl()->set_value(
2269 embedded_test_server()->GetURL(
2270 std::string("/") +
2271 (GetParam() ? kExistentTermsOfServicePath
2272 : kNonexistentTermsOfServicePath)).spec());
2273 UploadAndInstallDeviceLocalAccountPolicy();
2274 AddPublicSessionToDevicePolicy(kAccountId1);
2276 WaitForPolicy();
2278 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
2280 // Set up an observer that will quit the message loop when login has succeeded
2281 // and the first wizard screen, if any, is being shown.
2282 base::RunLoop login_wait_run_loop;
2283 chromeos::MockAuthStatusConsumer login_status_consumer;
2284 EXPECT_CALL(login_status_consumer, OnAuthSuccess(_)).Times(1).WillOnce(
2285 InvokeWithoutArgs(&login_wait_run_loop, &base::RunLoop::Quit));
2287 // Spin the loop until the observer fires. Then, unregister the observer.
2288 chromeos::ExistingUserController* controller =
2289 chromeos::ExistingUserController::current_controller();
2290 ASSERT_TRUE(controller);
2291 controller->set_login_status_consumer(&login_status_consumer);
2292 login_wait_run_loop.Run();
2293 controller->set_login_status_consumer(NULL);
2295 // Verify that the Terms of Service screen is being shown.
2296 chromeos::WizardController* wizard_controller =
2297 chromeos::WizardController::default_controller();
2298 ASSERT_TRUE(wizard_controller);
2299 ASSERT_TRUE(wizard_controller->current_screen());
2300 EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName,
2301 wizard_controller->current_screen()->GetName());
2303 // Wait for the Terms of Service to finish downloading, then get the status of
2304 // the screen's UI elements.
2305 std::string json;
2306 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
2307 "var screenElement = document.getElementById('terms-of-service');"
2308 "function SendReplyIfDownloadDone() {"
2309 " if (screenElement.classList.contains('tos-loading'))"
2310 " return false;"
2311 " var status = {};"
2312 " status.heading = document.getElementById('tos-heading').textContent;"
2313 " status.subheading ="
2314 " document.getElementById('tos-subheading').textContent;"
2315 " status.contentHeading ="
2316 " document.getElementById('tos-content-heading').textContent;"
2317 " status.content ="
2318 " document.getElementById('tos-content-main').textContent;"
2319 " status.error = screenElement.classList.contains('error');"
2320 " status.acceptEnabled ="
2321 " !document.getElementById('tos-accept-button').disabled;"
2322 " domAutomationController.send(JSON.stringify(status));"
2323 " observer.disconnect();"
2324 " return true;"
2326 "var observer = new MutationObserver(SendReplyIfDownloadDone);"
2327 "if (!SendReplyIfDownloadDone()) {"
2328 " var options = { attributes: true, attributeFilter: [ 'class' ] };"
2329 " observer.observe(screenElement, options);"
2330 "}",
2331 &json));
2332 scoped_ptr<base::Value> value_ptr = base::JSONReader::Read(json);
2333 const base::DictionaryValue* status = NULL;
2334 ASSERT_TRUE(value_ptr);
2335 ASSERT_TRUE(value_ptr->GetAsDictionary(&status));
2336 std::string heading;
2337 EXPECT_TRUE(status->GetString("heading", &heading));
2338 std::string subheading;
2339 EXPECT_TRUE(status->GetString("subheading", &subheading));
2340 std::string content_heading;
2341 EXPECT_TRUE(status->GetString("contentHeading", &content_heading));
2342 std::string content;
2343 EXPECT_TRUE(status->GetString("content", &content));
2344 bool error;
2345 EXPECT_TRUE(status->GetBoolean("error", &error));
2346 bool accept_enabled;
2347 EXPECT_TRUE(status->GetBoolean("acceptEnabled", &accept_enabled));
2349 // Verify that the screen's headings have been set correctly.
2350 EXPECT_EQ(
2351 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_HEADING,
2352 base::UTF8ToUTF16(kDomain)),
2353 heading);
2354 EXPECT_EQ(
2355 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_SUBHEADING,
2356 base::UTF8ToUTF16(kDomain)),
2357 subheading);
2358 EXPECT_EQ(
2359 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_CONTENT_HEADING,
2360 base::UTF8ToUTF16(kDomain)),
2361 content_heading);
2363 if (!GetParam()) {
2364 // The Terms of Service URL was invalid. Verify that the screen is showing
2365 // an error and the accept button is disabled.
2366 EXPECT_TRUE(error);
2367 EXPECT_FALSE(accept_enabled);
2368 return;
2371 // The Terms of Service URL was valid. Verify that the screen is showing the
2372 // downloaded Terms of Service and the accept button is enabled.
2373 base::FilePath test_dir;
2374 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
2375 std::string terms_of_service;
2376 ASSERT_TRUE(base::ReadFileToString(
2377 test_dir.Append(kExistentTermsOfServicePath), &terms_of_service));
2378 EXPECT_EQ(terms_of_service, content);
2379 EXPECT_FALSE(error);
2380 EXPECT_TRUE(accept_enabled);
2382 // Click the accept button.
2383 ASSERT_TRUE(content::ExecuteScript(contents_,
2384 "$('tos-accept-button').click();"));
2386 WaitForSessionStart();
2389 INSTANTIATE_TEST_CASE_P(TermsOfServiceDownloadTestInstance,
2390 TermsOfServiceDownloadTest, testing::Bool());
2392 } // namespace policy