1# Copyright 2016 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that 3# can be found in the LICENSE file. 4 5"""Class to control Asus RT-AC68U router.""" 6 7import logging 8 9import ap_spec 10import dynamic_ap_configurator 11 12from selenium.common.exceptions import UnexpectedAlertPresentException 13 14 15class AsusRTAC68UAPConfigurator( 16 dynamic_ap_configurator.DynamicAPConfigurator): 17 """Configurator for Asus RT-AC68U router.""" 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 @param alert: The modal dialog's contents. 25 """ 26 text = alert.text 27 if 'Open System' in text: 28 alert.accept() 29 else: 30 raise RuntimeError('Unhandled alert message: %s' % text) 31 32 33 def get_number_of_pages(self): 34 """Returns the number of available pages.""" 35 return 1 36 37 38 def get_supported_bands(self): 39 """Returns a list of dictionaries describing the supported bands.""" 40 return [{'band': ap_spec.BAND_2GHZ, 41 'channels': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]}, 42 {'band': ap_spec.BAND_5GHZ, 43 'channels': [36, 40, 44, 48, 149, 153, 157, 161, 165]}] 44 45 46 def get_supported_modes(self): 47 """Returns a list of dictionaries with the supported bands and modes.""" 48 return [{'band': ap_spec.BAND_2GHZ, 49 'modes': [ap_spec.MODE_N]}, 50 {'band': ap_spec.BAND_5GHZ, 51 'modes': [ap_spec.MODE_N, ap_spec.MODE_N|ap_spec.MODE_AC]}] 52 53 54 def get_supported_channel_widths(self): 55 """ 56 Returns a dictionary describing supported channel widths based on 57 band and mode. 58 59 @return a dictionary as described above. 60 """ 61 return {ap_spec.BAND_2GHZ: {ap_spec.MODE_N: [20]}, 62 ap_spec.BAND_5GHZ: {ap_spec.MODE_N: [20], 63 ap_spec.MODE_N|ap_spec.MODE_AC: [20]}} 64 65 66 def is_security_mode_supported(self, security_mode): 67 """Returns if a given security_type is supported for 2.4GHz and 68 5GHz bands. 69 70 @param security_mode: one security modes defined in the ap_spec. 71 72 @return True if the security mode is supported; False otherwise. 73 """ 74 return security_mode in (ap_spec.SECURITY_TYPE_DISABLED, 75 ap_spec.SECURITY_TYPE_WPA2PSK, 76 ap_spec.SECURITY_TYPE_MIXED) 77 78 79 def navigate_to_page(self, page_number): 80 """Navigates to the page corresponding to the given page number. 81 82 This method performs the translation between a page number and a url 83 to load. This is used internally by apply_setting. 84 85 @param page_number: page number of the page to load. 86 """ 87 self.get_url(self.admin_interface_url) 88 self._ap_login() 89 xpath = '//div[@id="subMenu"]//div[@id="option_str1"]' 90 self.click_button_by_xpath(xpath) 91 ssid_xpath = '//table[@id="WLgeneral"]//input[@id="wl_ssid"]' 92 self.wait_for_object_by_xpath(ssid_xpath) 93 94 95 def _ap_login(self): 96 """Login as admin to configure settings.""" 97 username = '//input[@id="login_username"]' 98 self.set_content_of_text_field_by_xpath('admin', username, 99 abort_check=True) 100 password = '//div[@class="password_gap"]//input[@name="login_passwd"]' 101 self.set_content_of_text_field_by_xpath('password', password, 102 abort_check=True) 103 self.click_button_by_xpath('//div[@class="button"]') 104 105 106 def _is_alert_present(self, xpath): 107 """Handle alerts if there is an alert on Save.""" 108 try: 109 self.driver.find_element_by_xpath(xpath) 110 return 111 except UnexpectedAlertPresentException: 112 alert = self.driver.switch_to_alert() 113 self._alert_handler(alert) 114 115 116 def save_page(self, page_number): 117 """Saves the given page. 118 119 @param page_number: Page number of the page to be saved. 120 """ 121 apply = '//div[@class="apply_gen"]//input[@id="applyButton"]' 122 self.click_button_by_xpath(apply) 123 self._is_alert_present(apply) 124 self.wait_for_object_by_xpath(apply) 125 126 127 def set_mode(self, mode, band=None): 128 """Sets the network mode. 129 130 @param mode: must be one of the modes listed in __init__(). 131 @param band: the band to select. 132 """ 133 self.add_item_to_command_list(self._set_mode, (mode, band), 1, 800) 134 135 136 def _set_mode(self, mode, band=None): 137 """Sets the network mode. 138 139 @param mode: must be one of the modes listed in __init__(). 140 @param band: the band to select. 141 """ 142 modes_2GHZ = {ap_spec.MODE_N:'N only'} 143 modes_5GHZ = {ap_spec.MODE_N:'N only', 144 ap_spec.MODE_N|ap_spec.MODE_AC:'N/AC mixed'} 145 modes = {ap_spec.BAND_2GHZ: modes_2GHZ, 146 ap_spec.BAND_5GHZ: modes_5GHZ} 147 mode_selected = modes.get(self.current_band).get(mode) 148 if not mode_selected: 149 raise RunTimeError('Mode %s with Band %s is not supported' 150 % (mode,band)) 151 self.driver.switch_to_default_content() 152 xpath = '//select[@name="wl_nmode_x"]' 153 self.wait_for_object_by_xpath(xpath) 154 self.select_item_from_popup_by_xpath(mode_selected, xpath) 155 156 157 def set_radio(self, enabled=True): 158 """Turns the radio on and off. 159 160 @param enabled: True to turn on the radio; False otherwise. 161 """ 162 self.add_item_to_command_list(self._set_radio, (enabled,), 1, 700) 163 164 165 def _set_radio(self, enabled=True): 166 """Turns the radio on and off. 167 168 @param enabled: True to turn on the radio; False otherwise. 169 """ 170 xpath = '//div[@id="tabMenu"]/table/tbody/tr/td[6]/div/span' 171 self.wait_for_object_by_xpath(xpath) 172 self.click_button_by_xpath(xpath) 173 174 if enabled: 175 xpath = '//input[@name="wl_radio" and @value="1"]' 176 else: 177 xpath = '//input[@name="wl_radio" and @value="0"]' 178 self.click_button_by_xpath(xpath) 179 180 xpath = '//div[@class="apply_gen"]//input[@class="button_gen"]' 181 self.click_button_by_xpath(xpath) 182 183 self.set_wait_time(30) 184 self.wait.until(lambda _: 185 self.wait_for_object_by_xpath(xpath).is_displayed()) 186 self.restore_default_wait_time() 187 188 xpath = '//div[@id="tabMenu"]/table/tbody/tr/td[1]/div/span/table/\ 189 tbody/tr/td' 190 self.click_button_by_xpath(xpath) 191 192 193 def set_ssid(self, ssid): 194 """Sets the SSID of the wireless network. 195 196 @param ssid: name of the wireless network. 197 """ 198 self.add_item_to_command_list(self._set_ssid, (ssid,), 1, 900) 199 200 201 def _set_ssid(self, ssid): 202 """Sets the SSID of the wireless network. 203 204 @param ssid: name of the wireless network. 205 """ 206 xpath = '//input[@id="wl_ssid"]' 207 self.set_content_of_text_field_by_xpath(ssid, xpath) 208 self._ssid = ssid 209 210 211 def set_channel(self, channel): 212 """Sets the channel of the wireless network. 213 214 @param channel: Integer value of the channel. 215 """ 216 self.add_item_to_command_list(self._set_channel, (channel,), 1, 900) 217 218 219 def _set_channel(self, channel): 220 """Sets the channel of the wireless network. 221 222 @param channel: Integer value of the channel. 223 """ 224 xpath = '//select[@name="wl_channel"]' 225 self.select_item_from_popup_by_xpath(str(channel), xpath) 226 227 228 def set_channel_width(self, channel_width): 229 """Adjusts the channel width. 230 231 @param width: the channel width. 232 """ 233 self.add_item_to_command_list(self._set_channel_width, 234 (channel_width,), 1, 900) 235 236 237 def _set_channel_width(self, channel_width): 238 """Adjusts the channel width. 239 240 @param width: the channel width. 241 """ 242 channel_width_choice = {20:'20 MHz'} 243 xpath = '//tr[@id="wl_bw_field"]//select[@name="wl_bw"]' 244 self.select_item_from_popup_by_xpath( 245 channel_width_choice.get(channel_width), xpath) 246 247 248 def set_band(self, band): 249 """Sets the band of the wireless network. 250 251 @param band: Constant describing band type. 252 """ 253 if band == ap_spec.BAND_5GHZ: 254 self.current_band = ap_spec.BAND_5GHZ 255 elif band == ap_spec.BAND_2GHZ: 256 self.current_band = ap_spec.BAND_2GHZ 257 else: 258 raise RuntimeError('Invalid band sent %s' % band) 259 self.add_item_to_command_list(self._set_band, (), 1, 700) 260 261 262 def _set_band(self): 263 """Sets the band of the wireless network.""" 264 xpath = '//tr[@id="wl_unit_field"]//select[@name="wl_unit"]' 265 if self.current_band == ap_spec.BAND_5GHZ: 266 selected_band = '5GHz' 267 else: 268 selected_band = '2.4GHz' 269 self.select_item_from_popup_by_xpath(selected_band, xpath) 270 271 272 def set_security_disabled(self): 273 """Disables the security of the wireless network.""" 274 self.add_item_to_command_list(self._set_security_disabled, (), 1, 900) 275 276 277 def _set_security_disabled(self): 278 """Disables the security of the wireless network.""" 279 xpath = ' //select[@name="wl_auth_mode_x"]' 280 self.select_item_from_popup_by_xpath('Open System', xpath) 281 282 283 def set_security_wep(self, key_value, authentication): 284 """Enables WEP security for the wireless network. 285 286 @param key_value: encryption key to use. 287 @param authentication: Open or Shared authentication types. 288 """ 289 logging.debug('WEP mode is not supported.') 290 291 292 def set_security_wpapsk(self, security, shared_key, update_interval=None): 293 """Enables WPA2-Personal security type for the wireless network. 294 295 @param security: security type to configure. 296 @param shared_key: shared encryption key to use. 297 @param updat_interval: number of seconds to wait before updating. 298 """ 299 self.add_item_to_command_list(self._set_security_wpapsk, 300 (security, shared_key, update_interval), 301 1, 900) 302 303 304 def _set_security_wpapsk(self, security, shared_key, update_interval=None): 305 """Enables WPA2-Personal and WPA-Auto-Personal(mixed mode) security type 306 for the wireless network. 307 308 @param security: security type to configure. 309 @param shared_key: shared encryption key to use. 310 @param update_interval: number of seconds to wait before updating. 311 """ 312 xpath = '//select[@name="wl_auth_mode_x"]' 313 passphrase = '//input[@name="wl_wpa_psk" and @class="input_32_table"]' 314 315 if security == ap_spec.SECURITY_TYPE_WPA2PSK: 316 popup_value = 'WPA2-Personal' 317 elif security == ap_spec.SECURITY_TYPE_MIXED: 318 popup_value = 'WPA-Auto-Personal' 319 else: 320 raise RunTimeError('Invalid Security Mode %s passed' % security) 321 322 self.select_item_from_popup_by_xpath(popup_value, xpath) 323 self.set_content_of_text_field_by_xpath(shared_key, passphrase, 324 abort_check=True) 325 326 327 def set_visibility(self, visible=True): 328 """Sets the SSID broadcast ON 329 330 @param visible: True to enable SSID broadcast. False otherwise. 331 """ 332 self.add_item_to_command_list(self._set_visibility, (visible,), 1, 900) 333 334 335 def _set_visibility(self, visible=True): 336 """Sets the SSID broadcast ON 337 338 @param visible: True to enable SSID broadcast. False otherwise. 339 """ 340 if visible == True: 341 xpath = '//input[@name="wl_closed" and @value="0"]' 342 else: 343 xpath = '//input[@name="wl_closed" and @value="1"]' 344 self.click_button_by_xpath(xpath) 345