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 5"""Class to control the DlinkAP router.""" 6 7import os 8 9import dynamic_ap_configurator 10import ap_spec 11from selenium.common.exceptions import TimeoutException as \ 12 SeleniumTimeoutException 13 14class DLinkAPConfigurator( 15 dynamic_ap_configurator.DynamicAPConfigurator): 16 """Derived class to control the DLink DAP-1522.""" 17 18 def _open_landing_page(self): 19 self.get_url('%s/index.php' % self.admin_interface_url, 20 page_title='D-Link Corporation') 21 page_name = os.path.basename(self.driver.current_url) 22 if page_name == 'login.php' or page_name == 'index.php': 23 try: 24 self.wait_for_object_by_xpath('//*[@name="login"]') 25 except SeleniumTimeoutException, e: 26 # Maybe we were re-routed to the configuration page 27 if (os.path.basename(self.driver.current_url) == 28 'bsc_wizard.php'): 29 return 30 raise SeleniumTimeoutException('Unable to navigate to the ' 31 'login or configuration page. ' 32 'WebDriver exception:%s', str(e)) 33 login_button = self.driver.find_element_by_xpath( 34 '//*[@name="login"]') 35 login_button.click() 36 37 38 def _open_configuration_page(self): 39 self._open_landing_page() 40 if os.path.basename(self.driver.current_url) != 'bsc_wizard.php': 41 raise SeleniumTimeoutException('Taken to an unknown page %s' % 42 os.path.basename(self.driver.current_url)) 43 44 # Else we are being logged in automatically to the landing page 45 wlan = '//*[@name="wlan_wireless"]' 46 self.wait_for_object_by_xpath(wlan) 47 wlan_button = self.driver.find_element_by_xpath(wlan) 48 wlan_button.click() 49 # Wait for the main configuration page, look for the radio button 50 self.wait_for_object_by_id('enable') 51 52 53 def get_number_of_pages(self): 54 return 1 55 56 57 def get_supported_bands(self): 58 return [{'band': ap_spec.BAND_2GHZ, 59 'channels': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]}, 60 {'band': ap_spec.BAND_5GHZ, 61 'channels': [26, 40, 44, 48, 149, 153, 157, 161, 165]}] 62 63 64 def get_supported_modes(self): 65 return [{'band': ap_spec.BAND_2GHZ, 66 'modes': [ap_spec.MODE_B, ap_spec.MODE_G, ap_spec.MODE_N, 67 ap_spec.MODE_B | ap_spec.MODE_G, 68 ap_spec.MODE_G | ap_spec.MODE_N]}, 69 {'band': ap_spec.BAND_5GHZ, 70 'modes': [ap_spec.MODE_A, ap_spec.MODE_N, 71 ap_spec.MODE_A | ap_spec.MODE_N]}] 72 73 74 def is_security_mode_supported(self, security_mode): 75 """ 76 Returns if a given security_type is supported. 77 78 @param security_mode: one security modes defined in the APSpec 79 80 @return True if the security mode is supported; False otherwise. 81 82 """ 83 return security_mode in (self.security_disabled, 84 self.security_wpapsk, 85 self.security_wep) 86 87 88 def navigate_to_page(self, page_number): 89 """ 90 Navigates to the page corresponding to the given page number. 91 92 This method performs the translation between a page number and a url to 93 load. This is used internally by apply_settings. 94 95 @param page_number: page number of the page to load 96 97 """ 98 # All settings are on the same page, so we always open the config page 99 self._open_configuration_page() 100 101 102 def save_page(self, page_number): 103 """ 104 Saves the given page. 105 106 @param page_number: Page number of the page to save. 107 108 """ 109 # All settings are on the same page, we can ignore page_number 110 button = self.driver.find_element_by_xpath('//input[@name="apply"]') 111 button.click() 112 # If we did not make changes we are sent to the continue screen. 113 continue_screen = True 114 button_xpath = '//input[@name="bt"]' 115 try: 116 self.wait_for_object_by_xpath(button_xpath) 117 except SeleniumTimeoutException, e: 118 continue_screen = False 119 if continue_screen: 120 button = self.driver.find_element_by_xpath(button_xpath) 121 button.click() 122 # We will be returned to the landing page when complete 123 self.wait_for_object_by_id('enable') 124 125 126 def set_mode(self, mode, band=None): 127 # Mode overrides the band. So if a band change is made after a mode 128 # change it may make an incompatible pairing. 129 self.add_item_to_command_list(self._set_mode, (mode, band), 1, 800) 130 131 132 def _set_mode(self, mode, band=None): 133 # Create the mode to popup item mapping 134 mode_mapping = {ap_spec.MODE_B: '802.11b Only', 135 ap_spec.MODE_G: '802.11g Only', 136 ap_spec.MODE_N: '802.11n Only', 137 ap_spec.MODE_B | ap_spec.MODE_G: 'Mixed 802.11g and 802.11b', 138 ap_spec.MODE_N | ap_spec.MODE_G: 'Mixed 802.11n and 802.11g', 139 ap_spec.MODE_N | ap_spec.MODE_G | ap_spec.MODE_B: 140 'Mixed 802.11n, 802.11g, and 802.11b', 141 ap_spec.MODE_N | ap_spec.MODE_G | ap_spec.MODE_B: 142 'Mixed 802.11n, 802.11g, and 802.11b', 143 ap_spec.MODE_A: '802.11a Only', 144 ap_spec.MODE_N | ap_spec.MODE_A: 'Mixed 802.11n and 802.11a'} 145 band_value = ap_spec.BAND_2GHZ 146 if mode in mode_mapping.keys(): 147 popup_value = mode_mapping[mode] 148 # If the mode contains 802.11a we use 5Ghz 149 if mode & ap_spec.MODE_A == ap_spec.MODE_A: 150 band_value = ap_spec.BAND_5GHZ 151 # If the mode is 802.11n mixed with 802.11a it must be 5Ghz 152 elif (mode & (ap_spec.MODE_N | ap_spec.MODE_A) == 153 (ap_spec.MODE_N | ap_spec.MODE_A)): 154 band_value = ap_spec.BAND_5GHZ 155 # If the mode is 802.11n mixed with other than 802.11a its 2Ghz 156 elif (mode & ap_spec.MODE_N == ap_spec.MODE_N and 157 mode ^ ap_spec.MODE_N > 0): 158 band_value = ap_spec.BAND_2GHZ 159 # If the mode is 802.11n then default to 5Ghz unless there is a band 160 elif mode == ap_spec.MODE_N: 161 band_value = ap_spec.BAND_5GHZ 162 if band: 163 band_value = band 164 else: 165 raise SeleniumTimeoutException('The mode selected %s is not ' 166 'supported by router %s.' % 167 (hex(mode), self.name)) 168 # Set the band first 169 self._set_band(band_value) 170 popup_id = 'mode_80211_11g' 171 if band_value == ap_spec.BAND_5GHZ: 172 popup_id = 'mode_80211_11a' 173 self.select_item_from_popup_by_id(popup_value, popup_id) 174 175 176 def set_radio(self, enabled=True): 177 # If we are enabling we are activating all other UI components, do 178 # it first. Otherwise we are turning everything off so do it last. 179 if enabled: 180 weight = 1 181 else: 182 weight = 1000 183 self.add_item_to_command_list(self._set_radio, (enabled,), 1, weight) 184 185 186 def _set_radio(self, enabled=True): 187 # The radio checkbox for this router always has a value of 1. So we need 188 # to use other methods to determine if the radio is on or not. Check if 189 # the ssid textfield is disabled. 190 ssid = self.driver.find_element_by_xpath('//input[@name="ssid"]') 191 if ssid.get_attribute('disabled') == 'true': 192 radio_enabled = False 193 else: 194 radio_enabled = True 195 if radio_enabled == enabled: 196 # Nothing to do 197 return 198 self.set_check_box_selected_by_id('enable', selected=False, 199 wait_for_xpath='id("security_type_ap")') 200 201 202 def set_ssid(self, ssid): 203 # Can be done as long as it is enabled 204 self.add_item_to_command_list(self._set_ssid, (ssid,), 1, 900) 205 206 207 def _set_ssid(self, ssid): 208 self._set_radio(enabled=True) 209 self.set_content_of_text_field_by_id(ssid, 'ssid') 210 self._ssid = ssid 211 212 213 def set_channel(self, channel): 214 self.add_item_to_command_list(self._set_channel, (channel,), 1, 900) 215 216 217 def _set_channel(self, channel): 218 position = self._get_channel_popup_position(channel) 219 self._set_radio(enabled=True) 220 self.set_check_box_selected_by_id('autochann', selected=False) 221 self.select_item_from_popup_by_id(str(position), 'channel_g') 222 223 224 def get_band(self): 225 """ 226 This is experimental 227 The radio buttons do more than run a script that adjusts the possible 228 channels. We will just check the channel to popup. 229 """ 230 self.set_radioSetting(enabled=True) 231 xpath = ('id("channel_g")') 232 self._open_configuration_page() 233 self.wait_for_object_by_xpath(xpath) 234 element = self.driver.find_element_by_xpath(xpath) 235 if element.find_elements_by_tag_name('option')[0].text == '1': 236 return ap_spec.BAND_2GHZ 237 return ap_spec.BAND_5GHZ 238 239 240 def set_band(self, band): 241 if band != ap_spec.BAND_2GHZ or band != ap_spec.BAND_5GHZ: 242 raise RuntimeError('Invalid band sent %s' % band) 243 self.add_item_to_command_list(self._set_band, (band,), 1, 900) 244 245 246 def _set_band(self, band): 247 self._set_radio(enabled=True) 248 if band == ap_spec.BAND_2GHZ: 249 int_value = 0 250 wait_for_id = 'mode_80211_11g' 251 elif band == ap_spec.BAND_5GHZ: 252 int_value = 1 253 wait_for_id = 'mode_80211_11a' 254 xpath = ('//*[contains(@class, "l_tb")]/input[@value="%d" ' 255 'and @name="band"]' % int_value) 256 element = self.driver.find_element_by_xpath(xpath) 257 element.click() 258 self.wait_for_object_by_id(wait_for_id) 259 260 261 def set_security_disabled(self): 262 self.add_item_to_command_list(self._set_security_disabled, (), 1, 900) 263 264 265 def _set_security_disabled(self): 266 self._set_radio(enabled=True) 267 security_disabled = 'Disable Wireless Security (not recommended)' 268 self.select_item_from_popup_by_id(security_disabled, 'security_type_ap') 269 270 271 def set_security_wep(self, key_value, authentication): 272 self.add_item_to_command_list(self._set_security_wep, 273 (key_value, authentication), 1, 900) 274 275 276 def _set_security_wep(self, key_value, authentication): 277 self._set_radio(enabled=True) 278 self.select_item_from_popup_by_id('WEP', 'security_type_ap', 279 wait_for_xpath='id("auth_type")') 280 self.select_item_from_popup_by_id(authentication, 'auth_type', 281 wait_for_xpath='id("wep_key_value")') 282 self.set_content_of_text_field_by_id(key_value, 'wep_key_value') 283 self.set_content_of_text_field_by_id(key_value, 'verify_wep_key_value') 284 285 286 def set_security_wpapsk(self, shared_key, update_interval=1800): 287 self.add_item_to_command_list(self._set_security_wpapsk, 288 (shared_key, update_interval), 1, 900) 289 290 291 def _set_security_wpapsk(self, shared_key, update_interval=1800): 292 self._set_radio(enabled=True) 293 self.select_item_from_popup_by_id('WPA-Personal', 294 'security_type_ap', 295 wait_for_xpath='id("wpa_mode")') 296 self.select_item_from_popup_by_id('WPA Only', 'wpa_mode', 297 wait_for_xpath='id("grp_key_interval")') 298 self.set_content_of_text_field_by_id(str(update_interval), 299 'grp_key_interval') 300 self.set_content_of_text_field_by_id(shared_key, 'wpapsk1') 301 302 303 def set_visibility(self, visible=True): 304 self.add_item_to_command_list(self._set_visibility, (visible,), 1, 900) 305 306 307 def _set_visibility(self, visible=True): 308 self._set_radio(enabled=True) 309 # value=0 is visible; value=1 is invisible 310 int_value = int(not visible) 311 xpath = ('//*[contains(@class, "l_tb")]/input[@value="%d" ' 312 'and @name="visibility_status"]' % int_value) 313 self.click_button_by_xpath(xpath) 314