1 // Copyright 2015 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.
8 #include "ash/strings/grit/ash_strings.h"
9 #include "ash/system/date/date_default_view.h"
10 #include "ash/system/date/tray_date.h"
11 #include "ash/system/tray/system_tray.h"
12 #include "ash/system/tray/tray_popup_header_button.h"
13 #include "ash/system/user/login_status.h"
14 #include "base/command_line.h"
15 #include "base/location.h"
16 #include "base/macros.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/message_loop/message_loop.h"
19 #include "base/run_loop.h"
20 #include "base/strings/stringprintf.h"
21 #include "chrome/browser/chrome_notification_types.h"
22 #include "chrome/browser/chromeos/login/lock/screen_locker.h"
23 #include "chrome/browser/chromeos/login/lock/screen_locker_tester.h"
24 #include "chrome/browser/chromeos/login/lock/webui_screen_locker.h"
25 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
26 #include "chrome/browser/chromeos/login/ui/webui_login_view.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/chromeos/policy/proto/chrome_device_policy.pb.h"
30 #include "chrome/browser/chromeos/settings/device_settings_service.h"
31 #include "chrome/browser/lifetime/application_lifetime.h"
32 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
33 #include "chromeos/chromeos_switches.h"
34 #include "chromeos/dbus/dbus_thread_manager.h"
35 #include "chromeos/dbus/fake_session_manager_client.h"
36 #include "chromeos/dbus/session_manager_client.h"
37 #include "content/public/browser/notification_service.h"
38 #include "content/public/browser/web_contents.h"
39 #include "content/public/browser/web_ui.h"
40 #include "content/public/test/browser_test_utils.h"
41 #include "content/public/test/test_utils.h"
42 #include "ui/base/l10n/l10n_util.h"
43 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
44 #include "ui/views/view.h"
46 namespace em
= enterprise_management
;
52 const char kWaitForHiddenStateScript
[] =
53 "var screenElement = document.getElementById('%s');"
54 "var expectation = %s;"
55 "function SendReplyIfAsExpected() {"
56 " if (screenElement.hidden != expectation)"
58 " domAutomationController.send(screenElement.hidden);"
59 " observer.disconnect();"
62 "var observer = new MutationObserver(SendReplyIfAsExpected);"
63 "if (!SendReplyIfAsExpected()) {"
64 " var options = { attributes: true };"
65 " observer.observe(screenElement, options);"
70 class ShutdownPolicyBaseTest
71 : public policy::DevicePolicyCrosBrowserTest
,
72 public DeviceSettingsService::Observer
{
74 ShutdownPolicyBaseTest() : contents_(nullptr) {}
75 ~ShutdownPolicyBaseTest() override
{}
77 // DeviceSettingsService::Observer:
78 void OwnershipStatusChanged() override
{}
79 void DeviceSettingsUpdated() override
{
83 void OnDeviceSettingsServiceShutdown() override
{}
85 // policy::DevicePolicyCrosBrowserTest:
86 void SetUpInProcessBrowserTestFixture() override
{
87 policy::DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
89 MarkAsEnterpriseOwned();
92 // A helper functions which prepares the script by injecting the element_id of
93 // the element whose hiddenness we want to check and the expectation.
94 std::string
PrepareScript(const std::string
& element_id
, bool expectation
) {
95 return base::StringPrintf(kWaitForHiddenStateScript
, element_id
.c_str(),
96 expectation
? "true" : "false");
99 // Checks whether the element identified by |element_id| is hidden and only
100 // returns if the expectation is fulfilled.
101 void PrepareAndRunScript(const std::string
& element_id
, bool expectation
) {
102 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
103 contents_
, PrepareScript(element_id
, expectation
),
107 // Updates the device shutdown policy and sets it to |reboot_on_shutdown|.
108 void UpdateRebootOnShutdownPolicy(bool reboot_on_shutdown
) {
109 policy::DevicePolicyBuilder
* builder
= device_policy();
110 ASSERT_TRUE(builder
);
111 em::ChromeDeviceSettingsProto
& proto(builder
->payload());
112 proto
.mutable_reboot_on_shutdown()->set_reboot_on_shutdown(
116 // Refreshes device policy and waits for it to be applied.
117 void SyncRefreshDevicePolicy() {
118 run_loop_
.reset(new base::RunLoop());
119 DeviceSettingsService::Get()->AddObserver(this);
120 RefreshDevicePolicy();
122 DeviceSettingsService::Get()->RemoveObserver(this);
126 // Blocks until the OobeUI indicates that the javascript side has been
128 void WaitUntilOobeUIIsReady(OobeUI
* oobe_ui
) {
129 ASSERT_TRUE(oobe_ui
);
130 base::RunLoop run_loop
;
131 const bool oobe_ui_ready
= oobe_ui
->IsJSReady(run_loop
.QuitClosure());
136 content::WebContents
* contents_
;
138 scoped_ptr
<base::RunLoop
> run_loop_
;
141 class ShutdownPolicyInSessionTest
142 : public ShutdownPolicyBaseTest
{
144 ShutdownPolicyInSessionTest() {}
145 ~ShutdownPolicyInSessionTest() override
{}
147 void SetUpOnMainThread() override
{
148 ShutdownPolicyBaseTest::SetUpOnMainThread();
149 ash::TrayDate
* tray_date
= ash::Shell::GetInstance()
150 ->GetPrimarySystemTray()
151 ->GetTrayDateForTesting();
152 ASSERT_TRUE(tray_date
);
153 date_default_view_
.reset(
154 static_cast<ash::DateDefaultView
*>(
155 tray_date
->CreateDefaultViewForTesting(ash::user::LOGGED_IN_USER
)));
156 ASSERT_TRUE(date_default_view_
);
159 void TearDownOnMainThread() override
{
160 date_default_view_
.reset();
161 ShutdownPolicyBaseTest::TearDownOnMainThread();
164 // Get the shutdown and reboot button view from the date default view.
165 const ash::TrayPopupHeaderButton
* GetShutdownButton() {
166 return static_cast<const ash::TrayPopupHeaderButton
*>(
167 date_default_view_
->GetShutdownButtonViewForTest());
170 bool HasButtonTooltipText(const ash::TrayPopupHeaderButton
* button
,
171 int message_id
) const {
172 base::string16 actual_tooltip
;
173 button
->GetTooltipText(gfx::Point(), &actual_tooltip
);
174 return l10n_util::GetStringUTF16(message_id
) == actual_tooltip
;
178 scoped_ptr
<ash::DateDefaultView
> date_default_view_
;
180 DISALLOW_COPY_AND_ASSIGN(ShutdownPolicyInSessionTest
);
183 IN_PROC_BROWSER_TEST_F(ShutdownPolicyInSessionTest
, TestBasic
) {
184 const ash::TrayPopupHeaderButton
*shutdown_button
= GetShutdownButton();
186 HasButtonTooltipText(shutdown_button
, IDS_ASH_STATUS_TRAY_SHUTDOWN
));
189 IN_PROC_BROWSER_TEST_F(ShutdownPolicyInSessionTest
, PolicyChange
) {
190 const ash::TrayPopupHeaderButton
*shutdown_button
= GetShutdownButton();
192 UpdateRebootOnShutdownPolicy(true);
193 SyncRefreshDevicePolicy();
195 HasButtonTooltipText(shutdown_button
, IDS_ASH_STATUS_TRAY_REBOOT
));
197 UpdateRebootOnShutdownPolicy(false);
198 SyncRefreshDevicePolicy();
200 HasButtonTooltipText(shutdown_button
, IDS_ASH_STATUS_TRAY_SHUTDOWN
));
203 class ShutdownPolicyLockerTest
: public ShutdownPolicyBaseTest
{
205 ShutdownPolicyLockerTest() : fake_session_manager_client_(nullptr) {}
206 ~ShutdownPolicyLockerTest() override
{}
208 void SetUpInProcessBrowserTestFixture() override
{
209 fake_session_manager_client_
= new FakeSessionManagerClient
;
210 DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
211 scoped_ptr
<SessionManagerClient
>(fake_session_manager_client_
));
213 ShutdownPolicyBaseTest::SetUpInProcessBrowserTestFixture();
214 zero_duration_mode_
.reset(new ui::ScopedAnimationDurationScaleMode(
215 ui::ScopedAnimationDurationScaleMode::ZERO_DURATION
));
217 MarkAsEnterpriseOwned();
220 void SetUpOnMainThread() override
{
221 ShutdownPolicyBaseTest::SetUpOnMainThread();
223 // Bring up the locker screen.
224 ScreenLocker::Show();
225 scoped_ptr
<test::ScreenLockerTester
> tester(ScreenLocker::GetTester());
226 tester
->EmulateWindowManagerReady();
227 content::WindowedNotificationObserver
lock_state_observer(
228 chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED
,
229 content::NotificationService::AllSources());
230 if (!tester
->IsLocked())
231 lock_state_observer
.Wait();
232 ScreenLocker
* screen_locker
= ScreenLocker::default_screen_locker();
233 WebUIScreenLocker
* web_ui_screen_locker
=
234 static_cast<WebUIScreenLocker
*>(screen_locker
->delegate());
235 ASSERT_TRUE(web_ui_screen_locker
);
236 content::WebUI
* web_ui
= web_ui_screen_locker
->GetWebUI();
238 contents_
= web_ui
->GetWebContents();
239 ASSERT_TRUE(contents_
);
241 // Wait for the login UI to be ready.
242 WaitUntilOobeUIIsReady(
243 static_cast<OobeUI
*>(web_ui
->GetController()));
247 scoped_ptr
<ui::ScopedAnimationDurationScaleMode
> zero_duration_mode_
;
248 FakeSessionManagerClient
* fake_session_manager_client_
;
250 DISALLOW_COPY_AND_ASSIGN(ShutdownPolicyLockerTest
);
253 IN_PROC_BROWSER_TEST_F(ShutdownPolicyLockerTest
, TestBasic
) {
254 PrepareAndRunScript("restart-header-bar-item", true);
255 PrepareAndRunScript("shutdown-header-bar-item", false);
258 IN_PROC_BROWSER_TEST_F(ShutdownPolicyLockerTest
, PolicyChange
) {
259 UpdateRebootOnShutdownPolicy(true);
260 RefreshDevicePolicy();
261 PrepareAndRunScript("restart-header-bar-item", false);
262 PrepareAndRunScript("shutdown-header-bar-item", true);
264 UpdateRebootOnShutdownPolicy(false);
265 RefreshDevicePolicy();
266 PrepareAndRunScript("restart-header-bar-item", true);
267 PrepareAndRunScript("shutdown-header-bar-item", false);
270 class ShutdownPolicyLoginTest
: public ShutdownPolicyBaseTest
{
272 ShutdownPolicyLoginTest() {}
273 ~ShutdownPolicyLoginTest() override
{}
275 // ShutdownPolicyBaseTest:
276 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
277 command_line
->AppendSwitch(switches::kLoginManager
);
278 command_line
->AppendSwitch(switches::kForceLoginManagerInTests
);
281 void SetUpInProcessBrowserTestFixture() override
{
282 ShutdownPolicyBaseTest::SetUpInProcessBrowserTestFixture();
284 MarkAsEnterpriseOwned();
287 void SetUpOnMainThread() override
{
288 ShutdownPolicyBaseTest::SetUpOnMainThread();
290 content::WindowedNotificationObserver(
291 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
,
292 content::NotificationService::AllSources()).Wait();
293 LoginDisplayHostImpl
* host
=
294 static_cast<LoginDisplayHostImpl
*>(
295 LoginDisplayHostImpl::default_host());
297 WebUILoginView
* web_ui_login_view
= host
->GetWebUILoginView();
298 ASSERT_TRUE(web_ui_login_view
);
299 content::WebUI
* web_ui
= web_ui_login_view
->GetWebUI();
301 contents_
= web_ui
->GetWebContents();
302 ASSERT_TRUE(contents_
);
304 // Wait for the login UI to be ready.
305 WaitUntilOobeUIIsReady(host
->GetOobeUI());
308 void TearDownOnMainThread() override
{
309 // If the login display is still showing, exit gracefully.
310 if (LoginDisplayHostImpl::default_host()) {
311 base::MessageLoop::current()->PostTask(FROM_HERE
,
312 base::Bind(&chrome::AttemptExit
));
313 content::RunMessageLoop();
318 DISALLOW_COPY_AND_ASSIGN(ShutdownPolicyLoginTest
);
321 IN_PROC_BROWSER_TEST_F(ShutdownPolicyLoginTest
, PolicyNotSet
) {
322 PrepareAndRunScript("restart-header-bar-item", true);
323 PrepareAndRunScript("shutdown-header-bar-item", false);
326 IN_PROC_BROWSER_TEST_F(ShutdownPolicyLoginTest
, PolicyChange
) {
327 UpdateRebootOnShutdownPolicy(true);
328 RefreshDevicePolicy();
329 PrepareAndRunScript("restart-header-bar-item", false);
330 PrepareAndRunScript("shutdown-header-bar-item", true);
332 UpdateRebootOnShutdownPolicy(false);
333 RefreshDevicePolicy();
334 PrepareAndRunScript("restart-header-bar-item", true);
335 PrepareAndRunScript("shutdown-header-bar-item", false);
338 } // namespace chromeos