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. 4 5 #include <map> 6 #include <string> 7 8 #include "base/basictypes.h" 9 #include "base/bind.h" 10 #include "base/bind_helpers.h" 11 #include "base/callback.h" 12 #include "base/command_line.h" 13 #include "base/file_util.h" 14 #include "base/files/file_path.h" 15 #include "base/files/scoped_temp_dir.h" 16 #include "base/json/json_reader.h" 17 #include "base/json/json_writer.h" 18 #include "base/location.h" 19 #include "base/memory/ref_counted.h" 20 #include "base/memory/scoped_ptr.h" 21 #include "base/message_loop/message_loop.h" 22 #include "base/message_loop/message_loop_proxy.h" 23 #include "base/path_service.h" 24 #include "base/prefs/pref_service.h" 25 #include "base/run_loop.h" 26 #include "base/sequenced_task_runner.h" 27 #include "base/strings/string_number_conversions.h" 28 #include "base/strings/string_util.h" 29 #include "base/strings/stringprintf.h" 30 #include "base/strings/utf_string_conversions.h" 31 #include "base/test/scoped_path_override.h" 32 #include "base/values.h" 33 #include "chrome/browser/browser_process.h" 34 #include "chrome/browser/chrome_notification_types.h" 35 #include "chrome/browser/chromeos/login/existing_user_controller.h" 36 #include "chrome/browser/chromeos/login/login_display_host.h" 37 #include "chrome/browser/chromeos/login/login_display_host_impl.h" 38 #include "chrome/browser/chromeos/login/mock_login_status_consumer.h" 39 #include "chrome/browser/chromeos/login/screens/wizard_screen.h" 40 #include "chrome/browser/chromeos/login/user.h" 41 #include "chrome/browser/chromeos/login/user_image_manager.h" 42 #include "chrome/browser/chromeos/login/user_image_manager_impl.h" 43 #include "chrome/browser/chromeos/login/user_image_manager_test_util.h" 44 #include "chrome/browser/chromeos/login/user_manager.h" 45 #include "chrome/browser/chromeos/login/webui_login_view.h" 46 #include "chrome/browser/chromeos/login/wizard_controller.h" 47 #include "chrome/browser/chromeos/policy/cloud_external_data_manager_base_test_util.h" 48 #include "chrome/browser/chromeos/policy/device_local_account.h" 49 #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h" 50 #include "chrome/browser/chromeos/policy/device_policy_builder.h" 51 #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h" 52 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h" 53 #include "chrome/browser/extensions/extension_service.h" 54 #include "chrome/browser/extensions/extension_system.h" 55 #include "chrome/browser/lifetime/application_lifetime.h" 56 #include "chrome/browser/policy/browser_policy_connector.h" 57 #include "chrome/browser/policy/profile_policy_connector.h" 58 #include "chrome/browser/policy/profile_policy_connector_factory.h" 59 #include "chrome/browser/policy/test/local_policy_test_server.h" 60 #include "chrome/browser/prefs/session_startup_pref.h" 61 #include "chrome/browser/profiles/profile.h" 62 #include "chrome/browser/profiles/profile_manager.h" 63 #include "chrome/browser/ui/browser.h" 64 #include "chrome/browser/ui/browser_commands.h" 65 #include "chrome/browser/ui/browser_finder.h" 66 #include "chrome/browser/ui/browser_list.h" 67 #include "chrome/browser/ui/browser_window.h" 68 #include "chrome/browser/ui/host_desktop.h" 69 #include "chrome/browser/ui/tabs/tab_strip_model.h" 70 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" 71 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" 72 #include "chrome/common/chrome_paths.h" 73 #include "chrome/common/chrome_switches.h" 74 #include "chromeos/chromeos_paths.h" 75 #include "chromeos/chromeos_switches.h" 76 #include "chromeos/dbus/fake_session_manager_client.h" 77 #include "components/policy/core/common/cloud/cloud_policy_constants.h" 78 #include "components/policy/core/common/cloud/cloud_policy_core.h" 79 #include "components/policy/core/common/cloud/cloud_policy_store.h" 80 #include "components/policy/core/common/cloud/policy_builder.h" 81 #include "components/policy/core/common/external_data_fetcher.h" 82 #include "components/policy/core/common/policy_map.h" 83 #include "components/policy/core/common/policy_namespace.h" 84 #include "components/policy/core/common/policy_service.h" 85 #include "content/public/browser/notification_details.h" 86 #include "content/public/browser/notification_source.h" 87 #include "content/public/browser/web_contents.h" 88 #include "content/public/browser/web_ui.h" 89 #include "content/public/test/browser_test_utils.h" 90 #include "content/public/test/test_utils.h" 91 #include "crypto/rsa_private_key.h" 92 #include "extensions/common/extension.h" 93 #include "grit/chromium_strings.h" 94 #include "grit/generated_resources.h" 95 #include "net/base/url_util.h" 96 #include "net/http/http_status_code.h" 97 #include "net/test/embedded_test_server/embedded_test_server.h" 98 #include "net/test/embedded_test_server/http_request.h" 99 #include "net/test/embedded_test_server/http_response.h" 100 #include "net/url_request/test_url_fetcher_factory.h" 101 #include "net/url_request/url_fetcher_delegate.h" 102 #include "net/url_request/url_request_status.h" 103 #include "policy/policy_constants.h" 104 #include "testing/gmock/include/gmock/gmock.h" 105 #include "ui/base/l10n/l10n_util.h" 106 #include "ui/gfx/image/image_skia.h" 107 #include "url/gurl.h" 108 //#include "third_party/cros_system_api/dbus/service_constants.h" 109 110 namespace em = enterprise_management; 111 112 using chromeos::LoginScreenContext; 113 using testing::InvokeWithoutArgs; 114 using testing::Return; 115 using testing::_; 116 117 namespace policy { 118 119 namespace { 120 121 const char kDomain[] = "example.com"; 122 const char kAccountId1[] = "dla1 (at) example.com"; 123 const char kAccountId2[] = "dla2 (at) example.com"; 124 const char kDisplayName[] = "display name"; 125 const char* kStartupURLs[] = { 126 "chrome://policy", 127 "chrome://about", 128 }; 129 const char kExistentTermsOfServicePath[] = "chromeos/enterprise/tos.txt"; 130 const char kNonexistentTermsOfServicePath[] = "chromeos/enterprise/tos404.txt"; 131 const char kRelativeUpdateURL[] = "/service/update2/crx"; 132 const char kUpdateManifestHeader[] = 133 "<?xml version='1.0' encoding='UTF-8'?>\n" 134 "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>\n"; 135 const char kUpdateManifestTemplate[] = 136 " <app appid='%s'>\n" 137 " <updatecheck codebase='%s' version='%s' />\n" 138 " </app>\n"; 139 const char kUpdateManifestFooter[] = 140 "</gupdate>\n"; 141 const char kHostedAppID[] = "kbmnembihfiondgfjekmnmcbddelicoi"; 142 const char kHostedAppCRXPath[] = "extensions/hosted_app.crx"; 143 const char kHostedAppVersion[] = "1.0.0.0"; 144 const char kGoodExtensionID[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; 145 const char kGoodExtensionCRXPath[] = "extensions/good.crx"; 146 const char kGoodExtensionVersion[] = "1.0"; 147 148 const char kExternalData[] = "External data"; 149 const char kExternalDataURL[] = "http://localhost/external_data"; 150 151 // Helper that serves extension update manifests to Chrome. 152 class TestingUpdateManifestProvider { 153 public: 154 155 // Update manifests will be served at |relative_update_url|. 156 explicit TestingUpdateManifestProvider( 157 const std::string& relative_update_url); 158 ~TestingUpdateManifestProvider(); 159 160 // When an update manifest is requested for the given extension |id|, indicate 161 // that |version| of the extension can be downloaded at |crx_url|. 162 void AddUpdate(const std::string& id, 163 const std::string& version, 164 const GURL& crx_url); 165 166 // This method must be registered with the test's EmbeddedTestServer to start 167 // serving update manifests. 168 scoped_ptr<net::test_server::HttpResponse> HandleRequest( 169 const net::test_server::HttpRequest& request); 170 171 private: 172 struct Update { 173 public: 174 Update(const std::string& version, const GURL& crx_url); 175 Update(); 176 177 std::string version; 178 GURL crx_url; 179 }; 180 typedef std::map<std::string, Update> UpdateMap; 181 UpdateMap updates_; 182 183 const std::string relative_update_url_; 184 185 DISALLOW_COPY_AND_ASSIGN(TestingUpdateManifestProvider); 186 }; 187 188 TestingUpdateManifestProvider::Update::Update(const std::string& version, 189 const GURL& crx_url) 190 : version(version), 191 crx_url(crx_url) { 192 } 193 194 TestingUpdateManifestProvider::Update::Update() { 195 } 196 197 TestingUpdateManifestProvider::TestingUpdateManifestProvider( 198 const std::string& relative_update_url) 199 : relative_update_url_(relative_update_url) { 200 } 201 202 TestingUpdateManifestProvider::~TestingUpdateManifestProvider() { 203 } 204 205 void TestingUpdateManifestProvider::AddUpdate(const std::string& id, 206 const std::string& version, 207 const GURL& crx_url) { 208 updates_[id] = Update(version, crx_url); 209 } 210 211 scoped_ptr<net::test_server::HttpResponse> 212 TestingUpdateManifestProvider::HandleRequest( 213 const net::test_server::HttpRequest& request) { 214 const GURL url("http://localhost" + request.relative_url); 215 if (url.path() != relative_update_url_) 216 return scoped_ptr<net::test_server::HttpResponse>(); 217 218 std::string content = kUpdateManifestHeader; 219 for (net::QueryIterator it(url); !it.IsAtEnd(); it.Advance()) { 220 if (it.GetKey() != "x") 221 continue; 222 // Extract the extension id from the subquery. Since GetValueForKeyInQuery() 223 // expects a complete URL, dummy scheme and host must be prepended. 224 std::string id; 225 net::GetValueForKeyInQuery(GURL("http://dummy?" + it.GetUnescapedValue()), 226 "id", &id); 227 UpdateMap::const_iterator entry = updates_.find(id); 228 if (entry != updates_.end()) { 229 content += base::StringPrintf(kUpdateManifestTemplate, 230 id.c_str(), 231 entry->second.crx_url.spec().c_str(), 232 entry->second.version.c_str()); 233 } 234 } 235 content += kUpdateManifestFooter; 236 scoped_ptr<net::test_server::BasicHttpResponse> 237 http_response(new net::test_server::BasicHttpResponse); 238 http_response->set_code(net::HTTP_OK); 239 http_response->set_content(content); 240 http_response->set_content_type("text/xml"); 241 return http_response.PassAs<net::test_server::HttpResponse>(); 242 } 243 244 bool DoesInstallSuccessReferToId(const std::string& id, 245 const content::NotificationSource& source, 246 const content::NotificationDetails& details) { 247 return content::Details<const extensions::InstalledExtensionInfo>(details)-> 248 extension->id() == id; 249 } 250 251 bool DoesInstallFailureReferToId(const std::string& id, 252 const content::NotificationSource& source, 253 const content::NotificationDetails& details) { 254 return content::Details<const base::string16>(details)->find(UTF8ToUTF16(id)) != 255 base::string16::npos; 256 } 257 258 scoped_ptr<net::FakeURLFetcher> RunCallbackAndReturnFakeURLFetcher( 259 scoped_refptr<base::SequencedTaskRunner> task_runner, 260 const base::Closure& callback, 261 const GURL& url, 262 net::URLFetcherDelegate* delegate, 263 const std::string& response_data, 264 net::HttpStatusCode response_code, 265 net::URLRequestStatus::Status status) { 266 task_runner->PostTask(FROM_HERE, callback); 267 return make_scoped_ptr(new net::FakeURLFetcher( 268 url, delegate, response_data, response_code, status)); 269 } 270 271 } // namespace 272 273 class DeviceLocalAccountTest : public DevicePolicyCrosBrowserTest, 274 public chromeos::UserManager::Observer { 275 protected: 276 DeviceLocalAccountTest() 277 : user_id_1_(GenerateDeviceLocalAccountUserId( 278 kAccountId1, DeviceLocalAccount::TYPE_PUBLIC_SESSION)), 279 user_id_2_(GenerateDeviceLocalAccountUserId( 280 kAccountId2, DeviceLocalAccount::TYPE_PUBLIC_SESSION)) {} 281 282 virtual ~DeviceLocalAccountTest() {} 283 284 virtual void SetUp() OVERRIDE { 285 // Configure and start the test server. 286 scoped_ptr<crypto::RSAPrivateKey> signing_key( 287 PolicyBuilder::CreateTestSigningKey()); 288 ASSERT_TRUE(test_server_.SetSigningKey(signing_key.get())); 289 signing_key.reset(); 290 test_server_.RegisterClient(PolicyBuilder::kFakeToken, 291 PolicyBuilder::kFakeDeviceId); 292 ASSERT_TRUE(test_server_.Start()); 293 294 ASSERT_TRUE(extension_cache_root_dir_.CreateUniqueTempDir()); 295 extension_cache_root_dir_override_.reset(new base::ScopedPathOverride( 296 chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS, 297 extension_cache_root_dir_.path())); 298 ASSERT_TRUE(external_data_cache_dir_.CreateUniqueTempDir()); 299 external_data_cache_dir_override_.reset(new base::ScopedPathOverride( 300 chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTERNAL_DATA, 301 external_data_cache_dir_.path())); 302 DevicePolicyCrosBrowserTest::SetUp(); 303 } 304 305 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 306 DevicePolicyCrosBrowserTest::SetUpCommandLine(command_line); 307 command_line->AppendSwitch(chromeos::switches::kLoginManager); 308 command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests); 309 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user"); 310 command_line->AppendSwitchASCII( 311 switches::kDeviceManagementUrl, test_server_.GetServiceURL().spec()); 312 } 313 314 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { 315 DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture(); 316 317 // Clear command-line arguments (but keep command-line switches) so the 318 // startup pages policy takes effect. 319 CommandLine* command_line = CommandLine::ForCurrentProcess(); 320 CommandLine::StringVector argv(command_line->argv()); 321 argv.erase(argv.begin() + argv.size() - command_line->GetArgs().size(), 322 argv.end()); 323 command_line->InitFromArgv(argv); 324 325 InstallOwnerKey(); 326 MarkAsEnterpriseOwned(); 327 328 InitializePolicy(); 329 } 330 331 virtual void CleanUpOnMainThread() OVERRIDE { 332 // This shuts down the login UI. 333 base::MessageLoop::current()->PostTask(FROM_HERE, 334 base::Bind(&chrome::AttemptExit)); 335 base::RunLoop().RunUntilIdle(); 336 } 337 338 virtual void LocalStateChanged(chromeos::UserManager* user_manager) OVERRIDE { 339 run_loop_->Quit(); 340 } 341 342 void InitializePolicy() { 343 device_policy()->policy_data().set_public_key_version(1); 344 em::ChromeDeviceSettingsProto& proto(device_policy()->payload()); 345 proto.mutable_show_user_names()->set_show_user_names(true); 346 347 device_local_account_policy_.policy_data().set_policy_type( 348 dm_protocol::kChromePublicAccountPolicyType); 349 device_local_account_policy_.policy_data().set_username(kAccountId1); 350 device_local_account_policy_.policy_data().set_settings_entity_id( 351 kAccountId1); 352 device_local_account_policy_.policy_data().set_public_key_version(1); 353 device_local_account_policy_.payload().mutable_userdisplayname()->set_value( 354 kDisplayName); 355 } 356 357 void BuildDeviceLocalAccountPolicy() { 358 device_local_account_policy_.SetDefaultSigningKey(); 359 device_local_account_policy_.Build(); 360 } 361 362 void UploadDeviceLocalAccountPolicy() { 363 BuildDeviceLocalAccountPolicy(); 364 test_server_.UpdatePolicy( 365 dm_protocol::kChromePublicAccountPolicyType, kAccountId1, 366 device_local_account_policy_.payload().SerializeAsString()); 367 } 368 369 void UploadAndInstallDeviceLocalAccountPolicy() { 370 UploadDeviceLocalAccountPolicy(); 371 session_manager_client()->set_device_local_account_policy( 372 kAccountId1, device_local_account_policy_.GetBlob()); 373 } 374 375 void AddPublicSessionToDevicePolicy(const std::string& username) { 376 em::ChromeDeviceSettingsProto& proto(device_policy()->payload()); 377 em::DeviceLocalAccountInfoProto* account = 378 proto.mutable_device_local_accounts()->add_account(); 379 account->set_account_id(username); 380 account->set_type( 381 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION); 382 RefreshDevicePolicy(); 383 test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType, 384 std::string(), proto.SerializeAsString()); 385 } 386 387 void CheckPublicSessionPresent(const std::string& id) { 388 const chromeos::User* user = chromeos::UserManager::Get()->FindUser(id); 389 ASSERT_TRUE(user); 390 EXPECT_EQ(id, user->email()); 391 EXPECT_EQ(chromeos::User::USER_TYPE_PUBLIC_ACCOUNT, user->GetType()); 392 } 393 394 base::FilePath GetCacheDirectoryForAccountID(const std::string& account_id) { 395 return extension_cache_root_dir_.path() 396 .Append(base::HexEncode(account_id.c_str(), account_id.size())); 397 } 398 399 base::FilePath GetCacheCRXFile(const std::string& account_id, 400 const std::string& id, 401 const std::string& version) { 402 return GetCacheDirectoryForAccountID(account_id) 403 .Append(base::StringPrintf("%s-%s.crx", id.c_str(), version.c_str())); 404 } 405 406 // Returns a profile which can be used for testing. 407 Profile* GetProfileForTest() { 408 // Any profile can be used here since this test does not test multi profile. 409 return ProfileManager::GetActiveUserProfile(); 410 } 411 412 const std::string user_id_1_; 413 const std::string user_id_2_; 414 415 scoped_ptr<base::RunLoop> run_loop_; 416 417 UserPolicyBuilder device_local_account_policy_; 418 LocalPolicyTestServer test_server_; 419 420 private: 421 base::ScopedTempDir extension_cache_root_dir_; 422 base::ScopedTempDir external_data_cache_dir_; 423 scoped_ptr<base::ScopedPathOverride> extension_cache_root_dir_override_; 424 scoped_ptr<base::ScopedPathOverride> external_data_cache_dir_override_; 425 426 DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountTest); 427 }; 428 429 static bool IsKnownUser(const std::string& account_id) { 430 return chromeos::UserManager::Get()->IsKnownUser(account_id); 431 } 432 433 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LoginScreen) { 434 AddPublicSessionToDevicePolicy(kAccountId1); 435 AddPublicSessionToDevicePolicy(kAccountId2); 436 437 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED, 438 base::Bind(&IsKnownUser, user_id_1_)) 439 .Wait(); 440 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED, 441 base::Bind(&IsKnownUser, user_id_2_)) 442 .Wait(); 443 444 CheckPublicSessionPresent(user_id_1_); 445 CheckPublicSessionPresent(user_id_2_); 446 } 447 448 static bool DisplayNameMatches(const std::string& account_id, 449 const std::string& display_name) { 450 const chromeos::User* user = 451 chromeos::UserManager::Get()->FindUser(account_id); 452 if (!user || user->display_name().empty()) 453 return false; 454 EXPECT_EQ(UTF8ToUTF16(display_name), user->display_name()); 455 return true; 456 } 457 458 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DisplayName) { 459 UploadAndInstallDeviceLocalAccountPolicy(); 460 AddPublicSessionToDevicePolicy(kAccountId1); 461 462 content::WindowedNotificationObserver( 463 chrome::NOTIFICATION_USER_LIST_CHANGED, 464 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 465 } 466 467 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyDownload) { 468 UploadDeviceLocalAccountPolicy(); 469 AddPublicSessionToDevicePolicy(kAccountId1); 470 471 // Policy for the account is not installed in session_manager_client. Because 472 // of this, the presence of the display name (which comes from policy) can be 473 // used as a signal that indicates successful policy download. 474 content::WindowedNotificationObserver( 475 chrome::NOTIFICATION_USER_LIST_CHANGED, 476 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 477 478 // Sanity check: The policy should be present now. 479 ASSERT_FALSE(session_manager_client()->device_local_account_policy( 480 kAccountId1).empty()); 481 } 482 483 static bool IsNotKnownUser(const std::string& account_id) { 484 return !IsKnownUser(account_id); 485 } 486 487 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DevicePolicyChange) { 488 AddPublicSessionToDevicePolicy(kAccountId1); 489 AddPublicSessionToDevicePolicy(kAccountId2); 490 491 // Wait until the login screen is up. 492 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED, 493 base::Bind(&IsKnownUser, user_id_1_)) 494 .Wait(); 495 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED, 496 base::Bind(&IsKnownUser, user_id_2_)) 497 .Wait(); 498 499 // Update policy to remove kAccountId2. 500 em::ChromeDeviceSettingsProto& proto(device_policy()->payload()); 501 proto.mutable_device_local_accounts()->clear_account(); 502 AddPublicSessionToDevicePolicy(kAccountId1); 503 504 em::ChromeDeviceSettingsProto policy; 505 policy.mutable_show_user_names()->set_show_user_names(true); 506 em::DeviceLocalAccountInfoProto* account1 = 507 policy.mutable_device_local_accounts()->add_account(); 508 account1->set_account_id(kAccountId1); 509 account1->set_type( 510 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION); 511 512 test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType, std::string(), 513 policy.SerializeAsString()); 514 g_browser_process->policy_service()->RefreshPolicies(base::Closure()); 515 516 // Make sure the second device-local account disappears. 517 content::WindowedNotificationObserver( 518 chrome::NOTIFICATION_USER_LIST_CHANGED, 519 base::Bind(&IsNotKnownUser, user_id_2_)).Wait(); 520 } 521 522 static bool IsSessionStarted() { 523 return chromeos::UserManager::Get()->IsSessionStarted(); 524 } 525 526 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, StartSession) { 527 // Specify startup pages. 528 device_local_account_policy_.payload().mutable_restoreonstartup()->set_value( 529 SessionStartupPref::kPrefValueURLs); 530 em::StringListPolicyProto* startup_urls_proto = 531 device_local_account_policy_.payload().mutable_restoreonstartupurls(); 532 for (size_t i = 0; i < arraysize(kStartupURLs); ++i) 533 startup_urls_proto->mutable_value()->add_entries(kStartupURLs[i]); 534 UploadAndInstallDeviceLocalAccountPolicy(); 535 AddPublicSessionToDevicePolicy(kAccountId1); 536 537 // This observes the display name becoming available as this indicates 538 // device-local account policy is fully loaded, which is a prerequisite for 539 // successful login. 540 content::WindowedNotificationObserver( 541 chrome::NOTIFICATION_USER_LIST_CHANGED, 542 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 543 544 // Wait for the login UI to be ready. 545 chromeos::LoginDisplayHostImpl* host = 546 reinterpret_cast<chromeos::LoginDisplayHostImpl*>( 547 chromeos::LoginDisplayHostImpl::default_host()); 548 ASSERT_TRUE(host); 549 chromeos::OobeUI* oobe_ui = host->GetOobeUI(); 550 ASSERT_TRUE(oobe_ui); 551 base::RunLoop run_loop; 552 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure()); 553 if (!oobe_ui_ready) 554 run_loop.Run(); 555 556 // Start login into the device-local account. 557 host->StartSignInScreen(LoginScreenContext()); 558 chromeos::ExistingUserController* controller = 559 chromeos::ExistingUserController::current_controller(); 560 ASSERT_TRUE(controller); 561 controller->LoginAsPublicAccount(user_id_1_); 562 563 // Wait for the session to start. 564 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED, 565 base::Bind(IsSessionStarted)).Wait(); 566 567 // Check that the startup pages specified in policy were opened. 568 BrowserList* browser_list = 569 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH); 570 EXPECT_EQ(1U, browser_list->size()); 571 Browser* browser = browser_list->get(0); 572 ASSERT_TRUE(browser); 573 574 TabStripModel* tabs = browser->tab_strip_model(); 575 ASSERT_TRUE(tabs); 576 int expected_tab_count = static_cast<int>(arraysize(kStartupURLs)); 577 EXPECT_EQ(expected_tab_count, tabs->count()); 578 for (int i = 0; i < expected_tab_count && i < tabs->count(); ++i) { 579 EXPECT_EQ(GURL(kStartupURLs[i]), 580 tabs->GetWebContentsAt(i)->GetVisibleURL()); 581 } 582 } 583 584 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, FullscreenDisallowed) { 585 UploadAndInstallDeviceLocalAccountPolicy(); 586 AddPublicSessionToDevicePolicy(kAccountId1); 587 588 // This observes the display name becoming available as this indicates 589 // device-local account policy is fully loaded, which is a prerequisite for 590 // successful login. 591 content::WindowedNotificationObserver( 592 chrome::NOTIFICATION_USER_LIST_CHANGED, 593 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 594 595 // Wait for the login UI to be ready. 596 chromeos::LoginDisplayHostImpl* host = 597 reinterpret_cast<chromeos::LoginDisplayHostImpl*>( 598 chromeos::LoginDisplayHostImpl::default_host()); 599 ASSERT_TRUE(host); 600 chromeos::OobeUI* oobe_ui = host->GetOobeUI(); 601 ASSERT_TRUE(oobe_ui); 602 base::RunLoop run_loop; 603 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure()); 604 if (!oobe_ui_ready) 605 run_loop.Run(); 606 607 // Ensure that the browser stays alive, even though no windows are opened 608 // during session start. 609 chrome::StartKeepAlive(); 610 611 // Start login into the device-local account. 612 host->StartSignInScreen(LoginScreenContext()); 613 chromeos::ExistingUserController* controller = 614 chromeos::ExistingUserController::current_controller(); 615 ASSERT_TRUE(controller); 616 controller->LoginAsPublicAccount(user_id_1_); 617 618 // Wait for the session to start. 619 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED, 620 base::Bind(IsSessionStarted)).Wait(); 621 622 // Open a browser window. 623 chrome::NewEmptyWindow(GetProfileForTest(), chrome::HOST_DESKTOP_TYPE_ASH); 624 BrowserList* browser_list = 625 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH); 626 EXPECT_EQ(1U, browser_list->size()); 627 Browser* browser = browser_list->get(0); 628 ASSERT_TRUE(browser); 629 BrowserWindow* browser_window = browser->window(); 630 ASSERT_TRUE(browser_window); 631 chrome::EndKeepAlive(); 632 633 // Verify that an attempt to enter fullscreen mode is denied. 634 EXPECT_FALSE(browser_window->IsFullscreen()); 635 chrome::ToggleFullscreenMode(browser); 636 EXPECT_FALSE(browser_window->IsFullscreen()); 637 } 638 639 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExtensionsUncached) { 640 // Make it possible to force-install a hosted app and an extension. 641 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 642 TestingUpdateManifestProvider testing_update_manifest_provider( 643 kRelativeUpdateURL); 644 testing_update_manifest_provider.AddUpdate( 645 kHostedAppID, 646 kHostedAppVersion, 647 embedded_test_server()->GetURL(std::string("/") + kHostedAppCRXPath)); 648 testing_update_manifest_provider.AddUpdate( 649 kGoodExtensionID, 650 kGoodExtensionVersion, 651 embedded_test_server()->GetURL(std::string("/") + kGoodExtensionCRXPath)); 652 embedded_test_server()->RegisterRequestHandler( 653 base::Bind(&TestingUpdateManifestProvider::HandleRequest, 654 base::Unretained(&testing_update_manifest_provider))); 655 656 // Specify policy to force-install the hosted app and the extension. 657 em::StringList* forcelist = device_local_account_policy_.payload() 658 .mutable_extensioninstallforcelist()->mutable_value(); 659 forcelist->add_entries(base::StringPrintf( 660 "%s;%s", 661 kHostedAppID, 662 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str())); 663 forcelist->add_entries(base::StringPrintf( 664 "%s;%s", 665 kGoodExtensionID, 666 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str())); 667 668 UploadAndInstallDeviceLocalAccountPolicy(); 669 AddPublicSessionToDevicePolicy(kAccountId1); 670 671 // This observes the display name becoming available as this indicates 672 // device-local account policy is fully loaded, which is a prerequisite for 673 // successful login. 674 content::WindowedNotificationObserver( 675 chrome::NOTIFICATION_USER_LIST_CHANGED, 676 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 677 678 // Wait for the login UI to be ready. 679 chromeos::LoginDisplayHostImpl* host = 680 reinterpret_cast<chromeos::LoginDisplayHostImpl*>( 681 chromeos::LoginDisplayHostImpl::default_host()); 682 ASSERT_TRUE(host); 683 chromeos::OobeUI* oobe_ui = host->GetOobeUI(); 684 ASSERT_TRUE(oobe_ui); 685 base::RunLoop run_loop; 686 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure()); 687 if (!oobe_ui_ready) 688 run_loop.Run(); 689 690 // Ensure that the browser stays alive, even though no windows are opened 691 // during session start. 692 chrome::StartKeepAlive(); 693 694 // Start listening for app/extension installation results. 695 content::WindowedNotificationObserver hosted_app_observer( 696 chrome::NOTIFICATION_EXTENSION_INSTALLED, 697 base::Bind(DoesInstallSuccessReferToId, kHostedAppID)); 698 content::WindowedNotificationObserver extension_observer( 699 chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, 700 base::Bind(DoesInstallFailureReferToId, kGoodExtensionID)); 701 702 // Start login into the device-local account. 703 host->StartSignInScreen(LoginScreenContext()); 704 chromeos::ExistingUserController* controller = 705 chromeos::ExistingUserController::current_controller(); 706 ASSERT_TRUE(controller); 707 controller->LoginAsPublicAccount(user_id_1_); 708 709 // Wait for the hosted app installation to succeed and the extension 710 // installation to fail (because hosted apps are whitelisted for use in 711 // device-local accounts and extensions are not). 712 hosted_app_observer.Wait(); 713 extension_observer.Wait(); 714 715 // Verify that the hosted app was installed. 716 Profile* profile = GetProfileForTest(); 717 ASSERT_TRUE(profile); 718 ExtensionService* extension_service = 719 extensions::ExtensionSystem::Get(profile)->extension_service(); 720 EXPECT_TRUE(extension_service->GetExtensionById(kHostedAppID, true)); 721 722 // Verify that the extension was not installed. 723 EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true)); 724 725 // Verify that the app was copied to the account's extension cache. 726 base::FilePath test_dir; 727 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir)); 728 EXPECT_TRUE(ContentsEqual( 729 GetCacheCRXFile(kAccountId1, kHostedAppID, kHostedAppVersion), 730 test_dir.Append(kHostedAppCRXPath))); 731 732 // Verify that the extension was not copied to the account's extension cache. 733 EXPECT_FALSE(PathExists(GetCacheCRXFile( 734 kAccountId1, kGoodExtensionID, kGoodExtensionVersion))); 735 } 736 737 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExtensionsCached) { 738 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 739 740 // Pre-populate the device local account's extension cache with a hosted app 741 // and an extension. 742 EXPECT_TRUE(base::CreateDirectory( 743 GetCacheDirectoryForAccountID(kAccountId1))); 744 base::FilePath test_dir; 745 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir)); 746 const base::FilePath cached_hosted_app = 747 GetCacheCRXFile(kAccountId1, kHostedAppID, kHostedAppVersion); 748 EXPECT_TRUE(CopyFile(test_dir.Append(kHostedAppCRXPath), 749 cached_hosted_app)); 750 const base::FilePath cached_extension = 751 GetCacheCRXFile(kAccountId1, kGoodExtensionID, kGoodExtensionVersion); 752 EXPECT_TRUE(CopyFile(test_dir.Append(kGoodExtensionCRXPath), 753 cached_extension)); 754 755 // Specify policy to force-install the hosted app. 756 em::StringList* forcelist = device_local_account_policy_.payload() 757 .mutable_extensioninstallforcelist()->mutable_value(); 758 forcelist->add_entries(base::StringPrintf( 759 "%s;%s", 760 kHostedAppID, 761 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str())); 762 forcelist->add_entries(base::StringPrintf( 763 "%s;%s", 764 kGoodExtensionID, 765 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str())); 766 767 UploadAndInstallDeviceLocalAccountPolicy(); 768 AddPublicSessionToDevicePolicy(kAccountId1); 769 770 // This observes the display name becoming available as this indicates 771 // device-local account policy is fully loaded, which is a prerequisite for 772 // successful login. 773 content::WindowedNotificationObserver( 774 chrome::NOTIFICATION_USER_LIST_CHANGED, 775 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 776 777 // Wait for the login UI to be ready. 778 chromeos::LoginDisplayHostImpl* host = 779 reinterpret_cast<chromeos::LoginDisplayHostImpl*>( 780 chromeos::LoginDisplayHostImpl::default_host()); 781 ASSERT_TRUE(host); 782 chromeos::OobeUI* oobe_ui = host->GetOobeUI(); 783 ASSERT_TRUE(oobe_ui); 784 base::RunLoop run_loop; 785 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure()); 786 if (!oobe_ui_ready) 787 run_loop.Run(); 788 789 // Ensure that the browser stays alive, even though no windows are opened 790 // during session start. 791 chrome::StartKeepAlive(); 792 793 // Start listening for app/extension installation results. 794 content::WindowedNotificationObserver hosted_app_observer( 795 chrome::NOTIFICATION_EXTENSION_INSTALLED, 796 base::Bind(DoesInstallSuccessReferToId, kHostedAppID)); 797 content::WindowedNotificationObserver extension_observer( 798 chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, 799 base::Bind(DoesInstallFailureReferToId, kGoodExtensionID)); 800 801 // Start login into the device-local account. 802 host->StartSignInScreen(LoginScreenContext()); 803 chromeos::ExistingUserController* controller = 804 chromeos::ExistingUserController::current_controller(); 805 ASSERT_TRUE(controller); 806 controller->LoginAsPublicAccount(user_id_1_); 807 808 // Wait for the hosted app installation to succeed and the extension 809 // installation to fail. 810 hosted_app_observer.Wait(); 811 extension_observer.Wait(); 812 813 // Verify that the hosted app was installed. 814 Profile* profile = GetProfileForTest(); 815 ASSERT_TRUE(profile); 816 ExtensionService* extension_service = 817 extensions::ExtensionSystem::Get(profile)->extension_service(); 818 EXPECT_TRUE(extension_service->GetExtensionById(kHostedAppID, true)); 819 820 // Verify that the extension was not installed. 821 EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true)); 822 823 // Verify that the app is still in the account's extension cache. 824 EXPECT_TRUE(PathExists(cached_hosted_app)); 825 826 // Verify that the extension was removed from the account's extension cache. 827 EXPECT_FALSE(PathExists(cached_extension)); 828 } 829 830 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExternalData) { 831 // chromeos::UserImageManagerImpl requests an external data fetch whenever the 832 // key::kUserAvatarImage policy is set. Since this test wants to verify that 833 // the underlying policy subsystem will start a fetch without this request as 834 // well, the chromeos::UserImageManagerImpl must be prevented from seeing the 835 // policy change. 836 reinterpret_cast<chromeos::UserImageManagerImpl*>( 837 chromeos::UserManager::Get()->GetUserImageManager())-> 838 StopPolicyObserverForTesting(); 839 840 UploadDeviceLocalAccountPolicy(); 841 AddPublicSessionToDevicePolicy(kAccountId1); 842 843 // This observes the display name becoming available as this indicates 844 // device-local account policy is fully loaded. 845 content::WindowedNotificationObserver( 846 chrome::NOTIFICATION_USER_LIST_CHANGED, 847 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 848 849 // Start serving external data at |kExternalDataURL|. 850 scoped_ptr<base::RunLoop> run_loop(new base::RunLoop); 851 scoped_ptr<net::FakeURLFetcherFactory> fetcher_factory( 852 new net::FakeURLFetcherFactory( 853 NULL, 854 base::Bind(&RunCallbackAndReturnFakeURLFetcher, 855 base::MessageLoopProxy::current(), 856 run_loop->QuitClosure()))); 857 fetcher_factory->SetFakeResponse(GURL(kExternalDataURL), 858 kExternalData, 859 net::HTTP_OK, 860 net::URLRequestStatus::SUCCESS); 861 862 // Specify an external data reference for the key::kUserAvatarImage policy. 863 scoped_ptr<base::DictionaryValue> metadata = 864 test::ConstructExternalDataReference(kExternalDataURL, kExternalData); 865 std::string policy; 866 base::JSONWriter::Write(metadata.get(), &policy); 867 device_local_account_policy_.payload().mutable_useravatarimage()->set_value( 868 policy); 869 UploadAndInstallDeviceLocalAccountPolicy(); 870 DeviceLocalAccountPolicyBroker* broker = 871 g_browser_process->browser_policy_connector()-> 872 GetDeviceLocalAccountPolicyService()->GetBrokerForUser(user_id_1_); 873 ASSERT_TRUE(broker); 874 broker->core()->store()->Load(); 875 876 // The external data should be fetched and cached automatically. Wait for this 877 // fetch. 878 run_loop->Run(); 879 880 // Stop serving external data at |kExternalDataURL|. 881 fetcher_factory.reset(); 882 883 const PolicyMap::Entry* policy_entry = 884 broker->core()->store()->policy_map().Get(key::kUserAvatarImage); 885 ASSERT_TRUE(policy_entry); 886 ASSERT_TRUE(policy_entry->external_data_fetcher); 887 888 // Retrieve the external data. Although the data is no longer being served at 889 // |kExternalDataURL|, the retrieval should succeed because the data has been 890 // cached. 891 run_loop.reset(new base::RunLoop); 892 scoped_ptr<std::string> fetched_external_data; 893 policy_entry->external_data_fetcher->Fetch(base::Bind( 894 &test::ExternalDataFetchCallback, 895 &fetched_external_data, 896 run_loop->QuitClosure())); 897 run_loop->Run(); 898 899 ASSERT_TRUE(fetched_external_data); 900 EXPECT_EQ(kExternalData, *fetched_external_data); 901 902 // Wait for the login UI to be ready. 903 chromeos::LoginDisplayHostImpl* host = 904 reinterpret_cast<chromeos::LoginDisplayHostImpl*>( 905 chromeos::LoginDisplayHostImpl::default_host()); 906 ASSERT_TRUE(host); 907 chromeos::OobeUI* oobe_ui = host->GetOobeUI(); 908 ASSERT_TRUE(oobe_ui); 909 run_loop.reset(new base::RunLoop); 910 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop->QuitClosure()); 911 if (!oobe_ui_ready) 912 run_loop->Run(); 913 914 // Ensure that the browser stays alive, even though no windows are opened 915 // during session start. 916 chrome::StartKeepAlive(); 917 918 // Start login into the device-local account. 919 host->StartSignInScreen(LoginScreenContext()); 920 chromeos::ExistingUserController* controller = 921 chromeos::ExistingUserController::current_controller(); 922 ASSERT_TRUE(controller); 923 controller->LoginAsPublicAccount(user_id_1_); 924 925 // Wait for the session to start. 926 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED, 927 base::Bind(IsSessionStarted)).Wait(); 928 929 // Verify that the external data reference has propagated to the device-local 930 // account's ProfilePolicyConnector. 931 ProfilePolicyConnector* policy_connector = 932 ProfilePolicyConnectorFactory::GetForProfile(GetProfileForTest()); 933 ASSERT_TRUE(policy_connector); 934 const PolicyMap& policies = policy_connector->policy_service()->GetPolicies( 935 PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())); 936 policy_entry = policies.Get(key::kUserAvatarImage); 937 ASSERT_TRUE(policy_entry); 938 EXPECT_TRUE(base::Value::Equals(metadata.get(), policy_entry->value)); 939 ASSERT_TRUE(policy_entry->external_data_fetcher); 940 941 // Retrieve the external data via the ProfilePolicyConnector. The retrieval 942 // should succeed because the data has been cached. 943 run_loop.reset(new base::RunLoop); 944 fetched_external_data.reset(); 945 policy_entry->external_data_fetcher->Fetch(base::Bind( 946 &test::ExternalDataFetchCallback, 947 &fetched_external_data, 948 run_loop->QuitClosure())); 949 run_loop->Run(); 950 951 ASSERT_TRUE(fetched_external_data); 952 EXPECT_EQ(kExternalData, *fetched_external_data); 953 } 954 955 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, UserAvatarImage) { 956 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 957 958 UploadDeviceLocalAccountPolicy(); 959 AddPublicSessionToDevicePolicy(kAccountId1); 960 961 // This observes the display name becoming available as this indicates 962 // device-local account policy is fully loaded. 963 content::WindowedNotificationObserver( 964 chrome::NOTIFICATION_USER_LIST_CHANGED, 965 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 966 967 base::FilePath test_dir; 968 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir)); 969 std::string image_data; 970 ASSERT_TRUE(base::ReadFileToString( 971 test_dir.Append(chromeos::test::kUserAvatarImage1RelativePath), 972 &image_data)); 973 974 std::string policy; 975 base::JSONWriter::Write(test::ConstructExternalDataReference( 976 embedded_test_server()->GetURL(std::string("/") + 977 chromeos::test::kUserAvatarImage1RelativePath).spec(), 978 image_data).get(), 979 &policy); 980 device_local_account_policy_.payload().mutable_useravatarimage()->set_value( 981 policy); 982 UploadAndInstallDeviceLocalAccountPolicy(); 983 DeviceLocalAccountPolicyBroker* broker = 984 g_browser_process->browser_policy_connector()-> 985 GetDeviceLocalAccountPolicyService()->GetBrokerForUser(user_id_1_); 986 ASSERT_TRUE(broker); 987 988 run_loop_.reset(new base::RunLoop); 989 chromeos::UserManager::Get()->AddObserver(this); 990 broker->core()->store()->Load(); 991 run_loop_->Run(); 992 chromeos::UserManager::Get()->RemoveObserver(this); 993 994 scoped_ptr<gfx::ImageSkia> policy_image = chromeos::test::ImageLoader( 995 test_dir.Append(chromeos::test::kUserAvatarImage1RelativePath)).Load(); 996 ASSERT_TRUE(policy_image); 997 998 const chromeos::User* user = 999 chromeos::UserManager::Get()->FindUser(user_id_1_); 1000 ASSERT_TRUE(user); 1001 1002 base::FilePath user_data_dir; 1003 ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)); 1004 const base::FilePath saved_image_path = 1005 user_data_dir.Append(user_id_1_).AddExtension("jpg"); 1006 1007 EXPECT_FALSE(user->HasDefaultImage()); 1008 EXPECT_EQ(chromeos::User::kExternalImageIndex, user->image_index()); 1009 EXPECT_TRUE(chromeos::test::AreImagesEqual(*policy_image, user->image())); 1010 const base::DictionaryValue* images_pref = 1011 g_browser_process->local_state()->GetDictionary("user_image_info"); 1012 ASSERT_TRUE(images_pref); 1013 const base::DictionaryValue* image_properties; 1014 ASSERT_TRUE(images_pref->GetDictionaryWithoutPathExpansion( 1015 user_id_1_, 1016 &image_properties)); 1017 int image_index; 1018 std::string image_path; 1019 ASSERT_TRUE(image_properties->GetInteger("index", &image_index)); 1020 ASSERT_TRUE(image_properties->GetString("path", &image_path)); 1021 EXPECT_EQ(chromeos::User::kExternalImageIndex, image_index); 1022 EXPECT_EQ(saved_image_path.value(), image_path); 1023 1024 scoped_ptr<gfx::ImageSkia> saved_image = 1025 chromeos::test::ImageLoader(saved_image_path).Load(); 1026 ASSERT_TRUE(saved_image); 1027 1028 // Check image dimensions. Images can't be compared since JPEG is lossy. 1029 EXPECT_EQ(policy_image->width(), saved_image->width()); 1030 EXPECT_EQ(policy_image->height(), saved_image->height()); 1031 } 1032 1033 class TermsOfServiceTest : public DeviceLocalAccountTest, 1034 public testing::WithParamInterface<bool> { 1035 }; 1036 1037 IN_PROC_BROWSER_TEST_P(TermsOfServiceTest, TermsOfServiceScreen) { 1038 // Specify Terms of Service URL. 1039 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 1040 device_local_account_policy_.payload().mutable_termsofserviceurl()->set_value( 1041 embedded_test_server()->GetURL( 1042 std::string("/") + 1043 (GetParam() ? kExistentTermsOfServicePath 1044 : kNonexistentTermsOfServicePath)).spec()); 1045 UploadAndInstallDeviceLocalAccountPolicy(); 1046 AddPublicSessionToDevicePolicy(kAccountId1); 1047 1048 // Wait for the device-local account policy to be fully loaded. 1049 content::WindowedNotificationObserver( 1050 chrome::NOTIFICATION_USER_LIST_CHANGED, 1051 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 1052 1053 // Wait for the login UI to be ready. 1054 chromeos::LoginDisplayHostImpl* host = 1055 reinterpret_cast<chromeos::LoginDisplayHostImpl*>( 1056 chromeos::LoginDisplayHostImpl::default_host()); 1057 ASSERT_TRUE(host); 1058 chromeos::OobeUI* oobe_ui = host->GetOobeUI(); 1059 ASSERT_TRUE(oobe_ui); 1060 base::RunLoop oobe_ui_wait_run_loop; 1061 const bool oobe_ui_ready = 1062 oobe_ui->IsJSReady(oobe_ui_wait_run_loop.QuitClosure()); 1063 if (!oobe_ui_ready) 1064 oobe_ui_wait_run_loop.Run(); 1065 1066 // Start login into the device-local account. 1067 host->StartSignInScreen(LoginScreenContext()); 1068 chromeos::ExistingUserController* controller = 1069 chromeos::ExistingUserController::current_controller(); 1070 ASSERT_TRUE(controller); 1071 controller->LoginAsPublicAccount(user_id_1_); 1072 1073 // Set up an observer that will quit the message loop when login has succeeded 1074 // and the first wizard screen, if any, is being shown. 1075 base::RunLoop login_wait_run_loop; 1076 chromeos::MockConsumer login_status_consumer; 1077 EXPECT_CALL(login_status_consumer, OnLoginSuccess(_)) 1078 .Times(1) 1079 .WillOnce(InvokeWithoutArgs(&login_wait_run_loop, &base::RunLoop::Quit)); 1080 1081 // Spin the loop until the observer fires. Then, unregister the observer. 1082 controller->set_login_status_consumer(&login_status_consumer); 1083 login_wait_run_loop.Run(); 1084 controller->set_login_status_consumer(NULL); 1085 1086 // Verify that the Terms of Service screen is being shown. 1087 chromeos::WizardController* wizard_controller = 1088 chromeos::WizardController::default_controller(); 1089 ASSERT_TRUE(wizard_controller); 1090 ASSERT_TRUE(wizard_controller->current_screen()); 1091 EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName, 1092 wizard_controller->current_screen()->GetName()); 1093 1094 // Wait for the Terms of Service to finish downloading, then get the status of 1095 // the screen's UI elements. 1096 chromeos::WebUILoginView* web_ui_login_view = host->GetWebUILoginView(); 1097 ASSERT_TRUE(web_ui_login_view); 1098 content::WebUI* web_ui = web_ui_login_view->GetWebUI(); 1099 ASSERT_TRUE(web_ui); 1100 content::WebContents* contents = web_ui->GetWebContents(); 1101 ASSERT_TRUE(contents); 1102 std::string json; 1103 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents, 1104 "var screen = document.getElementById('terms-of-service');" 1105 "function SendReplyIfDownloadDone() {" 1106 " if (screen.classList.contains('tos-loading'))" 1107 " return false;" 1108 " var status = {};" 1109 " status.heading = document.getElementById('tos-heading').textContent;" 1110 " status.subheading =" 1111 " document.getElementById('tos-subheading').textContent;" 1112 " status.contentHeading =" 1113 " document.getElementById('tos-content-heading').textContent;" 1114 " status.content =" 1115 " document.getElementById('tos-content-main').textContent;" 1116 " status.error = screen.classList.contains('error');" 1117 " status.acceptEnabled =" 1118 " !document.getElementById('tos-accept-button').disabled;" 1119 " domAutomationController.send(JSON.stringify(status));" 1120 " observer.disconnect();" 1121 " return true;" 1122 "}" 1123 "var observer = new MutationObserver(SendReplyIfDownloadDone);" 1124 "if (!SendReplyIfDownloadDone()) {" 1125 " var options = { attributes: true, attributeFilter: [ 'class' ] };" 1126 " observer.observe(screen, options);" 1127 "}", 1128 &json)); 1129 scoped_ptr<base::Value> value_ptr(base::JSONReader::Read(json)); 1130 const base::DictionaryValue* status = NULL; 1131 ASSERT_TRUE(value_ptr.get()); 1132 ASSERT_TRUE(value_ptr->GetAsDictionary(&status)); 1133 std::string heading; 1134 EXPECT_TRUE(status->GetString("heading", &heading)); 1135 std::string subheading; 1136 EXPECT_TRUE(status->GetString("subheading", &subheading)); 1137 std::string content_heading; 1138 EXPECT_TRUE(status->GetString("contentHeading", &content_heading)); 1139 std::string content; 1140 EXPECT_TRUE(status->GetString("content", &content)); 1141 bool error; 1142 EXPECT_TRUE(status->GetBoolean("error", &error)); 1143 bool accept_enabled; 1144 EXPECT_TRUE(status->GetBoolean("acceptEnabled", &accept_enabled)); 1145 1146 // Verify that the screen's headings have been set correctly. 1147 EXPECT_EQ( 1148 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_HEADING, 1149 UTF8ToUTF16(kDomain)), 1150 heading); 1151 EXPECT_EQ( 1152 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_SUBHEADING, 1153 UTF8ToUTF16(kDomain)), 1154 subheading); 1155 EXPECT_EQ( 1156 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_CONTENT_HEADING, 1157 UTF8ToUTF16(kDomain)), 1158 content_heading); 1159 1160 if (!GetParam()) { 1161 // The Terms of Service URL was invalid. Verify that the screen is showing 1162 // an error and the accept button is disabled. 1163 EXPECT_TRUE(error); 1164 EXPECT_FALSE(accept_enabled); 1165 return; 1166 } 1167 1168 // The Terms of Service URL was valid. Verify that the screen is showing the 1169 // downloaded Terms of Service and the accept button is enabled. 1170 base::FilePath test_dir; 1171 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir)); 1172 std::string terms_of_service; 1173 ASSERT_TRUE(base::ReadFileToString( 1174 test_dir.Append(kExistentTermsOfServicePath), &terms_of_service)); 1175 EXPECT_EQ(terms_of_service, content); 1176 EXPECT_FALSE(error); 1177 EXPECT_TRUE(accept_enabled); 1178 1179 // Click the accept button. 1180 ASSERT_TRUE(content::ExecuteScript(contents, 1181 "$('tos-accept-button').click();")); 1182 1183 // Wait for the session to start. 1184 if (!IsSessionStarted()) { 1185 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED, 1186 base::Bind(IsSessionStarted)).Wait(); 1187 } 1188 } 1189 1190 INSTANTIATE_TEST_CASE_P(TermsOfServiceTestInstance, 1191 TermsOfServiceTest, testing::Bool()); 1192 1193 } // namespace policy 1194