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 json
6import logging
7import time
8
9from autotest_lib.client.common_lib import error
10from autotest_lib.client.cros import enterprise_policy_base
11
12
13class policy_ManagedBookmarks(enterprise_policy_base.EnterprisePolicyTest):
14    """Test effect of ManagedBookmarks policy on Chrome OS behavior.
15
16    This test verifies the behavior of Chrome OS for a range of valid values
17    of the ManagedBookmarks user policy, as defined by three test cases:
18    NotSet, SingleBookmark_Shown, and MultiBookmark_Shown.
19
20    When NotSet, the policy value is undefined. This induces the default
21    behavior of not showing the managed bookmarks folder, which is equivalent
22    to what is seen by an un-managed user.
23
24    When one or more bookmarks are specified by the policy, then the Managed
25    Bookmarks folder is shown, and the specified bookmarks within it.
26
27    """
28    version = 1
29
30    POLICY_NAME = 'ManagedBookmarks'
31    SINGLE_BOOKMARK = '''
32    {
33      "name": "Google",
34      "url": "https://www.google.com/"
35    }
36    '''
37    MULTI_BOOKMARK = '''
38    {
39      "name": "Google",
40      "url": "https://www.google.com/"
41    }
42    ,{
43      "name": "CNN",
44      "url": "http://www.cnn.com/"
45    }
46    ,{
47      "name": "IRS",
48      "url": "http://www.irs.gov/"
49    }
50    '''
51    SUPPORTING_POLICIES = {
52        'BookmarkBarEnabled': True
53    }
54
55    # Dictionary of named test cases and policy values.
56    TEST_CASES = {
57        'NotSet_NotShown': None,
58        'SingleBookmark_Shown': SINGLE_BOOKMARK,
59        'MultiBookmark_Shown': MULTI_BOOKMARK
60    }
61
62    def _test_managed_bookmarks(self, policy_value, policies_json):
63        """Verify CrOS enforces ManagedBookmarks policy.
64
65        When ManagedBookmarks is not set, the UI shall not show the managed
66        bookmarks folder nor its contents. When set to one or more bookmarks
67        the UI shows the folder and its contents.
68
69        @param policy_value: policy value expected on chrome://policy page.
70        @param policies_json: policy JSON data to send to the fake DM server.
71
72        """
73        self.setup_case(self.POLICY_NAME, policy_value, policies_json)
74        logging.info('Running _test_managed_bookmarks(policy_value=%s, '
75                     'policies_json=%s)', policy_value, policies_json)
76        if policy_value is None:
77            if self._managed_bookmarks_are_shown(policy_value):
78                raise error.TestFail('Managed Bookmarks should be hidden.')
79        else:
80            if not self._managed_bookmarks_are_shown(policy_value):
81                raise error.TestFail('Managed Bookmarks should be shown.')
82
83    def _managed_bookmarks_are_shown(self, policy_bookmarks):
84        """Check whether managed bookmarks are shown in the UI.
85
86        @returns: True if the managed bookmarks are shown.
87
88        """
89        # Extract dictionary of folders shown in bookmark tree.
90        tab = self._open_boomark_manager_to_folder(0)
91        cmd = 'document.getElementsByClassName("tree-item");'
92        tree_items = self.get_elements_from_page(tab, cmd)
93
94        # Scan bookmark tree for a folder with the domain-name in title.
95        domain_name = self.USERNAME.split('@')[1]
96        folder_title = domain_name + ' bookmarks'
97        for bookmark_element in tree_items.itervalues():
98            bookmark_node = bookmark_element['bookmarkNode']
99            bookmark_title = bookmark_node['title']
100            if bookmark_title == folder_title:
101                folder_id = bookmark_node['id'].encode('ascii', 'ignore')
102                break
103        else:
104            tab.Close()
105            return False
106        tab.Close()
107
108        # Extract list of bookmarks shown in bookmark list-pane.
109        tab = self._open_boomark_manager_to_folder(folder_id)
110        cmd = '''
111            var bookmarks = [];
112            var listPane = document.getElementById("list-pane");
113            var labels = listPane.getElementsByClassName("label");
114            for (var i = 0; i < labels.length; i++) {
115               bookmarks.push(labels[i].textContent);
116            }
117            bookmarks;
118        '''
119        bookmark_items = self.get_elements_from_page(tab, cmd)
120        tab.Close()
121
122        # Get list of expected bookmarks as set by policy.
123        json_bookmarks = json.loads('[%s]' % policy_bookmarks)
124        bookmarks_expected = [bmk['name'] for bmk in json_bookmarks]
125
126        # Compare bookmarks shown vs expected.
127        if bookmark_items != bookmarks_expected:
128            raise error.TestFail('Bookmarks shown are not correct: %s '
129                                 '(expected: %s)' %
130                                 (bookmark_items, bookmarks_expected))
131        return True
132
133    def _open_boomark_manager_to_folder(self, folder_number):
134        """Open bookmark manager page and select specified folder.
135
136        @param folder_number: folder to select when opening page.
137        @returns: tab loaded with bookmark manager page.
138
139        """
140        # Open Bookmark Manager with specified folder selected.
141        bmp_url = ('chrome://bookmarks/#%s' % folder_number)
142        tab = self.navigate_to_url(bmp_url)
143
144        # Wait until list.reload() is defined on page.
145        tab.WaitForJavaScriptExpression(
146            "typeof bmm.list.reload == 'function'", 60)
147        time.sleep(1)  # Allow JS to run after function is defined.
148        return tab
149
150    def _run_test_case(self, case):
151        """Setup and run the test configured for the specified test case.
152
153        Set the expected |policy_value| string and |policies_json| data based
154        on the test |case|. If the user specified an expected |value| in the
155        command line args, then use it to set the |policy_value| and blank out
156        the |policies_json|.
157
158        @param case: Name of the test case to run.
159
160        """
161        if self.is_value_given:
162            # If |value| was given by user, then set expected |policy_value|
163            # to the given value, and setup |policies_json| to None.
164            policy_value = self.value
165            policies_json = None
166        else:
167            # Otherwise, set expected |policy_value| and setup |policies_json|
168            # data to the defaults required by the test |case|.
169            policies_json = self.SUPPORTING_POLICIES.copy()
170            if self.TEST_CASES[case] is None:
171                policy_value = None
172                policy_json = {self.POLICY_NAME: None}
173            else:
174                policy_value = self.TEST_CASES[case]
175                policy_json = {self.POLICY_NAME: ('[%s]' % policy_value)}
176            policies_json.update(policy_json)
177
178        # Run test using values configured for the test case.
179        self._test_managed_bookmarks(policy_value, policies_json)
180
181    def run_once(self):
182        self.run_once_impl(self._run_test_case)
183