Home | History | Annotate | Download | only in policy_DisableScreenshots
      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 
      5 import glob
      6 import logging
      7 import os
      8 import utils
      9 
     10 from autotest_lib.client.common_lib import error
     11 from autotest_lib.client.common_lib.cros import chrome
     12 from autotest_lib.client.cros.enterprise import enterprise_policy_base
     13 from autotest_lib.client.cros.input_playback import input_playback
     14 
     15 POLL_TIMEOUT = 5
     16 POLL_FREQUENCY = 0.5
     17 
     18 
     19 class 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