1# Copyright 2015 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
6import utils
7
8from autotest_lib.client.common_lib import error
9from autotest_lib.client.cros import enterprise_policy_base
10from autotest_lib.client.cros import httpd
11
12
13class policy_ImagesBlockedForUrls(enterprise_policy_base.EnterprisePolicyTest):
14    """Test ImagesBlockedForUrls policy effect on CrOS look & feel.
15
16    This test verifies the behavior of Chrome OS with a range of valid values
17    for the ImagesBlockedForUrls user policies. These values are covered by
18    four test cases, named: NotSet, 1Url, 2Urls, and 3Urls.
19
20    When policy value is None (as in case=NotSet), then images are not blocked
21    on any page. When the value is set to a single URL (case=1Url), then
22    images are blocked on any page with the same domain as the URL. When set
23    to multiple URLs (as in case=2Urls or 3Urls), then images are blocked on
24    any page that has the same domain as any of the specified URLs.
25
26    Two test cases (1Url, 3Urls) are designed to block images on the test
27    page. The other two test cases (NotSet, 2Urls) are designed to
28    allow images to be shown on the test page.
29
30    Note this test has a dependency on the DefaultImagesSetting policy, which
31    is partially tested herein, and by the test policy_ImagesAllowedForUrls.
32    For this test, we set DefaultImagesSetting=1 (or null). This allows images
33    on all pages except those with a domain listed in ImagesBlockedForUrls.
34    For the test of ImagesAllowedForUrls, we set DefaultImagesSetting=2.
35    That blocks images on all pages except those with domains listed in
36    ImagesAllowedForUrls.
37
38    """
39    version = 1
40
41    POLICY_NAME = 'ImagesBlockedForUrls'
42    URL_HOST = 'http://localhost'
43    URL_PORT = 8080
44    URL_BASE = '%s:%d' % (URL_HOST, URL_PORT)
45    URL_PAGE = '/kittens.html'
46    TEST_URL = URL_BASE + URL_PAGE
47
48    URL1_DATA = [URL_HOST]
49    URL2_DATA = ['http://www.bing.com', 'https://www.yahoo.com']
50    URL3_DATA = ['http://www.bing.com', URL_BASE,
51                 'https://www.yahoo.com']
52
53    TEST_CASES = {
54        'NotSet': '',
55        '1Url': URL1_DATA,
56        '2Urls': URL2_DATA,
57        '3Urls': URL3_DATA
58    }
59
60    STARTUP_URLS = ['chrome://policy', 'chrome://settings']
61    SUPPORTING_POLICIES = {
62        'DefaultImagesSetting': 1,
63        'BookmarkBarEnabled': False,
64        'RestoreOnStartupURLs': STARTUP_URLS,
65        'RestoreOnStartup': 4
66    }
67
68    def initialize(self, args=()):
69        super(policy_ImagesBlockedForUrls, self).initialize(args)
70        if self.mode == 'list':
71            self._web_server = None
72        else:
73            self._web_server = httpd.HTTPListener(
74                self.URL_PORT, docroot=self.bindir)
75            self._web_server.run()
76
77    def _wait_for_page_ready(self, tab):
78        utils.poll_for_condition(
79            lambda: tab.EvaluateJavaScript('pageReady'),
80            exception=error.TestError('Test page is not ready.'))
81
82    def _test_images_blocked_for_urls(self, policy_value, policies_json):
83        """
84        Verify CrOS enforces the ImagesBlockedForUrls policy.
85
86        When ImagesBlockedForUrls is undefined, images shall not be blocked on
87        any page. When ImagesBlockedForUrls contains one or more URLs, images
88        are blocked on any page whose domain matches any of the listed
89        domains.
90
91        @param policy_value: policy value expected on chrome://policy page.
92        @param policies_json: policy JSON data to send to the fake DM server.
93
94        """
95        self.setup_case(self.POLICY_NAME, policy_value, policies_json)
96        logging.info('Running _test_images_blocked_for_urls(%s, %s)',
97                     policy_value, policies_json)
98
99        tab = self.cr.browser.tabs.New()
100        tab.Activate()
101        tab.Navigate(self.TEST_URL, timeout=4)
102        tab.WaitForDocumentReadyStateToBeComplete()
103        self._wait_for_page_ready(tab)
104        image_is_blocked = tab.EvaluateJavaScript(
105            "document.getElementById('kittens_id').width") == 0
106
107        # String |URL_HOST| will be found in string |policy_value| for
108        # test cases 1Url and 3Urls, but not for cases NotSet and 2Urls.
109        if policy_value is not None and self.URL_HOST in policy_value:
110            if not image_is_blocked:
111                raise error.TestFail('Image should be blocked.')
112        else:
113            if image_is_blocked:
114                raise error.TestFail('Image should not be blocked.')
115        tab.Close()
116
117    def _run_test_case(self, case):
118        """
119        Setup and run the test configured for the specified test case.
120
121        Set the expected |policy_value| and |policies_json| data based on the
122        test |case|. If the user specified an expected |value| in the command
123        line args, then use it to set the |policy_value| and blank out the
124        |policies_json|.
125
126        @param case: Name of the test case to run.
127
128        """
129        if case not in self.TEST_CASES:
130            raise error.TestError('Test case %s is not valid.' % case)
131        logging.info('Running test case: %s', case)
132
133        if self.is_value_given:
134            # If |value| was given in the command line args, then set expected
135            # |policy_value| to the given value, and |policies_json| to None.
136            policy_value = self.value
137            policies_json = None
138        else:
139            # Otherwise, set expected |policy_value| and setup |policies_json|
140            # data to the values required by the test |case|.
141            policies_json = self.SUPPORTING_POLICIES.copy()
142            if case == 'NotSet':
143                policy_value = None
144                policy_json = {'ImagesBlockedForUrls': None}
145            elif case == '1Url':
146                policy_value = ','.join(self.URL1_DATA)
147                policy_json = {'ImagesBlockedForUrls': self.URL1_DATA}
148            elif case == '2Urls':
149                policy_value = ','.join(self.URL2_DATA)
150                policy_json = {'ImagesBlockedForUrls': self.URL2_DATA}
151            elif case == '3Urls':
152                policy_value = ','.join(self.URL3_DATA)
153                policy_json = {'ImagesBlockedForUrls': self.URL3_DATA}
154            policies_json.update(policy_json)
155
156        # Run test using the values configured for the test case.
157        self._test_images_blocked_for_urls(policy_value, policies_json)
158
159    def run_once(self):
160        """Main runner for the test cases."""
161        if self.mode == 'all':
162            for case in sorted(self.TEST_CASES):
163                self._run_test_case(case)
164        elif self.mode == 'single':
165            self._run_test_case(self.case)
166        elif self.mode == 'list':
167            logging.info('List Test Cases:')
168            for case, value in sorted(self.TEST_CASES.items()):
169                logging.info('  case=%s, value="%s"', case, value)
170        else:
171            raise error.TestError('Run mode %s is not valid.' % self.mode)
172
173    def cleanup(self):
174        if self._web_server:
175            self._web_server.stop()
176        super(policy_ImagesBlockedForUrls, self).cleanup()
177