1# Copyright (c) 2013 The Chromium OS 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
5import logging
6
7from autotest_lib.client.bin import test, utils
8from autotest_lib.client.common_lib import error
9from autotest_lib.client.common_lib.cros import chrome, session_manager
10from autotest_lib.client.cros import asan
11
12import gobject
13from dbus.mainloop.glib import DBusGMainLoop
14
15class desktopui_ScreenLocker(test.test):
16    """This is a client side test that exercises the screenlocker."""
17    version = 1
18
19    _SCREEN_IS_LOCKED_TIMEOUT = 30
20    # TODO(jdufault): Remove this timeout increase for asan bots once we figure
21    # out what's taking so long to lock the screen. See crbug.com/452599.
22    if asan.running_on_asan():
23      _SCREEN_IS_LOCKED_TIMEOUT *= 2
24
25
26    def initialize(self):
27        super(desktopui_ScreenLocker, self).initialize()
28        DBusGMainLoop(set_as_default=True)
29
30
31    @property
32    def screen_locked(self):
33        """True if the screen is locked."""
34        return self._chrome.login_status['isScreenLocked']
35
36
37    @property
38    def screenlocker_visible(self):
39        """True if the screenlocker screen is visible."""
40        oobe = self._chrome.browser.oobe
41        return (oobe and
42                oobe.EvaluateJavaScript(
43                    "(typeof Oobe == 'function') && "
44                    "(typeof Oobe.authenticateForTesting == 'function') && "
45                    "($('account-picker') != null)"))
46
47    @property
48    def error_bubble_visible(self):
49        """True if the error bubble for bad password is visible."""
50        return self._chrome.browser.oobe.EvaluateJavaScript(
51                "cr.ui.login.DisplayManager.errorMessageWasShownForTesting_;")
52
53
54    def attempt_unlock(self, password=''):
55        """Attempt to unlock a locked screen. The correct password is the empty
56           string.
57
58        @param password: password to use to attempt the unlock.
59
60        """
61        self._chrome.browser.oobe.ExecuteJavaScript(
62                "Oobe.authenticateForTesting('%s', '%s');"
63                % (self._chrome.username, password))
64
65
66    def lock_screen(self):
67        """Lock the screen."""
68        logging.debug('lock_screen')
69        if self.screen_locked:
70            raise error.TestFail('Screen already locked')
71        signal_listener = session_manager.ScreenIsLockedSignalListener(
72                gobject.MainLoop())
73        ext = self._chrome.autotest_ext
74        ext.EvaluateJavaScript('chrome.autotestPrivate.lockScreen();')
75        signal_listener.wait_for_signals(desc='Screen is locked.',
76                                         timeout=self._SCREEN_IS_LOCKED_TIMEOUT)
77        utils.poll_for_condition(lambda: self.screenlocker_visible,
78                exception=error.TestFail('Screenlock screen not visible'))
79        if not self.screen_locked:
80            raise error.TestFail('Screen not locked')
81
82
83    def attempt_unlock_bad_password(self):
84        """Attempt unlock with a bad password."""
85        logging.debug('attempt_unlock_bad_password')
86        if self.error_bubble_visible:
87            raise error.TestFail('Error bubble prematurely visible')
88        self.attempt_unlock('bad')
89        utils.poll_for_condition(lambda: self.error_bubble_visible,
90                exception=error.TestFail('Bad password bubble did not show'))
91        if not self.screen_locked:
92            raise error.TestFail('Screen unlocked with bad password')
93
94
95    def unlock_screen(self):
96        """Unlock the screen with the right password."""
97        logging.debug('unlock_screen')
98        self.attempt_unlock()
99        utils.poll_for_condition(
100                lambda: not self._chrome.browser.oobe_exists,
101                exception=error.TestFail('Failed to unlock screen'))
102        if self.screen_locked:
103            raise error.TestFail('Screen should be unlocked')
104
105
106    def run_once(self):
107        """
108        This test locks the screen, tries to unlock with a bad password,
109        then unlocks with the right password.
110
111        """
112        with chrome.Chrome(autotest_ext=True) as self._chrome:
113            self.lock_screen()
114            self.attempt_unlock_bad_password()
115            self.unlock_screen()
116
117