ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / chrome / browser / chromeos / policy / device_local_account_browsertest.cc
blob9dce9b60ce2f686847890bdc4c2d43ca8735e853
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/message_loop/message_loop_proxy.h"
28 #include "base/path_service.h"
29 #include "base/prefs/pref_change_registrar.h"
30 #include "base/prefs/pref_service.h"
31 #include "base/run_loop.h"
32 #include "base/sequenced_task_runner.h"
33 #include "base/strings/string_number_conversions.h"
34 #include "base/strings/string_util.h"
35 #include "base/strings/stringprintf.h"
36 #include "base/strings/utf_string_conversions.h"
37 #include "base/threading/sequenced_worker_pool.h"
38 #include "base/values.h"
39 #include "chrome/browser/browser_process.h"
40 #include "chrome/browser/chrome_notification_types.h"
41 #include "chrome/browser/chromeos/extensions/device_local_account_external_policy_loader.h"
42 #include "chrome/browser/chromeos/extensions/external_cache.h"
43 #include "chrome/browser/chromeos/input_method/input_method_util.h"
44 #include "chrome/browser/chromeos/login/existing_user_controller.h"
45 #include "chrome/browser/chromeos/login/screens/base_screen.h"
46 #include "chrome/browser/chromeos/login/signin_specifics.h"
47 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
48 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
49 #include "chrome/browser/chromeos/login/ui/webui_login_view.h"
50 #include "chrome/browser/chromeos/login/users/avatar/user_image_manager.h"
51 #include "chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.h"
52 #include "chrome/browser/chromeos/login/users/avatar/user_image_manager_test_util.h"
53 #include "chrome/browser/chromeos/login/users/chrome_user_manager_impl.h"
54 #include "chrome/browser/chromeos/login/wizard_controller.h"
55 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
56 #include "chrome/browser/chromeos/policy/cloud_external_data_manager_base_test_util.h"
57 #include "chrome/browser/chromeos/policy/device_local_account.h"
58 #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
59 #include "chrome/browser/chromeos/policy/device_policy_builder.h"
60 #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
61 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
62 #include "chrome/browser/extensions/crx_installer.h"
63 #include "chrome/browser/extensions/extension_service.h"
64 #include "chrome/browser/extensions/updater/extension_cache_impl.h"
65 #include "chrome/browser/extensions/updater/local_extension_cache.h"
66 #include "chrome/browser/lifetime/application_lifetime.h"
67 #include "chrome/browser/policy/profile_policy_connector.h"
68 #include "chrome/browser/policy/profile_policy_connector_factory.h"
69 #include "chrome/browser/policy/test/local_policy_test_server.h"
70 #include "chrome/browser/prefs/session_startup_pref.h"
71 #include "chrome/browser/profiles/profile.h"
72 #include "chrome/browser/profiles/profile_manager.h"
73 #include "chrome/browser/signin/signin_manager_factory.h"
74 #include "chrome/browser/ui/browser.h"
75 #include "chrome/browser/ui/browser_commands.h"
76 #include "chrome/browser/ui/browser_finder.h"
77 #include "chrome/browser/ui/browser_list.h"
78 #include "chrome/browser/ui/browser_list_observer.h"
79 #include "chrome/browser/ui/browser_window.h"
80 #include "chrome/browser/ui/extensions/app_launch_params.h"
81 #include "chrome/browser/ui/extensions/application_launch.h"
82 #include "chrome/browser/ui/host_desktop.h"
83 #include "chrome/browser/ui/tabs/tab_strip_model.h"
84 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
85 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
86 #include "chrome/common/chrome_paths.h"
87 #include "chrome/common/extensions/extension_constants.h"
88 #include "chrome/grit/chromium_strings.h"
89 #include "chrome/grit/generated_resources.h"
90 #include "chromeos/chromeos_paths.h"
91 #include "chromeos/chromeos_switches.h"
92 #include "chromeos/dbus/fake_session_manager_client.h"
93 #include "chromeos/login/auth/mock_auth_status_consumer.h"
94 #include "chromeos/login/auth/user_context.h"
95 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
96 #include "components/policy/core/common/cloud/cloud_policy_core.h"
97 #include "components/policy/core/common/cloud/cloud_policy_store.h"
98 #include "components/policy/core/common/cloud/policy_builder.h"
99 #include "components/policy/core/common/external_data_fetcher.h"
100 #include "components/policy/core/common/policy_map.h"
101 #include "components/policy/core/common/policy_namespace.h"
102 #include "components/policy/core/common/policy_service.h"
103 #include "components/policy/core/common/policy_switches.h"
104 #include "components/signin/core/browser/signin_manager.h"
105 #include "components/user_manager/user.h"
106 #include "components/user_manager/user_manager.h"
107 #include "components/user_manager/user_type.h"
108 #include "content/public/browser/browser_thread.h"
109 #include "content/public/browser/notification_details.h"
110 #include "content/public/browser/notification_service.h"
111 #include "content/public/browser/notification_source.h"
112 #include "content/public/browser/web_contents.h"
113 #include "content/public/browser/web_ui.h"
114 #include "content/public/test/browser_test_utils.h"
115 #include "content/public/test/test_utils.h"
116 #include "crypto/rsa_private_key.h"
117 #include "extensions/browser/app_window/app_window.h"
118 #include "extensions/browser/app_window/app_window_registry.h"
119 #include "extensions/browser/app_window/native_app_window.h"
120 #include "extensions/browser/extension_system.h"
121 #include "extensions/browser/install/crx_install_error.h"
122 #include "extensions/browser/management_policy.h"
123 #include "extensions/browser/notification_types.h"
124 #include "extensions/common/constants.h"
125 #include "extensions/common/extension.h"
126 #include "net/base/url_util.h"
127 #include "net/http/http_status_code.h"
128 #include "net/test/embedded_test_server/embedded_test_server.h"
129 #include "net/test/embedded_test_server/http_request.h"
130 #include "net/test/embedded_test_server/http_response.h"
131 #include "net/url_request/test_url_fetcher_factory.h"
132 #include "net/url_request/url_fetcher_delegate.h"
133 #include "net/url_request/url_request_status.h"
134 #include "policy/policy_constants.h"
135 #include "testing/gmock/include/gmock/gmock.h"
136 #include "third_party/icu/source/common/unicode/locid.h"
137 #include "ui/base/ime/chromeos/extension_ime_util.h"
138 #include "ui/base/ime/chromeos/input_method_descriptor.h"
139 #include "ui/base/ime/chromeos/input_method_manager.h"
140 #include "ui/base/l10n/l10n_util.h"
141 #include "ui/base/window_open_disposition.h"
142 #include "ui/gfx/image/image_skia.h"
143 #include "ui/views/widget/widget.h"
144 #include "url/gurl.h"
146 namespace em = enterprise_management;
148 using chromeos::LoginScreenContext;
149 using testing::InvokeWithoutArgs;
150 using testing::Return;
151 using testing::_;
153 namespace policy {
155 namespace {
157 const char kDomain[] = "example.com";
158 const char kAccountId1[] = "dla1@example.com";
159 const char kAccountId2[] = "dla2@example.com";
160 const char kDisplayName1[] = "display name 1";
161 const char kDisplayName2[] = "display name 2";
162 const char* const kStartupURLs[] = {
163 "chrome://policy",
164 "chrome://about",
166 const char kExistentTermsOfServicePath[] = "chromeos/enterprise/tos.txt";
167 const char kNonexistentTermsOfServicePath[] = "chromeos/enterprise/tos404.txt";
168 const char kRelativeUpdateURL[] = "/service/update2/crx";
169 const char kUpdateManifestHeader[] =
170 "<?xml version='1.0' encoding='UTF-8'?>\n"
171 "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>\n";
172 const char kUpdateManifestTemplate[] =
173 " <app appid='%s'>\n"
174 " <updatecheck codebase='%s' version='%s' />\n"
175 " </app>\n";
176 const char kUpdateManifestFooter[] =
177 "</gupdate>\n";
178 const char kHostedAppID[] = "kbmnembihfiondgfjekmnmcbddelicoi";
179 const char kHostedAppCRXPath[] = "extensions/hosted_app.crx";
180 const char kHostedAppVersion[] = "1.0.0.0";
181 const char kGoodExtensionID[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
182 const char kGoodExtensionCRXPath[] = "extensions/good.crx";
183 const char kGoodExtensionVersion[] = "1.0";
184 const char kPackagedAppCRXPath[] = "extensions/platform_apps/app_window_2.crx";
185 const char kShowManagedStorageID[] = "ongnjlefhnoajpbodoldndkbkdgfomlp";
186 const char kShowManagedStorageCRXPath[] = "extensions/show_managed_storage.crx";
187 const char kShowManagedStorageVersion[] = "1.0";
189 const char kExternalData[] = "External data";
190 const char kExternalDataURL[] = "http://localhost/external_data";
192 const char* const kSingleRecommendedLocale[] = {
193 "el",
195 const char* const kRecommendedLocales1[] = {
196 "pl",
197 "et",
198 "en-US",
200 const char* const kRecommendedLocales2[] = {
201 "fr",
202 "nl",
204 const char* const kInvalidRecommendedLocale[] = {
205 "xx",
207 const char kPublicSessionLocale[] = "de";
208 const char kPublicSessionInputMethodIDTemplate[] = "_comp_ime_%sxkb:de:neo:ger";
210 // The sequence token used by GetKeyboardLayoutsForLocale() for its background
211 // tasks.
212 const char kSequenceToken[] = "chromeos_login_l10n_util";
214 // Helper that serves extension update manifests to Chrome.
215 class TestingUpdateManifestProvider {
216 public:
217 // Update manifests will be served at |relative_update_url|.
218 explicit TestingUpdateManifestProvider(
219 const std::string& relative_update_url);
220 ~TestingUpdateManifestProvider();
222 // When an update manifest is requested for the given extension |id|, indicate
223 // that |version| of the extension can be downloaded at |crx_url|.
224 void AddUpdate(const std::string& id,
225 const std::string& version,
226 const GURL& crx_url);
228 // This method must be registered with the test's EmbeddedTestServer to start
229 // serving update manifests.
230 scoped_ptr<net::test_server::HttpResponse> HandleRequest(
231 const net::test_server::HttpRequest& request);
233 private:
234 struct Update {
235 public:
236 Update(const std::string& version, const GURL& crx_url);
237 Update();
239 std::string version;
240 GURL crx_url;
242 typedef std::map<std::string, Update> UpdateMap;
243 UpdateMap updates_;
245 const std::string relative_update_url_;
247 DISALLOW_COPY_AND_ASSIGN(TestingUpdateManifestProvider);
250 // Helper that observes the dictionary |pref| in local state and waits until the
251 // value stored for |key| matches |expected_value|.
252 class DictionaryPrefValueWaiter {
253 public:
254 DictionaryPrefValueWaiter(const std::string& pref,
255 const std::string& key,
256 const std::string& expected_value);
257 ~DictionaryPrefValueWaiter();
259 void Wait();
261 private:
262 void QuitLoopIfExpectedValueFound();
264 const std::string pref_;
265 const std::string key_;
266 const std::string expected_value_;
268 base::RunLoop run_loop_;
269 PrefChangeRegistrar pref_change_registrar_;
271 DISALLOW_COPY_AND_ASSIGN(DictionaryPrefValueWaiter);
274 TestingUpdateManifestProvider::Update::Update(const std::string& version,
275 const GURL& crx_url)
276 : version(version),
277 crx_url(crx_url) {
280 TestingUpdateManifestProvider::Update::Update() {
283 TestingUpdateManifestProvider::TestingUpdateManifestProvider(
284 const std::string& relative_update_url)
285 : relative_update_url_(relative_update_url) {
288 TestingUpdateManifestProvider::~TestingUpdateManifestProvider() {
291 void TestingUpdateManifestProvider::AddUpdate(const std::string& id,
292 const std::string& version,
293 const GURL& crx_url) {
294 updates_[id] = Update(version, crx_url);
297 scoped_ptr<net::test_server::HttpResponse>
298 TestingUpdateManifestProvider::HandleRequest(
299 const net::test_server::HttpRequest& request) {
300 const GURL url("http://localhost" + request.relative_url);
301 if (url.path() != relative_update_url_)
302 return scoped_ptr<net::test_server::HttpResponse>();
304 std::string content = kUpdateManifestHeader;
305 for (net::QueryIterator it(url); !it.IsAtEnd(); it.Advance()) {
306 if (it.GetKey() != "x")
307 continue;
308 // Extract the extension id from the subquery. Since GetValueForKeyInQuery()
309 // expects a complete URL, dummy scheme and host must be prepended.
310 std::string id;
311 net::GetValueForKeyInQuery(GURL("http://dummy?" + it.GetUnescapedValue()),
312 "id", &id);
313 UpdateMap::const_iterator entry = updates_.find(id);
314 if (entry != updates_.end()) {
315 content += base::StringPrintf(kUpdateManifestTemplate,
316 id.c_str(),
317 entry->second.crx_url.spec().c_str(),
318 entry->second.version.c_str());
321 content += kUpdateManifestFooter;
322 scoped_ptr<net::test_server::BasicHttpResponse>
323 http_response(new net::test_server::BasicHttpResponse);
324 http_response->set_code(net::HTTP_OK);
325 http_response->set_content(content);
326 http_response->set_content_type("text/xml");
327 return http_response.Pass();
330 DictionaryPrefValueWaiter::DictionaryPrefValueWaiter(
331 const std::string& pref,
332 const std::string& key,
333 const std::string& expected_value)
334 : pref_(pref),
335 key_(key),
336 expected_value_(expected_value) {
337 pref_change_registrar_.Init(g_browser_process->local_state());
340 DictionaryPrefValueWaiter::~DictionaryPrefValueWaiter() {
343 void DictionaryPrefValueWaiter::Wait() {
344 pref_change_registrar_.Add(
345 pref_.c_str(),
346 base::Bind(&DictionaryPrefValueWaiter::QuitLoopIfExpectedValueFound,
347 base::Unretained(this)));
348 QuitLoopIfExpectedValueFound();
349 run_loop_.Run();
352 void DictionaryPrefValueWaiter::QuitLoopIfExpectedValueFound() {
353 const base::DictionaryValue* pref =
354 pref_change_registrar_.prefs()->GetDictionary(pref_.c_str());
355 ASSERT_TRUE(pref);
356 std::string actual_value;
357 if (pref->GetStringWithoutPathExpansion(key_, &actual_value) &&
358 actual_value == expected_value_) {
359 run_loop_.Quit();
363 bool DoesInstallSuccessReferToId(const std::string& id,
364 const content::NotificationSource& source,
365 const content::NotificationDetails& details) {
366 return content::Details<const extensions::InstalledExtensionInfo>(details)->
367 extension->id() == id;
370 bool DoesInstallFailureReferToId(const std::string& id,
371 const content::NotificationSource& source,
372 const content::NotificationDetails& details) {
373 return content::Details<const extensions::CrxInstallError>(details)
374 ->message()
375 .find(base::UTF8ToUTF16(id)) != base::string16::npos;
378 scoped_ptr<net::FakeURLFetcher> RunCallbackAndReturnFakeURLFetcher(
379 scoped_refptr<base::SequencedTaskRunner> task_runner,
380 const base::Closure& callback,
381 const GURL& url,
382 net::URLFetcherDelegate* delegate,
383 const std::string& response_data,
384 net::HttpStatusCode response_code,
385 net::URLRequestStatus::Status status) {
386 task_runner->PostTask(FROM_HERE, callback);
387 return make_scoped_ptr(new net::FakeURLFetcher(
388 url, delegate, response_data, response_code, status));
391 bool IsSessionStarted() {
392 return user_manager::UserManager::Get()->IsSessionStarted();
395 void PolicyChangedCallback(const base::Closure& callback,
396 const base::Value* old_value,
397 const base::Value* new_value) {
398 callback.Run();
401 } // namespace
403 class DeviceLocalAccountTest : public DevicePolicyCrosBrowserTest,
404 public user_manager::UserManager::Observer,
405 public chrome::BrowserListObserver,
406 public extensions::AppWindowRegistry::Observer {
407 protected:
408 DeviceLocalAccountTest()
409 : user_id_1_(GenerateDeviceLocalAccountUserId(
410 kAccountId1, DeviceLocalAccount::TYPE_PUBLIC_SESSION)),
411 user_id_2_(GenerateDeviceLocalAccountUserId(
412 kAccountId2, DeviceLocalAccount::TYPE_PUBLIC_SESSION)),
413 public_session_input_method_id_(base::StringPrintf(
414 kPublicSessionInputMethodIDTemplate,
415 chromeos::extension_ime_util::kXkbExtensionId)),
416 contents_(NULL) {
417 set_exit_when_last_browser_closes(false);
420 ~DeviceLocalAccountTest() override {}
422 void SetUp() override {
423 // Configure and start the test server.
424 scoped_ptr<crypto::RSAPrivateKey> signing_key(
425 PolicyBuilder::CreateTestSigningKey());
426 ASSERT_TRUE(test_server_.SetSigningKeyAndSignature(
427 signing_key.get(), PolicyBuilder::GetTestSigningKeySignature()));
428 signing_key.reset();
429 test_server_.RegisterClient(PolicyBuilder::kFakeToken,
430 PolicyBuilder::kFakeDeviceId);
431 ASSERT_TRUE(test_server_.Start());
433 BrowserList::AddObserver(this);
435 DevicePolicyCrosBrowserTest::SetUp();
438 void SetUpCommandLine(base::CommandLine* command_line) override {
439 DevicePolicyCrosBrowserTest::SetUpCommandLine(command_line);
440 command_line->AppendSwitch(chromeos::switches::kLoginManager);
441 command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests);
442 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
443 command_line->AppendSwitchASCII(policy::switches::kDeviceManagementUrl,
444 test_server_.GetServiceURL().spec());
447 void SetUpInProcessBrowserTestFixture() override {
448 DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
450 // Clear command-line arguments (but keep command-line switches) so the
451 // startup pages policy takes effect.
452 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
453 base::CommandLine::StringVector argv(command_line->argv());
454 argv.erase(argv.begin() + argv.size() - command_line->GetArgs().size(),
455 argv.end());
456 command_line->InitFromArgv(argv);
458 InstallOwnerKey();
459 MarkAsEnterpriseOwned();
461 InitializePolicy();
464 void SetUpOnMainThread() override {
465 DevicePolicyCrosBrowserTest::SetUpOnMainThread();
467 initial_locale_ = g_browser_process->GetApplicationLocale();
468 initial_language_ = l10n_util::GetLanguage(initial_locale_);
470 content::WindowedNotificationObserver(
471 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
472 content::NotificationService::AllSources()).Wait();
474 chromeos::LoginDisplayHostImpl* host =
475 reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
476 chromeos::LoginDisplayHostImpl::default_host());
477 ASSERT_TRUE(host);
478 chromeos::WebUILoginView* web_ui_login_view = host->GetWebUILoginView();
479 ASSERT_TRUE(web_ui_login_view);
480 content::WebUI* web_ui = web_ui_login_view->GetWebUI();
481 ASSERT_TRUE(web_ui);
482 contents_ = web_ui->GetWebContents();
483 ASSERT_TRUE(contents_);
485 // Wait for the login UI to be ready.
486 chromeos::OobeUI* oobe_ui = host->GetOobeUI();
487 ASSERT_TRUE(oobe_ui);
488 base::RunLoop run_loop;
489 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure());
490 if (!oobe_ui_ready)
491 run_loop.Run();
493 // The network selection screen changes the application locale on load and
494 // once again on blur. Wait for the screen to load and blur it so that any
495 // locale changes caused by this screen happen now and do not affect any
496 // subsequent parts of the test.
497 bool done = false;
498 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
499 contents_,
500 "var languageSelect = document.getElementById('language-select');"
501 "var blurAndReportSuccess = function() {"
502 " languageSelect.blur();"
503 " domAutomationController.send(true);"
504 "};"
505 "var screenLoading = document.getElementById('outer-container')"
506 " .classList.contains('down');"
507 "if (document.activeElement == languageSelect || !screenLoading)"
508 " blurAndReportSuccess();"
509 "else"
510 " languageSelect.addEventListener('focus', blurAndReportSuccess);",
511 &done));
513 // Skip to the login screen.
514 chromeos::WizardController* wizard_controller =
515 chromeos::WizardController::default_controller();
516 ASSERT_TRUE(wizard_controller);
517 wizard_controller->SkipToLoginForTesting(LoginScreenContext());
520 void TearDownOnMainThread() override {
521 BrowserList::RemoveObserver(this);
523 // This shuts down the login UI.
524 base::MessageLoop::current()->PostTask(FROM_HERE,
525 base::Bind(&chrome::AttemptExit));
526 base::RunLoop().RunUntilIdle();
529 void LocalStateChanged(user_manager::UserManager* user_manager) override {
530 if (run_loop_)
531 run_loop_->Quit();
534 void OnBrowserRemoved(Browser* browser) override {
535 if (run_loop_)
536 run_loop_->Quit();
539 void OnAppWindowAdded(extensions::AppWindow* app_window) override {
540 if (run_loop_)
541 run_loop_->Quit();
544 void OnAppWindowRemoved(extensions::AppWindow* app_window) override {
545 if (run_loop_)
546 run_loop_->Quit();
549 void InitializePolicy() {
550 device_policy()->policy_data().set_public_key_version(1);
551 em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
552 proto.mutable_show_user_names()->set_show_user_names(true);
554 device_local_account_policy_.policy_data().set_policy_type(
555 dm_protocol::kChromePublicAccountPolicyType);
556 device_local_account_policy_.policy_data().set_username(kAccountId1);
557 device_local_account_policy_.policy_data().set_settings_entity_id(
558 kAccountId1);
559 device_local_account_policy_.policy_data().set_public_key_version(1);
560 device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
561 kDisplayName1);
564 void BuildDeviceLocalAccountPolicy() {
565 device_local_account_policy_.SetDefaultSigningKey();
566 device_local_account_policy_.Build();
569 void UploadDeviceLocalAccountPolicy() {
570 BuildDeviceLocalAccountPolicy();
571 ASSERT_TRUE(test_server_.UpdatePolicy(
572 dm_protocol::kChromePublicAccountPolicyType, kAccountId1,
573 device_local_account_policy_.payload().SerializeAsString()));
576 void UploadAndInstallDeviceLocalAccountPolicy() {
577 UploadDeviceLocalAccountPolicy();
578 session_manager_client()->set_device_local_account_policy(
579 kAccountId1, device_local_account_policy_.GetBlob());
582 void SetRecommendedLocales(const char* const recommended_locales[],
583 size_t array_size) {
584 em::StringListPolicyProto* session_locales_proto =
585 device_local_account_policy_.payload().mutable_sessionlocales();
586 session_locales_proto->mutable_policy_options()->set_mode(
587 em::PolicyOptions_PolicyMode_RECOMMENDED);
588 session_locales_proto->mutable_value()->Clear();
589 for (size_t i = 0; i < array_size; ++i) {
590 session_locales_proto->mutable_value()->add_entries(
591 recommended_locales[i]);
595 void AddPublicSessionToDevicePolicy(const std::string& username) {
596 em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
597 em::DeviceLocalAccountInfoProto* account =
598 proto.mutable_device_local_accounts()->add_account();
599 account->set_account_id(username);
600 account->set_type(
601 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
602 RefreshDevicePolicy();
603 ASSERT_TRUE(test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType,
604 std::string(),
605 proto.SerializeAsString()));
608 void EnableAutoLogin() {
609 em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
610 em::DeviceLocalAccountsProto* device_local_accounts =
611 proto.mutable_device_local_accounts();
612 device_local_accounts->set_auto_login_id(kAccountId1);
613 device_local_accounts->set_auto_login_delay(0);
614 RefreshDevicePolicy();
615 ASSERT_TRUE(test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType,
616 std::string(),
617 proto.SerializeAsString()));
620 void CheckPublicSessionPresent(const std::string& id) {
621 const user_manager::User* user =
622 user_manager::UserManager::Get()->FindUser(id);
623 ASSERT_TRUE(user);
624 EXPECT_EQ(id, user->email());
625 EXPECT_EQ(user_manager::USER_TYPE_PUBLIC_ACCOUNT, user->GetType());
628 base::FilePath GetExtensionCacheDirectoryForAccountID(
629 const std::string& account_id) {
630 base::FilePath extension_cache_root_dir;
631 if (!PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
632 &extension_cache_root_dir)) {
633 ADD_FAILURE();
635 return extension_cache_root_dir.Append(
636 base::HexEncode(account_id.c_str(), account_id.size()));
639 base::FilePath GetCacheCRXFilePath(const std::string& id,
640 const std::string& version,
641 const base::FilePath& path) {
642 return path.Append(
643 extensions::LocalExtensionCache::ExtensionFileName(id, version, ""));
646 base::FilePath GetCacheCRXFile(const std::string& account_id,
647 const std::string& id,
648 const std::string& version) {
649 return GetCacheCRXFilePath(
650 id, version, GetExtensionCacheDirectoryForAccountID(account_id));
653 // Returns a profile which can be used for testing.
654 Profile* GetProfileForTest() {
655 // Any profile can be used here since this test does not test multi profile.
656 return ProfileManager::GetActiveUserProfile();
659 void WaitForDisplayName(const std::string& user_id,
660 const std::string& expected_display_name) {
661 DictionaryPrefValueWaiter("UserDisplayName",
662 user_id,
663 expected_display_name).Wait();
666 void WaitForPolicy() {
667 // Wait for the display name becoming available as that indicates
668 // device-local account policy is fully loaded, which is a prerequisite for
669 // successful login.
670 WaitForDisplayName(user_id_1_, kDisplayName1);
673 void ExpandPublicSessionPod(bool expect_advanced) {
674 bool advanced = false;
675 // Click on the pod to expand it.
676 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
677 contents_,
678 base::StringPrintf(
679 "var pod ="
680 " document.getElementById('pod-row').getPodWithUsername_('%s');"
681 "pod.click();"
682 "domAutomationController.send(pod.classList.contains('advanced'));",
683 user_id_1_.c_str()),
684 &advanced));
685 // Verify that the pod expanded to its basic/advanced form, as expected.
686 EXPECT_EQ(expect_advanced, advanced);
688 // Verify that the construction of the pod's language list did not affect
689 // the current ICU locale.
690 EXPECT_EQ(initial_language_, icu::Locale::getDefault().getLanguage());
693 // GetKeyboardLayoutsForLocale() posts a task to a background task runner.
694 // This method flushes that task runner and the current thread's message loop
695 // to ensure that GetKeyboardLayoutsForLocale() is finished.
696 void WaitForGetKeyboardLayoutsForLocaleToFinish() {
697 base::SequencedWorkerPool* worker_pool =
698 content::BrowserThread::GetBlockingPool();
699 scoped_refptr<base::SequencedTaskRunner> background_task_runner =
700 worker_pool->GetSequencedTaskRunner(
701 worker_pool->GetNamedSequenceToken(kSequenceToken));
702 base::RunLoop run_loop;
703 background_task_runner->PostTaskAndReply(FROM_HERE,
704 base::Bind(&base::DoNothing),
705 run_loop.QuitClosure());
706 run_loop.Run();
707 base::RunLoop().RunUntilIdle();
709 // Verify that the construction of the keyboard layout list did not affect
710 // the current ICU locale.
711 EXPECT_EQ(initial_language_, icu::Locale::getDefault().getLanguage());
714 void StartLogin(const std::string& locale,
715 const std::string& input_method) {
716 // Start login into the device-local account.
717 chromeos::LoginDisplayHostImpl* host =
718 reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
719 chromeos::LoginDisplayHostImpl::default_host());
720 ASSERT_TRUE(host);
721 host->StartSignInScreen(LoginScreenContext());
722 chromeos::ExistingUserController* controller =
723 chromeos::ExistingUserController::current_controller();
724 ASSERT_TRUE(controller);
726 chromeos::UserContext user_context(user_manager::USER_TYPE_PUBLIC_ACCOUNT,
727 user_id_1_);
728 user_context.SetPublicSessionLocale(locale);
729 user_context.SetPublicSessionInputMethod(input_method);
730 controller->Login(user_context, chromeos::SigninSpecifics());
733 void WaitForSessionStart() {
734 if (IsSessionStarted())
735 return;
736 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED,
737 base::Bind(IsSessionStarted)).Wait();
740 void VerifyKeyboardLayoutMatchesLocale() {
741 chromeos::input_method::InputMethodManager* input_method_manager =
742 chromeos::input_method::InputMethodManager::Get();
743 std::vector<std::string> layouts_from_locale;
744 input_method_manager->GetInputMethodUtil()->
745 GetInputMethodIdsFromLanguageCode(
746 g_browser_process->GetApplicationLocale(),
747 chromeos::input_method::kKeyboardLayoutsOnly,
748 &layouts_from_locale);
749 ASSERT_FALSE(layouts_from_locale.empty());
750 EXPECT_EQ(layouts_from_locale.front(),
751 input_method_manager->GetActiveIMEState()
752 ->GetCurrentInputMethod()
753 .id());
756 const std::string user_id_1_;
757 const std::string user_id_2_;
758 const std::string public_session_input_method_id_;
760 std::string initial_locale_;
761 std::string initial_language_;
763 scoped_ptr<base::RunLoop> run_loop_;
765 UserPolicyBuilder device_local_account_policy_;
766 LocalPolicyTestServer test_server_;
768 content::WebContents* contents_;
770 private:
771 DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountTest);
774 static bool IsKnownUser(const std::string& account_id) {
775 return user_manager::UserManager::Get()->IsKnownUser(account_id);
778 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LoginScreen) {
779 AddPublicSessionToDevicePolicy(kAccountId1);
780 AddPublicSessionToDevicePolicy(kAccountId2);
782 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
783 base::Bind(&IsKnownUser, user_id_1_))
784 .Wait();
785 EXPECT_TRUE(IsKnownUser(user_id_2_));
787 CheckPublicSessionPresent(user_id_1_);
788 CheckPublicSessionPresent(user_id_2_);
791 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DisplayName) {
792 UploadAndInstallDeviceLocalAccountPolicy();
793 AddPublicSessionToDevicePolicy(kAccountId1);
795 WaitForPolicy();
797 // Verify that the display name is shown in the UI.
798 const std::string get_compact_pod_display_name = base::StringPrintf(
799 "domAutomationController.send(document.getElementById('pod-row')"
800 " .getPodWithUsername_('%s').nameElement.textContent);",
801 user_id_1_.c_str());
802 std::string display_name;
803 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
804 contents_,
805 get_compact_pod_display_name,
806 &display_name));
807 EXPECT_EQ(kDisplayName1, display_name);
808 const std::string get_expanded_pod_display_name = base::StringPrintf(
809 "domAutomationController.send(document.getElementById('pod-row')"
810 " .getPodWithUsername_('%s').querySelector('.expanded-pane-name')"
811 " .textContent);",
812 user_id_1_.c_str());
813 display_name.clear();
814 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
815 contents_,
816 get_expanded_pod_display_name,
817 &display_name));
818 EXPECT_EQ(kDisplayName1, display_name);
820 // Click on the pod to expand it.
821 ASSERT_TRUE(content::ExecuteScript(
822 contents_,
823 base::StringPrintf(
824 "document.getElementById('pod-row').getPodWithUsername_('%s')"
825 " .click();",
826 user_id_1_.c_str())));
828 // Change the display name.
829 device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
830 kDisplayName2);
831 UploadAndInstallDeviceLocalAccountPolicy();
832 policy::BrowserPolicyConnectorChromeOS* connector =
833 g_browser_process->platform_part()->browser_policy_connector_chromeos();
834 DeviceLocalAccountPolicyBroker* broker =
835 connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
836 user_id_1_);
837 ASSERT_TRUE(broker);
838 broker->core()->store()->Load();
839 WaitForDisplayName(user_id_1_, kDisplayName2);
841 // Verify that the new display name is shown in the UI.
842 display_name.clear();
843 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
844 contents_,
845 get_compact_pod_display_name,
846 &display_name));
847 EXPECT_EQ(kDisplayName2, display_name);
848 display_name.clear();
849 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
850 contents_,
851 get_expanded_pod_display_name,
852 &display_name));
853 EXPECT_EQ(kDisplayName2, display_name);
855 // Verify that the pod is still expanded. This indicates that the UI updated
856 // without reloading and losing state.
857 bool expanded = false;
858 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
859 contents_,
860 base::StringPrintf(
861 "domAutomationController.send(document.getElementById('pod-row')"
862 " .getPodWithUsername_('%s').expanded);",
863 user_id_1_.c_str()),
864 &expanded));
865 EXPECT_TRUE(expanded);
868 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyDownload) {
869 UploadDeviceLocalAccountPolicy();
870 AddPublicSessionToDevicePolicy(kAccountId1);
872 WaitForPolicy();
874 // Sanity check: The policy should be present now.
875 ASSERT_FALSE(session_manager_client()->device_local_account_policy(
876 kAccountId1).empty());
879 static bool IsNotKnownUser(const std::string& account_id) {
880 return !IsKnownUser(account_id);
883 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, AccountListChange) {
884 AddPublicSessionToDevicePolicy(kAccountId1);
885 AddPublicSessionToDevicePolicy(kAccountId2);
887 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
888 base::Bind(&IsKnownUser, user_id_1_))
889 .Wait();
890 EXPECT_TRUE(IsKnownUser(user_id_2_));
892 // Update policy to remove kAccountId2.
893 em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
894 proto.mutable_device_local_accounts()->clear_account();
895 AddPublicSessionToDevicePolicy(kAccountId1);
897 em::ChromeDeviceSettingsProto policy;
898 policy.mutable_show_user_names()->set_show_user_names(true);
899 em::DeviceLocalAccountInfoProto* account1 =
900 policy.mutable_device_local_accounts()->add_account();
901 account1->set_account_id(kAccountId1);
902 account1->set_type(
903 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
905 test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType, std::string(),
906 policy.SerializeAsString());
907 g_browser_process->policy_service()->RefreshPolicies(base::Closure());
909 // Make sure the second device-local account disappears.
910 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
911 base::Bind(&IsNotKnownUser, user_id_2_))
912 .Wait();
915 // Test fails under MSan, http://crbug.com/446950
916 #if defined(MEMORY_SANITIZER)
917 #define MAYBE_StartSession DISABLED_StartSession
918 #else
919 #define MAYBE_StartSession StartSession
920 #endif
922 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, MAYBE_StartSession) {
923 // Specify startup pages.
924 device_local_account_policy_.payload().mutable_restoreonstartup()->set_value(
925 SessionStartupPref::kPrefValueURLs);
926 em::StringListPolicyProto* startup_urls_proto =
927 device_local_account_policy_.payload().mutable_restoreonstartupurls();
928 for (size_t i = 0; i < arraysize(kStartupURLs); ++i)
929 startup_urls_proto->mutable_value()->add_entries(kStartupURLs[i]);
930 UploadAndInstallDeviceLocalAccountPolicy();
931 AddPublicSessionToDevicePolicy(kAccountId1);
933 WaitForPolicy();
935 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
936 WaitForSessionStart();
938 // Check that the startup pages specified in policy were opened.
939 BrowserList* browser_list =
940 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
941 EXPECT_EQ(1U, browser_list->size());
942 Browser* browser = browser_list->get(0);
943 ASSERT_TRUE(browser);
945 TabStripModel* tabs = browser->tab_strip_model();
946 ASSERT_TRUE(tabs);
947 int expected_tab_count = static_cast<int>(arraysize(kStartupURLs));
948 EXPECT_EQ(expected_tab_count, tabs->count());
949 for (int i = 0; i < expected_tab_count && i < tabs->count(); ++i) {
950 EXPECT_EQ(GURL(kStartupURLs[i]),
951 tabs->GetWebContentsAt(i)->GetVisibleURL());
954 // Verify that the session is not considered to be logged in with a GAIA
955 // account.
956 Profile* profile = GetProfileForTest();
957 ASSERT_TRUE(profile);
958 EXPECT_FALSE(
959 SigninManagerFactory::GetForProfile(profile)->IsAuthenticated());
962 // Test fails under MSan, http://crbug.com/446950
963 #if defined(MEMORY_SANITIZER)
964 #define MAYBE_FullscreenDisallowed DISABLED_FullscreenDisallowed
965 #else
966 #define MAYBE_FullscreenDisallowed FullscreenDisallowed
967 #endif
969 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, MAYBE_FullscreenDisallowed) {
970 UploadAndInstallDeviceLocalAccountPolicy();
971 AddPublicSessionToDevicePolicy(kAccountId1);
973 WaitForPolicy();
975 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
976 WaitForSessionStart();
978 BrowserList* browser_list =
979 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
980 EXPECT_EQ(1U, browser_list->size());
981 Browser* browser = browser_list->get(0);
982 ASSERT_TRUE(browser);
983 BrowserWindow* browser_window = browser->window();
984 ASSERT_TRUE(browser_window);
986 // Verify that an attempt to enter fullscreen mode is denied.
987 EXPECT_FALSE(browser_window->IsFullscreen());
988 chrome::ToggleFullscreenMode(browser);
989 EXPECT_FALSE(browser_window->IsFullscreen());
992 // Test fails under MSan, http://crbug.com/446950
993 #if defined(MEMORY_SANITIZER)
994 #define MAYBE_ExtensionsUncached DISABLED_ExtensionsUncached
995 #else
996 #define MAYBE_ExtensionsUncached ExtensionsUncached
997 #endif
999 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, MAYBE_ExtensionsUncached) {
1000 // Make it possible to force-install a hosted app and an extension.
1001 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
1002 TestingUpdateManifestProvider testing_update_manifest_provider(
1003 kRelativeUpdateURL);
1004 testing_update_manifest_provider.AddUpdate(
1005 kHostedAppID,
1006 kHostedAppVersion,
1007 embedded_test_server()->GetURL(std::string("/") + kHostedAppCRXPath));
1008 testing_update_manifest_provider.AddUpdate(
1009 kGoodExtensionID,
1010 kGoodExtensionVersion,
1011 embedded_test_server()->GetURL(std::string("/") + kGoodExtensionCRXPath));
1012 embedded_test_server()->RegisterRequestHandler(
1013 base::Bind(&TestingUpdateManifestProvider::HandleRequest,
1014 base::Unretained(&testing_update_manifest_provider)));
1016 // Specify policy to force-install the hosted app and the extension.
1017 em::StringList* forcelist = device_local_account_policy_.payload()
1018 .mutable_extensioninstallforcelist()->mutable_value();
1019 forcelist->add_entries(base::StringPrintf(
1020 "%s;%s",
1021 kHostedAppID,
1022 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
1023 forcelist->add_entries(base::StringPrintf(
1024 "%s;%s",
1025 kGoodExtensionID,
1026 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
1028 UploadAndInstallDeviceLocalAccountPolicy();
1029 AddPublicSessionToDevicePolicy(kAccountId1);
1031 WaitForPolicy();
1033 // Start listening for app/extension installation results.
1034 content::WindowedNotificationObserver hosted_app_observer(
1035 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
1036 base::Bind(DoesInstallSuccessReferToId, kHostedAppID));
1037 content::WindowedNotificationObserver extension_observer(
1038 extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR,
1039 base::Bind(DoesInstallFailureReferToId, kGoodExtensionID));
1041 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
1043 // Wait for the hosted app installation to succeed and the extension
1044 // installation to fail (because hosted apps are whitelisted for use in
1045 // device-local accounts and extensions are not).
1046 hosted_app_observer.Wait();
1047 extension_observer.Wait();
1049 // Verify that the hosted app was installed.
1050 Profile* profile = GetProfileForTest();
1051 ASSERT_TRUE(profile);
1052 ExtensionService* extension_service =
1053 extensions::ExtensionSystem::Get(profile)->extension_service();
1054 EXPECT_TRUE(extension_service->GetExtensionById(kHostedAppID, true));
1056 // Verify that the extension was not installed.
1057 EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true));
1059 // Verify that the app was downloaded to the account's extension cache.
1060 base::FilePath test_dir;
1061 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
1062 EXPECT_TRUE(ContentsEqual(
1063 GetCacheCRXFile(kAccountId1, kHostedAppID, kHostedAppVersion),
1064 test_dir.Append(kHostedAppCRXPath)));
1066 // Verify that the extension was removed from the account's extension cache
1067 // after the installation failure.
1068 DeviceLocalAccountPolicyBroker* broker =
1069 g_browser_process->platform_part()->browser_policy_connector_chromeos()->
1070 GetDeviceLocalAccountPolicyService()->GetBrokerForUser(user_id_1_);
1071 ASSERT_TRUE(broker);
1072 chromeos::ExternalCache* cache =
1073 broker->extension_loader()->GetExternalCacheForTesting();
1074 ASSERT_TRUE(cache);
1075 EXPECT_FALSE(cache->GetExtension(kGoodExtensionID, NULL, NULL));
1078 // Test fails under MSan, http://crbug.com/446950
1079 #if defined(MEMORY_SANITIZER)
1080 #define MAYBE_ExtensionsCached DISABLED_ExtensionsCached
1081 #else
1082 #define MAYBE_ExtensionsCached ExtensionsCached
1083 #endif
1085 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, MAYBE_ExtensionsCached) {
1086 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
1088 // Pre-populate the device local account's extension cache with a hosted app
1089 // and an extension.
1090 EXPECT_TRUE(base::CreateDirectory(
1091 GetExtensionCacheDirectoryForAccountID(kAccountId1)));
1092 base::FilePath test_dir;
1093 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
1094 const base::FilePath cached_hosted_app =
1095 GetCacheCRXFile(kAccountId1, kHostedAppID, kHostedAppVersion);
1096 EXPECT_TRUE(CopyFile(test_dir.Append(kHostedAppCRXPath),
1097 cached_hosted_app));
1098 EXPECT_TRUE(CopyFile(
1099 test_dir.Append(kGoodExtensionCRXPath),
1100 GetCacheCRXFile(kAccountId1, kGoodExtensionID, kGoodExtensionVersion)));
1102 // Specify policy to force-install the hosted app.
1103 em::StringList* forcelist = device_local_account_policy_.payload()
1104 .mutable_extensioninstallforcelist()->mutable_value();
1105 forcelist->add_entries(base::StringPrintf(
1106 "%s;%s",
1107 kHostedAppID,
1108 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
1109 forcelist->add_entries(base::StringPrintf(
1110 "%s;%s",
1111 kGoodExtensionID,
1112 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
1114 UploadAndInstallDeviceLocalAccountPolicy();
1115 AddPublicSessionToDevicePolicy(kAccountId1);
1117 WaitForPolicy();
1119 // Start listening for app/extension installation results.
1120 content::WindowedNotificationObserver hosted_app_observer(
1121 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
1122 base::Bind(DoesInstallSuccessReferToId, kHostedAppID));
1123 content::WindowedNotificationObserver extension_observer(
1124 extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR,
1125 base::Bind(DoesInstallFailureReferToId, kGoodExtensionID));
1127 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
1129 // Wait for the hosted app installation to succeed and the extension
1130 // installation to fail.
1131 hosted_app_observer.Wait();
1132 extension_observer.Wait();
1134 // Verify that the hosted app was installed.
1135 Profile* profile = GetProfileForTest();
1136 ASSERT_TRUE(profile);
1137 ExtensionService* extension_service =
1138 extensions::ExtensionSystem::Get(profile)->extension_service();
1139 EXPECT_TRUE(extension_service->GetExtensionById(kHostedAppID, true));
1141 // Verify that the extension was not installed.
1142 EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true));
1144 // Verify that the app is still in the account's extension cache.
1145 EXPECT_TRUE(PathExists(cached_hosted_app));
1147 // Verify that the extension was removed from the account's extension cache.
1148 DeviceLocalAccountPolicyBroker* broker =
1149 g_browser_process->platform_part()->browser_policy_connector_chromeos()->
1150 GetDeviceLocalAccountPolicyService()->GetBrokerForUser(user_id_1_);
1151 ASSERT_TRUE(broker);
1152 chromeos::ExternalCache* cache =
1153 broker->extension_loader()->GetExternalCacheForTesting();
1154 ASSERT_TRUE(cache);
1155 EXPECT_FALSE(cache->GetExtension(kGoodExtensionID, NULL, NULL));
1158 static void OnPutExtension(scoped_ptr<base::RunLoop>* run_loop,
1159 const base::FilePath& file_path,
1160 bool file_ownership_passed) {
1161 ASSERT_TRUE(*run_loop);
1162 (*run_loop)->Quit();
1165 static void OnExtensionCacheImplInitialized(
1166 scoped_ptr<base::RunLoop>* run_loop) {
1167 ASSERT_TRUE(*run_loop);
1168 (*run_loop)->Quit();
1171 static void CreateFile(const base::FilePath& file,
1172 size_t size,
1173 const base::Time& timestamp) {
1174 std::string data(size, 0);
1175 EXPECT_EQ(base::WriteFile(file, data.data(), data.size()), int(size));
1176 EXPECT_TRUE(base::TouchFile(file, timestamp, timestamp));
1179 // Test fails under MSan, http://crbug.com/446950
1180 #if defined(MEMORY_SANITIZER)
1181 #define MAYBE_ExtensionCacheImplTest DISABLED_ExtensionCacheImplTest
1182 #else
1183 #define MAYBE_ExtensionCacheImplTest ExtensionCacheImplTest
1184 #endif
1186 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, MAYBE_ExtensionCacheImplTest) {
1187 // Make it possible to force-install a hosted app and an extension.
1188 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
1189 TestingUpdateManifestProvider testing_update_manifest_provider(
1190 kRelativeUpdateURL);
1191 testing_update_manifest_provider.AddUpdate(
1192 kHostedAppID,
1193 kHostedAppVersion,
1194 embedded_test_server()->GetURL(std::string("/") + kHostedAppCRXPath));
1195 testing_update_manifest_provider.AddUpdate(
1196 kGoodExtensionID,
1197 kGoodExtensionVersion,
1198 embedded_test_server()->GetURL(std::string("/") + kGoodExtensionCRXPath));
1199 embedded_test_server()->RegisterRequestHandler(
1200 base::Bind(&TestingUpdateManifestProvider::HandleRequest,
1201 base::Unretained(&testing_update_manifest_provider)));
1203 // Create and initialize local cache.
1204 base::ScopedTempDir cache_dir;
1205 EXPECT_TRUE(cache_dir.CreateUniqueTempDir());
1206 const base::FilePath impl_path = cache_dir.path();
1207 EXPECT_TRUE(base::CreateDirectory(impl_path));
1208 CreateFile(impl_path.Append(
1209 extensions::LocalExtensionCache::kCacheReadyFlagFileName),
1210 0, base::Time::Now());
1211 extensions::ExtensionCacheImpl cache_impl(impl_path);
1212 scoped_ptr<base::RunLoop> run_loop;
1213 run_loop.reset(new base::RunLoop);
1214 cache_impl.Start(base::Bind(&OnExtensionCacheImplInitialized, &run_loop));
1215 run_loop->Run();
1217 // Put extension in the local cache.
1218 base::ScopedTempDir temp_dir;
1219 EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
1220 const base::FilePath temp_path = temp_dir.path();
1221 EXPECT_TRUE(base::CreateDirectory(temp_path));
1222 const base::FilePath temp_file =
1223 GetCacheCRXFilePath(kGoodExtensionID, kGoodExtensionVersion, temp_path);
1224 base::FilePath test_dir;
1225 std::string hash;
1226 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
1227 EXPECT_TRUE(CopyFile(test_dir.Append(kGoodExtensionCRXPath), temp_file));
1228 cache_impl.AllowCaching(kGoodExtensionID);
1229 run_loop.reset(new base::RunLoop);
1230 cache_impl.PutExtension(kGoodExtensionID, hash, temp_file,
1231 kGoodExtensionVersion,
1232 base::Bind(&OnPutExtension, &run_loop));
1233 run_loop->Run();
1235 // Verify that the extension file was added to the local cache.
1236 const base::FilePath local_file =
1237 GetCacheCRXFilePath(kGoodExtensionID, kGoodExtensionVersion, impl_path);
1238 EXPECT_TRUE(PathExists(local_file));
1240 // Specify policy to force-install the hosted app and the extension.
1241 em::StringList* forcelist = device_local_account_policy_.payload()
1242 .mutable_extensioninstallforcelist()->mutable_value();
1243 forcelist->add_entries(base::StringPrintf(
1244 "%s;%s",
1245 kHostedAppID,
1246 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
1247 forcelist->add_entries(base::StringPrintf(
1248 "%s;%s",
1249 kGoodExtensionID,
1250 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
1252 UploadAndInstallDeviceLocalAccountPolicy();
1253 AddPublicSessionToDevicePolicy(kAccountId1);
1255 WaitForPolicy();
1257 // Start listening for app/extension installation results.
1258 content::WindowedNotificationObserver hosted_app_observer(
1259 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
1260 base::Bind(DoesInstallSuccessReferToId, kHostedAppID));
1261 content::WindowedNotificationObserver extension_observer(
1262 extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR,
1263 base::Bind(DoesInstallFailureReferToId, kGoodExtensionID));
1265 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
1267 // Wait for the hosted app installation to succeed and the extension
1268 // installation to fail (because hosted apps are whitelisted for use in
1269 // device-local accounts and extensions are not).
1270 hosted_app_observer.Wait();
1271 extension_observer.Wait();
1273 // Verify that the extension was kept in the local cache.
1274 EXPECT_TRUE(cache_impl.GetExtension(kGoodExtensionID, hash, NULL, NULL));
1276 // Verify that the extension file was kept in the local cache.
1277 EXPECT_TRUE(PathExists(local_file));
1280 // Test fails under MSan, http://crbug.com/446950
1281 #if defined(MEMORY_SANITIZER)
1282 #define MAYBE_ExternalData DISABLED_ExternalData
1283 #else
1284 #define MAYBE_ExternalData ExternalData
1285 #endif
1287 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, MAYBE_ExternalData) {
1288 // user_manager::UserManager requests an external data fetch whenever
1289 // the key::kUserAvatarImage policy is set. Since this test wants to
1290 // verify that the underlying policy subsystem will start a fetch
1291 // without this request as well, the user_manager::UserManager must be
1292 // prevented from seeing the policy change.
1293 reinterpret_cast<chromeos::ChromeUserManagerImpl*>(
1294 user_manager::UserManager::Get())->StopPolicyObserverForTesting();
1296 UploadDeviceLocalAccountPolicy();
1297 AddPublicSessionToDevicePolicy(kAccountId1);
1299 WaitForPolicy();
1301 // Start serving external data at |kExternalDataURL|.
1302 scoped_ptr<base::RunLoop> run_loop(new base::RunLoop);
1303 scoped_ptr<net::FakeURLFetcherFactory> fetcher_factory(
1304 new net::FakeURLFetcherFactory(
1305 NULL,
1306 base::Bind(&RunCallbackAndReturnFakeURLFetcher,
1307 base::MessageLoopProxy::current(),
1308 run_loop->QuitClosure())));
1309 fetcher_factory->SetFakeResponse(GURL(kExternalDataURL),
1310 kExternalData,
1311 net::HTTP_OK,
1312 net::URLRequestStatus::SUCCESS);
1314 // Specify an external data reference for the key::kUserAvatarImage policy.
1315 scoped_ptr<base::DictionaryValue> metadata =
1316 test::ConstructExternalDataReference(kExternalDataURL, kExternalData);
1317 std::string policy;
1318 base::JSONWriter::Write(metadata.get(), &policy);
1319 device_local_account_policy_.payload().mutable_useravatarimage()->set_value(
1320 policy);
1321 UploadAndInstallDeviceLocalAccountPolicy();
1322 policy::BrowserPolicyConnectorChromeOS* connector =
1323 g_browser_process->platform_part()->browser_policy_connector_chromeos();
1324 DeviceLocalAccountPolicyBroker* broker =
1325 connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
1326 user_id_1_);
1327 ASSERT_TRUE(broker);
1328 broker->core()->store()->Load();
1330 // The external data should be fetched and cached automatically. Wait for this
1331 // fetch.
1332 run_loop->Run();
1334 // Stop serving external data at |kExternalDataURL|.
1335 fetcher_factory.reset();
1337 const PolicyMap::Entry* policy_entry =
1338 broker->core()->store()->policy_map().Get(key::kUserAvatarImage);
1339 ASSERT_TRUE(policy_entry);
1340 ASSERT_TRUE(policy_entry->external_data_fetcher);
1342 // Retrieve the external data. Although the data is no longer being served at
1343 // |kExternalDataURL|, the retrieval should succeed because the data has been
1344 // cached.
1345 run_loop.reset(new base::RunLoop);
1346 scoped_ptr<std::string> fetched_external_data;
1347 policy_entry->external_data_fetcher->Fetch(base::Bind(
1348 &test::ExternalDataFetchCallback,
1349 &fetched_external_data,
1350 run_loop->QuitClosure()));
1351 run_loop->Run();
1353 ASSERT_TRUE(fetched_external_data);
1354 EXPECT_EQ(kExternalData, *fetched_external_data);
1356 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
1357 WaitForSessionStart();
1359 // Verify that the external data reference has propagated to the device-local
1360 // account's ProfilePolicyConnector.
1361 ProfilePolicyConnector* policy_connector =
1362 ProfilePolicyConnectorFactory::GetForBrowserContext(GetProfileForTest());
1363 ASSERT_TRUE(policy_connector);
1364 const PolicyMap& policies = policy_connector->policy_service()->GetPolicies(
1365 PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
1366 policy_entry = policies.Get(key::kUserAvatarImage);
1367 ASSERT_TRUE(policy_entry);
1368 EXPECT_TRUE(base::Value::Equals(metadata.get(), policy_entry->value));
1369 ASSERT_TRUE(policy_entry->external_data_fetcher);
1371 // Retrieve the external data via the ProfilePolicyConnector. The retrieval
1372 // should succeed because the data has been cached.
1373 run_loop.reset(new base::RunLoop);
1374 fetched_external_data.reset();
1375 policy_entry->external_data_fetcher->Fetch(base::Bind(
1376 &test::ExternalDataFetchCallback,
1377 &fetched_external_data,
1378 run_loop->QuitClosure()));
1379 run_loop->Run();
1381 ASSERT_TRUE(fetched_external_data);
1382 EXPECT_EQ(kExternalData, *fetched_external_data);
1385 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, UserAvatarImage) {
1386 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
1388 UploadDeviceLocalAccountPolicy();
1389 AddPublicSessionToDevicePolicy(kAccountId1);
1391 WaitForPolicy();
1393 base::FilePath test_dir;
1394 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
1395 std::string image_data;
1396 ASSERT_TRUE(base::ReadFileToString(
1397 test_dir.Append(chromeos::test::kUserAvatarImage1RelativePath),
1398 &image_data));
1400 std::string policy;
1401 base::JSONWriter::Write(test::ConstructExternalDataReference(
1402 embedded_test_server()->GetURL(std::string("/") +
1403 chromeos::test::kUserAvatarImage1RelativePath).spec(),
1404 image_data).get(),
1405 &policy);
1406 device_local_account_policy_.payload().mutable_useravatarimage()->set_value(
1407 policy);
1408 UploadAndInstallDeviceLocalAccountPolicy();
1409 policy::BrowserPolicyConnectorChromeOS* connector =
1410 g_browser_process->platform_part()->browser_policy_connector_chromeos();
1411 DeviceLocalAccountPolicyBroker* broker =
1412 connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
1413 user_id_1_);
1414 ASSERT_TRUE(broker);
1416 run_loop_.reset(new base::RunLoop);
1417 user_manager::UserManager::Get()->AddObserver(this);
1418 broker->core()->store()->Load();
1419 run_loop_->Run();
1420 user_manager::UserManager::Get()->RemoveObserver(this);
1422 scoped_ptr<gfx::ImageSkia> policy_image = chromeos::test::ImageLoader(
1423 test_dir.Append(chromeos::test::kUserAvatarImage1RelativePath)).Load();
1424 ASSERT_TRUE(policy_image);
1426 const user_manager::User* user =
1427 user_manager::UserManager::Get()->FindUser(user_id_1_);
1428 ASSERT_TRUE(user);
1430 base::FilePath user_data_dir;
1431 ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
1432 const base::FilePath saved_image_path =
1433 user_data_dir.Append(user_id_1_).AddExtension("jpg");
1435 EXPECT_FALSE(user->HasDefaultImage());
1436 EXPECT_EQ(user_manager::User::USER_IMAGE_EXTERNAL, user->image_index());
1437 EXPECT_TRUE(chromeos::test::AreImagesEqual(*policy_image, user->GetImage()));
1438 const base::DictionaryValue* images_pref =
1439 g_browser_process->local_state()->GetDictionary("user_image_info");
1440 ASSERT_TRUE(images_pref);
1441 const base::DictionaryValue* image_properties;
1442 ASSERT_TRUE(images_pref->GetDictionaryWithoutPathExpansion(
1443 user_id_1_,
1444 &image_properties));
1445 int image_index;
1446 std::string image_path;
1447 ASSERT_TRUE(image_properties->GetInteger("index", &image_index));
1448 ASSERT_TRUE(image_properties->GetString("path", &image_path));
1449 EXPECT_EQ(user_manager::User::USER_IMAGE_EXTERNAL, image_index);
1450 EXPECT_EQ(saved_image_path.value(), image_path);
1452 scoped_ptr<gfx::ImageSkia> saved_image =
1453 chromeos::test::ImageLoader(saved_image_path).Load();
1454 ASSERT_TRUE(saved_image);
1456 // Check image dimensions. Images can't be compared since JPEG is lossy.
1457 EXPECT_EQ(policy_image->width(), saved_image->width());
1458 EXPECT_EQ(policy_image->height(), saved_image->height());
1461 // Test fails under MSan, http://crbug.com/446950
1462 #if defined(MEMORY_SANITIZER)
1463 #define MAYBE_LastWindowClosedLogoutReminder \
1464 DISABLED_LastWindowClosedLogoutReminder
1465 #else
1466 #define MAYBE_LastWindowClosedLogoutReminder LastWindowClosedLogoutReminder
1467 #endif
1469 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest,
1470 MAYBE_LastWindowClosedLogoutReminder) {
1471 UploadAndInstallDeviceLocalAccountPolicy();
1472 AddPublicSessionToDevicePolicy(kAccountId1);
1474 WaitForPolicy();
1476 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
1477 WaitForSessionStart();
1479 Profile* profile = GetProfileForTest();
1480 ASSERT_TRUE(profile);
1481 extensions::AppWindowRegistry* app_window_registry =
1482 extensions::AppWindowRegistry::Get(profile);
1483 app_window_registry->AddObserver(this);
1485 // Verify that the logout confirmation dialog is not showing.
1486 ash::LogoutConfirmationController* logout_confirmation_controller =
1487 ash::Shell::GetInstance()->logout_confirmation_controller();
1488 ASSERT_TRUE(logout_confirmation_controller);
1489 EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());
1491 // Remove policy that allows only explicitly whitelisted apps to be installed
1492 // in a public session.
1493 extensions::ExtensionSystem* extension_system =
1494 extensions::ExtensionSystem::Get(profile);
1495 ASSERT_TRUE(extension_system);
1496 extension_system->management_policy()->UnregisterAllProviders();
1498 // Install and a platform app.
1499 scoped_refptr<extensions::CrxInstaller> installer =
1500 extensions::CrxInstaller::CreateSilent(
1501 extension_system->extension_service());
1502 installer->set_allow_silent_install(true);
1503 installer->set_install_cause(extension_misc::INSTALL_CAUSE_USER_DOWNLOAD);
1504 installer->set_creation_flags(extensions::Extension::FROM_WEBSTORE);
1505 content::WindowedNotificationObserver app_install_observer(
1506 extensions::NOTIFICATION_CRX_INSTALLER_DONE,
1507 content::NotificationService::AllSources());
1508 base::FilePath test_dir;
1509 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
1510 installer->InstallCrx(test_dir.Append(kPackagedAppCRXPath));
1511 app_install_observer.Wait();
1512 const extensions::Extension* app =
1513 content::Details<const extensions::Extension>(
1514 app_install_observer.details()).ptr();
1516 // Start the platform app, causing it to open a window.
1517 run_loop_.reset(new base::RunLoop);
1518 OpenApplication(AppLaunchParams(profile, app,
1519 extensions::LAUNCH_CONTAINER_NONE, NEW_WINDOW,
1520 extensions::SOURCE_TEST));
1521 run_loop_->Run();
1522 EXPECT_EQ(1U, app_window_registry->app_windows().size());
1524 // Close the only open browser window.
1525 BrowserList* browser_list =
1526 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
1527 EXPECT_EQ(1U, browser_list->size());
1528 Browser* browser = browser_list->get(0);
1529 ASSERT_TRUE(browser);
1530 BrowserWindow* browser_window = browser->window();
1531 ASSERT_TRUE(browser_window);
1532 run_loop_.reset(new base::RunLoop);
1533 browser_window->Close();
1534 browser_window = NULL;
1535 run_loop_->Run();
1536 browser = NULL;
1537 EXPECT_TRUE(browser_list->empty());
1539 // Verify that the logout confirmation dialog is not showing because an app
1540 // window is still open.
1541 EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());
1543 // Open a browser window.
1544 Browser* first_browser = CreateBrowser(profile);
1545 EXPECT_EQ(1U, browser_list->size());
1547 // Close the app window.
1548 run_loop_.reset(new base::RunLoop);
1549 ASSERT_EQ(1U, app_window_registry->app_windows().size());
1550 app_window_registry->app_windows().front()->GetBaseWindow()->Close();
1551 run_loop_->Run();
1552 EXPECT_TRUE(app_window_registry->app_windows().empty());
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 // Open a second browser window.
1559 Browser* second_browser = CreateBrowser(profile);
1560 EXPECT_EQ(2U, browser_list->size());
1562 // Close the first browser window.
1563 browser_window = first_browser->window();
1564 ASSERT_TRUE(browser_window);
1565 run_loop_.reset(new base::RunLoop);
1566 browser_window->Close();
1567 browser_window = NULL;
1568 run_loop_->Run();
1569 first_browser = NULL;
1570 EXPECT_EQ(1U, browser_list->size());
1572 // Verify that the logout confirmation dialog is not showing because a browser
1573 // window is still open.
1574 EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());
1576 // Close the second browser window.
1577 browser_window = second_browser->window();
1578 ASSERT_TRUE(browser_window);
1579 run_loop_.reset(new base::RunLoop);
1580 browser_window->Close();
1581 browser_window = NULL;
1582 run_loop_->Run();
1583 second_browser = NULL;
1584 EXPECT_TRUE(browser_list->empty());
1586 // Verify that the logout confirmation dialog is showing.
1587 ash::LogoutConfirmationDialog* dialog =
1588 logout_confirmation_controller->dialog_for_testing();
1589 ASSERT_TRUE(dialog);
1591 // Deny the logout.
1592 dialog->GetWidget()->Close();
1593 dialog = NULL;
1594 base::RunLoop().RunUntilIdle();
1596 // Verify that the logout confirmation dialog is no longer showing.
1597 EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());
1599 // Open a browser window.
1600 browser = CreateBrowser(profile);
1601 EXPECT_EQ(1U, browser_list->size());
1603 // Close the browser window.
1604 browser_window = browser->window();
1605 ASSERT_TRUE(browser_window);
1606 run_loop_.reset(new base::RunLoop);
1607 browser_window->Close();
1608 browser_window = NULL;
1609 run_loop_->Run();
1610 browser = NULL;
1611 EXPECT_TRUE(browser_list->empty());
1613 // Verify that the logout confirmation dialog is showing again.
1614 dialog = logout_confirmation_controller->dialog_for_testing();
1615 ASSERT_TRUE(dialog);
1617 // Deny the logout.
1618 dialog->GetWidget()->Close();
1619 dialog = NULL;
1620 base::RunLoop().RunUntilIdle();
1622 app_window_registry->RemoveObserver(this);
1625 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, NoRecommendedLocaleNoSwitch) {
1626 UploadAndInstallDeviceLocalAccountPolicy();
1627 AddPublicSessionToDevicePolicy(kAccountId1);
1629 WaitForPolicy();
1631 ExpandPublicSessionPod(false);
1633 // Click the enter button to start the session.
1634 ASSERT_TRUE(content::ExecuteScript(
1635 contents_,
1636 base::StringPrintf(
1637 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1638 " .querySelector('.enter-button').click();",
1639 user_id_1_.c_str())));
1641 WaitForSessionStart();
1643 // Verify that the locale has not changed and the first keyboard layout
1644 // applicable to the locale was chosen.
1645 EXPECT_EQ(initial_locale_, g_browser_process->GetApplicationLocale());
1646 EXPECT_EQ(initial_language_, icu::Locale::getDefault().getLanguage());
1647 VerifyKeyboardLayoutMatchesLocale();
1650 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, NoRecommendedLocaleSwitch) {
1651 UploadAndInstallDeviceLocalAccountPolicy();
1652 AddPublicSessionToDevicePolicy(kAccountId1);
1654 WaitForPolicy();
1656 ExpandPublicSessionPod(false);
1658 // Click the link that switches the pod to its advanced form. Verify that the
1659 // pod switches from basic to advanced.
1660 bool advanced = false;
1661 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
1662 contents_,
1663 base::StringPrintf(
1664 "var pod ="
1665 " document.getElementById('pod-row').getPodWithUsername_('%s');"
1666 "pod.querySelector('.language-and-input').click();"
1667 "domAutomationController.send(pod.classList.contains('advanced'));",
1668 user_id_1_.c_str()),
1669 &advanced));
1670 EXPECT_FALSE(advanced);
1672 // Manually select a different locale.
1673 ASSERT_TRUE(content::ExecuteScript(
1674 contents_,
1675 base::StringPrintf(
1676 "var languageSelect = document.getElementById('pod-row')"
1677 " .getPodWithUsername_('%s').querySelector('.language-select');"
1678 "languageSelect.value = '%s';"
1679 "var event = document.createEvent('HTMLEvents');"
1680 "event.initEvent('change', false, true);"
1681 "languageSelect.dispatchEvent(event);",
1682 user_id_1_.c_str(),
1683 kPublicSessionLocale)));
1685 // The UI will have requested an updated list of keyboard layouts at this
1686 // point. Wait for the constructions of this list to finish.
1687 WaitForGetKeyboardLayoutsForLocaleToFinish();
1689 // Manually select a different keyboard layout and click the enter button to
1690 // start the session.
1691 ASSERT_TRUE(content::ExecuteScript(
1692 contents_,
1693 base::StringPrintf(
1694 "var pod ="
1695 " document.getElementById('pod-row').getPodWithUsername_('%s');"
1696 "pod.querySelector('.keyboard-select').value = '%s';"
1697 "pod.querySelector('.enter-button').click();",
1698 user_id_1_.c_str(),
1699 public_session_input_method_id_.c_str())));
1701 WaitForSessionStart();
1703 // Verify that the locale and keyboard layout have been applied.
1704 EXPECT_EQ(kPublicSessionLocale, g_browser_process->GetApplicationLocale());
1705 EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale),
1706 icu::Locale::getDefault().getLanguage());
1707 EXPECT_EQ(public_session_input_method_id_,
1708 chromeos::input_method::InputMethodManager::Get()
1709 ->GetActiveIMEState()
1710 ->GetCurrentInputMethod()
1711 .id());
1714 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, OneRecommendedLocale) {
1715 // Specify a recommended locale.
1716 SetRecommendedLocales(kSingleRecommendedLocale,
1717 arraysize(kSingleRecommendedLocale));
1718 UploadAndInstallDeviceLocalAccountPolicy();
1719 AddPublicSessionToDevicePolicy(kAccountId1);
1721 WaitForPolicy();
1723 ExpandPublicSessionPod(false);
1725 // Click the enter button to start the session.
1726 ASSERT_TRUE(content::ExecuteScript(
1727 contents_,
1728 base::StringPrintf(
1729 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1730 " .querySelector('.enter-button').click();",
1731 user_id_1_.c_str())));
1733 WaitForSessionStart();
1735 // Verify that the recommended locale has been applied and the first keyboard
1736 // layout applicable to the locale was chosen.
1737 EXPECT_EQ(kSingleRecommendedLocale[0],
1738 g_browser_process->GetApplicationLocale());
1739 EXPECT_EQ(l10n_util::GetLanguage(kSingleRecommendedLocale[0]),
1740 icu::Locale::getDefault().getLanguage());
1741 VerifyKeyboardLayoutMatchesLocale();
1744 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, MultipleRecommendedLocales) {
1745 // Specify recommended locales.
1746 SetRecommendedLocales(kRecommendedLocales1, arraysize(kRecommendedLocales1));
1747 UploadAndInstallDeviceLocalAccountPolicy();
1748 AddPublicSessionToDevicePolicy(kAccountId1);
1749 AddPublicSessionToDevicePolicy(kAccountId2);
1751 WaitForPolicy();
1753 ExpandPublicSessionPod(true);
1755 // Verify that the pod shows a list of locales beginning with the recommended
1756 // ones, followed by others.
1757 const std::string get_locale_list = base::StringPrintf(
1758 "var languageSelect = document.getElementById('pod-row')"
1759 " .getPodWithUsername_('%s').querySelector('.language-select');"
1760 "var locales = [];"
1761 "for (var i = 0; i < languageSelect.length; ++i)"
1762 " locales.push(languageSelect.options[i].value);"
1763 "domAutomationController.send(JSON.stringify(locales));",
1764 user_id_1_.c_str());
1765 std::string json;
1766 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
1767 get_locale_list,
1768 &json));
1769 scoped_ptr<base::Value> value_ptr(base::JSONReader::Read(json));
1770 const base::ListValue* locales = NULL;
1771 ASSERT_TRUE(value_ptr);
1772 ASSERT_TRUE(value_ptr->GetAsList(&locales));
1773 EXPECT_LT(arraysize(kRecommendedLocales1), locales->GetSize());
1775 // Verify that the list starts with the recommended locales, in correct order.
1776 for (size_t i = 0; i < arraysize(kRecommendedLocales1); ++i) {
1777 std::string locale;
1778 EXPECT_TRUE(locales->GetString(i, &locale));
1779 EXPECT_EQ(kRecommendedLocales1[i], locale);
1782 // Verify that the recommended locales do not appear again in the remainder of
1783 // the list.
1784 std::set<std::string> recommended_locales;
1785 for (size_t i = 0; i < arraysize(kRecommendedLocales1); ++i)
1786 recommended_locales.insert(kRecommendedLocales1[i]);
1787 for (size_t i = arraysize(kRecommendedLocales1); i < locales->GetSize();
1788 ++i) {
1789 std::string locale;
1790 EXPECT_TRUE(locales->GetString(i, &locale));
1791 EXPECT_EQ(recommended_locales.end(), recommended_locales.find(locale));
1794 // Verify that the first recommended locale is selected.
1795 const std::string get_selected_locale =
1796 base::StringPrintf(
1797 "domAutomationController.send(document.getElementById('pod-row')"
1798 " .getPodWithUsername_('%s').querySelector('.language-select')"
1799 " .value);",
1800 user_id_1_.c_str());
1801 std::string selected_locale;
1802 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
1803 get_selected_locale,
1804 &selected_locale));
1805 EXPECT_EQ(kRecommendedLocales1[0], selected_locale);
1807 // Change the list of recommended locales.
1808 SetRecommendedLocales(kRecommendedLocales2, arraysize(kRecommendedLocales2));
1810 // Also change the display name as it is easy to ensure that policy has been
1811 // updated by waiting for a display name change.
1812 device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
1813 kDisplayName2);
1814 UploadAndInstallDeviceLocalAccountPolicy();
1815 policy::BrowserPolicyConnectorChromeOS* connector =
1816 g_browser_process->platform_part()->browser_policy_connector_chromeos();
1817 DeviceLocalAccountPolicyBroker* broker =
1818 connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
1819 user_id_1_);
1820 ASSERT_TRUE(broker);
1821 broker->core()->store()->Load();
1822 WaitForDisplayName(user_id_1_, kDisplayName2);
1824 // Verify that the new list of locales is shown in the UI.
1825 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
1826 get_locale_list,
1827 &json));
1828 value_ptr.reset(base::JSONReader::Read(json));
1829 locales = NULL;
1830 ASSERT_TRUE(value_ptr);
1831 ASSERT_TRUE(value_ptr->GetAsList(&locales));
1832 EXPECT_LT(arraysize(kRecommendedLocales2), locales->GetSize());
1833 for (size_t i = 0; i < arraysize(kRecommendedLocales2); ++i) {
1834 std::string locale;
1835 EXPECT_TRUE(locales->GetString(i, &locale));
1836 EXPECT_EQ(kRecommendedLocales2[i], locale);
1839 // Verify that the first new recommended locale is selected.
1840 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
1841 get_selected_locale,
1842 &selected_locale));
1843 EXPECT_EQ(kRecommendedLocales2[0], selected_locale);
1845 // Manually select a different locale.
1846 ASSERT_TRUE(content::ExecuteScript(
1847 contents_,
1848 base::StringPrintf(
1849 "var languageSelect = document.getElementById('pod-row')"
1850 " .getPodWithUsername_('%s').querySelector('.language-select');"
1851 "languageSelect.value = '%s';"
1852 "var event = document.createEvent('HTMLEvents');"
1853 "event.initEvent('change', false, true);"
1854 "languageSelect.dispatchEvent(event);",
1855 user_id_1_.c_str(),
1856 kPublicSessionLocale)));
1858 // Change the list of recommended locales.
1859 SetRecommendedLocales(kRecommendedLocales2, arraysize(kRecommendedLocales2));
1860 device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
1861 kDisplayName1);
1862 UploadAndInstallDeviceLocalAccountPolicy();
1863 broker->core()->store()->Load();
1864 WaitForDisplayName(user_id_1_, kDisplayName1);
1866 // Verify that the manually selected locale is still selected.
1867 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
1868 get_selected_locale,
1869 &selected_locale));
1870 EXPECT_EQ(kPublicSessionLocale, selected_locale);
1872 // The UI will request an updated list of keyboard layouts at this point. Wait
1873 // for the constructions of this list to finish.
1874 WaitForGetKeyboardLayoutsForLocaleToFinish();
1876 // Manually select a different keyboard layout.
1877 ASSERT_TRUE(content::ExecuteScript(
1878 contents_,
1879 base::StringPrintf(
1880 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1881 " .querySelector('.keyboard-select').value = '%s';",
1882 user_id_1_.c_str(),
1883 public_session_input_method_id_.c_str())));
1885 // Click on a different pod, causing focus to shift away and the pod to
1886 // contract.
1887 ASSERT_TRUE(content::ExecuteScript(
1888 contents_,
1889 base::StringPrintf(
1890 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1891 " .click();",
1892 user_id_2_.c_str())));
1894 // Click on the pod again, causing it to expand again. Verify that the pod has
1895 // kept all its state (the advanced form is being shown, the manually selected
1896 // locale and keyboard layout are selected).
1897 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1898 contents_,
1899 base::StringPrintf(
1900 "var pod ="
1901 " document.getElementById('pod-row').getPodWithUsername_('%s');"
1902 "pod.click();"
1903 "var state = {};"
1904 "state.advanced = pod.classList.contains('advanced');"
1905 "state.locale = pod.querySelector('.language-select').value;"
1906 "state.keyboardLayout = pod.querySelector('.keyboard-select').value;"
1907 "console.log(JSON.stringify(state));"
1908 "domAutomationController.send(JSON.stringify(state));",
1909 user_id_1_.c_str()),
1910 &json));
1911 LOG(ERROR) << json;
1912 value_ptr.reset(base::JSONReader::Read(json));
1913 const base::DictionaryValue* state = NULL;
1914 ASSERT_TRUE(value_ptr);
1915 ASSERT_TRUE(value_ptr->GetAsDictionary(&state));
1916 bool advanced = false;
1917 EXPECT_TRUE(state->GetBoolean("advanced", &advanced));
1918 EXPECT_TRUE(advanced);
1919 EXPECT_TRUE(state->GetString("locale", &selected_locale));
1920 EXPECT_EQ(kPublicSessionLocale, selected_locale);
1921 std::string selected_keyboard_layout;
1922 EXPECT_TRUE(state->GetString("keyboardLayout", &selected_keyboard_layout));
1923 EXPECT_EQ(public_session_input_method_id_, selected_keyboard_layout);
1925 // Click the enter button to start the session.
1926 ASSERT_TRUE(content::ExecuteScript(
1927 contents_,
1928 base::StringPrintf(
1929 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1930 " .querySelector('.enter-button').click();",
1931 user_id_1_.c_str())));
1933 WaitForSessionStart();
1935 // Verify that the locale and keyboard layout have been applied.
1936 EXPECT_EQ(kPublicSessionLocale, g_browser_process->GetApplicationLocale());
1937 EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale),
1938 icu::Locale::getDefault().getLanguage());
1939 EXPECT_EQ(public_session_input_method_id_,
1940 chromeos::input_method::InputMethodManager::Get()
1941 ->GetActiveIMEState()
1942 ->GetCurrentInputMethod()
1943 .id());
1946 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, InvalidRecommendedLocale) {
1947 // Specify an invalid recommended locale.
1948 SetRecommendedLocales(kInvalidRecommendedLocale,
1949 arraysize(kInvalidRecommendedLocale));
1950 UploadAndInstallDeviceLocalAccountPolicy();
1951 AddPublicSessionToDevicePolicy(kAccountId1);
1953 WaitForPolicy();
1955 // Click on the pod to expand it. Verify that the pod expands to its basic
1956 // form as there is only one recommended locale.
1957 bool advanced = false;
1958 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
1959 contents_,
1960 base::StringPrintf(
1961 "var pod ="
1962 " document.getElementById('pod-row').getPodWithUsername_('%s');"
1963 "pod.click();"
1964 "domAutomationController.send(pod.classList.contains('advanced'));",
1965 user_id_1_.c_str()),
1966 &advanced));
1967 EXPECT_FALSE(advanced);
1968 EXPECT_EQ(l10n_util::GetLanguage(initial_locale_),
1969 icu::Locale::getDefault().getLanguage());
1971 // Click the enter button to start the session.
1972 ASSERT_TRUE(content::ExecuteScript(
1973 contents_,
1974 base::StringPrintf(
1975 "document.getElementById('pod-row').getPodWithUsername_('%s')"
1976 " .querySelector('.enter-button').click();",
1977 user_id_1_.c_str())));
1979 WaitForSessionStart();
1981 // Verify that since the recommended locale was invalid, the locale has not
1982 // changed and the first keyboard layout applicable to the locale was chosen.
1983 EXPECT_EQ(initial_locale_, g_browser_process->GetApplicationLocale());
1984 EXPECT_EQ(l10n_util::GetLanguage(initial_locale_),
1985 icu::Locale::getDefault().getLanguage());
1986 VerifyKeyboardLayoutMatchesLocale();
1989 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest,
1990 AutoLoginWithoutRecommendedLocales) {
1991 UploadAndInstallDeviceLocalAccountPolicy();
1992 AddPublicSessionToDevicePolicy(kAccountId1);
1993 EnableAutoLogin();
1995 WaitForPolicy();
1997 WaitForSessionStart();
1999 // Verify that the locale has not changed and the first keyboard layout
2000 // applicable to the locale was chosen.
2001 EXPECT_EQ(initial_locale_, g_browser_process->GetApplicationLocale());
2002 EXPECT_EQ(initial_language_, icu::Locale::getDefault().getLanguage());
2003 VerifyKeyboardLayoutMatchesLocale();
2006 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest,
2007 AutoLoginWithRecommendedLocales) {
2008 // Specify recommended locales.
2009 SetRecommendedLocales(kRecommendedLocales1, arraysize(kRecommendedLocales1));
2010 UploadAndInstallDeviceLocalAccountPolicy();
2011 AddPublicSessionToDevicePolicy(kAccountId1);
2012 EnableAutoLogin();
2014 WaitForPolicy();
2016 WaitForSessionStart();
2018 // Verify that the first recommended locale has been applied and the first
2019 // keyboard layout applicable to the locale was chosen.
2020 EXPECT_EQ(kRecommendedLocales1[0], g_browser_process->GetApplicationLocale());
2021 EXPECT_EQ(l10n_util::GetLanguage(kRecommendedLocales1[0]),
2022 icu::Locale::getDefault().getLanguage());
2023 VerifyKeyboardLayoutMatchesLocale();
2026 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, TermsOfServiceWithLocaleSwitch) {
2027 // Specify Terms of Service URL.
2028 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
2029 device_local_account_policy_.payload().mutable_termsofserviceurl()->set_value(
2030 embedded_test_server()->GetURL(
2031 std::string("/") + kExistentTermsOfServicePath).spec());
2032 UploadAndInstallDeviceLocalAccountPolicy();
2033 AddPublicSessionToDevicePolicy(kAccountId1);
2035 WaitForPolicy();
2037 // Select a different locale.
2038 ASSERT_TRUE(content::ExecuteScript(
2039 contents_,
2040 base::StringPrintf(
2041 "var languageSelect = document.getElementById('pod-row')"
2042 " .getPodWithUsername_('%s').querySelector('.language-select');"
2043 "languageSelect.value = '%s';"
2044 "var event = document.createEvent('HTMLEvents');"
2045 "event.initEvent('change', false, true);"
2046 "languageSelect.dispatchEvent(event);",
2047 user_id_1_.c_str(),
2048 kPublicSessionLocale)));
2050 // The UI will have requested an updated list of keyboard layouts at this
2051 // point. Wait for the constructions of this list to finish.
2052 WaitForGetKeyboardLayoutsForLocaleToFinish();
2054 // Set up an observer that will quit the message loop when login has succeeded
2055 // and the first wizard screen, if any, is being shown.
2056 base::RunLoop login_wait_run_loop;
2057 chromeos::MockAuthStatusConsumer login_status_consumer;
2058 EXPECT_CALL(login_status_consumer, OnAuthSuccess(_)).Times(1).WillOnce(
2059 InvokeWithoutArgs(&login_wait_run_loop, &base::RunLoop::Quit));
2060 chromeos::ExistingUserController* controller =
2061 chromeos::ExistingUserController::current_controller();
2062 ASSERT_TRUE(controller);
2063 controller->set_login_status_consumer(&login_status_consumer);
2065 // Manually select a different keyboard layout and click the enter button to
2066 // start the session.
2067 ASSERT_TRUE(content::ExecuteScript(
2068 contents_,
2069 base::StringPrintf(
2070 "var pod ="
2071 " document.getElementById('pod-row').getPodWithUsername_('%s');"
2072 "pod.querySelector('.keyboard-select').value = '%s';"
2073 "pod.querySelector('.enter-button').click();",
2074 user_id_1_.c_str(),
2075 public_session_input_method_id_.c_str())));
2077 // Spin the loop until the login observer fires. Then, unregister the
2078 // observer.
2079 login_wait_run_loop.Run();
2080 controller->set_login_status_consumer(NULL);
2082 // Verify that the Terms of Service screen is being shown.
2083 chromeos::WizardController* wizard_controller =
2084 chromeos::WizardController::default_controller();
2085 ASSERT_TRUE(wizard_controller);
2086 ASSERT_TRUE(wizard_controller->current_screen());
2087 EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName,
2088 wizard_controller->current_screen()->GetName());
2090 // Wait for the Terms of Service to finish downloading.
2091 bool done = false;
2092 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(contents_,
2093 "var screenElement = document.getElementById('terms-of-service');"
2094 "function SendReplyIfDownloadDone() {"
2095 " if (screenElement.classList.contains('tos-loading'))"
2096 " return false;"
2097 " domAutomationController.send(true);"
2098 " observer.disconnect();"
2099 " return true;"
2101 "var observer = new MutationObserver(SendReplyIfDownloadDone);"
2102 "if (!SendReplyIfDownloadDone()) {"
2103 " var options = { attributes: true, attributeFilter: [ 'class' ] };"
2104 " observer.observe(screenElement, options);"
2105 "}",
2106 &done));
2108 // Verify that the locale and keyboard layout have been applied.
2109 EXPECT_EQ(kPublicSessionLocale, g_browser_process->GetApplicationLocale());
2110 EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale),
2111 icu::Locale::getDefault().getLanguage());
2112 EXPECT_EQ(public_session_input_method_id_,
2113 chromeos::input_method::InputMethodManager::Get()
2114 ->GetActiveIMEState()
2115 ->GetCurrentInputMethod()
2116 .id());
2118 // Wait for 'tos-accept-button' to become enabled.
2119 done = false;
2120 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
2121 contents_,
2122 "var screenElement = document.getElementById('tos-accept-button');"
2123 "function SendReplyIfAcceptEnabled() {"
2124 " if ($('tos-accept-button').disabled)"
2125 " return false;"
2126 " domAutomationController.send(true);"
2127 " observer.disconnect();"
2128 " return true;"
2130 "var observer = new MutationObserver(SendReplyIfAcceptEnabled);"
2131 "if (!SendReplyIfAcceptEnabled()) {"
2132 " var options = { attributes: true };"
2133 " observer.observe(screenElement, options);"
2134 "}",
2135 &done));
2137 // Click the accept button.
2138 ASSERT_TRUE(content::ExecuteScript(contents_,
2139 "$('tos-accept-button').click();"));
2141 WaitForSessionStart();
2143 // Verify that the locale and keyboard layout are still in force.
2144 EXPECT_EQ(kPublicSessionLocale, g_browser_process->GetApplicationLocale());
2145 EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale),
2146 icu::Locale::getDefault().getLanguage());
2147 EXPECT_EQ(public_session_input_method_id_,
2148 chromeos::input_method::InputMethodManager::Get()
2149 ->GetActiveIMEState()
2150 ->GetCurrentInputMethod()
2151 .id());
2154 // Test fails under MSan, http://crbug.com/446950
2155 #if defined(MEMORY_SANITIZER)
2156 #define MAYBE_PolicyForExtensions DISABLED_PolicyForExtensions
2157 #else
2158 #define MAYBE_PolicyForExtensions PolicyForExtensions
2159 #endif
2161 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, MAYBE_PolicyForExtensions) {
2162 // Set up a test update server for the Show Managed Storage app.
2163 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
2164 TestingUpdateManifestProvider testing_update_manifest_provider(
2165 kRelativeUpdateURL);
2166 testing_update_manifest_provider.AddUpdate(
2167 kShowManagedStorageID,
2168 kShowManagedStorageVersion,
2169 embedded_test_server()->GetURL(std::string("/") +
2170 kShowManagedStorageCRXPath));
2171 embedded_test_server()->RegisterRequestHandler(
2172 base::Bind(&TestingUpdateManifestProvider::HandleRequest,
2173 base::Unretained(&testing_update_manifest_provider)));
2175 // Force-install the Show Managed Storage app. This app can be installed in
2176 // public sessions because it's whitelisted for testing purposes.
2177 em::StringList* forcelist = device_local_account_policy_.payload()
2178 .mutable_extensioninstallforcelist()->mutable_value();
2179 forcelist->add_entries(base::StringPrintf(
2180 "%s;%s",
2181 kShowManagedStorageID,
2182 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
2184 // Set a policy for the app at the policy testserver.
2185 // Note that the policy for the device-local account will be fetched before
2186 // the session is started, so the policy for the app must be installed before
2187 // the first device policy fetch.
2188 ASSERT_TRUE(test_server_.UpdatePolicyData(
2189 dm_protocol::kChromeExtensionPolicyType, kShowManagedStorageID,
2191 " \"string\": {"
2192 " \"Value\": \"policy test value one\""
2193 " }"
2194 "}"));
2196 // Install and refresh the device policy now. This will also fetch the initial
2197 // user policy for the device-local account now.
2198 UploadAndInstallDeviceLocalAccountPolicy();
2199 AddPublicSessionToDevicePolicy(kAccountId1);
2200 WaitForPolicy();
2202 // Observe the app installation after login.
2203 content::WindowedNotificationObserver extension_observer(
2204 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
2205 base::Bind(DoesInstallSuccessReferToId, kShowManagedStorageID));
2206 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
2207 WaitForSessionStart();
2208 extension_observer.Wait();
2210 // Verify that the app was installed.
2211 Profile* profile = GetProfileForTest();
2212 ASSERT_TRUE(profile);
2213 ExtensionService* extension_service =
2214 extensions::ExtensionSystem::Get(profile)->extension_service();
2215 EXPECT_TRUE(extension_service->GetExtensionById(kShowManagedStorageID, true));
2217 // Wait for the app policy if it hasn't been fetched yet.
2218 ProfilePolicyConnector* connector =
2219 ProfilePolicyConnectorFactory::GetForBrowserContext(profile);
2220 ASSERT_TRUE(connector);
2221 PolicyService* policy_service = connector->policy_service();
2222 ASSERT_TRUE(policy_service);
2223 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, kShowManagedStorageID);
2224 if (policy_service->GetPolicies(ns).empty()) {
2225 PolicyChangeRegistrar policy_registrar(policy_service, ns);
2226 base::RunLoop run_loop;
2227 policy_registrar.Observe(
2228 "string", base::Bind(&PolicyChangedCallback, run_loop.QuitClosure()));
2229 run_loop.Run();
2232 // Verify that the app policy was set.
2233 base::StringValue expected_value("policy test value one");
2234 EXPECT_TRUE(base::Value::Equals(
2235 &expected_value,
2236 policy_service->GetPolicies(ns).GetValue("string")));
2238 // Now update the policy at the server.
2239 ASSERT_TRUE(test_server_.UpdatePolicyData(
2240 dm_protocol::kChromeExtensionPolicyType, kShowManagedStorageID,
2242 " \"string\": {"
2243 " \"Value\": \"policy test value two\""
2244 " }"
2245 "}"));
2247 // And issue a policy refresh.
2249 PolicyChangeRegistrar policy_registrar(policy_service, ns);
2250 base::RunLoop run_loop;
2251 policy_registrar.Observe(
2252 "string", base::Bind(&PolicyChangedCallback, run_loop.QuitClosure()));
2253 policy_service->RefreshPolicies(base::Closure());
2254 run_loop.Run();
2257 // Verify that the app policy was updated.
2258 base::StringValue expected_new_value("policy test value two");
2259 EXPECT_TRUE(base::Value::Equals(
2260 &expected_new_value,
2261 policy_service->GetPolicies(ns).GetValue("string")));
2264 class TermsOfServiceDownloadTest : public DeviceLocalAccountTest,
2265 public testing::WithParamInterface<bool> {
2268 // Test fails under MSan, http://crbug.com/446950
2269 #if defined(MEMORY_SANITIZER)
2270 #define MAYBE_TermsOfServiceScreen DISABLED_TermsOfServiceScreen
2271 #else
2272 #define MAYBE_TermsOfServiceScreen TermsOfServiceScreen
2273 #endif
2275 IN_PROC_BROWSER_TEST_P(TermsOfServiceDownloadTest, MAYBE_TermsOfServiceScreen) {
2276 // Specify Terms of Service URL.
2277 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
2278 device_local_account_policy_.payload().mutable_termsofserviceurl()->set_value(
2279 embedded_test_server()->GetURL(
2280 std::string("/") +
2281 (GetParam() ? kExistentTermsOfServicePath
2282 : kNonexistentTermsOfServicePath)).spec());
2283 UploadAndInstallDeviceLocalAccountPolicy();
2284 AddPublicSessionToDevicePolicy(kAccountId1);
2286 WaitForPolicy();
2288 ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
2290 // Set up an observer that will quit the message loop when login has succeeded
2291 // and the first wizard screen, if any, is being shown.
2292 base::RunLoop login_wait_run_loop;
2293 chromeos::MockAuthStatusConsumer login_status_consumer;
2294 EXPECT_CALL(login_status_consumer, OnAuthSuccess(_)).Times(1).WillOnce(
2295 InvokeWithoutArgs(&login_wait_run_loop, &base::RunLoop::Quit));
2297 // Spin the loop until the observer fires. Then, unregister the observer.
2298 chromeos::ExistingUserController* controller =
2299 chromeos::ExistingUserController::current_controller();
2300 ASSERT_TRUE(controller);
2301 controller->set_login_status_consumer(&login_status_consumer);
2302 login_wait_run_loop.Run();
2303 controller->set_login_status_consumer(NULL);
2305 // Verify that the Terms of Service screen is being shown.
2306 chromeos::WizardController* wizard_controller =
2307 chromeos::WizardController::default_controller();
2308 ASSERT_TRUE(wizard_controller);
2309 ASSERT_TRUE(wizard_controller->current_screen());
2310 EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName,
2311 wizard_controller->current_screen()->GetName());
2313 // Wait for the Terms of Service to finish downloading, then get the status of
2314 // the screen's UI elements.
2315 std::string json;
2316 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
2317 "var screenElement = document.getElementById('terms-of-service');"
2318 "function SendReplyIfDownloadDone() {"
2319 " if (screenElement.classList.contains('tos-loading'))"
2320 " return false;"
2321 " var status = {};"
2322 " status.heading = document.getElementById('tos-heading').textContent;"
2323 " status.subheading ="
2324 " document.getElementById('tos-subheading').textContent;"
2325 " status.contentHeading ="
2326 " document.getElementById('tos-content-heading').textContent;"
2327 " status.content ="
2328 " document.getElementById('tos-content-main').textContent;"
2329 " status.error = screenElement.classList.contains('error');"
2330 " status.acceptEnabled ="
2331 " !document.getElementById('tos-accept-button').disabled;"
2332 " domAutomationController.send(JSON.stringify(status));"
2333 " observer.disconnect();"
2334 " return true;"
2336 "var observer = new MutationObserver(SendReplyIfDownloadDone);"
2337 "if (!SendReplyIfDownloadDone()) {"
2338 " var options = { attributes: true, attributeFilter: [ 'class' ] };"
2339 " observer.observe(screenElement, options);"
2340 "}",
2341 &json));
2342 scoped_ptr<base::Value> value_ptr(base::JSONReader::Read(json));
2343 const base::DictionaryValue* status = NULL;
2344 ASSERT_TRUE(value_ptr);
2345 ASSERT_TRUE(value_ptr->GetAsDictionary(&status));
2346 std::string heading;
2347 EXPECT_TRUE(status->GetString("heading", &heading));
2348 std::string subheading;
2349 EXPECT_TRUE(status->GetString("subheading", &subheading));
2350 std::string content_heading;
2351 EXPECT_TRUE(status->GetString("contentHeading", &content_heading));
2352 std::string content;
2353 EXPECT_TRUE(status->GetString("content", &content));
2354 bool error;
2355 EXPECT_TRUE(status->GetBoolean("error", &error));
2356 bool accept_enabled;
2357 EXPECT_TRUE(status->GetBoolean("acceptEnabled", &accept_enabled));
2359 // Verify that the screen's headings have been set correctly.
2360 EXPECT_EQ(
2361 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_HEADING,
2362 base::UTF8ToUTF16(kDomain)),
2363 heading);
2364 EXPECT_EQ(
2365 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_SUBHEADING,
2366 base::UTF8ToUTF16(kDomain)),
2367 subheading);
2368 EXPECT_EQ(
2369 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_CONTENT_HEADING,
2370 base::UTF8ToUTF16(kDomain)),
2371 content_heading);
2373 if (!GetParam()) {
2374 // The Terms of Service URL was invalid. Verify that the screen is showing
2375 // an error and the accept button is disabled.
2376 EXPECT_TRUE(error);
2377 EXPECT_FALSE(accept_enabled);
2378 return;
2381 // The Terms of Service URL was valid. Verify that the screen is showing the
2382 // downloaded Terms of Service and the accept button is enabled.
2383 base::FilePath test_dir;
2384 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
2385 std::string terms_of_service;
2386 ASSERT_TRUE(base::ReadFileToString(
2387 test_dir.Append(kExistentTermsOfServicePath), &terms_of_service));
2388 EXPECT_EQ(terms_of_service, content);
2389 EXPECT_FALSE(error);
2390 EXPECT_TRUE(accept_enabled);
2392 // Click the accept button.
2393 ASSERT_TRUE(content::ExecuteScript(contents_,
2394 "$('tos-accept-button').click();"));
2396 WaitForSessionStart();
2399 INSTANTIATE_TEST_CASE_P(TermsOfServiceDownloadTestInstance,
2400 TermsOfServiceDownloadTest, testing::Bool());
2402 } // namespace policy