• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2017 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 glob
6import logging
7import os
8import utils
9
10from autotest_lib.client.common_lib import error
11from autotest_lib.client.common_lib.cros import chrome
12from autotest_lib.client.cros.enterprise import enterprise_policy_base
13from autotest_lib.client.cros.input_playback import input_playback
14
15POLL_TIMEOUT = 5
16POLL_FREQUENCY = 0.5
17
18
19class policy_DisableScreenshots(
20        enterprise_policy_base.EnterprisePolicyTest):
21    version = 1
22
23    def initialize(self, **kwargs):
24        """Emulate a keyboard in order to play back the screenshot shortcut."""
25        self._initialize_test_constants()
26        super(policy_DisableScreenshots, self).initialize(**kwargs)
27        self.player = input_playback.InputPlayback()
28        self.player.emulate(input_type='keyboard')
29        self.player.find_connected_inputs()
30
31
32    def _initialize_test_constants(self):
33        """Initialize test-specific constants, some from class constants."""
34        self.POLICY_NAME = 'DisableScreenshots'
35        self._DOWNLOADS = '/home/chronos/user/Downloads/'
36        self._SCREENSHOT_PATTERN = 'Screenshot*'
37        self._SCREENSHOT_FILENAME = self._DOWNLOADS + self._SCREENSHOT_PATTERN
38
39        self.TEST_CASES = {
40            'DisableScreenshot_Block': True,
41            'False_Allow': False,
42            'NotSet_Allow': None
43        }
44
45        # Possible API methods to capture the screen
46        self.CAPTURE_CMDS = [
47                'captureVisibleTab',
48                # TODO(timkovich): https://crbug.com/839630
49                # 'tabCapture',
50                # TODO(timkovich): https://crbug.com/817497
51                # 'desktopCapture'
52        ]
53
54
55    def _screenshot_file_exists(self):
56        """
57        Checks if screenshot file was created by keyboard shortcut.
58
59        @returns boolean indicating if screenshot file was saved or not.
60
61        """
62        try:
63            utils.poll_for_condition(
64                    lambda: len(glob.glob(self._SCREENSHOT_FILENAME)) > 0,
65                    timeout=POLL_TIMEOUT,
66                    sleep_interval=POLL_FREQUENCY)
67        except utils.TimeoutError:
68            logging.info('Screenshot file not found.')
69            return False
70
71        logging.info('Screenshot file found.')
72        return True
73
74
75    def _delete_screenshot_files(self):
76        """Delete existing screenshot files, if any."""
77        for filename in glob.glob(self._SCREENSHOT_FILENAME):
78            os.remove(filename)
79
80
81    def cleanup(self):
82        """Cleanup files created in this test, if any and close the player."""
83        self._delete_screenshot_files()
84        self.player.close()
85        super(policy_DisableScreenshots, self).cleanup()
86
87
88    def _test_screenshot_shortcut(self, policy_value):
89        """
90        Verify DisableScreenshots is enforced for the screenshot shortcut.
91
92        When DisableScreenshots policy value is undefined, screenshots shall
93        be captured via the keyboard shortcut Ctrl + F5.
94        When DisableScreenshots policy is set to True screenshots shall not
95        be captured.
96
97        @param policy_value: policy value for this case.
98
99        """
100        logging.info('Deleting preexisting Screenshot files.')
101        self._delete_screenshot_files()
102
103        # Keyboard shortcut for screenshots
104        self.player.blocking_playback_of_default_file(
105                input_type='keyboard', filename='keyboard_ctrl+f5')
106
107        screenshot_file_captured = self._screenshot_file_exists()
108        if policy_value:
109            if screenshot_file_captured:
110                raise error.TestFail('Screenshot should not be captured')
111        elif not screenshot_file_captured:
112            raise error.TestFail('Screenshot should be captured')
113
114
115    def _test_screenshot_apis(self, policy_value):
116        """
117        Verify DisableScreenshot policy blocks API calls.
118
119        Attempts to capture the screen using all of the methods to capture
120        the screen through the APIs. Captures should not happen when
121        policy_value is True and should happen in the other cases.
122
123        @param policy_value: policy value for this case
124
125        @raises error.TestFail: In the case where the capture behavior
126            does not match the policy value
127
128        """
129        tab = self.navigate_to_url('https://google.com')
130
131        current_dir = os.path.dirname(os.path.realpath(__file__))
132
133        for method in self.CAPTURE_CMDS:
134            # Set the document.title to the test name
135            tab.ExecuteJavaScript('document.title = "%s"' % method)
136
137            # Call the extension's shortcut to trigger the API call
138            self.player.blocking_playback(
139                    input_type='keyboard',
140                    filepath=os.path.join(current_dir, 'keyboard_ctrl+shift+y'))
141
142            # desktopCapture opens a prompt window that needs to be OKed
143            if method == 'desktopCapture':
144                self.player.blocking_playback_of_default_file(
145                        input_type='keyboard', filename='keyboard_enter')
146
147            # The document.title is used to pass information to and from
148            # the DOM and the extension. The return value of the screenshot
149            # API call is set to the document.title.
150            try:
151                utils.poll_for_condition(
152                        lambda: tab.EvaluateJavaScript(
153                            'document.title != "%s"' % method
154                        ),
155                        timeout=POLL_TIMEOUT)
156                capture = tab.EvaluateJavaScript('document.title')
157            except utils.TimeoutError:
158                capture = None
159
160            if capture == 'undefined':
161                capture = None
162
163            if policy_value:
164                if capture is not None:
165                    raise error.TestFail('Screen should not be captured. '
166                                         'method = %s, capture = %s'
167                                         % (method, capture))
168            elif capture is None:
169                raise error.TestFail('Screen should be captured. '
170                                     'method = %s, capture = %s'
171                                     % (method, capture))
172
173
174    def run_once(self, case):
175        """
176        Setup and run the test configured for the specified test case.
177
178        @param case: Name of the test case to run.
179
180        """
181        case_value = self.TEST_CASES[case]
182        self._extension_path = os.path.join(os.path.dirname(__file__),
183                                            'Screenshooter')
184
185        self.setup_case(user_policies={self.POLICY_NAME: case_value},
186                        extension_paths=[self._extension_path])
187
188        self._test_screenshot_shortcut(case_value)
189        self._test_screenshot_apis(case_value)
190