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