1# Copyright 2018 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
5from autotest_lib.client.common_lib import error
6from autotest_lib.client.common_lib import utils
7from autotest_lib.client.cros.enterprise import enterprise_policy_base
8
9
10class policy_SystemTimezone(
11        enterprise_policy_base.EnterprisePolicyTest):
12    """
13    Test effect of SystemTimezone policy on Chrome OS behavior.
14
15    This will test that both the timezone can be set by the policy, and that
16    when the policy is not set a user can change the settings.
17
18    """
19    version = 1
20    POLICY_NAME = 'SystemTimezone'
21
22    JS_WRAPPER = "document.querySelector('{ID}'){action}"
23    DROPDOWN_MENU = "* /deep/ #timezoneSelector /deep/ #userTimeZoneSelector /deep/ #dropdownMenu"
24
25    def change_timezone(self, settings_tab, selection):
26        """
27        Change the timezone via the dropdown menu on the settings page.
28
29        @param settings_tab: The tab object for the settings page.
30        @param selection: int, index of item in DROPDOWN_MENU to change to.
31
32        """
33        SELECT_INDEX = ".selectedIndex = '{n}'"
34
35        selected_index = SELECT_INDEX.format(n=selection)
36        change_timezone = self.JS_WRAPPER.format(ID=self.DROPDOWN_MENU,
37                                                 action=selected_index)
38        settings_tab.ExecuteJavaScript(change_timezone)
39        settings_tab.WaitForDocumentReadyStateToBeComplete()
40        self._dispatch_event(settings_tab)
41
42    def _dispatch_event(self, settings_tab):
43        """
44        Confirms the dropdown select by running a JS dispatchEvent().
45
46        @param settings_tab: The tab object for the settings page.
47
48        """
49        new_event = "var event = new Event('change');"
50        dispatch = ".dispatchEvent(event);"
51        settings_tab.ExecuteJavaScript(new_event)
52        settings_tab.ExecuteJavaScript(
53            self.JS_WRAPPER.format(ID=self.DROPDOWN_MENU,
54                                   action=dispatch))
55
56    def _test_timezone(self, expected):
57        """
58        Verify the Timezone set on the device.
59
60        This is done by running the UNIX date command (%z) and verifying the
61        timezone matches the expected result.
62
63        """
64        def check_timezone(expected):
65            return utils.system_output('date +%z') == expected
66
67        utils.poll_for_condition(
68            lambda: check_timezone(expected),
69            exception=error.TestFail('Time zone was not set! Expected {}'
70                                     .format(expected)),
71            timeout=5,
72            sleep_interval=1,
73            desc='Polling for timezone change')
74
75    def set_timezones(self):
76        """
77        Iterate through different time zones, and verify they can be set.
78
79        This is specifically being done to verify the timezone via seeing
80        the reported timezone is changing, and not just on the first one via
81        luck.
82
83        """
84        cases = [{'policy': 'America/Costa_Rica', 'expected': '-0600'},
85                 {'policy': 'Asia/Kathmandu', 'expected': '+0545'}]
86
87        for setting in cases:
88            policy_value = setting['policy']
89            expected = setting['expected']
90            policies = {self.POLICY_NAME: policy_value}
91            self.setup_case(device_policies=policies, enroll=True)
92
93            # Logout so the policy can take effect
94            self.log_out_via_keyboard()
95
96            self._test_timezone(expected)
97
98    def set_empty_timezone(self):
99        """
100        Manually set and verify the timezone when the policy is empty.
101
102        This will be done by adjusting the setting on the ://settings page,
103        and verfying the date reported. Additionally log out, then verify the
104        timezone matches as well.
105
106        """
107        SETTINGS_URL = "chrome://settings/dateTime/timeZone"
108        CLICK = ".click()"
109        USER_TIMEZONE_BUTTON = "* /deep/ #timeZoneAutoDetectOff"
110        autodetect_disable = self.JS_WRAPPER.format(ID=USER_TIMEZONE_BUTTON,
111                                                    action=CLICK)
112
113        policies = {self.POLICY_NAME: ''}
114        self.setup_case(device_policies=policies, enroll=True)
115
116        # Open the Timezone settings page
117        settings_tab = self.navigate_to_url(SETTINGS_URL)
118        settings_tab.WaitForDocumentReadyStateToBeComplete()
119
120        # Select the manual timezone settings radio button
121        settings_tab.ExecuteJavaScript(autodetect_disable)
122        settings_tab.WaitForDocumentReadyStateToBeComplete()
123
124        # Change the timezone to the first index on the list
125        self.change_timezone(settings_tab, 0)
126        self._test_timezone('-1100')
127
128        # Close the tab, then logout
129        settings_tab.Close()
130        self.log_out_via_keyboard()
131        self._test_timezone('-1100')
132
133    def run_once(self, case):
134        """
135        Run the proper test based on the selected case.
136
137        @param case: bool or None, value of the test case to run.
138
139        """
140        if case:
141            self.set_timezones()
142        else:
143            self.set_empty_timezone()
144