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