device_local_account_browsertest.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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 "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 "content/public/browser/notification_details.h" 95#include "content/public/browser/notification_service.h" 96#include "content/public/browser/notification_source.h" 97#include "content/public/browser/web_contents.h" 98#include "content/public/browser/web_ui.h" 99#include "content/public/test/browser_test_utils.h" 100#include "content/public/test/test_utils.h" 101#include "crypto/rsa_private_key.h" 102#include "extensions/browser/extension_system.h" 103#include "extensions/browser/management_policy.h" 104#include "extensions/common/extension.h" 105#include "grit/chromium_strings.h" 106#include "grit/generated_resources.h" 107#include "net/base/url_util.h" 108#include "net/http/http_status_code.h" 109#include "net/test/embedded_test_server/embedded_test_server.h" 110#include "net/test/embedded_test_server/http_request.h" 111#include "net/test/embedded_test_server/http_response.h" 112#include "net/url_request/test_url_fetcher_factory.h" 113#include "net/url_request/url_fetcher_delegate.h" 114#include "net/url_request/url_request_status.h" 115#include "policy/policy_constants.h" 116#include "testing/gmock/include/gmock/gmock.h" 117#include "ui/base/l10n/l10n_util.h" 118#include "ui/base/window_open_disposition.h" 119#include "ui/gfx/image/image_skia.h" 120#include "ui/views/widget/widget.h" 121#include "url/gurl.h" 122//#include "third_party/cros_system_api/dbus/service_constants.h" 123 124namespace em = enterprise_management; 125 126using chromeos::LoginScreenContext; 127using testing::InvokeWithoutArgs; 128using testing::Return; 129using testing::_; 130 131namespace policy { 132 133namespace { 134 135const char kDomain[] = "example.com"; 136const char kAccountId1[] = "dla1@example.com"; 137const char kAccountId2[] = "dla2@example.com"; 138const char kDisplayName[] = "display name"; 139const char* kStartupURLs[] = { 140 "chrome://policy", 141 "chrome://about", 142}; 143const char kExistentTermsOfServicePath[] = "chromeos/enterprise/tos.txt"; 144const char kNonexistentTermsOfServicePath[] = "chromeos/enterprise/tos404.txt"; 145const char kRelativeUpdateURL[] = "/service/update2/crx"; 146const char kUpdateManifestHeader[] = 147 "<?xml version='1.0' encoding='UTF-8'?>\n" 148 "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>\n"; 149const char kUpdateManifestTemplate[] = 150 " <app appid='%s'>\n" 151 " <updatecheck codebase='%s' version='%s' />\n" 152 " </app>\n"; 153const char kUpdateManifestFooter[] = 154 "</gupdate>\n"; 155const char kHostedAppID[] = "kbmnembihfiondgfjekmnmcbddelicoi"; 156const char kHostedAppCRXPath[] = "extensions/hosted_app.crx"; 157const char kHostedAppVersion[] = "1.0.0.0"; 158const char kGoodExtensionID[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; 159const char kGoodExtensionCRXPath[] = "extensions/good.crx"; 160const char kGoodExtensionVersion[] = "1.0"; 161const char kPackagedAppCRXPath[] = "extensions/platform_apps/app_window_2.crx"; 162 163const char kExternalData[] = "External data"; 164const char kExternalDataURL[] = "http://localhost/external_data"; 165 166// Helper that serves extension update manifests to Chrome. 167class TestingUpdateManifestProvider { 168 public: 169 // Update manifests will be served at |relative_update_url|. 170 explicit TestingUpdateManifestProvider( 171 const std::string& relative_update_url); 172 ~TestingUpdateManifestProvider(); 173 174 // When an update manifest is requested for the given extension |id|, indicate 175 // that |version| of the extension can be downloaded at |crx_url|. 176 void AddUpdate(const std::string& id, 177 const std::string& version, 178 const GURL& crx_url); 179 180 // This method must be registered with the test's EmbeddedTestServer to start 181 // serving update manifests. 182 scoped_ptr<net::test_server::HttpResponse> HandleRequest( 183 const net::test_server::HttpRequest& request); 184 185 private: 186 struct Update { 187 public: 188 Update(const std::string& version, const GURL& crx_url); 189 Update(); 190 191 std::string version; 192 GURL crx_url; 193 }; 194 typedef std::map<std::string, Update> UpdateMap; 195 UpdateMap updates_; 196 197 const std::string relative_update_url_; 198 199 DISALLOW_COPY_AND_ASSIGN(TestingUpdateManifestProvider); 200}; 201 202TestingUpdateManifestProvider::Update::Update(const std::string& version, 203 const GURL& crx_url) 204 : version(version), 205 crx_url(crx_url) { 206} 207 208TestingUpdateManifestProvider::Update::Update() { 209} 210 211TestingUpdateManifestProvider::TestingUpdateManifestProvider( 212 const std::string& relative_update_url) 213 : relative_update_url_(relative_update_url) { 214} 215 216TestingUpdateManifestProvider::~TestingUpdateManifestProvider() { 217} 218 219void TestingUpdateManifestProvider::AddUpdate(const std::string& id, 220 const std::string& version, 221 const GURL& crx_url) { 222 updates_[id] = Update(version, crx_url); 223} 224 225scoped_ptr<net::test_server::HttpResponse> 226 TestingUpdateManifestProvider::HandleRequest( 227 const net::test_server::HttpRequest& request) { 228 const GURL url("http://localhost" + request.relative_url); 229 if (url.path() != relative_update_url_) 230 return scoped_ptr<net::test_server::HttpResponse>(); 231 232 std::string content = kUpdateManifestHeader; 233 for (net::QueryIterator it(url); !it.IsAtEnd(); it.Advance()) { 234 if (it.GetKey() != "x") 235 continue; 236 // Extract the extension id from the subquery. Since GetValueForKeyInQuery() 237 // expects a complete URL, dummy scheme and host must be prepended. 238 std::string id; 239 net::GetValueForKeyInQuery(GURL("http://dummy?" + it.GetUnescapedValue()), 240 "id", &id); 241 UpdateMap::const_iterator entry = updates_.find(id); 242 if (entry != updates_.end()) { 243 content += base::StringPrintf(kUpdateManifestTemplate, 244 id.c_str(), 245 entry->second.crx_url.spec().c_str(), 246 entry->second.version.c_str()); 247 } 248 } 249 content += kUpdateManifestFooter; 250 scoped_ptr<net::test_server::BasicHttpResponse> 251 http_response(new net::test_server::BasicHttpResponse); 252 http_response->set_code(net::HTTP_OK); 253 http_response->set_content(content); 254 http_response->set_content_type("text/xml"); 255 return http_response.PassAs<net::test_server::HttpResponse>(); 256} 257 258bool DoesInstallSuccessReferToId(const std::string& id, 259 const content::NotificationSource& source, 260 const content::NotificationDetails& details) { 261 return content::Details<const extensions::InstalledExtensionInfo>(details)-> 262 extension->id() == id; 263} 264 265bool DoesInstallFailureReferToId(const std::string& id, 266 const content::NotificationSource& source, 267 const content::NotificationDetails& details) { 268 return content::Details<const base::string16>(details)-> 269 find(base::UTF8ToUTF16(id)) != base::string16::npos; 270} 271 272scoped_ptr<net::FakeURLFetcher> RunCallbackAndReturnFakeURLFetcher( 273 scoped_refptr<base::SequencedTaskRunner> task_runner, 274 const base::Closure& callback, 275 const GURL& url, 276 net::URLFetcherDelegate* delegate, 277 const std::string& response_data, 278 net::HttpStatusCode response_code, 279 net::URLRequestStatus::Status status) { 280 task_runner->PostTask(FROM_HERE, callback); 281 return make_scoped_ptr(new net::FakeURLFetcher( 282 url, delegate, response_data, response_code, status)); 283} 284 285} // namespace 286 287class DeviceLocalAccountTest : public DevicePolicyCrosBrowserTest, 288 public chromeos::UserManager::Observer, 289 public chrome::BrowserListObserver, 290 public apps::AppWindowRegistry::Observer { 291 protected: 292 DeviceLocalAccountTest() 293 : user_id_1_(GenerateDeviceLocalAccountUserId( 294 kAccountId1, DeviceLocalAccount::TYPE_PUBLIC_SESSION)), 295 user_id_2_(GenerateDeviceLocalAccountUserId( 296 kAccountId2, DeviceLocalAccount::TYPE_PUBLIC_SESSION)) { 297 set_exit_when_last_browser_closes(false); 298 } 299 300 virtual ~DeviceLocalAccountTest() {} 301 302 virtual void SetUp() OVERRIDE { 303 // Configure and start the test server. 304 scoped_ptr<crypto::RSAPrivateKey> signing_key( 305 PolicyBuilder::CreateTestSigningKey()); 306 ASSERT_TRUE(test_server_.SetSigningKeyAndSignature( 307 signing_key.get(), PolicyBuilder::GetTestSigningKeySignature())); 308 signing_key.reset(); 309 test_server_.RegisterClient(PolicyBuilder::kFakeToken, 310 PolicyBuilder::kFakeDeviceId); 311 ASSERT_TRUE(test_server_.Start()); 312 313 ASSERT_TRUE(extension_cache_root_dir_.CreateUniqueTempDir()); 314 extension_cache_root_dir_override_.reset(new base::ScopedPathOverride( 315 chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS, 316 extension_cache_root_dir_.path())); 317 ASSERT_TRUE(external_data_cache_dir_.CreateUniqueTempDir()); 318 external_data_cache_dir_override_.reset(new base::ScopedPathOverride( 319 chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTERNAL_DATA, 320 external_data_cache_dir_.path())); 321 322 BrowserList::AddObserver(this); 323 324 DevicePolicyCrosBrowserTest::SetUp(); 325 } 326 327 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 328 DevicePolicyCrosBrowserTest::SetUpCommandLine(command_line); 329 command_line->AppendSwitch(chromeos::switches::kLoginManager); 330 command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests); 331 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user"); 332 command_line->AppendSwitchASCII(policy::switches::kDeviceManagementUrl, 333 test_server_.GetServiceURL().spec()); 334 command_line->AppendSwitch(policy::switches::kEnablePolicyKeyVerification); 335 } 336 337 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { 338 DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture(); 339 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(), 345 argv.end()); 346 command_line->InitFromArgv(argv); 347 348 InstallOwnerKey(); 349 MarkAsEnterpriseOwned(); 350 351 InitializePolicy(); 352 } 353 354 virtual void CleanUpOnMainThread() OVERRIDE { 355 BrowserList::RemoveObserver(this); 356 357 // This shuts down the login UI. 358 base::MessageLoop::current()->PostTask(FROM_HERE, 359 base::Bind(&chrome::AttemptExit)); 360 base::RunLoop().RunUntilIdle(); 361 } 362 363 virtual void LocalStateChanged(chromeos::UserManager* user_manager) OVERRIDE { 364 if (run_loop_) 365 run_loop_->Quit(); 366 } 367 368 virtual void OnBrowserRemoved(Browser* browser) OVERRIDE { 369 if (run_loop_) 370 run_loop_->Quit(); 371 } 372 373 virtual void OnAppWindowAdded(apps::AppWindow* app_window) OVERRIDE { 374 if (run_loop_) 375 run_loop_->Quit(); 376 } 377 378 virtual void OnAppWindowIconChanged(apps::AppWindow* app_window) OVERRIDE {} 379 380 virtual void OnAppWindowRemoved(apps::AppWindow* app_window) OVERRIDE { 381 if (run_loop_) 382 run_loop_->Quit(); 383 } 384 385 void InitializePolicy() { 386 device_policy()->policy_data().set_public_key_version(1); 387 em::ChromeDeviceSettingsProto& proto(device_policy()->payload()); 388 proto.mutable_show_user_names()->set_show_user_names(true); 389 390 device_local_account_policy_.policy_data().set_policy_type( 391 dm_protocol::kChromePublicAccountPolicyType); 392 device_local_account_policy_.policy_data().set_username(kAccountId1); 393 device_local_account_policy_.policy_data().set_settings_entity_id( 394 kAccountId1); 395 device_local_account_policy_.policy_data().set_public_key_version(1); 396 device_local_account_policy_.payload().mutable_userdisplayname()->set_value( 397 kDisplayName); 398 } 399 400 void BuildDeviceLocalAccountPolicy() { 401 device_local_account_policy_.SetDefaultSigningKey(); 402 device_local_account_policy_.Build(); 403 } 404 405 void UploadDeviceLocalAccountPolicy() { 406 BuildDeviceLocalAccountPolicy(); 407 test_server_.UpdatePolicy( 408 dm_protocol::kChromePublicAccountPolicyType, kAccountId1, 409 device_local_account_policy_.payload().SerializeAsString()); 410 } 411 412 void UploadAndInstallDeviceLocalAccountPolicy() { 413 UploadDeviceLocalAccountPolicy(); 414 session_manager_client()->set_device_local_account_policy( 415 kAccountId1, device_local_account_policy_.GetBlob()); 416 } 417 418 void AddPublicSessionToDevicePolicy(const std::string& username) { 419 em::ChromeDeviceSettingsProto& proto(device_policy()->payload()); 420 em::DeviceLocalAccountInfoProto* account = 421 proto.mutable_device_local_accounts()->add_account(); 422 account->set_account_id(username); 423 account->set_type( 424 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION); 425 RefreshDevicePolicy(); 426 test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType, 427 std::string(), proto.SerializeAsString()); 428 } 429 430 void CheckPublicSessionPresent(const std::string& id) { 431 const chromeos::User* user = chromeos::UserManager::Get()->FindUser(id); 432 ASSERT_TRUE(user); 433 EXPECT_EQ(id, user->email()); 434 EXPECT_EQ(chromeos::User::USER_TYPE_PUBLIC_ACCOUNT, user->GetType()); 435 } 436 437 base::FilePath GetCacheDirectoryForAccountID(const std::string& account_id) { 438 return extension_cache_root_dir_.path() 439 .Append(base::HexEncode(account_id.c_str(), account_id.size())); 440 } 441 442 base::FilePath GetCacheCRXFile(const std::string& account_id, 443 const std::string& id, 444 const std::string& version) { 445 return GetCacheDirectoryForAccountID(account_id) 446 .Append(base::StringPrintf("%s-%s.crx", id.c_str(), version.c_str())); 447 } 448 449 // Returns a profile which can be used for testing. 450 Profile* GetProfileForTest() { 451 // Any profile can be used here since this test does not test multi profile. 452 return ProfileManager::GetActiveUserProfile(); 453 } 454 455 const std::string user_id_1_; 456 const std::string user_id_2_; 457 458 scoped_ptr<base::RunLoop> run_loop_; 459 460 UserPolicyBuilder device_local_account_policy_; 461 LocalPolicyTestServer test_server_; 462 463 private: 464 base::ScopedTempDir extension_cache_root_dir_; 465 base::ScopedTempDir external_data_cache_dir_; 466 scoped_ptr<base::ScopedPathOverride> extension_cache_root_dir_override_; 467 scoped_ptr<base::ScopedPathOverride> external_data_cache_dir_override_; 468 469 DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountTest); 470}; 471 472static bool IsKnownUser(const std::string& account_id) { 473 return chromeos::UserManager::Get()->IsKnownUser(account_id); 474} 475 476IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LoginScreen) { 477 AddPublicSessionToDevicePolicy(kAccountId1); 478 AddPublicSessionToDevicePolicy(kAccountId2); 479 480 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED, 481 base::Bind(&IsKnownUser, user_id_1_)) 482 .Wait(); 483 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED, 484 base::Bind(&IsKnownUser, user_id_2_)) 485 .Wait(); 486 487 CheckPublicSessionPresent(user_id_1_); 488 CheckPublicSessionPresent(user_id_2_); 489} 490 491static bool DisplayNameMatches(const std::string& account_id, 492 const std::string& display_name) { 493 const chromeos::User* user = 494 chromeos::UserManager::Get()->FindUser(account_id); 495 if (!user || user->display_name().empty()) 496 return false; 497 EXPECT_EQ(base::UTF8ToUTF16(display_name), user->display_name()); 498 return true; 499} 500 501IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DisplayName) { 502 UploadAndInstallDeviceLocalAccountPolicy(); 503 AddPublicSessionToDevicePolicy(kAccountId1); 504 505 content::WindowedNotificationObserver( 506 chrome::NOTIFICATION_USER_LIST_CHANGED, 507 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 508} 509 510IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyDownload) { 511 UploadDeviceLocalAccountPolicy(); 512 AddPublicSessionToDevicePolicy(kAccountId1); 513 514 // Policy for the account is not installed in session_manager_client. Because 515 // of this, the presence of the display name (which comes from policy) can be 516 // used as a signal that indicates successful policy download. 517 content::WindowedNotificationObserver( 518 chrome::NOTIFICATION_USER_LIST_CHANGED, 519 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 520 521 // Sanity check: The policy should be present now. 522 ASSERT_FALSE(session_manager_client()->device_local_account_policy( 523 kAccountId1).empty()); 524} 525 526static bool IsNotKnownUser(const std::string& account_id) { 527 return !IsKnownUser(account_id); 528} 529 530IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DevicePolicyChange) { 531 AddPublicSessionToDevicePolicy(kAccountId1); 532 AddPublicSessionToDevicePolicy(kAccountId2); 533 534 // Wait until the login screen is up. 535 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED, 536 base::Bind(&IsKnownUser, user_id_1_)) 537 .Wait(); 538 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED, 539 base::Bind(&IsKnownUser, user_id_2_)) 540 .Wait(); 541 542 // Update policy to remove kAccountId2. 543 em::ChromeDeviceSettingsProto& proto(device_policy()->payload()); 544 proto.mutable_device_local_accounts()->clear_account(); 545 AddPublicSessionToDevicePolicy(kAccountId1); 546 547 em::ChromeDeviceSettingsProto policy; 548 policy.mutable_show_user_names()->set_show_user_names(true); 549 em::DeviceLocalAccountInfoProto* account1 = 550 policy.mutable_device_local_accounts()->add_account(); 551 account1->set_account_id(kAccountId1); 552 account1->set_type( 553 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION); 554 555 test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType, std::string(), 556 policy.SerializeAsString()); 557 g_browser_process->policy_service()->RefreshPolicies(base::Closure()); 558 559 // Make sure the second device-local account disappears. 560 content::WindowedNotificationObserver( 561 chrome::NOTIFICATION_USER_LIST_CHANGED, 562 base::Bind(&IsNotKnownUser, user_id_2_)).Wait(); 563} 564 565static bool IsSessionStarted() { 566 return chromeos::UserManager::Get()->IsSessionStarted(); 567} 568 569IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, StartSession) { 570 // Specify startup pages. 571 device_local_account_policy_.payload().mutable_restoreonstartup()->set_value( 572 SessionStartupPref::kPrefValueURLs); 573 em::StringListPolicyProto* startup_urls_proto = 574 device_local_account_policy_.payload().mutable_restoreonstartupurls(); 575 for (size_t i = 0; i < arraysize(kStartupURLs); ++i) 576 startup_urls_proto->mutable_value()->add_entries(kStartupURLs[i]); 577 UploadAndInstallDeviceLocalAccountPolicy(); 578 AddPublicSessionToDevicePolicy(kAccountId1); 579 580 // This observes the display name becoming available as this indicates 581 // device-local account policy is fully loaded, which is a prerequisite for 582 // successful login. 583 content::WindowedNotificationObserver( 584 chrome::NOTIFICATION_USER_LIST_CHANGED, 585 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 586 587 // Wait for the login UI to be ready. 588 chromeos::LoginDisplayHostImpl* host = 589 reinterpret_cast<chromeos::LoginDisplayHostImpl*>( 590 chromeos::LoginDisplayHostImpl::default_host()); 591 ASSERT_TRUE(host); 592 chromeos::OobeUI* oobe_ui = host->GetOobeUI(); 593 ASSERT_TRUE(oobe_ui); 594 base::RunLoop run_loop; 595 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure()); 596 if (!oobe_ui_ready) 597 run_loop.Run(); 598 599 // Start login into the device-local account. 600 host->StartSignInScreen(LoginScreenContext()); 601 chromeos::ExistingUserController* controller = 602 chromeos::ExistingUserController::current_controller(); 603 ASSERT_TRUE(controller); 604 controller->LoginAsPublicAccount(user_id_1_); 605 606 // Wait for the session to start. 607 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED, 608 base::Bind(IsSessionStarted)).Wait(); 609 610 // Check that the startup pages specified in policy were opened. 611 BrowserList* browser_list = 612 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH); 613 EXPECT_EQ(1U, browser_list->size()); 614 Browser* browser = browser_list->get(0); 615 ASSERT_TRUE(browser); 616 617 TabStripModel* tabs = browser->tab_strip_model(); 618 ASSERT_TRUE(tabs); 619 int expected_tab_count = static_cast<int>(arraysize(kStartupURLs)); 620 EXPECT_EQ(expected_tab_count, tabs->count()); 621 for (int i = 0; i < expected_tab_count && i < tabs->count(); ++i) { 622 EXPECT_EQ(GURL(kStartupURLs[i]), 623 tabs->GetWebContentsAt(i)->GetVisibleURL()); 624 } 625} 626 627IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, FullscreenDisallowed) { 628 UploadAndInstallDeviceLocalAccountPolicy(); 629 AddPublicSessionToDevicePolicy(kAccountId1); 630 631 // This observes the display name becoming available as this indicates 632 // device-local account policy is fully loaded, which is a prerequisite for 633 // successful login. 634 content::WindowedNotificationObserver( 635 chrome::NOTIFICATION_USER_LIST_CHANGED, 636 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 637 638 // Wait for the login UI to be ready. 639 chromeos::LoginDisplayHostImpl* host = 640 reinterpret_cast<chromeos::LoginDisplayHostImpl*>( 641 chromeos::LoginDisplayHostImpl::default_host()); 642 ASSERT_TRUE(host); 643 chromeos::OobeUI* oobe_ui = host->GetOobeUI(); 644 ASSERT_TRUE(oobe_ui); 645 base::RunLoop run_loop; 646 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure()); 647 if (!oobe_ui_ready) 648 run_loop.Run(); 649 650 // Start login into the device-local account. 651 host->StartSignInScreen(LoginScreenContext()); 652 chromeos::ExistingUserController* controller = 653 chromeos::ExistingUserController::current_controller(); 654 ASSERT_TRUE(controller); 655 controller->LoginAsPublicAccount(user_id_1_); 656 657 // Wait for the session to start. 658 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED, 659 base::Bind(IsSessionStarted)).Wait(); 660 661 BrowserList* browser_list = 662 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH); 663 EXPECT_EQ(1U, browser_list->size()); 664 Browser* browser = browser_list->get(0); 665 ASSERT_TRUE(browser); 666 BrowserWindow* browser_window = browser->window(); 667 ASSERT_TRUE(browser_window); 668 669 // Verify that an attempt to enter fullscreen mode is denied. 670 EXPECT_FALSE(browser_window->IsFullscreen()); 671 chrome::ToggleFullscreenMode(browser); 672 EXPECT_FALSE(browser_window->IsFullscreen()); 673} 674 675IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExtensionsUncached) { 676 // Make it possible to force-install a hosted app and an extension. 677 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 678 TestingUpdateManifestProvider testing_update_manifest_provider( 679 kRelativeUpdateURL); 680 testing_update_manifest_provider.AddUpdate( 681 kHostedAppID, 682 kHostedAppVersion, 683 embedded_test_server()->GetURL(std::string("/") + kHostedAppCRXPath)); 684 testing_update_manifest_provider.AddUpdate( 685 kGoodExtensionID, 686 kGoodExtensionVersion, 687 embedded_test_server()->GetURL(std::string("/") + kGoodExtensionCRXPath)); 688 embedded_test_server()->RegisterRequestHandler( 689 base::Bind(&TestingUpdateManifestProvider::HandleRequest, 690 base::Unretained(&testing_update_manifest_provider))); 691 692 // Specify policy to force-install the hosted app and the extension. 693 em::StringList* forcelist = device_local_account_policy_.payload() 694 .mutable_extensioninstallforcelist()->mutable_value(); 695 forcelist->add_entries(base::StringPrintf( 696 "%s;%s", 697 kHostedAppID, 698 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str())); 699 forcelist->add_entries(base::StringPrintf( 700 "%s;%s", 701 kGoodExtensionID, 702 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str())); 703 704 UploadAndInstallDeviceLocalAccountPolicy(); 705 AddPublicSessionToDevicePolicy(kAccountId1); 706 707 // This observes the display name becoming available as this indicates 708 // device-local account policy is fully loaded, which is a prerequisite for 709 // successful login. 710 content::WindowedNotificationObserver( 711 chrome::NOTIFICATION_USER_LIST_CHANGED, 712 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 713 714 // Wait for the login UI to be ready. 715 chromeos::LoginDisplayHostImpl* host = 716 reinterpret_cast<chromeos::LoginDisplayHostImpl*>( 717 chromeos::LoginDisplayHostImpl::default_host()); 718 ASSERT_TRUE(host); 719 chromeos::OobeUI* oobe_ui = host->GetOobeUI(); 720 ASSERT_TRUE(oobe_ui); 721 base::RunLoop run_loop; 722 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure()); 723 if (!oobe_ui_ready) 724 run_loop.Run(); 725 726 // Start listening for app/extension installation results. 727 content::WindowedNotificationObserver hosted_app_observer( 728 chrome::NOTIFICATION_EXTENSION_INSTALLED, 729 base::Bind(DoesInstallSuccessReferToId, kHostedAppID)); 730 content::WindowedNotificationObserver extension_observer( 731 chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, 732 base::Bind(DoesInstallFailureReferToId, kGoodExtensionID)); 733 734 // Start login into the device-local account. 735 host->StartSignInScreen(LoginScreenContext()); 736 chromeos::ExistingUserController* controller = 737 chromeos::ExistingUserController::current_controller(); 738 ASSERT_TRUE(controller); 739 controller->LoginAsPublicAccount(user_id_1_); 740 741 // Wait for the hosted app installation to succeed and the extension 742 // installation to fail (because hosted apps are whitelisted for use in 743 // device-local accounts and extensions are not). 744 hosted_app_observer.Wait(); 745 extension_observer.Wait(); 746 747 // Verify that the hosted app was installed. 748 Profile* profile = GetProfileForTest(); 749 ASSERT_TRUE(profile); 750 ExtensionService* extension_service = 751 extensions::ExtensionSystem::Get(profile)->extension_service(); 752 EXPECT_TRUE(extension_service->GetExtensionById(kHostedAppID, true)); 753 754 // Verify that the extension was not installed. 755 EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true)); 756 757 // Verify that the app was copied to the account's extension cache. 758 base::FilePath test_dir; 759 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir)); 760 EXPECT_TRUE(ContentsEqual( 761 GetCacheCRXFile(kAccountId1, kHostedAppID, kHostedAppVersion), 762 test_dir.Append(kHostedAppCRXPath))); 763 764 // Verify that the extension was not copied to the account's extension cache. 765 EXPECT_FALSE(PathExists(GetCacheCRXFile( 766 kAccountId1, kGoodExtensionID, kGoodExtensionVersion))); 767} 768 769IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExtensionsCached) { 770 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 771 772 // Pre-populate the device local account's extension cache with a hosted app 773 // and an extension. 774 EXPECT_TRUE(base::CreateDirectory( 775 GetCacheDirectoryForAccountID(kAccountId1))); 776 base::FilePath test_dir; 777 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir)); 778 const base::FilePath cached_hosted_app = 779 GetCacheCRXFile(kAccountId1, kHostedAppID, kHostedAppVersion); 780 EXPECT_TRUE(CopyFile(test_dir.Append(kHostedAppCRXPath), 781 cached_hosted_app)); 782 const base::FilePath cached_extension = 783 GetCacheCRXFile(kAccountId1, kGoodExtensionID, kGoodExtensionVersion); 784 EXPECT_TRUE(CopyFile(test_dir.Append(kGoodExtensionCRXPath), 785 cached_extension)); 786 787 // Specify policy to force-install the hosted app. 788 em::StringList* forcelist = device_local_account_policy_.payload() 789 .mutable_extensioninstallforcelist()->mutable_value(); 790 forcelist->add_entries(base::StringPrintf( 791 "%s;%s", 792 kHostedAppID, 793 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str())); 794 forcelist->add_entries(base::StringPrintf( 795 "%s;%s", 796 kGoodExtensionID, 797 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str())); 798 799 UploadAndInstallDeviceLocalAccountPolicy(); 800 AddPublicSessionToDevicePolicy(kAccountId1); 801 802 // This observes the display name becoming available as this indicates 803 // device-local account policy is fully loaded, which is a prerequisite for 804 // successful login. 805 content::WindowedNotificationObserver( 806 chrome::NOTIFICATION_USER_LIST_CHANGED, 807 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 808 809 // Wait for the login UI to be ready. 810 chromeos::LoginDisplayHostImpl* host = 811 reinterpret_cast<chromeos::LoginDisplayHostImpl*>( 812 chromeos::LoginDisplayHostImpl::default_host()); 813 ASSERT_TRUE(host); 814 chromeos::OobeUI* oobe_ui = host->GetOobeUI(); 815 ASSERT_TRUE(oobe_ui); 816 base::RunLoop run_loop; 817 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure()); 818 if (!oobe_ui_ready) 819 run_loop.Run(); 820 821 // Start listening for app/extension installation results. 822 content::WindowedNotificationObserver hosted_app_observer( 823 chrome::NOTIFICATION_EXTENSION_INSTALLED, 824 base::Bind(DoesInstallSuccessReferToId, kHostedAppID)); 825 content::WindowedNotificationObserver extension_observer( 826 chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, 827 base::Bind(DoesInstallFailureReferToId, kGoodExtensionID)); 828 829 // Start login into the device-local account. 830 host->StartSignInScreen(LoginScreenContext()); 831 chromeos::ExistingUserController* controller = 832 chromeos::ExistingUserController::current_controller(); 833 ASSERT_TRUE(controller); 834 controller->LoginAsPublicAccount(user_id_1_); 835 836 // Wait for the hosted app installation to succeed and the extension 837 // installation to fail. 838 hosted_app_observer.Wait(); 839 extension_observer.Wait(); 840 841 // Verify that the hosted app was installed. 842 Profile* profile = GetProfileForTest(); 843 ASSERT_TRUE(profile); 844 ExtensionService* extension_service = 845 extensions::ExtensionSystem::Get(profile)->extension_service(); 846 EXPECT_TRUE(extension_service->GetExtensionById(kHostedAppID, true)); 847 848 // Verify that the extension was not installed. 849 EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true)); 850 851 // Verify that the app is still in the account's extension cache. 852 EXPECT_TRUE(PathExists(cached_hosted_app)); 853 854 // Verify that the extension was removed from the account's extension cache. 855 EXPECT_FALSE(PathExists(cached_extension)); 856} 857 858IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExternalData) { 859 // chromeos::UserManager requests an external data fetch whenever 860 // the key::kUserAvatarImage policy is set. Since this test wants to 861 // verify that the underlying policy subsystem will start a fetch 862 // without this request as well, the chromeos::UserManager must be 863 // prevented from seeing the policy change. 864 reinterpret_cast<chromeos::UserManagerImpl*>(chromeos::UserManager::Get())-> 865 StopPolicyObserverForTesting(); 866 867 UploadDeviceLocalAccountPolicy(); 868 AddPublicSessionToDevicePolicy(kAccountId1); 869 870 // This observes the display name becoming available as this indicates 871 // device-local account policy is fully loaded. 872 content::WindowedNotificationObserver( 873 chrome::NOTIFICATION_USER_LIST_CHANGED, 874 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 875 876 // Start serving external data at |kExternalDataURL|. 877 scoped_ptr<base::RunLoop> run_loop(new base::RunLoop); 878 scoped_ptr<net::FakeURLFetcherFactory> fetcher_factory( 879 new net::FakeURLFetcherFactory( 880 NULL, 881 base::Bind(&RunCallbackAndReturnFakeURLFetcher, 882 base::MessageLoopProxy::current(), 883 run_loop->QuitClosure()))); 884 fetcher_factory->SetFakeResponse(GURL(kExternalDataURL), 885 kExternalData, 886 net::HTTP_OK, 887 net::URLRequestStatus::SUCCESS); 888 889 // Specify an external data reference for the key::kUserAvatarImage policy. 890 scoped_ptr<base::DictionaryValue> metadata = 891 test::ConstructExternalDataReference(kExternalDataURL, kExternalData); 892 std::string policy; 893 base::JSONWriter::Write(metadata.get(), &policy); 894 device_local_account_policy_.payload().mutable_useravatarimage()->set_value( 895 policy); 896 UploadAndInstallDeviceLocalAccountPolicy(); 897 policy::BrowserPolicyConnectorChromeOS* connector = 898 g_browser_process->platform_part()->browser_policy_connector_chromeos(); 899 DeviceLocalAccountPolicyBroker* broker = 900 connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser( 901 user_id_1_); 902 ASSERT_TRUE(broker); 903 broker->core()->store()->Load(); 904 905 // The external data should be fetched and cached automatically. Wait for this 906 // fetch. 907 run_loop->Run(); 908 909 // Stop serving external data at |kExternalDataURL|. 910 fetcher_factory.reset(); 911 912 const PolicyMap::Entry* policy_entry = 913 broker->core()->store()->policy_map().Get(key::kUserAvatarImage); 914 ASSERT_TRUE(policy_entry); 915 ASSERT_TRUE(policy_entry->external_data_fetcher); 916 917 // Retrieve the external data. Although the data is no longer being served at 918 // |kExternalDataURL|, the retrieval should succeed because the data has been 919 // cached. 920 run_loop.reset(new base::RunLoop); 921 scoped_ptr<std::string> fetched_external_data; 922 policy_entry->external_data_fetcher->Fetch(base::Bind( 923 &test::ExternalDataFetchCallback, 924 &fetched_external_data, 925 run_loop->QuitClosure())); 926 run_loop->Run(); 927 928 ASSERT_TRUE(fetched_external_data); 929 EXPECT_EQ(kExternalData, *fetched_external_data); 930 931 // Wait for the login UI to be ready. 932 chromeos::LoginDisplayHostImpl* host = 933 reinterpret_cast<chromeos::LoginDisplayHostImpl*>( 934 chromeos::LoginDisplayHostImpl::default_host()); 935 ASSERT_TRUE(host); 936 chromeos::OobeUI* oobe_ui = host->GetOobeUI(); 937 ASSERT_TRUE(oobe_ui); 938 run_loop.reset(new base::RunLoop); 939 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop->QuitClosure()); 940 if (!oobe_ui_ready) 941 run_loop->Run(); 942 943 // Start login into the device-local account. 944 host->StartSignInScreen(LoginScreenContext()); 945 chromeos::ExistingUserController* controller = 946 chromeos::ExistingUserController::current_controller(); 947 ASSERT_TRUE(controller); 948 controller->LoginAsPublicAccount(user_id_1_); 949 950 // Wait for the session to start. 951 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED, 952 base::Bind(IsSessionStarted)).Wait(); 953 954 // Verify that the external data reference has propagated to the device-local 955 // account's ProfilePolicyConnector. 956 ProfilePolicyConnector* policy_connector = 957 ProfilePolicyConnectorFactory::GetForProfile(GetProfileForTest()); 958 ASSERT_TRUE(policy_connector); 959 const PolicyMap& policies = policy_connector->policy_service()->GetPolicies( 960 PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())); 961 policy_entry = policies.Get(key::kUserAvatarImage); 962 ASSERT_TRUE(policy_entry); 963 EXPECT_TRUE(base::Value::Equals(metadata.get(), policy_entry->value)); 964 ASSERT_TRUE(policy_entry->external_data_fetcher); 965 966 // Retrieve the external data via the ProfilePolicyConnector. The retrieval 967 // should succeed because the data has been cached. 968 run_loop.reset(new base::RunLoop); 969 fetched_external_data.reset(); 970 policy_entry->external_data_fetcher->Fetch(base::Bind( 971 &test::ExternalDataFetchCallback, 972 &fetched_external_data, 973 run_loop->QuitClosure())); 974 run_loop->Run(); 975 976 ASSERT_TRUE(fetched_external_data); 977 EXPECT_EQ(kExternalData, *fetched_external_data); 978} 979 980IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, UserAvatarImage) { 981 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 982 983 UploadDeviceLocalAccountPolicy(); 984 AddPublicSessionToDevicePolicy(kAccountId1); 985 986 // This observes the display name becoming available as this indicates 987 // device-local account policy is fully loaded. 988 content::WindowedNotificationObserver( 989 chrome::NOTIFICATION_USER_LIST_CHANGED, 990 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 991 992 base::FilePath test_dir; 993 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir)); 994 std::string image_data; 995 ASSERT_TRUE(base::ReadFileToString( 996 test_dir.Append(chromeos::test::kUserAvatarImage1RelativePath), 997 &image_data)); 998 999 std::string policy; 1000 base::JSONWriter::Write(test::ConstructExternalDataReference( 1001 embedded_test_server()->GetURL(std::string("/") + 1002 chromeos::test::kUserAvatarImage1RelativePath).spec(), 1003 image_data).get(), 1004 &policy); 1005 device_local_account_policy_.payload().mutable_useravatarimage()->set_value( 1006 policy); 1007 UploadAndInstallDeviceLocalAccountPolicy(); 1008 policy::BrowserPolicyConnectorChromeOS* connector = 1009 g_browser_process->platform_part()->browser_policy_connector_chromeos(); 1010 DeviceLocalAccountPolicyBroker* broker = 1011 connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser( 1012 user_id_1_); 1013 ASSERT_TRUE(broker); 1014 1015 run_loop_.reset(new base::RunLoop); 1016 chromeos::UserManager::Get()->AddObserver(this); 1017 broker->core()->store()->Load(); 1018 run_loop_->Run(); 1019 chromeos::UserManager::Get()->RemoveObserver(this); 1020 1021 scoped_ptr<gfx::ImageSkia> policy_image = chromeos::test::ImageLoader( 1022 test_dir.Append(chromeos::test::kUserAvatarImage1RelativePath)).Load(); 1023 ASSERT_TRUE(policy_image); 1024 1025 const chromeos::User* user = 1026 chromeos::UserManager::Get()->FindUser(user_id_1_); 1027 ASSERT_TRUE(user); 1028 1029 base::FilePath user_data_dir; 1030 ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)); 1031 const base::FilePath saved_image_path = 1032 user_data_dir.Append(user_id_1_).AddExtension("jpg"); 1033 1034 EXPECT_FALSE(user->HasDefaultImage()); 1035 EXPECT_EQ(chromeos::User::kExternalImageIndex, user->image_index()); 1036 EXPECT_TRUE(chromeos::test::AreImagesEqual(*policy_image, user->image())); 1037 const base::DictionaryValue* images_pref = 1038 g_browser_process->local_state()->GetDictionary("user_image_info"); 1039 ASSERT_TRUE(images_pref); 1040 const base::DictionaryValue* image_properties; 1041 ASSERT_TRUE(images_pref->GetDictionaryWithoutPathExpansion( 1042 user_id_1_, 1043 &image_properties)); 1044 int image_index; 1045 std::string image_path; 1046 ASSERT_TRUE(image_properties->GetInteger("index", &image_index)); 1047 ASSERT_TRUE(image_properties->GetString("path", &image_path)); 1048 EXPECT_EQ(chromeos::User::kExternalImageIndex, image_index); 1049 EXPECT_EQ(saved_image_path.value(), image_path); 1050 1051 scoped_ptr<gfx::ImageSkia> saved_image = 1052 chromeos::test::ImageLoader(saved_image_path).Load(); 1053 ASSERT_TRUE(saved_image); 1054 1055 // Check image dimensions. Images can't be compared since JPEG is lossy. 1056 EXPECT_EQ(policy_image->width(), saved_image->width()); 1057 EXPECT_EQ(policy_image->height(), saved_image->height()); 1058} 1059 1060IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LastWindowClosedLogoutReminder) { 1061 UploadAndInstallDeviceLocalAccountPolicy(); 1062 AddPublicSessionToDevicePolicy(kAccountId1); 1063 1064 // This observes the display name becoming available as this indicates 1065 // device-local account policy is fully loaded. 1066 content::WindowedNotificationObserver( 1067 chrome::NOTIFICATION_USER_LIST_CHANGED, 1068 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 1069 1070 // Wait for the login UI to be ready. 1071 chromeos::LoginDisplayHostImpl* host = 1072 reinterpret_cast<chromeos::LoginDisplayHostImpl*>( 1073 chromeos::LoginDisplayHostImpl::default_host()); 1074 ASSERT_TRUE(host); 1075 chromeos::OobeUI* oobe_ui = host->GetOobeUI(); 1076 ASSERT_TRUE(oobe_ui); 1077 base::RunLoop run_loop; 1078 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure()); 1079 if (!oobe_ui_ready) 1080 run_loop.Run(); 1081 1082 // Start login into the device-local account. 1083 host->StartSignInScreen(LoginScreenContext()); 1084 chromeos::ExistingUserController* controller = 1085 chromeos::ExistingUserController::current_controller(); 1086 ASSERT_TRUE(controller); 1087 controller->LoginAsPublicAccount(user_id_1_); 1088 1089 // Wait for the session to start. 1090 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED, 1091 base::Bind(IsSessionStarted)).Wait(); 1092 1093 Profile* profile = GetProfileForTest(); 1094 ASSERT_TRUE(profile); 1095 apps::AppWindowRegistry* app_window_registry = 1096 apps::AppWindowRegistry::Get(profile); 1097 app_window_registry->AddObserver(this); 1098 1099 // Verify that the logout confirmation dialog is not showing. 1100 ash::internal::LogoutConfirmationController* logout_confirmation_controller = 1101 ash::Shell::GetInstance()->logout_confirmation_controller(); 1102 ASSERT_TRUE(logout_confirmation_controller); 1103 EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing()); 1104 1105 // Remove policy that allows only explicitly whitelisted apps to be installed 1106 // in a public session. 1107 extensions::ExtensionSystem* extension_system = 1108 extensions::ExtensionSystem::Get(profile); 1109 ASSERT_TRUE(extension_system); 1110 extension_system->management_policy()->UnregisterAllProviders(); 1111 1112 // Install and a platform app. 1113 scoped_refptr<extensions::CrxInstaller> installer = 1114 extensions::CrxInstaller::CreateSilent( 1115 extension_system->extension_service()); 1116 installer->set_allow_silent_install(true); 1117 installer->set_install_cause(extension_misc::INSTALL_CAUSE_USER_DOWNLOAD); 1118 installer->set_creation_flags(extensions::Extension::FROM_WEBSTORE); 1119 content::WindowedNotificationObserver app_install_observer( 1120 chrome::NOTIFICATION_CRX_INSTALLER_DONE, 1121 content::NotificationService::AllSources()); 1122 base::FilePath test_dir; 1123 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir)); 1124 installer->InstallCrx(test_dir.Append(kPackagedAppCRXPath)); 1125 app_install_observer.Wait(); 1126 const extensions::Extension* app = 1127 content::Details<const extensions::Extension>( 1128 app_install_observer.details()).ptr(); 1129 1130 // Start the platform app, causing it to open a window. 1131 run_loop_.reset(new base::RunLoop); 1132 OpenApplication(AppLaunchParams( 1133 profile, app, extensions::LAUNCH_CONTAINER_NONE, NEW_WINDOW)); 1134 run_loop_->Run(); 1135 EXPECT_EQ(1U, app_window_registry->app_windows().size()); 1136 1137 // Close the only open browser window. 1138 BrowserList* browser_list = 1139 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH); 1140 EXPECT_EQ(1U, browser_list->size()); 1141 Browser* browser = browser_list->get(0); 1142 ASSERT_TRUE(browser); 1143 BrowserWindow* browser_window = browser->window(); 1144 ASSERT_TRUE(browser_window); 1145 run_loop_.reset(new base::RunLoop); 1146 browser_window->Close(); 1147 browser_window = NULL; 1148 run_loop_->Run(); 1149 browser = NULL; 1150 EXPECT_TRUE(browser_list->empty()); 1151 1152 // Verify that the logout confirmation dialog is not showing because an app 1153 // window is still open. 1154 EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing()); 1155 1156 // Open a browser window. 1157 Browser* first_browser = CreateBrowser(profile); 1158 EXPECT_EQ(1U, browser_list->size()); 1159 1160 // Close the app window. 1161 run_loop_.reset(new base::RunLoop); 1162 ASSERT_EQ(1U, app_window_registry->app_windows().size()); 1163 app_window_registry->app_windows().front()->GetBaseWindow()->Close(); 1164 run_loop_->Run(); 1165 EXPECT_TRUE(app_window_registry->app_windows().empty()); 1166 1167 // Verify that the logout confirmation dialog is not showing because a browser 1168 // window is still open. 1169 EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing()); 1170 1171 // Open a second browser window. 1172 Browser* second_browser = CreateBrowser(profile); 1173 EXPECT_EQ(2U, browser_list->size()); 1174 1175 // Close the first browser window. 1176 browser_window = first_browser->window(); 1177 ASSERT_TRUE(browser_window); 1178 run_loop_.reset(new base::RunLoop); 1179 browser_window->Close(); 1180 browser_window = NULL; 1181 run_loop_->Run(); 1182 first_browser = NULL; 1183 EXPECT_EQ(1U, browser_list->size()); 1184 1185 // Verify that the logout confirmation dialog is not showing because a browser 1186 // window is still open. 1187 EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing()); 1188 1189 // Close the second browser window. 1190 browser_window = second_browser->window(); 1191 ASSERT_TRUE(browser_window); 1192 run_loop_.reset(new base::RunLoop); 1193 browser_window->Close(); 1194 browser_window = NULL; 1195 run_loop_->Run(); 1196 second_browser = NULL; 1197 EXPECT_TRUE(browser_list->empty()); 1198 1199 // Verify that the logout confirmation dialog is showing. 1200 ash::internal::LogoutConfirmationDialog* dialog = 1201 logout_confirmation_controller->dialog_for_testing(); 1202 ASSERT_TRUE(dialog); 1203 1204 // Deny the logout. 1205 dialog->GetWidget()->Close(); 1206 dialog = NULL; 1207 base::RunLoop().RunUntilIdle(); 1208 1209 // Verify that the logout confirmation dialog is no longer showing. 1210 EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing()); 1211 1212 // Open a browser window. 1213 browser = CreateBrowser(profile); 1214 EXPECT_EQ(1U, browser_list->size()); 1215 1216 // Close the browser window. 1217 browser_window = browser->window(); 1218 ASSERT_TRUE(browser_window); 1219 run_loop_.reset(new base::RunLoop); 1220 browser_window->Close(); 1221 browser_window = NULL; 1222 run_loop_->Run(); 1223 browser = NULL; 1224 EXPECT_TRUE(browser_list->empty()); 1225 1226 // Verify that the logout confirmation dialog is showing again. 1227 dialog = logout_confirmation_controller->dialog_for_testing(); 1228 ASSERT_TRUE(dialog); 1229 1230 // Deny the logout. 1231 dialog->GetWidget()->Close(); 1232 dialog = NULL; 1233 base::RunLoop().RunUntilIdle(); 1234 1235 app_window_registry->RemoveObserver(this); 1236}; 1237 1238class TermsOfServiceTest : public DeviceLocalAccountTest, 1239 public testing::WithParamInterface<bool> { 1240}; 1241 1242IN_PROC_BROWSER_TEST_P(TermsOfServiceTest, TermsOfServiceScreen) { 1243 // Specify Terms of Service URL. 1244 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 1245 device_local_account_policy_.payload().mutable_termsofserviceurl()->set_value( 1246 embedded_test_server()->GetURL( 1247 std::string("/") + 1248 (GetParam() ? kExistentTermsOfServicePath 1249 : kNonexistentTermsOfServicePath)).spec()); 1250 UploadAndInstallDeviceLocalAccountPolicy(); 1251 AddPublicSessionToDevicePolicy(kAccountId1); 1252 1253 // Wait for the device-local account policy to be fully loaded. 1254 content::WindowedNotificationObserver( 1255 chrome::NOTIFICATION_USER_LIST_CHANGED, 1256 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 1257 1258 // Wait for the login UI to be ready. 1259 chromeos::LoginDisplayHostImpl* host = 1260 reinterpret_cast<chromeos::LoginDisplayHostImpl*>( 1261 chromeos::LoginDisplayHostImpl::default_host()); 1262 ASSERT_TRUE(host); 1263 chromeos::OobeUI* oobe_ui = host->GetOobeUI(); 1264 ASSERT_TRUE(oobe_ui); 1265 base::RunLoop oobe_ui_wait_run_loop; 1266 const bool oobe_ui_ready = 1267 oobe_ui->IsJSReady(oobe_ui_wait_run_loop.QuitClosure()); 1268 if (!oobe_ui_ready) 1269 oobe_ui_wait_run_loop.Run(); 1270 1271 // Start login into the device-local account. 1272 host->StartSignInScreen(LoginScreenContext()); 1273 chromeos::ExistingUserController* controller = 1274 chromeos::ExistingUserController::current_controller(); 1275 ASSERT_TRUE(controller); 1276 controller->LoginAsPublicAccount(user_id_1_); 1277 1278 // Set up an observer that will quit the message loop when login has succeeded 1279 // and the first wizard screen, if any, is being shown. 1280 base::RunLoop login_wait_run_loop; 1281 chromeos::MockConsumer login_status_consumer; 1282 EXPECT_CALL(login_status_consumer, OnLoginSuccess(_)) 1283 .Times(1) 1284 .WillOnce(InvokeWithoutArgs(&login_wait_run_loop, &base::RunLoop::Quit)); 1285 1286 // Spin the loop until the observer fires. Then, unregister the observer. 1287 controller->set_login_status_consumer(&login_status_consumer); 1288 login_wait_run_loop.Run(); 1289 controller->set_login_status_consumer(NULL); 1290 1291 // Verify that the Terms of Service screen is being shown. 1292 chromeos::WizardController* wizard_controller = 1293 chromeos::WizardController::default_controller(); 1294 ASSERT_TRUE(wizard_controller); 1295 ASSERT_TRUE(wizard_controller->current_screen()); 1296 EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName, 1297 wizard_controller->current_screen()->GetName()); 1298 1299 // Wait for the Terms of Service to finish downloading, then get the status of 1300 // the screen's UI elements. 1301 chromeos::WebUILoginView* web_ui_login_view = host->GetWebUILoginView(); 1302 ASSERT_TRUE(web_ui_login_view); 1303 content::WebUI* web_ui = web_ui_login_view->GetWebUI(); 1304 ASSERT_TRUE(web_ui); 1305 content::WebContents* contents = web_ui->GetWebContents(); 1306 ASSERT_TRUE(contents); 1307 std::string json; 1308 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents, 1309 "var screen = document.getElementById('terms-of-service');" 1310 "function SendReplyIfDownloadDone() {" 1311 " if (screen.classList.contains('tos-loading'))" 1312 " return false;" 1313 " var status = {};" 1314 " status.heading = document.getElementById('tos-heading').textContent;" 1315 " status.subheading =" 1316 " document.getElementById('tos-subheading').textContent;" 1317 " status.contentHeading =" 1318 " document.getElementById('tos-content-heading').textContent;" 1319 " status.content =" 1320 " document.getElementById('tos-content-main').textContent;" 1321 " status.error = screen.classList.contains('error');" 1322 " status.acceptEnabled =" 1323 " !document.getElementById('tos-accept-button').disabled;" 1324 " domAutomationController.send(JSON.stringify(status));" 1325 " observer.disconnect();" 1326 " return true;" 1327 "}" 1328 "var observer = new MutationObserver(SendReplyIfDownloadDone);" 1329 "if (!SendReplyIfDownloadDone()) {" 1330 " var options = { attributes: true, attributeFilter: [ 'class' ] };" 1331 " observer.observe(screen, options);" 1332 "}", 1333 &json)); 1334 scoped_ptr<base::Value> value_ptr(base::JSONReader::Read(json)); 1335 const base::DictionaryValue* status = NULL; 1336 ASSERT_TRUE(value_ptr.get()); 1337 ASSERT_TRUE(value_ptr->GetAsDictionary(&status)); 1338 std::string heading; 1339 EXPECT_TRUE(status->GetString("heading", &heading)); 1340 std::string subheading; 1341 EXPECT_TRUE(status->GetString("subheading", &subheading)); 1342 std::string content_heading; 1343 EXPECT_TRUE(status->GetString("contentHeading", &content_heading)); 1344 std::string content; 1345 EXPECT_TRUE(status->GetString("content", &content)); 1346 bool error; 1347 EXPECT_TRUE(status->GetBoolean("error", &error)); 1348 bool accept_enabled; 1349 EXPECT_TRUE(status->GetBoolean("acceptEnabled", &accept_enabled)); 1350 1351 // Verify that the screen's headings have been set correctly. 1352 EXPECT_EQ( 1353 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_HEADING, 1354 base::UTF8ToUTF16(kDomain)), 1355 heading); 1356 EXPECT_EQ( 1357 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_SUBHEADING, 1358 base::UTF8ToUTF16(kDomain)), 1359 subheading); 1360 EXPECT_EQ( 1361 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_CONTENT_HEADING, 1362 base::UTF8ToUTF16(kDomain)), 1363 content_heading); 1364 1365 if (!GetParam()) { 1366 // The Terms of Service URL was invalid. Verify that the screen is showing 1367 // an error and the accept button is disabled. 1368 EXPECT_TRUE(error); 1369 EXPECT_FALSE(accept_enabled); 1370 return; 1371 } 1372 1373 // The Terms of Service URL was valid. Verify that the screen is showing the 1374 // downloaded Terms of Service and the accept button is enabled. 1375 base::FilePath test_dir; 1376 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir)); 1377 std::string terms_of_service; 1378 ASSERT_TRUE(base::ReadFileToString( 1379 test_dir.Append(kExistentTermsOfServicePath), &terms_of_service)); 1380 EXPECT_EQ(terms_of_service, content); 1381 EXPECT_FALSE(error); 1382 EXPECT_TRUE(accept_enabled); 1383 1384 // Click the accept button. 1385 ASSERT_TRUE(content::ExecuteScript(contents, 1386 "$('tos-accept-button').click();")); 1387 1388 // Wait for the session to start. 1389 if (!IsSessionStarted()) { 1390 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED, 1391 base::Bind(IsSessionStarted)).Wait(); 1392 } 1393} 1394 1395INSTANTIATE_TEST_CASE_P(TermsOfServiceTestInstance, 1396 TermsOfServiceTest, testing::Bool()); 1397 1398} // namespace policy 1399