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