1# Copyright (c) 2012 The Chromium 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 time
7import urlparse
8
9import dynamic_ap_configurator
10import ap_spec
11from selenium.common.exceptions import TimeoutException as \
12SeleniumTimeoutException
13
14
15class TrendnetAPConfigurator(
16        dynamic_ap_configurator.DynamicAPConfigurator):
17    """Derived class to control the Trendnet TEW-639GR."""
18
19
20    def _alert_handler(self, alert):
21        """Checks for any modal dialogs which popup to alert the user and
22        either raises a RuntimeError or ignores the alert.
23
24        Args:
25          alert: The modal dialog's contents.
26        """
27        text = alert.text
28        if 'Please input 10 or 26 characters of WEP key1' in text:
29            alert.accept()
30            raise RuntimeError(text)
31
32
33    def get_number_of_pages(self):
34        return 2
35
36
37    def get_supported_bands(self):
38        return [{'band': ap_spec.BAND_2GHZ, 'channels': range(1, 12)}]
39
40
41    def get_supported_modes(self):
42        return [{'band': ap_spec.BAND_2GHZ,
43                 'modes': [ap_spec.MODE_N,
44                           ap_spec.MODE_B | ap_spec.MODE_G,
45                           ap_spec.MODE_B | ap_spec.MODE_G | ap_spec.MODE_N]}]
46
47
48    def is_security_mode_supported(self, security_mode):
49        return security_mode in (ap_spec.SECURITY_TYPE_DISABLED,
50                                 ap_spec.SECURITY_TYPE_WEP,
51                                 ap_spec.SECURITY_TYPE_WPAPSK,
52                                 ap_spec.SECURITY_TYPE_WPA2PSK)
53
54
55    def navigate_to_page(self, page_number):
56        # All settings are on the same page, so we always open the config page
57        if page_number == 1:
58            page_url = urlparse.urljoin(self.admin_interface_url,
59                                        'wireless/basic.asp')
60            self.get_url(page_url, page_title='TEW')
61            ids_list = ['display_SSID1', 'sz11gChannel']
62        elif page_number == 2:
63            page_url = urlparse.urljoin(self.admin_interface_url,
64                                        'wireless/security.asp')
65            self.get_url(page_url, page_title='TEW')
66            ids_list = ['ssidIndex', 'security_mode']
67        else:
68            raise RuntimeError('Invalid page number passed.  Number of pages '
69                               '%d, page value sent was %d' %
70                               (self.get_number_of_pages(), page_number))
71        try:
72            self.wait_for_objects_by_id(ids_list, wait_time=30)
73        except SeleniumTimeoutException, e:
74            logging.info('Page did not load completely. Refresh driver')
75            self.driver.refresh()
76            self.wait_for_objects_by_id(ids_list, wait_time=30)
77
78
79    def wait_for_progress_bar(self):
80        """Watch the progress bar and wait for up to two minutes."""
81        for i in xrange(240):
82            if not self.object_by_id_exist('progressValue'):
83                return
84            try:
85                progress_value = self.wait_for_object_by_id('progressValue')
86                html = self.driver.execute_script(
87                        'return arguments[0].innerHTML', progress_value)
88            except Exception as e:
89                # The progress bar is gone and the page reloaded.  This can
90                # happen if we fly from < 95% to done.
91                return
92            percentage = html.rstrip('%')
93            if int(percentage) < 95:
94                time.sleep(0.5)
95            else:
96                break
97
98
99    def save_page(self, page_number):
100        if page_number == 1:
101            xpath = ('//input[@type="submit" and @value="Apply"]')
102        elif page_number == 2:
103            xpath = ('//input[@class="button_submit" and @value="Apply"]')
104        self.click_button_by_xpath(xpath, alert_handler=self._alert_handler)
105        # Wait for the settings progress bar to save the setting.
106        self.wait_for_progress_bar()
107
108
109    def set_mode(self, mode, band=None):
110        self.add_item_to_command_list(self._set_mode, (mode,), 1, 100)
111
112
113    def _set_mode(self, mode, band=None):
114        # Different bands are not supported so we ignore.
115        # Create the mode to popup item mapping
116        mode_mapping = {ap_spec.MODE_B | ap_spec.MODE_G | ap_spec.MODE_N:
117                        '2.4GHz 802.11 b/g/n mixed mode',
118                        ap_spec.MODE_N: '2.4GHz 802.11 n only',
119                        ap_spec.MODE_B | ap_spec.MODE_G:
120                        '2.4GHz 802.11 b/g mixed mode'}
121        mode_name = ''
122        if mode in mode_mapping.keys():
123            mode_name = mode_mapping[mode]
124        else:
125            raise RuntimeError('The mode selected %d is not supported by router'
126                               ' %s.', hex(mode), self.name)
127        self.select_item_from_popup_by_id(mode_name, 'wirelessmode',
128                                          wait_for_xpath='id("wds_mode")')
129
130
131    def set_radio(self, enabled=True):
132        logging.debug('Enabling/Disabling the radio is not supported on this '
133                      'router (%s).', self.name)
134        return None
135
136
137    def set_ssid(self, ssid):
138        self.add_item_to_command_list(self._set_ssid, (ssid,), 1, 100)
139
140
141    def _set_ssid(self, ssid):
142        self.set_content_of_text_field_by_id(ssid, 'display_SSID1')
143        self._ssid = ssid
144
145
146    def set_channel(self, channel):
147        self.add_item_to_command_list(self._set_channel, (channel,), 1, 100)
148
149
150    def _set_channel(self, channel):
151        position = self._get_channel_popup_position(channel)
152        channel_choices = ['2412MHz (Channel 1)', '2417MHz (Channel 2)',
153                           '2422MHz (Channel 3)', '2427MHz (Channel 4)',
154                           '2432MHz (Channel 5)', '2437MHz (Channel 6)',
155                           '2442MHz (Channel 7)', '2447MHz (Channel 8)',
156                           '2452MHz (Channel 9)', '2457MHz (Channel 10)',
157                           '2462MHz (Channel 11)']
158        self.select_item_from_popup_by_id(channel_choices[position],
159                                          'sz11gChannel')
160
161
162    def set_band(self, band):
163        return None
164
165
166    def set_security_disabled(self):
167        self.add_item_to_command_list(self._set_security_disabled, (), 2, 1000)
168
169
170    def _set_security_disabled(self):
171        self.wait_for_object_by_id('security_mode')
172        self.select_item_from_popup_by_id('Disable', 'security_mode')
173
174
175    def set_security_wep(self, key_value, authentication):
176        self.add_item_to_command_list(self._set_security_wep,
177                                      (key_value, authentication), 2, 900)
178
179
180    def _set_security_wep(self, key_value, authentication):
181        text_field = 'id("WEP1")'
182        popup_id = 'security_mode'
183        self.wait_for_object_by_id(popup_id)
184        self.select_item_from_popup_by_id('WEP-OPEN',
185                                          popup_id, wait_for_xpath=text_field)
186        self.set_content_of_text_field_by_xpath(key_value, text_field,
187                                                abort_check=True)
188
189
190    def set_security_wpapsk(self, security, shared_key, update_interval=1800):
191        self.add_item_to_command_list(self._set_security_wpapsk,
192                                      (security, shared_key, update_interval),
193                                       2, 900)
194
195
196    def _set_security_wpapsk(self, security, shared_key, update_interval=1800):
197        self.wait_for_object_by_id('security_mode')
198        if security == ap_spec.SECURITY_TYPE_WPAPSK:
199            wpa_item = 'WPA-PSK'
200        else:
201            wpa_item = 'WPA2-PSK'
202        self.select_item_from_popup_by_id(wpa_item, 'security_mode',
203                                          wait_for_xpath='id("passphrase")')
204        self.set_content_of_text_field_by_id(shared_key, 'passphrase')
205        self.set_content_of_text_field_by_id(update_interval,
206                                             'keyRenewalInterval')
207
208
209    def set_visibility(self, visible=True):
210        self.add_item_to_command_list(self._set_visibility, (visible,), 1, 100)
211
212
213    def _set_visibility(self, visible=True):
214        # value=1 is visible; value=0 is invisible
215        int_value = int(visible)
216        xpath = ('//input[@value="%d" and @name="broadcastssid"]' % int_value)
217        self.click_button_by_xpath(xpath)
218