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