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 6 7from autotest_lib.client.cros import httpd 8from autotest_lib.client.common_lib import error 9from autotest_lib.client.cros import enterprise_policy_base 10 11POLICY_NAME = 'URLBlacklist' 12URL_HOST = 'http://localhost' 13URL_PORT = 8080 14URL_BASE = '%s:%d/%s' % (URL_HOST, URL_PORT, 'test_data') 15ALL_URLS_LIST = [URL_BASE + website for website in 16 ['/website1.html', 17 '/website2.html', 18 '/website3.html']] 19SINGLE_BLACKLISTED_FILE_DATA = ALL_URLS_LIST[:1] 20MULTIPLE_BLACKLISTED_FILES_DATA = ALL_URLS_LIST[:2] 21BLOCKED_USER_MESSAGE = 'Webpage Blocked' 22BLOCKED_ERROR_MESSAGE = 'ERR_BLOCKED_BY_ADMINISTRATOR' 23 24 25class policy_URLBlacklist(enterprise_policy_base.EnterprisePolicyTest): 26 """ 27 Test effect of URLBlacklist policy on Chrome OS behavior. 28 29 Navigate to each the URLs in the ALL_URLS_LIST and verify that the URLs 30 specified by the URLBlackList policy are blocked. 31 Throw a warning if the user message on the blocked page is incorrect. 32 33 Two test cases (SingleBlacklistedFile, MultipleBlacklistedFiles) are 34 designed to verify that URLs specified in the URLBlacklist policy are 35 blocked. 36 The third test case(NotSet) is designed to verify that none of the URLs 37 are blocked since the URLBlacklist policy is set to None 38 39 The test case shall pass if the URLs that are part of the URLBlacklist 40 policy value are blocked. 41 The test case shall also pass if the URLs that are not part of the 42 URLBlacklist policy value are not blocked. 43 The test case shall fail if the above behavior is not enforced. 44 45 """ 46 version = 1 47 TEST_CASES = { 48 'NotSet': '', 49 'SingleBlacklistedFile': SINGLE_BLACKLISTED_FILE_DATA, 50 'MultipleBlacklistedFiles': MULTIPLE_BLACKLISTED_FILES_DATA, 51 } 52 53 def initialize(self, args=()): 54 super(policy_URLBlacklist, self).initialize(args) 55 self.start_webserver(URL_PORT) 56 57 def navigate_to_website(self, url): 58 """ 59 Open a new tab in the browser and navigate to the URL. 60 61 @param url: the URL that the browser is navigated to. 62 @returns: a chrome browser tab navigated to the URL. 63 64 """ 65 tab = self.cr.browser.tabs.New() 66 logging.info('Navigating to URL:%s', url) 67 try: 68 tab.Navigate(url, timeout=10) 69 except Exception, err: 70 logging.error('Timeout Exception in navigating URL: %s\n %s', 71 url, err) 72 tab.WaitForDocumentReadyStateToBeComplete() 73 return tab 74 75 def scrape_text_from_website(self, tab): 76 """ 77 Returns a list of the text content matching the page_scrape_cmd filter. 78 79 @param tab: tab containing the website to be parsed. 80 @raises: TestFail if the expected text content was not found on the 81 page. 82 83 """ 84 parsed_message_string = '' 85 parsed_message_list = [] 86 page_scrape_cmd = 'document.getElementById("main-message").innerText;' 87 try: 88 parsed_message_string = tab.EvaluateJavaScript(page_scrape_cmd) 89 except Exception as err: 90 raise error.TestFail('Unable to find the expected ' 91 'text content on the test page: %s\n %r'%(tab.url, err)) 92 logging.info('Parsed message:%s', parsed_message_string) 93 parsed_message_list = [str(word) for word in 94 parsed_message_string.split('\n') if word] 95 return parsed_message_list 96 97 def is_url_blocked(self, url): 98 """ 99 Returns True if the URL is blocked else returns False. 100 101 @param url: The URL to be checked whether it is blocked. 102 103 """ 104 parsed_message_list = [] 105 tab = self.navigate_to_website(url) 106 parsed_message_list = self.scrape_text_from_website(tab) 107 if len(parsed_message_list) == 2 and \ 108 parsed_message_list[0] == 'Website enabled' and \ 109 parsed_message_list[1] == 'Website is enabled': 110 return False 111 112 #Check if the accurate user error message displayed on the error page. 113 if parsed_message_list[0] != BLOCKED_USER_MESSAGE or \ 114 parsed_message_list[1] != BLOCKED_ERROR_MESSAGE: 115 logging.warning('The Blocked page user notification ' 116 'messages, %s and %s are not displayed on ' 117 'the blocked page. The messages may have ' 118 'been modified. Please check and update the ' 119 'messages in this file accordingly.', 120 BLOCKED_USER_MESSAGE, BLOCKED_ERROR_MESSAGE) 121 return True 122 123 def _test_URLBlacklist(self, policy_value, policies_json): 124 """ 125 Verify CrOS enforces URLBlacklist policy value. 126 127 When the URLBlacklist policy is set to one or more Domains, 128 check that navigation to URLs in the Blocked list are blocked. 129 When set to None, check that none of the websites are blocked. 130 131 @param policy_value: policy value expected on chrome://policy page. 132 @param policies_json: policy JSON data to send to the fake DM server. 133 @raises: TestFail if url is blocked/not blocked based on the 134 corresponding policy values. 135 136 """ 137 url_is_blocked = None 138 self.setup_case(POLICY_NAME, policy_value, policies_json) 139 logging.info('Running _test_URLBlacklist(%s, %s)', 140 policy_value, policies_json) 141 142 for url in ALL_URLS_LIST: 143 url_is_blocked = self.is_url_blocked(url) 144 if policy_value: 145 if url in policy_value and not url_is_blocked: 146 raise error.TestFail('The URL %s should have been blocked' 147 ' by policy, but it was allowed' % url) 148 elif url_is_blocked: 149 raise error.TestFail('The URL %s should have been allowed' 150 'by policy, but it was blocked' % url) 151 152 def _run_test_case(self, case): 153 """ 154 Setup and run the test configured for the specified test case. 155 156 Set the expected |policy_value| and |policies_json| data based on the 157 test |case|. If the user specified an expected |value| in the command 158 line args, then use it to set the |policy_value| and blank out the 159 |policies_json|. 160 161 @param case: Name of the test case to run. 162 163 """ 164 policy_value = None 165 policies_json = None 166 167 if case not in self.TEST_CASES: 168 raise error.TestError('Test case %s is not valid.' % case) 169 logging.info('Running test case: %s', case) 170 171 if self.is_value_given: 172 # If |value| was given in the command line args, then set expected 173 # |policy_value| to the given value, and |policies_json| to None. 174 policy_value = self.value 175 policies_json = None 176 else: 177 # Otherwise, set expected |policy_value| and setup |policies_json| 178 # data to the values required by the test |case|. 179 if case == 'NotSet': 180 policy_value = None 181 policies_json = {'URLBlacklist': None} 182 elif case == 'SingleBlacklistedFile': 183 policy_value = ','.join(SINGLE_BLACKLISTED_FILE_DATA) 184 policies_json = {'URLBlacklist': SINGLE_BLACKLISTED_FILE_DATA} 185 186 elif case == 'MultipleBlacklistedFiles': 187 policy_value = ','.join(MULTIPLE_BLACKLISTED_FILES_DATA) 188 policies_json = { 189 'URLBlacklist': MULTIPLE_BLACKLISTED_FILES_DATA 190 } 191 192 # Run test using the values configured for the test case. 193 self._test_URLBlacklist(policy_value, policies_json) 194 195 def run_once(self): 196 self.run_once_impl(self._run_test_case) 197