device_local_account_browsertest.cc revision 2385ea399aae016c0806a4f9ef3c9cfe3d2a39df
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 InitializePolicy() {
130    device_policy()->policy_data().set_public_key_version(1);
131    em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
132    proto.mutable_show_user_names()->set_show_user_names(true);
133
134    device_local_account_policy_.policy_data().set_policy_type(
135        dm_protocol::kChromePublicAccountPolicyType);
136    device_local_account_policy_.policy_data().set_username(kAccountId1);
137    device_local_account_policy_.policy_data().set_settings_entity_id(
138        kAccountId1);
139    device_local_account_policy_.policy_data().set_public_key_version(1);
140    device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
141        kDisplayName);
142  }
143
144  void BuildDeviceLocalAccountPolicy() {
145    device_local_account_policy_.SetDefaultSigningKey();
146    device_local_account_policy_.Build();
147  }
148
149  void InstallDeviceLocalAccountPolicy() {
150    BuildDeviceLocalAccountPolicy();
151    session_manager_client()->set_device_local_account_policy(
152        kAccountId1, device_local_account_policy_.GetBlob());
153  }
154
155  void UploadDeviceLocalAccountPolicy() {
156    BuildDeviceLocalAccountPolicy();
157    ASSERT_TRUE(session_manager_client()->device_local_account_policy(
158        kAccountId1).empty());
159    test_server_.UpdatePolicy(
160        dm_protocol::kChromePublicAccountPolicyType, kAccountId1,
161        device_local_account_policy_.payload().SerializeAsString());
162  }
163
164  void AddPublicSessionToDevicePolicy(const std::string& username) {
165    em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
166    em::DeviceLocalAccountInfoProto* account =
167        proto.mutable_device_local_accounts()->add_account();
168    account->set_account_id(username);
169    account->set_type(
170        em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
171    RefreshDevicePolicy();
172    test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType,
173                              std::string(), proto.SerializeAsString());
174  }
175
176  void CheckPublicSessionPresent(const std::string& id) {
177    const chromeos::User* user = chromeos::UserManager::Get()->FindUser(id);
178    ASSERT_TRUE(user);
179    EXPECT_EQ(id, user->email());
180    EXPECT_EQ(chromeos::User::USER_TYPE_PUBLIC_ACCOUNT, user->GetType());
181  }
182
183  const std::string user_id_1_;
184  const std::string user_id_2_;
185
186  UserPolicyBuilder device_local_account_policy_;
187  LocalPolicyTestServer test_server_;
188};
189
190static bool IsKnownUser(const std::string& account_id) {
191  return chromeos::UserManager::Get()->IsKnownUser(account_id);
192}
193
194IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LoginScreen) {
195  AddPublicSessionToDevicePolicy(kAccountId1);
196  AddPublicSessionToDevicePolicy(kAccountId2);
197
198  content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
199                                        base::Bind(&IsKnownUser, user_id_1_))
200      .Wait();
201  content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
202                                        base::Bind(&IsKnownUser, user_id_2_))
203      .Wait();
204
205  CheckPublicSessionPresent(user_id_1_);
206  CheckPublicSessionPresent(user_id_2_);
207}
208
209static bool DisplayNameMatches(const std::string& account_id,
210                               const std::string& display_name) {
211  const chromeos::User* user =
212      chromeos::UserManager::Get()->FindUser(account_id);
213  if (!user || user->display_name().empty())
214    return false;
215  EXPECT_EQ(UTF8ToUTF16(display_name), user->display_name());
216  return true;
217}
218
219IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DisplayName) {
220  InstallDeviceLocalAccountPolicy();
221  AddPublicSessionToDevicePolicy(kAccountId1);
222
223  content::WindowedNotificationObserver(
224      chrome::NOTIFICATION_USER_LIST_CHANGED,
225      base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
226}
227
228IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyDownload) {
229  UploadDeviceLocalAccountPolicy();
230  AddPublicSessionToDevicePolicy(kAccountId1);
231
232  // Policy for the account is not installed in session_manager_client. Because
233  // of this, the presence of the display name (which comes from policy) can be
234  // used as a signal that indicates successful policy download.
235  content::WindowedNotificationObserver(
236      chrome::NOTIFICATION_USER_LIST_CHANGED,
237      base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
238
239  // Sanity check: The policy should be present now.
240  ASSERT_FALSE(session_manager_client()->device_local_account_policy(
241      kAccountId1).empty());
242}
243
244static bool IsNotKnownUser(const std::string& account_id) {
245  return !IsKnownUser(account_id);
246}
247
248IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DevicePolicyChange) {
249  AddPublicSessionToDevicePolicy(kAccountId1);
250  AddPublicSessionToDevicePolicy(kAccountId2);
251
252  // Wait until the login screen is up.
253  content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
254                                        base::Bind(&IsKnownUser, user_id_1_))
255      .Wait();
256  content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
257                                        base::Bind(&IsKnownUser, user_id_2_))
258      .Wait();
259
260  // Update policy to remove kAccountId2.
261  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
262  proto.mutable_device_local_accounts()->clear_account();
263  AddPublicSessionToDevicePolicy(kAccountId1);
264
265  em::ChromeDeviceSettingsProto policy;
266  policy.mutable_show_user_names()->set_show_user_names(true);
267  em::DeviceLocalAccountInfoProto* account1 =
268      policy.mutable_device_local_accounts()->add_account();
269  account1->set_account_id(kAccountId1);
270  account1->set_type(
271      em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
272
273  test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType, std::string(),
274                            policy.SerializeAsString());
275  g_browser_process->policy_service()->RefreshPolicies(base::Closure());
276
277  // Make sure the second device-local account disappears.
278  content::WindowedNotificationObserver(
279      chrome::NOTIFICATION_USER_LIST_CHANGED,
280      base::Bind(&IsNotKnownUser, user_id_2_)).Wait();
281}
282
283static bool IsSessionStarted() {
284  return chromeos::UserManager::Get()->IsSessionStarted();
285}
286
287IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, StartSession) {
288  // Specify startup pages.
289  device_local_account_policy_.payload().mutable_restoreonstartup()->set_value(
290      SessionStartupPref::kPrefValueURLs);
291  em::StringListPolicyProto* startup_urls_proto =
292      device_local_account_policy_.payload().mutable_restoreonstartupurls();
293  for (size_t i = 0; i < arraysize(kStartupURLs); ++i)
294    startup_urls_proto->mutable_value()->add_entries(kStartupURLs[i]);
295  InstallDeviceLocalAccountPolicy();
296  AddPublicSessionToDevicePolicy(kAccountId1);
297
298  // This observes the display name becoming available as this indicates
299  // device-local account policy is fully loaded, which is a prerequisite for
300  // successful login.
301  content::WindowedNotificationObserver(
302      chrome::NOTIFICATION_USER_LIST_CHANGED,
303      base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
304
305  chromeos::LoginDisplayHost* host =
306      chromeos::LoginDisplayHostImpl::default_host();
307  ASSERT_TRUE(host);
308  host->StartSignInScreen();
309  chromeos::ExistingUserController* controller =
310      chromeos::ExistingUserController::current_controller();
311  ASSERT_TRUE(controller);
312  controller->LoginAsPublicAccount(user_id_1_);
313
314  // Wait for the session to start.
315  content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED,
316                                        base::Bind(IsSessionStarted)).Wait();
317
318  // Check that the startup pages specified in policy were opened.
319  BrowserList* browser_list =
320    BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
321  EXPECT_EQ(1U, browser_list->size());
322  Browser* browser = browser_list->get(0);
323  ASSERT_TRUE(browser);
324
325  TabStripModel* tabs = browser->tab_strip_model();
326  ASSERT_TRUE(tabs);
327  int expected_tab_count = static_cast<int>(arraysize(kStartupURLs));
328  EXPECT_EQ(expected_tab_count, tabs->count());
329  for (int i = 0; i < expected_tab_count && i < tabs->count(); ++i) {
330    EXPECT_EQ(GURL(kStartupURLs[i]),
331              tabs->GetWebContentsAt(i)->GetVisibleURL());
332  }
333}
334
335IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, TermsOfService) {
336  // Specify Terms of Service. The URL does not really matter as the test does
337  // not wait for the terms to load.
338  device_local_account_policy_.payload().mutable_termsofserviceurl()->set_value(
339      "http://localhost/tos");
340  InstallDeviceLocalAccountPolicy();
341  AddPublicSessionToDevicePolicy(kAccountId1);
342
343  // Wait for the device-local account policy to be fully loaded.
344  content::WindowedNotificationObserver(
345      chrome::NOTIFICATION_USER_LIST_CHANGED,
346      base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
347
348  // Start login into the device-local account.
349  chromeos::LoginDisplayHost* host =
350      chromeos::LoginDisplayHostImpl::default_host();
351  ASSERT_TRUE(host);
352  host->StartSignInScreen();
353  chromeos::ExistingUserController* controller =
354      chromeos::ExistingUserController::current_controller();
355  ASSERT_TRUE(controller);
356  controller->LoginAsPublicAccount(user_id_1_);
357
358  // Set up an observer that will quit the message loop when login has succeeded
359  // and the first wizard screen, if any, is being shown.
360  base::RunLoop run_loop;
361  chromeos::MockConsumer login_status_consumer;
362  EXPECT_CALL(login_status_consumer, OnLoginSuccess(_, false, false))
363      .Times(1)
364      .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
365
366  // Spin the loop until the observer fires. Then, unregister the observer.
367  controller->set_login_status_consumer(&login_status_consumer);
368  run_loop.Run();
369  controller->set_login_status_consumer(NULL);
370
371  // Verify that the Terms of Service screen is being shown.
372  chromeos::WizardController* wizard_controller =
373        chromeos::WizardController::default_controller();
374  ASSERT_TRUE(wizard_controller);
375  ASSERT_TRUE(wizard_controller->current_screen());
376  EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName,
377            wizard_controller->current_screen()->GetName());
378}
379
380}  // namespace policy
381