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