1# Copyright (c) 2013 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 ap_spec
6import dynamic_ap_configurator
7import os
8import time
9
10from selenium.common.exceptions import ElementNotVisibleException
11
12
13class EdimaxAPConfigurator(
14        dynamic_ap_configurator.DynamicAPConfigurator):
15    """Derived class to control the Edimax AP."""
16
17    def navigate_to_page(self, page_number):
18        """Navigate to the required page.
19
20        @param page_number: The page number to navigate to.
21
22        """
23        if page_number != 1 and page_number != 2:
24            raise RuntimeError('Invalid page number passed.  Number of pages is'
25                               '%d, page value sent was %d' %
26                               (self.get_number_of_pages(), page_number))
27        page_url = os.path.join(self.admin_interface_url ,'index.asp')
28        self.get_url(page_url, page_title='EDIMAX Technology')
29        frame = self.driver.find_element_by_xpath('//frame[@name="mainFrame"]')
30        self.driver.switch_to_frame(frame)
31        main_tabs = self.driver.find_elements_by_css_selector('div')
32        main_tabs[2].click()
33        sub_tabs = self.driver.find_elements_by_xpath( \
34                                                     '//span[@class="style11"]')
35        sub_tabs[2].click()
36        if page_number == 1:
37            # Open the general settings page.
38            self.click_button_by_xpath('//input[@onclick="c_fun(0)" and \
39                                        @name="sys"]')
40            self.wait_for_object_by_xpath('//select[@name="band"]')
41        else:
42            # Open the security settings page.
43            self.click_button_by_xpath('//input[@onclick="c_fun(1)" and \
44                                        @name="sys"]')
45            self.wait_for_object_by_xpath('//select[@name="method"]')
46
47
48    def get_number_of_pages(self):
49        return 2
50
51
52    def save_page(self, page_number):
53        """ Save page after applying settings.
54
55        @param page_number: The page number to be saved.
56
57        """
58        xpath_ok = ('//input[@name="okbutton"]')
59        try:
60            self.click_button_by_xpath('//input[@name="B1" and @value="Apply"]',
61                                       alert_handler=self._alert_handler)
62        except ElementNotVisibleException, e:
63            # If the default Apply button is not visible then we are on Security
64            # settings page that has a different Apply button. Click that.
65            xpath = '//input[@type="submit" and @value="Apply"]'
66            apply_tabs = self.driver.find_elements_by_xpath(xpath)
67            apply_tabs[2].click()
68        self.driver.find_element_by_xpath('//input[@value="APPLY"]').click()
69        element = self.wait_for_object_by_xpath(xpath_ok)
70        xpath_done = '//input[@name="okbutton" and @value="OK"]'
71        while element and not(self.object_by_xpath_exist(xpath_done)):
72            time.sleep(0.5)
73        self.click_button_by_xpath(xpath_ok, alert_handler=self._alert_handler)
74
75
76    def get_supported_bands(self):
77        return [{'band': ap_spec.BAND_2GHZ, 'channels': range(1, 11)}]
78
79
80    def set_band(self, band):
81        return None
82
83
84    def get_supported_modes(self):
85        return [{'band': ap_spec.BAND_2GHZ,
86                 'modes': [ap_spec.MODE_B,
87                           ap_spec.MODE_G,
88                           ap_spec.MODE_N,
89                           ap_spec.MODE_B | ap_spec.MODE_G,
90                           ap_spec.MODE_B | ap_spec.MODE_G | ap_spec.MODE_N]}]
91
92
93    def set_mode(self, mode, band=None):
94        self.add_item_to_command_list(self._set_mode, (mode,), 1, 800)
95
96
97    def _set_mode(self, mode, band=None):
98        # Different bands are not supported so we ignore.
99        # Create the mode to popup item mapping
100        mode_mapping = {ap_spec.MODE_B | ap_spec.MODE_G | ap_spec.MODE_N:
101                        '2.4 GHz (B+G+N)',
102                        ap_spec.MODE_N: '2.4 GHz (N)',
103                        ap_spec.MODE_B: '2.4 GHz (B)',
104                        ap_spec.MODE_G: '2.4 GHz (G)',
105                        ap_spec.MODE_B | ap_spec.MODE_G: '2.4 GHz (B+G)'}
106        mode_name = ''
107        if mode in mode_mapping.keys():
108            mode_name = mode_mapping[mode]
109        else:
110            raise RuntimeError('The mode selected %d is not supported by router'
111                               ' %s.', hex(mode), self.name)
112        xpath = '//select[@name="band"]'
113        self.select_item_from_popup_by_xpath(mode_name, xpath)
114
115
116    def set_channel(self, channel):
117        self.add_item_to_command_list(self._set_channel, (channel,), 1, 900)
118
119
120    def _set_channel(self, channel):
121        position = self._get_channel_popup_position(channel)
122        channel_choices = ['1', '2', '3', '4', '5',
123                           '6', '7', '8', '9', '10', '11']
124        self.select_item_from_popup_by_xpath(channel_choices[position],
125                                             '//select[@name="chan"]')
126
127
128    def is_security_mode_supported(self, security_mode):
129        """Check if the AP supports this mode of security.
130
131        @param security_mode: Type of security.
132
133        """
134        return security_mode in (ap_spec.SECURITY_TYPE_DISABLED,
135                                 ap_spec.SECURITY_TYPE_WEP,
136                                 ap_spec.SECURITY_TYPE_WPAPSK)
137
138
139    def set_ssid(self, ssid):
140        self.add_item_to_command_list(self._set_ssid, (ssid,), 1, 1000)
141
142
143    def _set_ssid(self, ssid):
144        self.set_content_of_text_field_by_xpath(ssid, '//input[@name="ssid"]',
145                                                abort_check=True)
146        self._ssid = ssid
147
148
149    def is_visibility_supported(self):
150        """
151        Returns if AP supports setting the visibility (SSID broadcast).
152
153        @return True if supported; False otherwise.
154
155        """
156        return False
157
158
159    def is_update_interval_supported(self):
160        """
161        Returns True if setting the PSK refresh interval is supported.
162
163        @return True is supported; False otherwise.
164
165        """
166        return False
167
168
169    def set_radio(self, enabled=True):
170        # AP does not aupport setting Radio.
171        return None
172
173
174    def set_security_disabled(self):
175        self.add_item_to_command_list(self._set_security_disabled, (), 2, 1000)
176
177
178    def _set_security_disabled(self):
179        self.select_item_from_popup_by_xpath('Disable',
180                                             '//select[@name="method"]')
181
182
183    def set_security_wpapsk(self, security, shared_key, update_interval=None):
184        self.add_item_to_command_list(self._set_security_wpapsk,
185                                      (security, shared_key, update_interval),
186                                       2, 1000)
187
188
189    def _set_security_wpapsk(self, security, shared_key, update_interval=None):
190        self.wait_for_object_by_xpath('//input[@name="pskValue"]')
191        self.select_item_from_popup_by_xpath('WPA pre-shared key',
192                                             '//select[@name="method"]')
193        if security == ap_spec.SECURITY_TYPE_WPAPSK:
194            wpa_item = 'wpaCipher1'
195        else:
196            wpa_item = 'wpaCipher2'
197        self.click_button_by_id(wpa_item, alert_handler=self._alert_handler)
198        self.select_item_from_popup_by_xpath('Passphrase',
199                                             '//select[@name="pskFormat"]')
200        self.set_content_of_text_field_by_xpath(shared_key,
201                                                '//input[@name="pskValue"]')
202
203
204    def set_security_wep(self, key_value, authentication):
205        self.add_item_to_command_list(self._set_security_wep,
206                                      (key_value, authentication), 2, 1000)
207
208
209    def _set_security_wep(self, key_value, authentication):
210        self.wait_for_object_by_xpath('//input[@name="key1"]')
211        self.select_item_from_popup_by_xpath('WEP', '//select[@name="method"]')
212        self.select_item_from_popup_by_xpath('64-bit',
213                                             '//select[@name="length"]')
214        self.select_item_from_popup_by_xpath('ASCII (5  characters)',
215                                             '//select[@name="format"]')
216        self.set_content_of_text_field_by_xpath(key_value,
217                                                '//input[@name="key1"]')
218
219
220    def _alert_handler(self, alert):
221        """Checks for any modal dialogs which popup to alert the user and
222        either raises a RuntimeError or ignores the alert.
223
224        @param alert: The modal dialog's contents.
225        """
226        text = alert.text
227        if 'Pre-Shared Key values should be set at least characters' in text:
228            alert.accept()
229        else:
230            raise RuntimeError('An unexpected modal dialog blocked the'
231                               'operation, dialog text: %s', text)
232