device_local_account_browsertest.cc revision 9ab5563a3196760eb381d102cbb2bc0f7abc6a50
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/command_line.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/message_loop/message_loop.h"
13#include "base/run_loop.h"
14#include "base/strings/string_util.h"
15#include "base/strings/utf_string_conversions.h"
16#include "chrome/browser/browser_process.h"
17#include "chrome/browser/chrome_notification_types.h"
18#include "chrome/browser/chromeos/login/existing_user_controller.h"
19#include "chrome/browser/chromeos/login/login_display_host.h"
20#include "chrome/browser/chromeos/login/login_display_host_impl.h"
21#include "chrome/browser/chromeos/login/mock_login_status_consumer.h"
22#include "chrome/browser/chromeos/login/screens/wizard_screen.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_local_account.h"
27#include "chrome/browser/chromeos/policy/device_policy_builder.h"
28#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
29#include "chrome/browser/lifetime/application_lifetime.h"
30#include "chrome/browser/policy/cloud/cloud_policy_constants.h"
31#include "chrome/browser/policy/cloud/policy_builder.h"
32#include "chrome/browser/policy/policy_service.h"
33#include "chrome/browser/policy/proto/chromeos/chrome_device_policy.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_switches.h"
41#include "chromeos/chromeos_switches.h"
42#include "chromeos/dbus/cryptohome_client.h"
43#include "chromeos/dbus/dbus_method_call_status.h"
44#include "chromeos/dbus/fake_cryptohome_client.h"
45#include "chromeos/dbus/fake_session_manager_client.h"
46#include "chromeos/dbus/session_manager_client.h"
47#include "content/public/browser/web_contents.h"
48#include "content/public/test/test_utils.h"
49#include "crypto/rsa_private_key.h"
50#include "testing/gmock/include/gmock/gmock.h"
51#include "third_party/cros_system_api/dbus/service_constants.h"
52
53namespace em = enterprise_management;
54
55using testing::InvokeWithoutArgs;
56using testing::Return;
57using testing::_;
58
59namespace policy {
60
61namespace {
62
63const char kAccountId1[] = "dla1@example.com";
64const char kAccountId2[] = "dla2@example.com";
65const char kDisplayName[] = "display name";
66const char* kStartupURLs[] = {
67  "chrome://policy",
68  "chrome://about",
69};
70
71}  // namespace
72
73class DeviceLocalAccountTest : public DevicePolicyCrosBrowserTest {
74 protected:
75  DeviceLocalAccountTest()
76      : user_id_1_(GenerateDeviceLocalAccountUserId(
77            kAccountId1, DeviceLocalAccount::TYPE_PUBLIC_SESSION)),
78        user_id_2_(GenerateDeviceLocalAccountUserId(
79            kAccountId2, DeviceLocalAccount::TYPE_PUBLIC_SESSION)) {}
80
81  virtual ~DeviceLocalAccountTest() {}
82
83  virtual void SetUp() OVERRIDE {
84    // Configure and start the test server.
85    scoped_ptr<crypto::RSAPrivateKey> signing_key(
86        PolicyBuilder::CreateTestSigningKey());
87    ASSERT_TRUE(test_server_.SetSigningKey(signing_key.get()));
88    signing_key.reset();
89    test_server_.RegisterClient(PolicyBuilder::kFakeToken,
90                                PolicyBuilder::kFakeDeviceId);
91    ASSERT_TRUE(test_server_.Start());
92
93    DevicePolicyCrosBrowserTest::SetUp();
94  }
95
96  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
97    command_line->AppendSwitch(chromeos::switches::kLoginManager);
98    command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests);
99    command_line->AppendSwitchASCII(
100        switches::kDeviceManagementUrl, test_server_.GetServiceURL().spec());
101    command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
102  }
103
104  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
105    DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
106
107    // Clear command-line arguments (but keep command-line switches) so the
108    // startup pages policy takes effect.
109    CommandLine* command_line = CommandLine::ForCurrentProcess();
110    CommandLine::StringVector argv(command_line->argv());
111    argv.erase(argv.begin() + argv.size() - command_line->GetArgs().size(),
112               argv.end());
113    command_line->InitFromArgv(argv);
114
115    InstallOwnerKey();
116    MarkAsEnterpriseOwned();
117
118    InitializePolicy();
119  }
120
121  virtual void CleanUpOnMainThread() OVERRIDE {
122    // This shuts down the login UI.
123    base::MessageLoop::current()->PostTask(FROM_HERE,
124                                           base::Bind(&chrome::AttemptExit));
125    base::RunLoop().RunUntilIdle();
126  }
127
128  void RemoveOwnerPrivateKeyFromPolicyBuilders() {
129    // Any instances of the private half of the owner key held by policy
130    // builders must be dropped as otherwise the NSS library will tell Chrome
131    // that the key is available - which is incorrect and leads to Chrome
132    // behaving as if a local owner were logged in.
133    device_policy()->set_signing_key(scoped_ptr<crypto::RSAPrivateKey>());
134    device_policy()->set_new_signing_key(scoped_ptr<crypto::RSAPrivateKey>());
135    device_local_account_policy_.set_signing_key(
136        scoped_ptr<crypto::RSAPrivateKey>());
137    device_local_account_policy_.set_new_signing_key(
138        scoped_ptr<crypto::RSAPrivateKey>());
139  }
140
141  void InitializePolicy() {
142    device_policy()->policy_data().set_public_key_version(1);
143    em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
144    proto.mutable_show_user_names()->set_show_user_names(true);
145
146    device_local_account_policy_.policy_data().set_policy_type(
147        dm_protocol::kChromePublicAccountPolicyType);
148    device_local_account_policy_.policy_data().set_username(kAccountId1);
149    device_local_account_policy_.policy_data().set_settings_entity_id(
150        kAccountId1);
151    device_local_account_policy_.policy_data().set_public_key_version(1);
152    device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
153        kDisplayName);
154
155    RemoveOwnerPrivateKeyFromPolicyBuilders();
156  }
157
158  void BuildDeviceLocalAccountPolicy() {
159    device_local_account_policy_.set_signing_key(
160        PolicyBuilder::CreateTestSigningKey());
161    device_local_account_policy_.Build();
162    RemoveOwnerPrivateKeyFromPolicyBuilders();
163  }
164
165  void InstallDeviceLocalAccountPolicy() {
166    BuildDeviceLocalAccountPolicy();
167    session_manager_client()->set_device_local_account_policy(
168        kAccountId1, device_local_account_policy_.GetBlob());
169  }
170
171  void UploadDeviceLocalAccountPolicy() {
172    BuildDeviceLocalAccountPolicy();
173    ASSERT_TRUE(session_manager_client()->device_local_account_policy(
174        kAccountId1).empty());
175    test_server_.UpdatePolicy(
176        dm_protocol::kChromePublicAccountPolicyType, kAccountId1,
177        device_local_account_policy_.payload().SerializeAsString());
178  }
179
180  void AddPublicSessionToDevicePolicy(const std::string& username) {
181    em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
182    em::DeviceLocalAccountInfoProto* account =
183        proto.mutable_device_local_accounts()->add_account();
184    account->set_account_id(username);
185    account->set_type(
186        em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
187    RefreshDevicePolicy();
188    test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType,
189                              std::string(), proto.SerializeAsString());
190  }
191
192  void CheckPublicSessionPresent(const std::string& id) {
193    const chromeos::User* user = chromeos::UserManager::Get()->FindUser(id);
194    ASSERT_TRUE(user);
195    EXPECT_EQ(id, user->email());
196    EXPECT_EQ(chromeos::User::USER_TYPE_PUBLIC_ACCOUNT, user->GetType());
197  }
198
199  const std::string user_id_1_;
200  const std::string user_id_2_;
201
202  UserPolicyBuilder device_local_account_policy_;
203  LocalPolicyTestServer test_server_;
204};
205
206static bool IsKnownUser(const std::string& account_id) {
207  return chromeos::UserManager::Get()->IsKnownUser(account_id);
208}
209
210IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LoginScreen) {
211  AddPublicSessionToDevicePolicy(kAccountId1);
212  AddPublicSessionToDevicePolicy(kAccountId2);
213
214  content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
215                                        base::Bind(&IsKnownUser, user_id_1_))
216      .Wait();
217  content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
218                                        base::Bind(&IsKnownUser, user_id_2_))
219      .Wait();
220
221  CheckPublicSessionPresent(user_id_1_);
222  CheckPublicSessionPresent(user_id_2_);
223}
224
225static bool DisplayNameMatches(const std::string& account_id,
226                               const std::string& display_name) {
227  const chromeos::User* user =
228      chromeos::UserManager::Get()->FindUser(account_id);
229  if (!user || user->display_name().empty())
230    return false;
231  EXPECT_EQ(UTF8ToUTF16(display_name), user->display_name());
232  return true;
233}
234
235IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DisplayName) {
236  InstallDeviceLocalAccountPolicy();
237  AddPublicSessionToDevicePolicy(kAccountId1);
238
239  content::WindowedNotificationObserver(
240      chrome::NOTIFICATION_USER_LIST_CHANGED,
241      base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
242}
243
244IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyDownload) {
245  UploadDeviceLocalAccountPolicy();
246  AddPublicSessionToDevicePolicy(kAccountId1);
247
248  // Policy for the account is not installed in session_manager_client. Because
249  // of this, the presence of the display name (which comes from policy) can be
250  // used as a signal that indicates successful policy download.
251  content::WindowedNotificationObserver(
252      chrome::NOTIFICATION_USER_LIST_CHANGED,
253      base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
254
255  // Sanity check: The policy should be present now.
256  ASSERT_FALSE(session_manager_client()->device_local_account_policy(
257      kAccountId1).empty());
258}
259
260static bool IsNotKnownUser(const std::string& account_id) {
261  return !IsKnownUser(account_id);
262}
263
264IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DevicePolicyChange) {
265  AddPublicSessionToDevicePolicy(kAccountId1);
266  AddPublicSessionToDevicePolicy(kAccountId2);
267
268  // Wait until the login screen is up.
269  content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
270                                        base::Bind(&IsKnownUser, user_id_1_))
271      .Wait();
272  content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
273                                        base::Bind(&IsKnownUser, user_id_2_))
274      .Wait();
275
276  // Update policy to remove kAccountId2.
277  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
278  proto.mutable_device_local_accounts()->clear_account();
279  AddPublicSessionToDevicePolicy(kAccountId1);
280
281  em::ChromeDeviceSettingsProto policy;
282  policy.mutable_show_user_names()->set_show_user_names(true);
283  em::DeviceLocalAccountInfoProto* account1 =
284      policy.mutable_device_local_accounts()->add_account();
285  account1->set_account_id(kAccountId1);
286  account1->set_type(
287      em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
288
289  test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType, std::string(),
290                            policy.SerializeAsString());
291  g_browser_process->policy_service()->RefreshPolicies(base::Closure());
292
293  // Make sure the second device-local account disappears.
294  content::WindowedNotificationObserver(
295      chrome::NOTIFICATION_USER_LIST_CHANGED,
296      base::Bind(&IsNotKnownUser, user_id_2_)).Wait();
297}
298
299static bool IsSessionStarted() {
300  return chromeos::UserManager::Get()->IsSessionStarted();
301}
302
303IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, StartSession) {
304  // Specify startup pages.
305  device_local_account_policy_.payload().mutable_restoreonstartup()->set_value(
306      SessionStartupPref::kPrefValueURLs);
307  em::StringListPolicyProto* startup_urls_proto =
308      device_local_account_policy_.payload().mutable_restoreonstartupurls();
309  for (size_t i = 0; i < arraysize(kStartupURLs); ++i)
310    startup_urls_proto->mutable_value()->add_entries(kStartupURLs[i]);
311  InstallDeviceLocalAccountPolicy();
312  AddPublicSessionToDevicePolicy(kAccountId1);
313
314  // This observes the display name becoming available as this indicates
315  // device-local account policy is fully loaded, which is a prerequisite for
316  // successful login.
317  content::WindowedNotificationObserver(
318      chrome::NOTIFICATION_USER_LIST_CHANGED,
319      base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
320
321  chromeos::LoginDisplayHost* host =
322      chromeos::LoginDisplayHostImpl::default_host();
323  ASSERT_TRUE(host);
324  host->StartSignInScreen();
325  chromeos::ExistingUserController* controller =
326      chromeos::ExistingUserController::current_controller();
327  ASSERT_TRUE(controller);
328  controller->LoginAsPublicAccount(user_id_1_);
329
330  // Wait for the session to start.
331  content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED,
332                                        base::Bind(IsSessionStarted)).Wait();
333
334  // Check that the startup pages specified in policy were opened.
335  EXPECT_EQ(1U, chrome::GetTotalBrowserCount());
336  Browser* browser =
337      chrome::FindLastActiveWithHostDesktopType(chrome::HOST_DESKTOP_TYPE_ASH);
338  ASSERT_TRUE(browser);
339
340  TabStripModel* tabs = browser->tab_strip_model();
341  ASSERT_TRUE(tabs);
342  int expected_tab_count = static_cast<int>(arraysize(kStartupURLs));
343  EXPECT_EQ(expected_tab_count, tabs->count());
344  for (int i = 0; i < expected_tab_count && i < tabs->count(); ++i)
345    EXPECT_EQ(GURL(kStartupURLs[i]), tabs->GetWebContentsAt(i)->GetURL());
346}
347
348IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, TermsOfService) {
349  // Specify Terms of Service. The URL does not really matter as the test does
350  // not wait for the terms to load.
351  device_local_account_policy_.payload().mutable_termsofserviceurl()->set_value(
352      "http://localhost/tos");
353  InstallDeviceLocalAccountPolicy();
354  AddPublicSessionToDevicePolicy(kAccountId1);
355
356  // Wait for the device-local account policy to be fully loaded.
357  content::WindowedNotificationObserver(
358      chrome::NOTIFICATION_USER_LIST_CHANGED,
359      base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
360
361  // Start login into the device-local account.
362  chromeos::LoginDisplayHost* host =
363      chromeos::LoginDisplayHostImpl::default_host();
364  ASSERT_TRUE(host);
365  host->StartSignInScreen();
366  chromeos::ExistingUserController* controller =
367      chromeos::ExistingUserController::current_controller();
368  ASSERT_TRUE(controller);
369  controller->LoginAsPublicAccount(user_id_1_);
370
371  // Set up an observer that will quit the message loop when login has succeeded
372  // and the first wizard screen, if any, is being shown.
373  base::RunLoop run_loop;
374  chromeos::MockConsumer login_status_consumer;
375  EXPECT_CALL(login_status_consumer, OnLoginSuccess(_, false, false))
376      .Times(1)
377      .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
378
379  // Spin the loop until the observer fires. Then, unregister the observer.
380  controller->set_login_status_consumer(&login_status_consumer);
381  run_loop.Run();
382  controller->set_login_status_consumer(NULL);
383
384  // Verify that the Terms of Service screen is being shown.
385  chromeos::WizardController* wizard_controller =
386        chromeos::WizardController::default_controller();
387  ASSERT_TRUE(wizard_controller);
388  ASSERT_TRUE(wizard_controller->current_screen());
389  EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName,
390            wizard_controller->current_screen()->GetName());
391}
392
393}  // namespace policy
394