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