# Copyright 2015 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import logging from autotest_lib.client.cros import httpd from autotest_lib.client.common_lib import error from autotest_lib.client.cros import enterprise_policy_base POLICY_NAME = 'URLBlacklist' URL_HOST = 'http://localhost' URL_PORT = 8080 URL_BASE = '%s:%d/%s' % (URL_HOST, URL_PORT, 'test_data') ALL_URLS_LIST = [URL_BASE + website for website in ['/website1.html', '/website2.html', '/website3.html']] SINGLE_BLACKLISTED_FILE_DATA = ALL_URLS_LIST[:1] MULTIPLE_BLACKLISTED_FILES_DATA = ALL_URLS_LIST[:2] BLOCKED_USER_MESSAGE = 'Webpage Blocked' BLOCKED_ERROR_MESSAGE = 'ERR_BLOCKED_BY_ADMINISTRATOR' class policy_URLBlacklist(enterprise_policy_base.EnterprisePolicyTest): """ Test effect of URLBlacklist policy on Chrome OS behavior. Navigate to each the URLs in the ALL_URLS_LIST and verify that the URLs specified by the URLBlackList policy are blocked. Throw a warning if the user message on the blocked page is incorrect. Two test cases (SingleBlacklistedFile, MultipleBlacklistedFiles) are designed to verify that URLs specified in the URLBlacklist policy are blocked. The third test case(NotSet) is designed to verify that none of the URLs are blocked since the URLBlacklist policy is set to None The test case shall pass if the URLs that are part of the URLBlacklist policy value are blocked. The test case shall also pass if the URLs that are not part of the URLBlacklist policy value are not blocked. The test case shall fail if the above behavior is not enforced. """ version = 1 TEST_CASES = { 'NotSet': '', 'SingleBlacklistedFile': SINGLE_BLACKLISTED_FILE_DATA, 'MultipleBlacklistedFiles': MULTIPLE_BLACKLISTED_FILES_DATA, } def initialize(self, args=()): super(policy_URLBlacklist, self).initialize(args) self.start_webserver(URL_PORT) def navigate_to_website(self, url): """ Open a new tab in the browser and navigate to the URL. @param url: the URL that the browser is navigated to. @returns: a chrome browser tab navigated to the URL. """ tab = self.cr.browser.tabs.New() logging.info('Navigating to URL:%s', url) try: tab.Navigate(url, timeout=10) except Exception, err: logging.error('Timeout Exception in navigating URL: %s\n %s', url, err) tab.WaitForDocumentReadyStateToBeComplete() return tab def scrape_text_from_website(self, tab): """ Returns a list of the text content matching the page_scrape_cmd filter. @param tab: tab containing the website to be parsed. @raises: TestFail if the expected text content was not found on the page. """ parsed_message_string = '' parsed_message_list = [] page_scrape_cmd = 'document.getElementById("main-message").innerText;' try: parsed_message_string = tab.EvaluateJavaScript(page_scrape_cmd) except Exception as err: raise error.TestFail('Unable to find the expected ' 'text content on the test page: %s\n %r'%(tab.url, err)) logging.info('Parsed message:%s', parsed_message_string) parsed_message_list = [str(word) for word in parsed_message_string.split('\n') if word] return parsed_message_list def is_url_blocked(self, url): """ Returns True if the URL is blocked else returns False. @param url: The URL to be checked whether it is blocked. """ parsed_message_list = [] tab = self.navigate_to_website(url) parsed_message_list = self.scrape_text_from_website(tab) if len(parsed_message_list) == 2 and \ parsed_message_list[0] == 'Website enabled' and \ parsed_message_list[1] == 'Website is enabled': return False #Check if the accurate user error message displayed on the error page. if parsed_message_list[0] != BLOCKED_USER_MESSAGE or \ parsed_message_list[1] != BLOCKED_ERROR_MESSAGE: logging.warning('The Blocked page user notification ' 'messages, %s and %s are not displayed on ' 'the blocked page. The messages may have ' 'been modified. Please check and update the ' 'messages in this file accordingly.', BLOCKED_USER_MESSAGE, BLOCKED_ERROR_MESSAGE) return True def _test_URLBlacklist(self, policy_value, policies_json): """ Verify CrOS enforces URLBlacklist policy value. When the URLBlacklist policy is set to one or more Domains, check that navigation to URLs in the Blocked list are blocked. When set to None, check that none of the websites are blocked. @param policy_value: policy value expected on chrome://policy page. @param policies_json: policy JSON data to send to the fake DM server. @raises: TestFail if url is blocked/not blocked based on the corresponding policy values. """ url_is_blocked = None self.setup_case(POLICY_NAME, policy_value, policies_json) logging.info('Running _test_URLBlacklist(%s, %s)', policy_value, policies_json) for url in ALL_URLS_LIST: url_is_blocked = self.is_url_blocked(url) if policy_value: if url in policy_value and not url_is_blocked: raise error.TestFail('The URL %s should have been blocked' ' by policy, but it was allowed' % url) elif url_is_blocked: raise error.TestFail('The URL %s should have been allowed' 'by policy, but it was blocked' % url) def _run_test_case(self, case): """ Setup and run the test configured for the specified test case. Set the expected |policy_value| and |policies_json| data based on the test |case|. If the user specified an expected |value| in the command line args, then use it to set the |policy_value| and blank out the |policies_json|. @param case: Name of the test case to run. """ policy_value = None policies_json = None if case not in self.TEST_CASES: raise error.TestError('Test case %s is not valid.' % case) logging.info('Running test case: %s', case) if self.is_value_given: # If |value| was given in the command line args, then set expected # |policy_value| to the given value, and |policies_json| to None. policy_value = self.value policies_json = None else: # Otherwise, set expected |policy_value| and setup |policies_json| # data to the values required by the test |case|. if case == 'NotSet': policy_value = None policies_json = {'URLBlacklist': None} elif case == 'SingleBlacklistedFile': policy_value = ','.join(SINGLE_BLACKLISTED_FILE_DATA) policies_json = {'URLBlacklist': SINGLE_BLACKLISTED_FILE_DATA} elif case == 'MultipleBlacklistedFiles': policy_value = ','.join(MULTIPLE_BLACKLISTED_FILES_DATA) policies_json = { 'URLBlacklist': MULTIPLE_BLACKLISTED_FILES_DATA } # Run test using the values configured for the test case. self._test_URLBlacklist(policy_value, policies_json) def run_once(self): self.run_once_impl(self._run_test_case)