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.
8 #include "apps/app_window_registry.h"
9 #include "apps/ui/native_app_window.h"
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/file_util.h"
19 #include "base/files/file_path.h"
20 #include "base/files/scoped_temp_dir.h"
21 #include "base/json/json_reader.h"
22 #include "base/json/json_writer.h"
23 #include "base/location.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_service.h"
30 #include "base/run_loop.h"
31 #include "base/sequenced_task_runner.h"
32 #include "base/strings/string_number_conversions.h"
33 #include "base/strings/string_util.h"
34 #include "base/strings/stringprintf.h"
35 #include "base/strings/utf_string_conversions.h"
36 #include "base/test/scoped_path_override.h"
37 #include "base/values.h"
38 #include "chrome/browser/browser_process.h"
39 #include "chrome/browser/chrome_notification_types.h"
40 #include "chrome/browser/chromeos/login/existing_user_controller.h"
41 #include "chrome/browser/chromeos/login/login_display_host.h"
42 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
43 #include "chrome/browser/chromeos/login/mock_login_status_consumer.h"
44 #include "chrome/browser/chromeos/login/screens/wizard_screen.h"
45 #include "chrome/browser/chromeos/login/user.h"
46 #include "chrome/browser/chromeos/login/user_image_manager.h"
47 #include "chrome/browser/chromeos/login/user_image_manager_impl.h"
48 #include "chrome/browser/chromeos/login/user_image_manager_test_util.h"
49 #include "chrome/browser/chromeos/login/user_manager.h"
50 #include "chrome/browser/chromeos/login/user_manager_impl.h"
51 #include "chrome/browser/chromeos/login/webui_login_view.h"
52 #include "chrome/browser/chromeos/login/wizard_controller.h"
53 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
54 #include "chrome/browser/chromeos/policy/cloud_external_data_manager_base_test_util.h"
55 #include "chrome/browser/chromeos/policy/device_local_account.h"
56 #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
57 #include "chrome/browser/chromeos/policy/device_policy_builder.h"
58 #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
59 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
60 #include "chrome/browser/extensions/crx_installer.h"
61 #include "chrome/browser/extensions/extension_service.h"
62 #include "chrome/browser/lifetime/application_lifetime.h"
63 #include "chrome/browser/policy/profile_policy_connector.h"
64 #include "chrome/browser/policy/profile_policy_connector_factory.h"
65 #include "chrome/browser/policy/test/local_policy_test_server.h"
66 #include "chrome/browser/prefs/session_startup_pref.h"
67 #include "chrome/browser/profiles/profile.h"
68 #include "chrome/browser/profiles/profile_manager.h"
69 #include "chrome/browser/ui/browser.h"
70 #include "chrome/browser/ui/browser_commands.h"
71 #include "chrome/browser/ui/browser_finder.h"
72 #include "chrome/browser/ui/browser_list.h"
73 #include "chrome/browser/ui/browser_list_observer.h"
74 #include "chrome/browser/ui/browser_window.h"
75 #include "chrome/browser/ui/extensions/application_launch.h"
76 #include "chrome/browser/ui/host_desktop.h"
77 #include "chrome/browser/ui/tabs/tab_strip_model.h"
78 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
79 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
80 #include "chrome/common/chrome_paths.h"
81 #include "chrome/common/extensions/extension_constants.h"
82 #include "chromeos/chromeos_paths.h"
83 #include "chromeos/chromeos_switches.h"
84 #include "chromeos/dbus/fake_session_manager_client.h"
85 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
86 #include "components/policy/core/common/cloud/cloud_policy_core.h"
87 #include "components/policy/core/common/cloud/cloud_policy_store.h"
88 #include "components/policy/core/common/cloud/policy_builder.h"
89 #include "components/policy/core/common/external_data_fetcher.h"
90 #include "components/policy/core/common/policy_map.h"
91 #include "components/policy/core/common/policy_namespace.h"
92 #include "components/policy/core/common/policy_service.h"
93 #include "components/policy/core/common/policy_switches.h"
94 #include "components/signin/core/common/signin_pref_names.h"
95 #include "content/public/browser/notification_details.h"
96 #include "content/public/browser/notification_service.h"
97 #include "content/public/browser/notification_source.h"
98 #include "content/public/browser/web_contents.h"
99 #include "content/public/browser/web_ui.h"
100 #include "content/public/test/browser_test_utils.h"
101 #include "content/public/test/test_utils.h"
102 #include "crypto/rsa_private_key.h"
103 #include "extensions/browser/extension_system.h"
104 #include "extensions/browser/management_policy.h"
105 #include "extensions/common/extension.h"
106 #include "grit/chromium_strings.h"
107 #include "grit/generated_resources.h"
108 #include "net/base/url_util.h"
109 #include "net/http/http_status_code.h"
110 #include "net/test/embedded_test_server/embedded_test_server.h"
111 #include "net/test/embedded_test_server/http_request.h"
112 #include "net/test/embedded_test_server/http_response.h"
113 #include "net/url_request/test_url_fetcher_factory.h"
114 #include "net/url_request/url_fetcher_delegate.h"
115 #include "net/url_request/url_request_status.h"
116 #include "policy/policy_constants.h"
117 #include "testing/gmock/include/gmock/gmock.h"
118 #include "ui/base/l10n/l10n_util.h"
119 #include "ui/base/window_open_disposition.h"
120 #include "ui/gfx/image/image_skia.h"
121 #include "ui/views/widget/widget.h"
122 #include "url/gurl.h"
123 //#include "third_party/cros_system_api/dbus/service_constants.h"
125 namespace em = enterprise_management;
127 using chromeos::LoginScreenContext;
128 using testing::InvokeWithoutArgs;
129 using testing::Return;
136 const char kDomain[] = "example.com";
137 const char kAccountId1[] = "dla1@example.com";
138 const char kAccountId2[] = "dla2@example.com";
139 const char kDisplayName[] = "display name";
140 const char* kStartupURLs[] = {
144 const char kExistentTermsOfServicePath[] = "chromeos/enterprise/tos.txt";
145 const char kNonexistentTermsOfServicePath[] = "chromeos/enterprise/tos404.txt";
146 const char kRelativeUpdateURL[] = "/service/update2/crx";
147 const char kUpdateManifestHeader[] =
148 "<?xml version='1.0' encoding='UTF-8'?>\n"
149 "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>\n";
150 const char kUpdateManifestTemplate[] =
151 " <app appid='%s'>\n"
152 " <updatecheck codebase='%s' version='%s' />\n"
154 const char kUpdateManifestFooter[] =
156 const char kHostedAppID[] = "kbmnembihfiondgfjekmnmcbddelicoi";
157 const char kHostedAppCRXPath[] = "extensions/hosted_app.crx";
158 const char kHostedAppVersion[] = "1.0.0.0";
159 const char kGoodExtensionID[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
160 const char kGoodExtensionCRXPath[] = "extensions/good.crx";
161 const char kGoodExtensionVersion[] = "1.0";
162 const char kPackagedAppCRXPath[] = "extensions/platform_apps/app_window_2.crx";
164 const char kExternalData[] = "External data";
165 const char kExternalDataURL[] = "http://localhost/external_data";
167 // Helper that serves extension update manifests to Chrome.
168 class TestingUpdateManifestProvider {
170 // Update manifests will be served at |relative_update_url|.
171 explicit TestingUpdateManifestProvider(
172 const std::string& relative_update_url);
173 ~TestingUpdateManifestProvider();
175 // When an update manifest is requested for the given extension |id|, indicate
176 // that |version| of the extension can be downloaded at |crx_url|.
177 void AddUpdate(const std::string& id,
178 const std::string& version,
179 const GURL& crx_url);
181 // This method must be registered with the test's EmbeddedTestServer to start
182 // serving update manifests.
183 scoped_ptr<net::test_server::HttpResponse> HandleRequest(
184 const net::test_server::HttpRequest& request);
189 Update(const std::string& version, const GURL& crx_url);
195 typedef std::map<std::string, Update> UpdateMap;
198 const std::string relative_update_url_;
200 DISALLOW_COPY_AND_ASSIGN(TestingUpdateManifestProvider);
203 TestingUpdateManifestProvider::Update::Update(const std::string& version,
209 TestingUpdateManifestProvider::Update::Update() {
212 TestingUpdateManifestProvider::TestingUpdateManifestProvider(
213 const std::string& relative_update_url)
214 : relative_update_url_(relative_update_url) {
217 TestingUpdateManifestProvider::~TestingUpdateManifestProvider() {
220 void TestingUpdateManifestProvider::AddUpdate(const std::string& id,
221 const std::string& version,
222 const GURL& crx_url) {
223 updates_[id] = Update(version, crx_url);
226 scoped_ptr<net::test_server::HttpResponse>
227 TestingUpdateManifestProvider::HandleRequest(
228 const net::test_server::HttpRequest& request) {
229 const GURL url("http://localhost" + request.relative_url);
230 if (url.path() != relative_update_url_)
231 return scoped_ptr<net::test_server::HttpResponse>();
233 std::string content = kUpdateManifestHeader;
234 for (net::QueryIterator it(url); !it.IsAtEnd(); it.Advance()) {
235 if (it.GetKey() != "x")
237 // Extract the extension id from the subquery. Since GetValueForKeyInQuery()
238 // expects a complete URL, dummy scheme and host must be prepended.
240 net::GetValueForKeyInQuery(GURL("http://dummy?" + it.GetUnescapedValue()),
242 UpdateMap::const_iterator entry = updates_.find(id);
243 if (entry != updates_.end()) {
244 content += base::StringPrintf(kUpdateManifestTemplate,
246 entry->second.crx_url.spec().c_str(),
247 entry->second.version.c_str());
250 content += kUpdateManifestFooter;
251 scoped_ptr<net::test_server::BasicHttpResponse>
252 http_response(new net::test_server::BasicHttpResponse);
253 http_response->set_code(net::HTTP_OK);
254 http_response->set_content(content);
255 http_response->set_content_type("text/xml");
256 return http_response.PassAs<net::test_server::HttpResponse>();
259 bool DoesInstallSuccessReferToId(const std::string& id,
260 const content::NotificationSource& source,
261 const content::NotificationDetails& details) {
262 return content::Details<const extensions::InstalledExtensionInfo>(details)->
263 extension->id() == id;
266 bool DoesInstallFailureReferToId(const std::string& id,
267 const content::NotificationSource& source,
268 const content::NotificationDetails& details) {
269 return content::Details<const base::string16>(details)->
270 find(base::UTF8ToUTF16(id)) != base::string16::npos;
273 scoped_ptr<net::FakeURLFetcher> RunCallbackAndReturnFakeURLFetcher(
274 scoped_refptr<base::SequencedTaskRunner> task_runner,
275 const base::Closure& callback,
277 net::URLFetcherDelegate* delegate,
278 const std::string& response_data,
279 net::HttpStatusCode response_code,
280 net::URLRequestStatus::Status status) {
281 task_runner->PostTask(FROM_HERE, callback);
282 return make_scoped_ptr(new net::FakeURLFetcher(
283 url, delegate, response_data, response_code, status));
288 class DeviceLocalAccountTest : public DevicePolicyCrosBrowserTest,
289 public chromeos::UserManager::Observer,
290 public chrome::BrowserListObserver,
291 public apps::AppWindowRegistry::Observer {
293 DeviceLocalAccountTest()
294 : user_id_1_(GenerateDeviceLocalAccountUserId(
295 kAccountId1, DeviceLocalAccount::TYPE_PUBLIC_SESSION)),
296 user_id_2_(GenerateDeviceLocalAccountUserId(
297 kAccountId2, DeviceLocalAccount::TYPE_PUBLIC_SESSION)) {
298 set_exit_when_last_browser_closes(false);
301 virtual ~DeviceLocalAccountTest() {}
303 virtual void SetUp() OVERRIDE {
304 // Configure and start the test server.
305 scoped_ptr<crypto::RSAPrivateKey> signing_key(
306 PolicyBuilder::CreateTestSigningKey());
307 ASSERT_TRUE(test_server_.SetSigningKeyAndSignature(
308 signing_key.get(), PolicyBuilder::GetTestSigningKeySignature()));
310 test_server_.RegisterClient(PolicyBuilder::kFakeToken,
311 PolicyBuilder::kFakeDeviceId);
312 ASSERT_TRUE(test_server_.Start());
314 ASSERT_TRUE(extension_cache_root_dir_.CreateUniqueTempDir());
315 extension_cache_root_dir_override_.reset(new base::ScopedPathOverride(
316 chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
317 extension_cache_root_dir_.path()));
318 ASSERT_TRUE(external_data_cache_dir_.CreateUniqueTempDir());
319 external_data_cache_dir_override_.reset(new base::ScopedPathOverride(
320 chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTERNAL_DATA,
321 external_data_cache_dir_.path()));
323 BrowserList::AddObserver(this);
325 DevicePolicyCrosBrowserTest::SetUp();
328 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
329 DevicePolicyCrosBrowserTest::SetUpCommandLine(command_line);
330 command_line->AppendSwitch(chromeos::switches::kLoginManager);
331 command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests);
332 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
333 command_line->AppendSwitchASCII(policy::switches::kDeviceManagementUrl,
334 test_server_.GetServiceURL().spec());
337 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
338 DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
340 // Clear command-line arguments (but keep command-line switches) so the
341 // startup pages policy takes effect.
342 CommandLine* command_line = CommandLine::ForCurrentProcess();
343 CommandLine::StringVector argv(command_line->argv());
344 argv.erase(argv.begin() + argv.size() - command_line->GetArgs().size(),
346 command_line->InitFromArgv(argv);
349 MarkAsEnterpriseOwned();
354 virtual void CleanUpOnMainThread() OVERRIDE {
355 BrowserList::RemoveObserver(this);
357 // This shuts down the login UI.
358 base::MessageLoop::current()->PostTask(FROM_HERE,
359 base::Bind(&chrome::AttemptExit));
360 base::RunLoop().RunUntilIdle();
363 virtual void LocalStateChanged(chromeos::UserManager* user_manager) OVERRIDE {
368 virtual void OnBrowserRemoved(Browser* browser) OVERRIDE {
373 virtual void OnAppWindowAdded(apps::AppWindow* app_window) OVERRIDE {
378 virtual void OnAppWindowRemoved(apps::AppWindow* app_window) OVERRIDE {
383 void InitializePolicy() {
384 device_policy()->policy_data().set_public_key_version(1);
385 em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
386 proto.mutable_show_user_names()->set_show_user_names(true);
388 device_local_account_policy_.policy_data().set_policy_type(
389 dm_protocol::kChromePublicAccountPolicyType);
390 device_local_account_policy_.policy_data().set_username(kAccountId1);
391 device_local_account_policy_.policy_data().set_settings_entity_id(
393 device_local_account_policy_.policy_data().set_public_key_version(1);
394 device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
398 void BuildDeviceLocalAccountPolicy() {
399 device_local_account_policy_.SetDefaultSigningKey();
400 device_local_account_policy_.Build();
403 void UploadDeviceLocalAccountPolicy() {
404 BuildDeviceLocalAccountPolicy();
405 test_server_.UpdatePolicy(
406 dm_protocol::kChromePublicAccountPolicyType, kAccountId1,
407 device_local_account_policy_.payload().SerializeAsString());
410 void UploadAndInstallDeviceLocalAccountPolicy() {
411 UploadDeviceLocalAccountPolicy();
412 session_manager_client()->set_device_local_account_policy(
413 kAccountId1, device_local_account_policy_.GetBlob());
416 void AddPublicSessionToDevicePolicy(const std::string& username) {
417 em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
418 em::DeviceLocalAccountInfoProto* account =
419 proto.mutable_device_local_accounts()->add_account();
420 account->set_account_id(username);
422 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
423 RefreshDevicePolicy();
424 test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType,
425 std::string(), proto.SerializeAsString());
428 void CheckPublicSessionPresent(const std::string& id) {
429 const chromeos::User* user = chromeos::UserManager::Get()->FindUser(id);
431 EXPECT_EQ(id, user->email());
432 EXPECT_EQ(chromeos::User::USER_TYPE_PUBLIC_ACCOUNT, user->GetType());
435 base::FilePath GetCacheDirectoryForAccountID(const std::string& account_id) {
436 return extension_cache_root_dir_.path()
437 .Append(base::HexEncode(account_id.c_str(), account_id.size()));
440 base::FilePath GetCacheCRXFile(const std::string& account_id,
441 const std::string& id,
442 const std::string& version) {
443 return GetCacheDirectoryForAccountID(account_id)
444 .Append(base::StringPrintf("%s-%s.crx", id.c_str(), version.c_str()));
447 // Returns a profile which can be used for testing.
448 Profile* GetProfileForTest() {
449 // Any profile can be used here since this test does not test multi profile.
450 return ProfileManager::GetActiveUserProfile();
453 const std::string user_id_1_;
454 const std::string user_id_2_;
456 scoped_ptr<base::RunLoop> run_loop_;
458 UserPolicyBuilder device_local_account_policy_;
459 LocalPolicyTestServer test_server_;
462 base::ScopedTempDir extension_cache_root_dir_;
463 base::ScopedTempDir external_data_cache_dir_;
464 scoped_ptr<base::ScopedPathOverride> extension_cache_root_dir_override_;
465 scoped_ptr<base::ScopedPathOverride> external_data_cache_dir_override_;
467 DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountTest);
470 static bool IsKnownUser(const std::string& account_id) {
471 return chromeos::UserManager::Get()->IsKnownUser(account_id);
474 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LoginScreen) {
475 AddPublicSessionToDevicePolicy(kAccountId1);
476 AddPublicSessionToDevicePolicy(kAccountId2);
478 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
479 base::Bind(&IsKnownUser, user_id_1_))
481 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
482 base::Bind(&IsKnownUser, user_id_2_))
485 CheckPublicSessionPresent(user_id_1_);
486 CheckPublicSessionPresent(user_id_2_);
489 static bool DisplayNameMatches(const std::string& account_id,
490 const std::string& display_name) {
491 const chromeos::User* user =
492 chromeos::UserManager::Get()->FindUser(account_id);
493 if (!user || user->display_name().empty())
495 EXPECT_EQ(base::UTF8ToUTF16(display_name), user->display_name());
499 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DisplayName) {
500 UploadAndInstallDeviceLocalAccountPolicy();
501 AddPublicSessionToDevicePolicy(kAccountId1);
503 content::WindowedNotificationObserver(
504 chrome::NOTIFICATION_USER_LIST_CHANGED,
505 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
508 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyDownload) {
509 UploadDeviceLocalAccountPolicy();
510 AddPublicSessionToDevicePolicy(kAccountId1);
512 // Policy for the account is not installed in session_manager_client. Because
513 // of this, the presence of the display name (which comes from policy) can be
514 // used as a signal that indicates successful policy download.
515 content::WindowedNotificationObserver(
516 chrome::NOTIFICATION_USER_LIST_CHANGED,
517 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
519 // Sanity check: The policy should be present now.
520 ASSERT_FALSE(session_manager_client()->device_local_account_policy(
521 kAccountId1).empty());
524 static bool IsNotKnownUser(const std::string& account_id) {
525 return !IsKnownUser(account_id);
528 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DevicePolicyChange) {
529 AddPublicSessionToDevicePolicy(kAccountId1);
530 AddPublicSessionToDevicePolicy(kAccountId2);
532 // Wait until the login screen is up.
533 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
534 base::Bind(&IsKnownUser, user_id_1_))
536 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
537 base::Bind(&IsKnownUser, user_id_2_))
540 // Update policy to remove kAccountId2.
541 em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
542 proto.mutable_device_local_accounts()->clear_account();
543 AddPublicSessionToDevicePolicy(kAccountId1);
545 em::ChromeDeviceSettingsProto policy;
546 policy.mutable_show_user_names()->set_show_user_names(true);
547 em::DeviceLocalAccountInfoProto* account1 =
548 policy.mutable_device_local_accounts()->add_account();
549 account1->set_account_id(kAccountId1);
551 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
553 test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType, std::string(),
554 policy.SerializeAsString());
555 g_browser_process->policy_service()->RefreshPolicies(base::Closure());
557 // Make sure the second device-local account disappears.
558 content::WindowedNotificationObserver(
559 chrome::NOTIFICATION_USER_LIST_CHANGED,
560 base::Bind(&IsNotKnownUser, user_id_2_)).Wait();
563 static bool IsSessionStarted() {
564 return chromeos::UserManager::Get()->IsSessionStarted();
567 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, StartSession) {
568 // Specify startup pages.
569 device_local_account_policy_.payload().mutable_restoreonstartup()->set_value(
570 SessionStartupPref::kPrefValueURLs);
571 em::StringListPolicyProto* startup_urls_proto =
572 device_local_account_policy_.payload().mutable_restoreonstartupurls();
573 for (size_t i = 0; i < arraysize(kStartupURLs); ++i)
574 startup_urls_proto->mutable_value()->add_entries(kStartupURLs[i]);
575 UploadAndInstallDeviceLocalAccountPolicy();
576 AddPublicSessionToDevicePolicy(kAccountId1);
578 // This observes the display name becoming available as this indicates
579 // device-local account policy is fully loaded, which is a prerequisite for
581 content::WindowedNotificationObserver(
582 chrome::NOTIFICATION_USER_LIST_CHANGED,
583 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
585 // Wait for the login UI to be ready.
586 chromeos::LoginDisplayHostImpl* host =
587 reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
588 chromeos::LoginDisplayHostImpl::default_host());
590 chromeos::OobeUI* oobe_ui = host->GetOobeUI();
591 ASSERT_TRUE(oobe_ui);
592 base::RunLoop run_loop;
593 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure());
597 // Start login into the device-local account.
598 host->StartSignInScreen(LoginScreenContext());
599 chromeos::ExistingUserController* controller =
600 chromeos::ExistingUserController::current_controller();
601 ASSERT_TRUE(controller);
602 controller->LoginAsPublicAccount(user_id_1_);
604 // Wait for the session to start.
605 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED,
606 base::Bind(IsSessionStarted)).Wait();
608 // Check that the startup pages specified in policy were opened.
609 BrowserList* browser_list =
610 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
611 EXPECT_EQ(1U, browser_list->size());
612 Browser* browser = browser_list->get(0);
613 ASSERT_TRUE(browser);
615 TabStripModel* tabs = browser->tab_strip_model();
617 int expected_tab_count = static_cast<int>(arraysize(kStartupURLs));
618 EXPECT_EQ(expected_tab_count, tabs->count());
619 for (int i = 0; i < expected_tab_count && i < tabs->count(); ++i) {
620 EXPECT_EQ(GURL(kStartupURLs[i]),
621 tabs->GetWebContentsAt(i)->GetVisibleURL());
624 // Verify that the session is not considered to be logged in with a GAIA
626 Profile* profile = GetProfileForTest();
627 ASSERT_TRUE(profile);
628 EXPECT_FALSE(profile->GetPrefs()->HasPrefPath(
629 prefs::kGoogleServicesUsername));
632 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, FullscreenDisallowed) {
633 UploadAndInstallDeviceLocalAccountPolicy();
634 AddPublicSessionToDevicePolicy(kAccountId1);
636 // This observes the display name becoming available as this indicates
637 // device-local account policy is fully loaded, which is a prerequisite for
639 content::WindowedNotificationObserver(
640 chrome::NOTIFICATION_USER_LIST_CHANGED,
641 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
643 // Wait for the login UI to be ready.
644 chromeos::LoginDisplayHostImpl* host =
645 reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
646 chromeos::LoginDisplayHostImpl::default_host());
648 chromeos::OobeUI* oobe_ui = host->GetOobeUI();
649 ASSERT_TRUE(oobe_ui);
650 base::RunLoop run_loop;
651 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure());
655 // Start login into the device-local account.
656 host->StartSignInScreen(LoginScreenContext());
657 chromeos::ExistingUserController* controller =
658 chromeos::ExistingUserController::current_controller();
659 ASSERT_TRUE(controller);
660 controller->LoginAsPublicAccount(user_id_1_);
662 // Wait for the session to start.
663 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED,
664 base::Bind(IsSessionStarted)).Wait();
666 BrowserList* browser_list =
667 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
668 EXPECT_EQ(1U, browser_list->size());
669 Browser* browser = browser_list->get(0);
670 ASSERT_TRUE(browser);
671 BrowserWindow* browser_window = browser->window();
672 ASSERT_TRUE(browser_window);
674 // Verify that an attempt to enter fullscreen mode is denied.
675 EXPECT_FALSE(browser_window->IsFullscreen());
676 chrome::ToggleFullscreenMode(browser);
677 EXPECT_FALSE(browser_window->IsFullscreen());
680 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExtensionsUncached) {
681 // Make it possible to force-install a hosted app and an extension.
682 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
683 TestingUpdateManifestProvider testing_update_manifest_provider(
685 testing_update_manifest_provider.AddUpdate(
688 embedded_test_server()->GetURL(std::string("/") + kHostedAppCRXPath));
689 testing_update_manifest_provider.AddUpdate(
691 kGoodExtensionVersion,
692 embedded_test_server()->GetURL(std::string("/") + kGoodExtensionCRXPath));
693 embedded_test_server()->RegisterRequestHandler(
694 base::Bind(&TestingUpdateManifestProvider::HandleRequest,
695 base::Unretained(&testing_update_manifest_provider)));
697 // Specify policy to force-install the hosted app and the extension.
698 em::StringList* forcelist = device_local_account_policy_.payload()
699 .mutable_extensioninstallforcelist()->mutable_value();
700 forcelist->add_entries(base::StringPrintf(
703 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
704 forcelist->add_entries(base::StringPrintf(
707 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
709 UploadAndInstallDeviceLocalAccountPolicy();
710 AddPublicSessionToDevicePolicy(kAccountId1);
712 // This observes the display name becoming available as this indicates
713 // device-local account policy is fully loaded, which is a prerequisite for
715 content::WindowedNotificationObserver(
716 chrome::NOTIFICATION_USER_LIST_CHANGED,
717 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
719 // Wait for the login UI to be ready.
720 chromeos::LoginDisplayHostImpl* host =
721 reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
722 chromeos::LoginDisplayHostImpl::default_host());
724 chromeos::OobeUI* oobe_ui = host->GetOobeUI();
725 ASSERT_TRUE(oobe_ui);
726 base::RunLoop run_loop;
727 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure());
731 // Start listening for app/extension installation results.
732 content::WindowedNotificationObserver hosted_app_observer(
733 chrome::NOTIFICATION_EXTENSION_INSTALLED,
734 base::Bind(DoesInstallSuccessReferToId, kHostedAppID));
735 content::WindowedNotificationObserver extension_observer(
736 chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
737 base::Bind(DoesInstallFailureReferToId, kGoodExtensionID));
739 // Start login into the device-local account.
740 host->StartSignInScreen(LoginScreenContext());
741 chromeos::ExistingUserController* controller =
742 chromeos::ExistingUserController::current_controller();
743 ASSERT_TRUE(controller);
744 controller->LoginAsPublicAccount(user_id_1_);
746 // Wait for the hosted app installation to succeed and the extension
747 // installation to fail (because hosted apps are whitelisted for use in
748 // device-local accounts and extensions are not).
749 hosted_app_observer.Wait();
750 extension_observer.Wait();
752 // Verify that the hosted app was installed.
753 Profile* profile = GetProfileForTest();
754 ASSERT_TRUE(profile);
755 ExtensionService* extension_service =
756 extensions::ExtensionSystem::Get(profile)->extension_service();
757 EXPECT_TRUE(extension_service->GetExtensionById(kHostedAppID, true));
759 // Verify that the extension was not installed.
760 EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true));
762 // Verify that the app was copied to the account's extension cache.
763 base::FilePath test_dir;
764 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
765 EXPECT_TRUE(ContentsEqual(
766 GetCacheCRXFile(kAccountId1, kHostedAppID, kHostedAppVersion),
767 test_dir.Append(kHostedAppCRXPath)));
769 // Verify that the extension was not copied to the account's extension cache.
770 EXPECT_FALSE(PathExists(GetCacheCRXFile(
771 kAccountId1, kGoodExtensionID, kGoodExtensionVersion)));
774 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExtensionsCached) {
775 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
777 // Pre-populate the device local account's extension cache with a hosted app
779 EXPECT_TRUE(base::CreateDirectory(
780 GetCacheDirectoryForAccountID(kAccountId1)));
781 base::FilePath test_dir;
782 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
783 const base::FilePath cached_hosted_app =
784 GetCacheCRXFile(kAccountId1, kHostedAppID, kHostedAppVersion);
785 EXPECT_TRUE(CopyFile(test_dir.Append(kHostedAppCRXPath),
787 const base::FilePath cached_extension =
788 GetCacheCRXFile(kAccountId1, kGoodExtensionID, kGoodExtensionVersion);
789 EXPECT_TRUE(CopyFile(test_dir.Append(kGoodExtensionCRXPath),
792 // Specify policy to force-install the hosted app.
793 em::StringList* forcelist = device_local_account_policy_.payload()
794 .mutable_extensioninstallforcelist()->mutable_value();
795 forcelist->add_entries(base::StringPrintf(
798 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
799 forcelist->add_entries(base::StringPrintf(
802 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
804 UploadAndInstallDeviceLocalAccountPolicy();
805 AddPublicSessionToDevicePolicy(kAccountId1);
807 // This observes the display name becoming available as this indicates
808 // device-local account policy is fully loaded, which is a prerequisite for
810 content::WindowedNotificationObserver(
811 chrome::NOTIFICATION_USER_LIST_CHANGED,
812 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
814 // Wait for the login UI to be ready.
815 chromeos::LoginDisplayHostImpl* host =
816 reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
817 chromeos::LoginDisplayHostImpl::default_host());
819 chromeos::OobeUI* oobe_ui = host->GetOobeUI();
820 ASSERT_TRUE(oobe_ui);
821 base::RunLoop run_loop;
822 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure());
826 // Start listening for app/extension installation results.
827 content::WindowedNotificationObserver hosted_app_observer(
828 chrome::NOTIFICATION_EXTENSION_INSTALLED,
829 base::Bind(DoesInstallSuccessReferToId, kHostedAppID));
830 content::WindowedNotificationObserver extension_observer(
831 chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
832 base::Bind(DoesInstallFailureReferToId, kGoodExtensionID));
834 // Start login into the device-local account.
835 host->StartSignInScreen(LoginScreenContext());
836 chromeos::ExistingUserController* controller =
837 chromeos::ExistingUserController::current_controller();
838 ASSERT_TRUE(controller);
839 controller->LoginAsPublicAccount(user_id_1_);
841 // Wait for the hosted app installation to succeed and the extension
842 // installation to fail.
843 hosted_app_observer.Wait();
844 extension_observer.Wait();
846 // Verify that the hosted app was installed.
847 Profile* profile = GetProfileForTest();
848 ASSERT_TRUE(profile);
849 ExtensionService* extension_service =
850 extensions::ExtensionSystem::Get(profile)->extension_service();
851 EXPECT_TRUE(extension_service->GetExtensionById(kHostedAppID, true));
853 // Verify that the extension was not installed.
854 EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true));
856 // Verify that the app is still in the account's extension cache.
857 EXPECT_TRUE(PathExists(cached_hosted_app));
859 // Verify that the extension was removed from the account's extension cache.
860 EXPECT_FALSE(PathExists(cached_extension));
863 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExternalData) {
864 // chromeos::UserManager requests an external data fetch whenever
865 // the key::kUserAvatarImage policy is set. Since this test wants to
866 // verify that the underlying policy subsystem will start a fetch
867 // without this request as well, the chromeos::UserManager must be
868 // prevented from seeing the policy change.
869 reinterpret_cast<chromeos::UserManagerImpl*>(chromeos::UserManager::Get())->
870 StopPolicyObserverForTesting();
872 UploadDeviceLocalAccountPolicy();
873 AddPublicSessionToDevicePolicy(kAccountId1);
875 // This observes the display name becoming available as this indicates
876 // device-local account policy is fully loaded.
877 content::WindowedNotificationObserver(
878 chrome::NOTIFICATION_USER_LIST_CHANGED,
879 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
881 // Start serving external data at |kExternalDataURL|.
882 scoped_ptr<base::RunLoop> run_loop(new base::RunLoop);
883 scoped_ptr<net::FakeURLFetcherFactory> fetcher_factory(
884 new net::FakeURLFetcherFactory(
886 base::Bind(&RunCallbackAndReturnFakeURLFetcher,
887 base::MessageLoopProxy::current(),
888 run_loop->QuitClosure())));
889 fetcher_factory->SetFakeResponse(GURL(kExternalDataURL),
892 net::URLRequestStatus::SUCCESS);
894 // Specify an external data reference for the key::kUserAvatarImage policy.
895 scoped_ptr<base::DictionaryValue> metadata =
896 test::ConstructExternalDataReference(kExternalDataURL, kExternalData);
898 base::JSONWriter::Write(metadata.get(), &policy);
899 device_local_account_policy_.payload().mutable_useravatarimage()->set_value(
901 UploadAndInstallDeviceLocalAccountPolicy();
902 policy::BrowserPolicyConnectorChromeOS* connector =
903 g_browser_process->platform_part()->browser_policy_connector_chromeos();
904 DeviceLocalAccountPolicyBroker* broker =
905 connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
908 broker->core()->store()->Load();
910 // The external data should be fetched and cached automatically. Wait for this
914 // Stop serving external data at |kExternalDataURL|.
915 fetcher_factory.reset();
917 const PolicyMap::Entry* policy_entry =
918 broker->core()->store()->policy_map().Get(key::kUserAvatarImage);
919 ASSERT_TRUE(policy_entry);
920 ASSERT_TRUE(policy_entry->external_data_fetcher);
922 // Retrieve the external data. Although the data is no longer being served at
923 // |kExternalDataURL|, the retrieval should succeed because the data has been
925 run_loop.reset(new base::RunLoop);
926 scoped_ptr<std::string> fetched_external_data;
927 policy_entry->external_data_fetcher->Fetch(base::Bind(
928 &test::ExternalDataFetchCallback,
929 &fetched_external_data,
930 run_loop->QuitClosure()));
933 ASSERT_TRUE(fetched_external_data);
934 EXPECT_EQ(kExternalData, *fetched_external_data);
936 // Wait for the login UI to be ready.
937 chromeos::LoginDisplayHostImpl* host =
938 reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
939 chromeos::LoginDisplayHostImpl::default_host());
941 chromeos::OobeUI* oobe_ui = host->GetOobeUI();
942 ASSERT_TRUE(oobe_ui);
943 run_loop.reset(new base::RunLoop);
944 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop->QuitClosure());
948 // Start login into the device-local account.
949 host->StartSignInScreen(LoginScreenContext());
950 chromeos::ExistingUserController* controller =
951 chromeos::ExistingUserController::current_controller();
952 ASSERT_TRUE(controller);
953 controller->LoginAsPublicAccount(user_id_1_);
955 // Wait for the session to start.
956 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED,
957 base::Bind(IsSessionStarted)).Wait();
959 // Verify that the external data reference has propagated to the device-local
960 // account's ProfilePolicyConnector.
961 ProfilePolicyConnector* policy_connector =
962 ProfilePolicyConnectorFactory::GetForProfile(GetProfileForTest());
963 ASSERT_TRUE(policy_connector);
964 const PolicyMap& policies = policy_connector->policy_service()->GetPolicies(
965 PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
966 policy_entry = policies.Get(key::kUserAvatarImage);
967 ASSERT_TRUE(policy_entry);
968 EXPECT_TRUE(base::Value::Equals(metadata.get(), policy_entry->value));
969 ASSERT_TRUE(policy_entry->external_data_fetcher);
971 // Retrieve the external data via the ProfilePolicyConnector. The retrieval
972 // should succeed because the data has been cached.
973 run_loop.reset(new base::RunLoop);
974 fetched_external_data.reset();
975 policy_entry->external_data_fetcher->Fetch(base::Bind(
976 &test::ExternalDataFetchCallback,
977 &fetched_external_data,
978 run_loop->QuitClosure()));
981 ASSERT_TRUE(fetched_external_data);
982 EXPECT_EQ(kExternalData, *fetched_external_data);
985 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, UserAvatarImage) {
986 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
988 UploadDeviceLocalAccountPolicy();
989 AddPublicSessionToDevicePolicy(kAccountId1);
991 // This observes the display name becoming available as this indicates
992 // device-local account policy is fully loaded.
993 content::WindowedNotificationObserver(
994 chrome::NOTIFICATION_USER_LIST_CHANGED,
995 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
997 base::FilePath test_dir;
998 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
999 std::string image_data;
1000 ASSERT_TRUE(base::ReadFileToString(
1001 test_dir.Append(chromeos::test::kUserAvatarImage1RelativePath),
1005 base::JSONWriter::Write(test::ConstructExternalDataReference(
1006 embedded_test_server()->GetURL(std::string("/") +
1007 chromeos::test::kUserAvatarImage1RelativePath).spec(),
1010 device_local_account_policy_.payload().mutable_useravatarimage()->set_value(
1012 UploadAndInstallDeviceLocalAccountPolicy();
1013 policy::BrowserPolicyConnectorChromeOS* connector =
1014 g_browser_process->platform_part()->browser_policy_connector_chromeos();
1015 DeviceLocalAccountPolicyBroker* broker =
1016 connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
1018 ASSERT_TRUE(broker);
1020 run_loop_.reset(new base::RunLoop);
1021 chromeos::UserManager::Get()->AddObserver(this);
1022 broker->core()->store()->Load();
1024 chromeos::UserManager::Get()->RemoveObserver(this);
1026 scoped_ptr<gfx::ImageSkia> policy_image = chromeos::test::ImageLoader(
1027 test_dir.Append(chromeos::test::kUserAvatarImage1RelativePath)).Load();
1028 ASSERT_TRUE(policy_image);
1030 const chromeos::User* user =
1031 chromeos::UserManager::Get()->FindUser(user_id_1_);
1034 base::FilePath user_data_dir;
1035 ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
1036 const base::FilePath saved_image_path =
1037 user_data_dir.Append(user_id_1_).AddExtension("jpg");
1039 EXPECT_FALSE(user->HasDefaultImage());
1040 EXPECT_EQ(chromeos::User::kExternalImageIndex, user->image_index());
1041 EXPECT_TRUE(chromeos::test::AreImagesEqual(*policy_image, user->GetImage()));
1042 const base::DictionaryValue* images_pref =
1043 g_browser_process->local_state()->GetDictionary("user_image_info");
1044 ASSERT_TRUE(images_pref);
1045 const base::DictionaryValue* image_properties;
1046 ASSERT_TRUE(images_pref->GetDictionaryWithoutPathExpansion(
1048 &image_properties));
1050 std::string image_path;
1051 ASSERT_TRUE(image_properties->GetInteger("index", &image_index));
1052 ASSERT_TRUE(image_properties->GetString("path", &image_path));
1053 EXPECT_EQ(chromeos::User::kExternalImageIndex, image_index);
1054 EXPECT_EQ(saved_image_path.value(), image_path);
1056 scoped_ptr<gfx::ImageSkia> saved_image =
1057 chromeos::test::ImageLoader(saved_image_path).Load();
1058 ASSERT_TRUE(saved_image);
1060 // Check image dimensions. Images can't be compared since JPEG is lossy.
1061 EXPECT_EQ(policy_image->width(), saved_image->width());
1062 EXPECT_EQ(policy_image->height(), saved_image->height());
1065 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LastWindowClosedLogoutReminder) {
1066 UploadAndInstallDeviceLocalAccountPolicy();
1067 AddPublicSessionToDevicePolicy(kAccountId1);
1069 // This observes the display name becoming available as this indicates
1070 // device-local account policy is fully loaded.
1071 content::WindowedNotificationObserver(
1072 chrome::NOTIFICATION_USER_LIST_CHANGED,
1073 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
1075 // Wait for the login UI to be ready.
1076 chromeos::LoginDisplayHostImpl* host =
1077 reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
1078 chromeos::LoginDisplayHostImpl::default_host());
1080 chromeos::OobeUI* oobe_ui = host->GetOobeUI();
1081 ASSERT_TRUE(oobe_ui);
1082 base::RunLoop run_loop;
1083 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure());
1087 // Start login into the device-local account.
1088 host->StartSignInScreen(LoginScreenContext());
1089 chromeos::ExistingUserController* controller =
1090 chromeos::ExistingUserController::current_controller();
1091 ASSERT_TRUE(controller);
1092 controller->LoginAsPublicAccount(user_id_1_);
1094 // Wait for the session to start.
1095 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED,
1096 base::Bind(IsSessionStarted)).Wait();
1098 Profile* profile = GetProfileForTest();
1099 ASSERT_TRUE(profile);
1100 apps::AppWindowRegistry* app_window_registry =
1101 apps::AppWindowRegistry::Get(profile);
1102 app_window_registry->AddObserver(this);
1104 // Verify that the logout confirmation dialog is not showing.
1105 ash::LogoutConfirmationController* logout_confirmation_controller =
1106 ash::Shell::GetInstance()->logout_confirmation_controller();
1107 ASSERT_TRUE(logout_confirmation_controller);
1108 EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());
1110 // Remove policy that allows only explicitly whitelisted apps to be installed
1111 // in a public session.
1112 extensions::ExtensionSystem* extension_system =
1113 extensions::ExtensionSystem::Get(profile);
1114 ASSERT_TRUE(extension_system);
1115 extension_system->management_policy()->UnregisterAllProviders();
1117 // Install and a platform app.
1118 scoped_refptr<extensions::CrxInstaller> installer =
1119 extensions::CrxInstaller::CreateSilent(
1120 extension_system->extension_service());
1121 installer->set_allow_silent_install(true);
1122 installer->set_install_cause(extension_misc::INSTALL_CAUSE_USER_DOWNLOAD);
1123 installer->set_creation_flags(extensions::Extension::FROM_WEBSTORE);
1124 content::WindowedNotificationObserver app_install_observer(
1125 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
1126 content::NotificationService::AllSources());
1127 base::FilePath test_dir;
1128 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
1129 installer->InstallCrx(test_dir.Append(kPackagedAppCRXPath));
1130 app_install_observer.Wait();
1131 const extensions::Extension* app =
1132 content::Details<const extensions::Extension>(
1133 app_install_observer.details()).ptr();
1135 // Start the platform app, causing it to open a window.
1136 run_loop_.reset(new base::RunLoop);
1137 OpenApplication(AppLaunchParams(
1138 profile, app, extensions::LAUNCH_CONTAINER_NONE, NEW_WINDOW));
1140 EXPECT_EQ(1U, app_window_registry->app_windows().size());
1142 // Close the only open browser window.
1143 BrowserList* browser_list =
1144 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
1145 EXPECT_EQ(1U, browser_list->size());
1146 Browser* browser = browser_list->get(0);
1147 ASSERT_TRUE(browser);
1148 BrowserWindow* browser_window = browser->window();
1149 ASSERT_TRUE(browser_window);
1150 run_loop_.reset(new base::RunLoop);
1151 browser_window->Close();
1152 browser_window = NULL;
1155 EXPECT_TRUE(browser_list->empty());
1157 // Verify that the logout confirmation dialog is not showing because an app
1158 // window is still open.
1159 EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());
1161 // Open a browser window.
1162 Browser* first_browser = CreateBrowser(profile);
1163 EXPECT_EQ(1U, browser_list->size());
1165 // Close the app window.
1166 run_loop_.reset(new base::RunLoop);
1167 ASSERT_EQ(1U, app_window_registry->app_windows().size());
1168 app_window_registry->app_windows().front()->GetBaseWindow()->Close();
1170 EXPECT_TRUE(app_window_registry->app_windows().empty());
1172 // Verify that the logout confirmation dialog is not showing because a browser
1173 // window is still open.
1174 EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());
1176 // Open a second browser window.
1177 Browser* second_browser = CreateBrowser(profile);
1178 EXPECT_EQ(2U, browser_list->size());
1180 // Close the first browser window.
1181 browser_window = first_browser->window();
1182 ASSERT_TRUE(browser_window);
1183 run_loop_.reset(new base::RunLoop);
1184 browser_window->Close();
1185 browser_window = NULL;
1187 first_browser = NULL;
1188 EXPECT_EQ(1U, browser_list->size());
1190 // Verify that the logout confirmation dialog is not showing because a browser
1191 // window is still open.
1192 EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());
1194 // Close the second browser window.
1195 browser_window = second_browser->window();
1196 ASSERT_TRUE(browser_window);
1197 run_loop_.reset(new base::RunLoop);
1198 browser_window->Close();
1199 browser_window = NULL;
1201 second_browser = NULL;
1202 EXPECT_TRUE(browser_list->empty());
1204 // Verify that the logout confirmation dialog is showing.
1205 ash::LogoutConfirmationDialog* dialog =
1206 logout_confirmation_controller->dialog_for_testing();
1207 ASSERT_TRUE(dialog);
1210 dialog->GetWidget()->Close();
1212 base::RunLoop().RunUntilIdle();
1214 // Verify that the logout confirmation dialog is no longer showing.
1215 EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());
1217 // Open a browser window.
1218 browser = CreateBrowser(profile);
1219 EXPECT_EQ(1U, browser_list->size());
1221 // Close the browser window.
1222 browser_window = browser->window();
1223 ASSERT_TRUE(browser_window);
1224 run_loop_.reset(new base::RunLoop);
1225 browser_window->Close();
1226 browser_window = NULL;
1229 EXPECT_TRUE(browser_list->empty());
1231 // Verify that the logout confirmation dialog is showing again.
1232 dialog = logout_confirmation_controller->dialog_for_testing();
1233 ASSERT_TRUE(dialog);
1236 dialog->GetWidget()->Close();
1238 base::RunLoop().RunUntilIdle();
1240 app_window_registry->RemoveObserver(this);
1243 class TermsOfServiceTest : public DeviceLocalAccountTest,
1244 public testing::WithParamInterface<bool> {
1247 IN_PROC_BROWSER_TEST_P(TermsOfServiceTest, TermsOfServiceScreen) {
1248 // Specify Terms of Service URL.
1249 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
1250 device_local_account_policy_.payload().mutable_termsofserviceurl()->set_value(
1251 embedded_test_server()->GetURL(
1253 (GetParam() ? kExistentTermsOfServicePath
1254 : kNonexistentTermsOfServicePath)).spec());
1255 UploadAndInstallDeviceLocalAccountPolicy();
1256 AddPublicSessionToDevicePolicy(kAccountId1);
1258 // Wait for the device-local account policy to be fully loaded.
1259 content::WindowedNotificationObserver(
1260 chrome::NOTIFICATION_USER_LIST_CHANGED,
1261 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
1263 // Wait for the login UI to be ready.
1264 chromeos::LoginDisplayHostImpl* host =
1265 reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
1266 chromeos::LoginDisplayHostImpl::default_host());
1268 chromeos::OobeUI* oobe_ui = host->GetOobeUI();
1269 ASSERT_TRUE(oobe_ui);
1270 base::RunLoop oobe_ui_wait_run_loop;
1271 const bool oobe_ui_ready =
1272 oobe_ui->IsJSReady(oobe_ui_wait_run_loop.QuitClosure());
1274 oobe_ui_wait_run_loop.Run();
1276 // Start login into the device-local account.
1277 host->StartSignInScreen(LoginScreenContext());
1278 chromeos::ExistingUserController* controller =
1279 chromeos::ExistingUserController::current_controller();
1280 ASSERT_TRUE(controller);
1281 controller->LoginAsPublicAccount(user_id_1_);
1283 // Set up an observer that will quit the message loop when login has succeeded
1284 // and the first wizard screen, if any, is being shown.
1285 base::RunLoop login_wait_run_loop;
1286 chromeos::MockConsumer login_status_consumer;
1287 EXPECT_CALL(login_status_consumer, OnLoginSuccess(_))
1289 .WillOnce(InvokeWithoutArgs(&login_wait_run_loop, &base::RunLoop::Quit));
1291 // Spin the loop until the observer fires. Then, unregister the observer.
1292 controller->set_login_status_consumer(&login_status_consumer);
1293 login_wait_run_loop.Run();
1294 controller->set_login_status_consumer(NULL);
1296 // Verify that the Terms of Service screen is being shown.
1297 chromeos::WizardController* wizard_controller =
1298 chromeos::WizardController::default_controller();
1299 ASSERT_TRUE(wizard_controller);
1300 ASSERT_TRUE(wizard_controller->current_screen());
1301 EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName,
1302 wizard_controller->current_screen()->GetName());
1304 // Wait for the Terms of Service to finish downloading, then get the status of
1305 // the screen's UI elements.
1306 chromeos::WebUILoginView* web_ui_login_view = host->GetWebUILoginView();
1307 ASSERT_TRUE(web_ui_login_view);
1308 content::WebUI* web_ui = web_ui_login_view->GetWebUI();
1309 ASSERT_TRUE(web_ui);
1310 content::WebContents* contents = web_ui->GetWebContents();
1311 ASSERT_TRUE(contents);
1313 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents,
1314 "var screenElement = document.getElementById('terms-of-service');"
1315 "function SendReplyIfDownloadDone() {"
1316 " if (screenElement.classList.contains('tos-loading'))"
1319 " status.heading = document.getElementById('tos-heading').textContent;"
1320 " status.subheading ="
1321 " document.getElementById('tos-subheading').textContent;"
1322 " status.contentHeading ="
1323 " document.getElementById('tos-content-heading').textContent;"
1325 " document.getElementById('tos-content-main').textContent;"
1326 " status.error = screenElement.classList.contains('error');"
1327 " status.acceptEnabled ="
1328 " !document.getElementById('tos-accept-button').disabled;"
1329 " domAutomationController.send(JSON.stringify(status));"
1330 " observer.disconnect();"
1333 "var observer = new MutationObserver(SendReplyIfDownloadDone);"
1334 "if (!SendReplyIfDownloadDone()) {"
1335 " var options = { attributes: true, attributeFilter: [ 'class' ] };"
1336 " observer.observe(screenElement, options);"
1339 scoped_ptr<base::Value> value_ptr(base::JSONReader::Read(json));
1340 const base::DictionaryValue* status = NULL;
1341 ASSERT_TRUE(value_ptr.get());
1342 ASSERT_TRUE(value_ptr->GetAsDictionary(&status));
1343 std::string heading;
1344 EXPECT_TRUE(status->GetString("heading", &heading));
1345 std::string subheading;
1346 EXPECT_TRUE(status->GetString("subheading", &subheading));
1347 std::string content_heading;
1348 EXPECT_TRUE(status->GetString("contentHeading", &content_heading));
1349 std::string content;
1350 EXPECT_TRUE(status->GetString("content", &content));
1352 EXPECT_TRUE(status->GetBoolean("error", &error));
1353 bool accept_enabled;
1354 EXPECT_TRUE(status->GetBoolean("acceptEnabled", &accept_enabled));
1356 // Verify that the screen's headings have been set correctly.
1358 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_HEADING,
1359 base::UTF8ToUTF16(kDomain)),
1362 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_SUBHEADING,
1363 base::UTF8ToUTF16(kDomain)),
1366 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_CONTENT_HEADING,
1367 base::UTF8ToUTF16(kDomain)),
1371 // The Terms of Service URL was invalid. Verify that the screen is showing
1372 // an error and the accept button is disabled.
1374 EXPECT_FALSE(accept_enabled);
1378 // The Terms of Service URL was valid. Verify that the screen is showing the
1379 // downloaded Terms of Service and the accept button is enabled.
1380 base::FilePath test_dir;
1381 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
1382 std::string terms_of_service;
1383 ASSERT_TRUE(base::ReadFileToString(
1384 test_dir.Append(kExistentTermsOfServicePath), &terms_of_service));
1385 EXPECT_EQ(terms_of_service, content);
1386 EXPECT_FALSE(error);
1387 EXPECT_TRUE(accept_enabled);
1389 // Click the accept button.
1390 ASSERT_TRUE(content::ExecuteScript(contents,
1391 "$('tos-accept-button').click();"));
1393 // Wait for the session to start.
1394 if (!IsSessionStarted()) {
1395 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED,
1396 base::Bind(IsSessionStarted)).Wait();
1400 INSTANTIATE_TEST_CASE_P(TermsOfServiceTestInstance,
1401 TermsOfServiceTest, testing::Bool());
1403 } // namespace policy