device_local_account_browsertest.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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/callback.h"
11#include "base/command_line.h"
12#include "base/file_util.h"
13#include "base/files/file_path.h"
14#include "base/files/scoped_temp_dir.h"
15#include "base/message_loop.h"
16#include "base/path_service.h"
17#include "base/run_loop.h"
18#include "base/stl_util.h"
19#include "base/string_util.h"
20#include "base/utf_string_conversions.h"
21#include "chrome/browser/browser_process.h"
22#include "chrome/browser/chromeos/login/existing_user_controller.h"
23#include "chrome/browser/chromeos/login/user.h"
24#include "chrome/browser/chromeos/login/user_manager.h"
25#include "chrome/browser/chromeos/login/wizard_controller.h"
26#include "chrome/browser/chromeos/policy/device_policy_builder.h"
27#include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
28#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
29#include "chrome/browser/chromeos/policy/proto/install_attributes.pb.h"
30#include "chrome/browser/lifetime/application_lifetime.h"
31#include "chrome/browser/policy/cloud/cloud_policy_constants.h"
32#include "chrome/browser/policy/cloud/policy_builder.h"
33#include "chrome/browser/policy/policy_service.h"
34#include "chrome/browser/policy/test/local_policy_test_server.h"
35#include "chrome/browser/prefs/session_startup_pref.h"
36#include "chrome/browser/ui/browser.h"
37#include "chrome/browser/ui/browser_finder.h"
38#include "chrome/browser/ui/host_desktop.h"
39#include "chrome/browser/ui/tabs/tab_strip_model.h"
40#include "chrome/common/chrome_notification_types.h"
41#include "chrome/common/chrome_paths.h"
42#include "chrome/common/chrome_switches.h"
43#include "chrome/test/base/in_process_browser_test.h"
44#include "chromeos/dbus/cryptohome_client.h"
45#include "chromeos/dbus/dbus_method_call_status.h"
46#include "chromeos/dbus/dbus_thread_manager.h"
47#include "chromeos/dbus/mock_dbus_thread_manager.h"
48#include "chromeos/dbus/mock_update_engine_client.h"
49#include "chromeos/dbus/session_manager_client.h"
50#include "content/public/browser/notification_observer.h"
51#include "content/public/browser/notification_registrar.h"
52#include "content/public/browser/notification_service.h"
53#include "content/public/browser/web_contents.h"
54#include "testing/gmock/include/gmock/gmock.h"
55#include "third_party/cros_system_api/dbus/service_constants.h"
56
57namespace em = enterprise_management;
58
59using testing::Return;
60
61namespace policy {
62
63namespace {
64
65const char kAccountId1[] = "dla1@example.com";
66const char kAccountId2[] = "dla2@example.com";
67const char kDisplayName1[] = "display name for account 1";
68const char kDisplayName2[] = "display name for account 2";
69const char* kStartupURLs[] = {
70  "chrome://policy",
71  "chrome://about",
72};
73
74// Observes a specific notification type and quits the message loop once a
75// condition holds.
76class NotificationWatcher : public content::NotificationObserver {
77 public:
78  // Callback invoked on notifications. Should return true when the condition
79  // that the caller is waiting for is satisfied.
80  typedef base::Callback<bool(void)> ConditionTestCallback;
81
82  explicit NotificationWatcher(int notification_type,
83                               const ConditionTestCallback& callback)
84      : type_(notification_type),
85        callback_(callback) {}
86
87  void Run() {
88    if (callback_.Run())
89      return;
90
91    content::NotificationRegistrar registrar;
92    registrar.Add(this, type_, content::NotificationService::AllSources());
93    run_loop_.Run();
94  }
95
96  // content::NotificationObserver:
97  virtual void Observe(int type,
98                       const content::NotificationSource& source,
99                       const content::NotificationDetails& details) OVERRIDE {
100    if (callback_.Run())
101      run_loop_.Quit();
102  }
103
104 private:
105  int type_;
106  ConditionTestCallback callback_;
107  base::RunLoop run_loop_;
108
109  DISALLOW_COPY_AND_ASSIGN(NotificationWatcher);
110};
111
112// A fake implementation of session_manager. Accepts policy blobs to be set and
113// returns them unmodified.
114class FakeSessionManagerClient : public chromeos::SessionManagerClient {
115 public:
116  FakeSessionManagerClient() {}
117  virtual ~FakeSessionManagerClient() {}
118
119  // SessionManagerClient:
120  virtual void AddObserver(Observer* observer) OVERRIDE {}
121  virtual void RemoveObserver(Observer* observer) OVERRIDE {}
122  virtual bool HasObserver(Observer* observer) OVERRIDE { return false; }
123  virtual void EmitLoginPromptReady() OVERRIDE {}
124  virtual void EmitLoginPromptVisible() OVERRIDE {}
125  virtual void RestartJob(int pid, const std::string& command_line) OVERRIDE {}
126  virtual void RestartEntd() OVERRIDE {}
127  virtual void StartSession(const std::string& user_email) OVERRIDE {}
128  virtual void StopSession() OVERRIDE {}
129  virtual void StartDeviceWipe() OVERRIDE {}
130  virtual void RequestLockScreen() OVERRIDE {}
131  virtual void NotifyLockScreenShown() OVERRIDE {}
132  virtual void RequestUnlockScreen() OVERRIDE {}
133  virtual void NotifyLockScreenDismissed() OVERRIDE {}
134  virtual void RetrieveDevicePolicy(
135      const RetrievePolicyCallback& callback) OVERRIDE {
136    MessageLoop::current()->PostTask(FROM_HERE,
137                                     base::Bind(callback, device_policy_));
138  }
139  virtual void RetrieveUserPolicy(
140      const RetrievePolicyCallback& callback) OVERRIDE {
141    MessageLoop::current()->PostTask(FROM_HERE,
142                                     base::Bind(callback, user_policy_));
143  }
144  virtual void RetrieveDeviceLocalAccountPolicy(
145      const std::string& account_id,
146      const RetrievePolicyCallback& callback) OVERRIDE {
147    MessageLoop::current()->PostTask(
148        FROM_HERE,
149        base::Bind(callback, device_local_account_policy_[account_id]));
150  }
151  virtual void StoreDevicePolicy(const std::string& policy_blob,
152                                 const StorePolicyCallback& callback) OVERRIDE {
153    device_policy_ = policy_blob;
154    MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, true));
155  }
156  virtual void StoreUserPolicy(const std::string& policy_blob,
157                               const StorePolicyCallback& callback) OVERRIDE {
158    user_policy_ = policy_blob;
159    MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, true));
160  }
161  virtual void StoreDeviceLocalAccountPolicy(
162      const std::string& account_id,
163      const std::string& policy_blob,
164      const StorePolicyCallback& callback) OVERRIDE {
165    device_local_account_policy_[account_id] = policy_blob;
166    MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, true));
167  }
168
169  const std::string& device_policy() const {
170    return device_policy_;
171  }
172  void set_device_policy(const std::string& policy_blob) {
173    device_policy_ = policy_blob;
174  }
175
176  const std::string& user_policy() const {
177    return user_policy_;
178  }
179  void set_user_policy(const std::string& policy_blob) {
180    user_policy_ = policy_blob;
181  }
182
183  const std::string& device_local_account_policy(
184      const std::string& account_id) const {
185    std::map<std::string, std::string>::const_iterator entry =
186        device_local_account_policy_.find(account_id);
187    return entry != device_local_account_policy_.end() ? entry->second
188                                                       : EmptyString();
189  }
190  void set_device_local_account_policy(const std::string& account_id,
191                                       const std::string& policy_blob) {
192    device_local_account_policy_[account_id] = policy_blob;
193  }
194
195 private:
196  std::string device_policy_;
197  std::string user_policy_;
198  std::map<std::string, std::string> device_local_account_policy_;
199
200  DISALLOW_COPY_AND_ASSIGN(FakeSessionManagerClient);
201};
202
203class FakeCryptohomeClient : public chromeos::CryptohomeClient {
204 public:
205  using chromeos::CryptohomeClient::AsyncMethodCallback;
206  using chromeos::CryptohomeClient::AsyncCallStatusHandler;
207  using chromeos::CryptohomeClient::AsyncCallStatusWithDataHandler;
208
209  FakeCryptohomeClient() {}
210  virtual ~FakeCryptohomeClient() {}
211
212  virtual void SetAsyncCallStatusHandlers(
213      const AsyncCallStatusHandler& handler,
214      const AsyncCallStatusWithDataHandler& data_handler) OVERRIDE {
215    handler_ = handler;
216    data_handler_ = data_handler;
217  }
218  virtual void ResetAsyncCallStatusHandlers() OVERRIDE {
219    handler_.Reset();
220    data_handler_.Reset();
221  }
222  virtual void IsMounted(
223      const chromeos::BoolDBusMethodCallback& callback) OVERRIDE {}
224  virtual bool Unmount(bool* success) OVERRIDE {
225    *success = true;
226    return true;
227  }
228  virtual void AsyncCheckKey(const std::string& username,
229                             const std::string& key,
230                             const AsyncMethodCallback& callback) OVERRIDE {}
231  virtual void AsyncMigrateKey(const std::string& username,
232                               const std::string& from_key,
233                               const std::string& to_key,
234                               const AsyncMethodCallback& callback) OVERRIDE {}
235  virtual void AsyncRemove(const std::string& username,
236                           const AsyncMethodCallback& callback) OVERRIDE {}
237  virtual bool GetSystemSalt(std::vector<uint8>* salt) OVERRIDE {
238    return false;
239  }
240  virtual void GetSanitizedUsername(
241      const std::string& username,
242      const chromeos::StringDBusMethodCallback& callback) OVERRIDE {}
243  virtual void AsyncMount(const std::string& username,
244                          const std::string& key,
245                          int flags,
246                          const AsyncMethodCallback& callback) OVERRIDE {
247    MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, 1));
248    MessageLoop::current()->PostTask(
249        FROM_HERE, base::Bind(handler_, 1, true, cryptohome::MOUNT_ERROR_NONE));
250  }
251  virtual void AsyncMountGuest(const AsyncMethodCallback& callback) OVERRIDE {}
252  virtual void TpmIsReady(
253      const chromeos::BoolDBusMethodCallback& callback) OVERRIDE {}
254  virtual void TpmIsEnabled(
255      const chromeos::BoolDBusMethodCallback& callback) OVERRIDE {}
256  virtual bool CallTpmIsEnabledAndBlock(bool* enabled) OVERRIDE {
257    return false;
258  }
259  virtual void TpmGetPassword(
260      const chromeos::StringDBusMethodCallback& callback) OVERRIDE {}
261  virtual void TpmIsOwned(
262      const chromeos::BoolDBusMethodCallback& kallback) OVERRIDE {}
263  virtual bool CallTpmIsOwnedAndBlock(bool* owned) OVERRIDE {
264    return false;
265  }
266  virtual void TpmIsBeingOwned(
267      const chromeos::BoolDBusMethodCallback& kallback) OVERRIDE {}
268  virtual bool CallTpmIsBeingOwnedAndBlock(bool* owning) OVERRIDE {
269    return false;
270  }
271  virtual void TpmCanAttemptOwnership(
272      const chromeos::VoidDBusMethodCallback& callback) OVERRIDE {}
273  virtual bool CallTpmClearStoredPasswordAndBlock() OVERRIDE {
274    return false;
275  }
276  virtual void TpmClearStoredPassword(
277      const chromeos::VoidDBusMethodCallback& kallback) OVERRIDE {}
278  virtual void Pkcs11IsTpmTokenReady(
279      const chromeos::BoolDBusMethodCallback& callback) OVERRIDE {}
280  virtual void Pkcs11GetTpmTokenInfo(
281      const Pkcs11GetTpmTokenInfoCallback& callback) OVERRIDE {}
282  virtual bool InstallAttributesGet(const std::string& name,
283                                    std::vector<uint8>* value,
284                                    bool* successful) OVERRIDE {
285    return false;
286  }
287  virtual bool InstallAttributesSet(const std::string& name,
288                                    const std::vector<uint8>& value,
289                                    bool* successful) OVERRIDE {
290    return false;
291  }
292  virtual bool InstallAttributesFinalize(bool* successful) OVERRIDE {
293    return false;
294  }
295  virtual bool InstallAttributesIsReady(bool* is_ready) OVERRIDE {
296    return false;
297  }
298  virtual bool InstallAttributesIsInvalid(bool* is_invalid) OVERRIDE {
299    return true;
300  }
301  virtual bool InstallAttributesIsFirstInstall(
302      bool* is_first_install) OVERRIDE {
303    return false;
304  }
305  virtual void TpmAttestationIsPrepared(
306        const chromeos::BoolDBusMethodCallback& callback) OVERRIDE {}
307  virtual void TpmAttestationIsEnrolled(
308        const chromeos::BoolDBusMethodCallback& callback) OVERRIDE {}
309  virtual void AsyncTpmAttestationCreateEnrollRequest(
310      const AsyncMethodCallback& callback) OVERRIDE {}
311  virtual void AsyncTpmAttestationEnroll(
312      const std::string& pca_response,
313      const AsyncMethodCallback& callback) OVERRIDE {}
314  virtual void AsyncTpmAttestationCreateCertRequest(
315      bool is_cert_for_owner,
316      const AsyncMethodCallback& callback) OVERRIDE {}
317  virtual void AsyncTpmAttestationFinishCertRequest(
318      const std::string& pca_response,
319      const AsyncMethodCallback& callback) OVERRIDE {}
320
321 private:
322  AsyncCallStatusHandler handler_;
323  AsyncCallStatusWithDataHandler data_handler_;
324
325  DISALLOW_COPY_AND_ASSIGN(FakeCryptohomeClient);
326};
327
328}  // namespace
329
330class DeviceLocalAccountTest : public InProcessBrowserTest {
331 protected:
332  DeviceLocalAccountTest() {}
333  virtual ~DeviceLocalAccountTest() {}
334
335  virtual void SetUp() OVERRIDE {
336    // Configure and start the test server.
337    scoped_ptr<crypto::RSAPrivateKey> signing_key(
338        PolicyBuilder::CreateTestSigningKey());
339    ASSERT_TRUE(test_server_.SetSigningKey(signing_key.get()));
340    signing_key.reset();
341    test_server_.RegisterClient(PolicyBuilder::kFakeToken,
342                                PolicyBuilder::kFakeDeviceId);
343    ASSERT_TRUE(test_server_.Start());
344
345    InProcessBrowserTest::SetUp();
346  }
347
348  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
349    command_line->AppendSwitch(switches::kLoginManager);
350    command_line->AppendSwitch(switches::kForceLoginManagerInTests);
351    command_line->AppendSwitchASCII(
352        switches::kLoginScreen, chromeos::WizardController::kLoginScreenName);
353    command_line->AppendSwitchASCII(
354        switches::kDeviceManagementUrl, test_server_.GetServiceURL().spec());
355    command_line->AppendSwitchASCII(
356        switches::kLoginProfile, "user");
357  }
358
359  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
360    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
361
362    // Clear command-line arguments (but keep command-line switches) so the
363    // startup pages policy takes effect.
364    CommandLine* command_line = CommandLine::ForCurrentProcess();
365    CommandLine::StringVector argv(command_line->argv());
366    argv.erase(argv.begin() + argv.size() - command_line->GetArgs().size(),
367               argv.end());
368    command_line->InitFromArgv(argv);
369
370    // Mark the device enterprise-enrolled.
371    SetUpInstallAttributes();
372
373    SetUpPolicy();
374
375    // Redirect session_manager DBus calls to FakeSessionManagerClient.
376    chromeos::MockDBusThreadManager* dbus_thread_manager =
377        new chromeos::MockDBusThreadManager();
378    EXPECT_CALL(*dbus_thread_manager, GetSessionManagerClient())
379        .WillRepeatedly(Return(&session_manager_client_));
380    chromeos::DBusThreadManager::InitializeForTesting(dbus_thread_manager);
381
382    // Mock out cryptohome mount calls to succeed immediately.
383    EXPECT_CALL(*dbus_thread_manager, GetCryptohomeClient())
384        .WillRepeatedly(Return(&cryptohome_client_));
385
386    // Set up the MockUpdateEngineClient.
387    EXPECT_CALL(*dbus_thread_manager->mock_update_engine_client(),
388                GetLastStatus())
389        .Times(1)
390        .WillOnce(Return(chromeos::MockUpdateEngineClient::Status()));
391  }
392
393  virtual void CleanUpOnMainThread() OVERRIDE {
394    // This shuts down the login UI.
395    MessageLoop::current()->PostTask(FROM_HERE,
396                                     base::Bind(&chrome::AttemptExit));
397    base::RunLoop().RunUntilIdle();
398  }
399
400  void SetUpInstallAttributes() {
401    cryptohome::SerializedInstallAttributes install_attrs_proto;
402    cryptohome::SerializedInstallAttributes::Attribute* attribute = NULL;
403
404    attribute = install_attrs_proto.add_attributes();
405    attribute->set_name(EnterpriseInstallAttributes::kAttrEnterpriseOwned);
406    attribute->set_value("true");
407
408    attribute = install_attrs_proto.add_attributes();
409    attribute->set_name(EnterpriseInstallAttributes::kAttrEnterpriseUser);
410    attribute->set_value(PolicyBuilder::kFakeUsername);
411
412    base::FilePath install_attrs_file =
413        temp_dir_.path().AppendASCII("install_attributes.pb");
414    const std::string install_attrs_blob(
415        install_attrs_proto.SerializeAsString());
416    ASSERT_EQ(static_cast<int>(install_attrs_blob.size()),
417              file_util::WriteFile(install_attrs_file,
418                                   install_attrs_blob.c_str(),
419                                   install_attrs_blob.size()));
420    ASSERT_TRUE(PathService::Override(chrome::FILE_INSTALL_ATTRIBUTES,
421                                      install_attrs_file));
422  }
423
424  void SetUpPolicy() {
425    // Configure two device-local accounts in device settings.
426    DevicePolicyBuilder device_policy;
427    device_policy.policy_data().set_public_key_version(1);
428    em::ChromeDeviceSettingsProto& proto(device_policy.payload());
429    proto.mutable_show_user_names()->set_show_user_names(true);
430    proto.mutable_device_local_accounts()->add_account()->set_id(kAccountId1);
431    proto.mutable_device_local_accounts()->add_account()->set_id(kAccountId2);
432    device_policy.Build();
433    session_manager_client_.set_device_policy(device_policy.GetBlob());
434    test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType,
435                              std::string(), proto.SerializeAsString());
436
437    // Install the owner key.
438    base::FilePath owner_key_file = temp_dir_.path().AppendASCII("owner.key");
439    std::vector<uint8> owner_key_bits;
440    ASSERT_TRUE(device_policy.signing_key()->ExportPublicKey(&owner_key_bits));
441    ASSERT_EQ(
442        static_cast<int>(owner_key_bits.size()),
443        file_util::WriteFile(
444            owner_key_file,
445            reinterpret_cast<const char*>(vector_as_array(&owner_key_bits)),
446            owner_key_bits.size()));
447    ASSERT_TRUE(PathService::Override(chrome::FILE_OWNER_KEY, owner_key_file));
448
449    // Configure device-local account policy for the first device-local account.
450    UserPolicyBuilder device_local_account_policy;
451    device_local_account_policy.policy_data().set_policy_type(
452        dm_protocol::kChromePublicAccountPolicyType);
453    device_local_account_policy.policy_data().set_username(kAccountId1);
454    device_local_account_policy.policy_data().set_settings_entity_id(
455        kAccountId1);
456    device_local_account_policy.policy_data().set_public_key_version(1);
457    device_local_account_policy.payload().mutable_restoreonstartup()->set_value(
458        SessionStartupPref::kPrefValueURLs);
459    em::StringListPolicyProto* startup_urls_proto =
460        device_local_account_policy.payload().mutable_restoreonstartupurls();
461    for (size_t i = 0; i < arraysize(kStartupURLs); ++i)
462      startup_urls_proto->mutable_value()->add_entries(kStartupURLs[i]);
463    device_local_account_policy.payload().mutable_userdisplayname()->set_value(
464        kDisplayName1);
465    device_local_account_policy.Build();
466    session_manager_client_.set_device_local_account_policy(
467        kAccountId1, device_local_account_policy.GetBlob());
468    test_server_.UpdatePolicy(
469        dm_protocol::kChromePublicAccountPolicyType, kAccountId1,
470        device_local_account_policy.payload().SerializeAsString());
471
472    // Make policy for the second account available from the server.
473    device_local_account_policy.payload().mutable_userdisplayname()->set_value(
474        kDisplayName2);
475    test_server_.UpdatePolicy(
476        dm_protocol::kChromePublicAccountPolicyType, kAccountId2,
477        device_local_account_policy.payload().SerializeAsString());
478
479    // Don't install policy for |kAccountId2| yet so initial download gets
480    // test coverage.
481    ASSERT_TRUE(session_manager_client_.device_local_account_policy(
482        kAccountId2).empty());
483  }
484
485  void CheckPublicSessionPresent(const std::string& id) {
486    const chromeos::User* user = chromeos::UserManager::Get()->FindUser(id);
487    ASSERT_TRUE(user);
488    EXPECT_EQ(id, user->email());
489    EXPECT_EQ(chromeos::User::USER_TYPE_PUBLIC_ACCOUNT, user->GetType());
490  }
491
492  LocalPolicyTestServer test_server_;
493  base::ScopedTempDir temp_dir_;
494
495  FakeSessionManagerClient session_manager_client_;
496  FakeCryptohomeClient cryptohome_client_;
497};
498
499static bool IsKnownUser(const std::string& account_id) {
500  return chromeos::UserManager::Get()->IsKnownUser(account_id);
501}
502
503IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LoginScreen) {
504  NotificationWatcher(chrome::NOTIFICATION_USER_LIST_CHANGED,
505                      base::Bind(&IsKnownUser, kAccountId1)).Run();
506  NotificationWatcher(chrome::NOTIFICATION_USER_LIST_CHANGED,
507                      base::Bind(&IsKnownUser, kAccountId2)).Run();
508
509  CheckPublicSessionPresent(kAccountId1);
510  CheckPublicSessionPresent(kAccountId2);
511}
512
513static bool DisplayNameMatches(const std::string& account_id,
514                        const std::string& display_name) {
515  const chromeos::User* user =
516      chromeos::UserManager::Get()->FindUser(account_id);
517  if (!user || user->display_name().empty())
518    return false;
519  EXPECT_EQ(UTF8ToUTF16(display_name), user->display_name());
520  return true;
521}
522
523IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DisplayName) {
524  NotificationWatcher(
525      chrome::NOTIFICATION_USER_LIST_CHANGED,
526      base::Bind(&DisplayNameMatches, kAccountId1, kDisplayName1)).Run();
527}
528
529IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyDownload) {
530  // Policy for kAccountId2 is not installed in session_manager_client, make
531  // sure it gets fetched from the server. Note that the test setup doesn't set
532  // up policy for kAccountId2, so the presence of the display name can be used
533  // as signal to indicate successful policy download.
534  NotificationWatcher(
535      chrome::NOTIFICATION_USER_LIST_CHANGED,
536      base::Bind(&DisplayNameMatches, kAccountId2, kDisplayName2)).Run();
537
538  // Sanity check: The policy should be present now.
539  ASSERT_FALSE(session_manager_client_.device_local_account_policy(
540      kAccountId2).empty());
541}
542
543static bool IsNotKnownUser(const std::string& account_id) {
544  return !IsKnownUser(account_id);
545}
546
547IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DevicePolicyChange) {
548  // Wait until the login screen is up.
549  NotificationWatcher(chrome::NOTIFICATION_USER_LIST_CHANGED,
550                      base::Bind(&IsKnownUser, kAccountId1)).Run();
551  NotificationWatcher(chrome::NOTIFICATION_USER_LIST_CHANGED,
552                      base::Bind(&IsKnownUser, kAccountId2)).Run();
553
554  // Update policy to remove kAccountId2.
555  em::ChromeDeviceSettingsProto policy;
556  policy.mutable_show_user_names()->set_show_user_names(true);
557  policy.mutable_device_local_accounts()->add_account()->set_id(kAccountId1);
558
559  test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType, std::string(),
560                            policy.SerializeAsString());
561  g_browser_process->policy_service()->RefreshPolicies(base::Closure());
562
563  // Make sure the second device-local account disappears.
564  NotificationWatcher(chrome::NOTIFICATION_USER_LIST_CHANGED,
565                      base::Bind(&IsNotKnownUser, kAccountId2)).Run();
566}
567
568static bool IsSessionStarted() {
569  return chromeos::UserManager::Get()->IsSessionStarted();
570}
571
572IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, StartSession) {
573  // This observes the display name becoming available as this indicates
574  // device-local account policy is fully loaded, which is a prerequisite for
575  // successful login.
576  NotificationWatcher(
577      chrome::NOTIFICATION_USER_LIST_CHANGED,
578      base::Bind(&DisplayNameMatches, kAccountId1, kDisplayName1)).Run();
579
580  chromeos::ExistingUserController* controller =
581      chromeos::ExistingUserController::current_controller();
582  ASSERT_TRUE(controller);
583  controller->LoginAsPublicAccount(kAccountId1);
584
585  // Wait for the session to start.
586  NotificationWatcher(chrome::NOTIFICATION_SESSION_STARTED,
587                      base::Bind(IsSessionStarted)).Run();
588
589  // Check that the startup pages specified in policy were opened.
590  EXPECT_EQ(1U, chrome::GetTotalBrowserCount());
591  Browser* browser =
592      chrome::FindLastActiveWithHostDesktopType(chrome::HOST_DESKTOP_TYPE_ASH);
593  ASSERT_TRUE(browser);
594
595  TabStripModel* tabs = browser->tab_strip_model();
596  ASSERT_TRUE(tabs);
597  int expected_tab_count = static_cast<int>(arraysize(kStartupURLs));
598  EXPECT_EQ(expected_tab_count, tabs->count());
599  for (int i = 0; i < expected_tab_count && i < tabs->count(); ++i)
600    EXPECT_EQ(GURL(kStartupURLs[i]), tabs->GetWebContentsAt(i)->GetURL());
601}
602
603}  // namespace policy
604