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