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 Belkin router.""" 6 7import logging 8import os 9import time 10import urlparse 11 12import dynamic_ap_configurator 13import ap_spec 14from selenium.common.exceptions import NoSuchElementException as \ 15 SeleniumNoSuchElementException 16 17 18class BelkinAPConfigurator( 19 dynamic_ap_configurator.DynamicAPConfigurator): 20 """Base class for Belkin F5D8235-4 V2 router.""" 21 22 23 def _security_alert(self, alert): 24 text = alert.text 25 if "Invalid character" in text: 26 alert.accept() 27 else: 28 raise RuntimeError('Unhandled alert: %s', text) 29 30 31 def _open_landing_page(self): 32 page_url = urlparse.urljoin(self.admin_interface_url,'home.htm') 33 self.get_url(page_url, page_title='Setup Home') 34 # Do we need to login? 35 try: 36 self.driver.find_element_by_link_text('Login') 37 except SeleniumNoSuchElementException: 38 # already logged in, return 39 return 40 login_element = self.driver.find_element_by_link_text('Login') 41 login_element.click() 42 xpath = '//input[@name="www_password"]' 43 self.set_content_of_text_field_by_xpath('password', xpath, 44 abort_check=True) 45 self.click_button_by_id('submitBtn_submit') 46 47 48 def get_supported_bands(self): 49 return [{'band': ap_spec.BAND_2GHZ, 50 'channels': ['Auto', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]}] 51 52 53 def get_supported_modes(self): 54 return [{'band': ap_spec.BAND_2GHZ, 55 'modes': [ap_spec.MODE_G | ap_spec.MODE_B, ap_spec.MODE_N, 56 ap_spec.MODE_B | ap_spec.MODE_G | ap_spec.MODE_N]}] 57 58 59 def get_number_of_pages(self): 60 return 2 61 62 63 def is_security_mode_supported(self, security_mode): 64 """ 65 Returns if a given security_type is supported. 66 67 @param security_mode: one security modes defined in the APSpec 68 69 @return True if the security mode is supported; False otherwise. 70 71 """ 72 return security_mode in (ap_spec.SECURITY_TYPE_DISABLED, 73 ap_spec.SECURITY_TYPE_WPAPSK, 74 ap_spec.SECURITY_TYPE_WEP) 75 76 77 def navigate_to_page(self, page_number): 78 """ 79 Navigates to the page corresponding to the given page number. 80 81 This method performs the translation between a page number and a url to 82 load. This is used internally by apply_settings. 83 84 @param page_number: page number of the page to load 85 86 """ 87 self._open_landing_page() 88 if page_number == 1: 89 page_url = urlparse.urljoin(self.admin_interface_url, 90 'wireless_chan.htm') 91 self.get_url(page_url, page_title='SSID') 92 elif page_number == 2: 93 page_url = urlparse.urljoin(self.admin_interface_url, 94 'wireless_encrypt_64.htm') 95 self.get_url(page_url, page_title='Security') 96 else: 97 raise RuntimeError('Invalid page number passed. Number of pages ' 98 '%d, page value sent was %d' % 99 (self.get_number_of_pages(), page_number)) 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 self.click_button_by_id('submitBtn_apply', 110 alert_handler=self._security_alert) 111 if os.path.basename(self.driver.current_url) == 'post.cgi': 112 # Give belkin some time to save settings. 113 time.sleep(5) 114 else: 115 raise RuntimeError('Settings not applied. Invalid page %s' % 116 os.path.basename(self.driver.current_url)) 117 if (os.path.basename(self.driver.current_url) == 'wireless_chan.htm' or 118 'wireless_encrypt_64.htm' or 'wireless_wpa_psk_wpa2_psk.htm' 119 or 'wireless_encrypt_no.htm'): 120 self.driver.find_element_by_xpath('//a[text()="Logout"]') 121 self.click_button_by_xpath('//a[text()="Logout"]') 122 123 124 def set_ssid(self, ssid): 125 self.add_item_to_command_list(self._set_ssid, (ssid,), 1, 900) 126 127 128 def _set_ssid(self, ssid): 129 # Belkin does not accept special characters for SSID. 130 # Invalid character: ~!@#$%^&*()={}[]|'\":;?/.,<>- 131 xpath = '//input[@name="wl_ssid"]' 132 self.set_content_of_text_field_by_xpath(ssid, xpath, abort_check=False) 133 self._ssid = ssid 134 135 136 def set_channel(self, channel): 137 self.add_item_to_command_list(self._set_channel, (channel,), 1, 900) 138 139 140 def _set_channel(self, channel): 141 position = self._get_channel_popup_position(channel) 142 channel_choices = ['Auto', '1', '2', '3', '4', '5', '6', '7', '8', 143 '9', '10', '11'] 144 xpath = '//select[@name="wl_channel"]' 145 self.select_item_from_popup_by_xpath(channel_choices[position], xpath) 146 147 148 def set_mode(self, mode): 149 self.add_item_to_command_list(self._set_mode, (mode,), 1, 900) 150 151 152 def _set_mode(self, mode): 153 mode_mapping = {ap_spec.MODE_G | ap_spec.MODE_B: '802.11g&802.11b', 154 ap_spec.MODE_N: '802.11n only', 155 ap_spec.MODE_B | ap_spec.MODE_G | ap_spec.MODE_N: 156 '802.11b&802.11g&802.11n'} 157 mode_name = mode_mapping.get(mode) 158 if not mode_name: 159 raise RuntimeError('The mode %d not supported by router %s. ', 160 hex(mode), self.name) 161 xpath = '//select[@name="wl_gmode"]' 162 self.select_item_from_popup_by_xpath(mode_name, xpath) 163 164 165 def set_ch_width(self, channel_width): 166 """ 167 Adjusts the channel width. 168 169 @param channel_width: the channel width 170 """ 171 self.add_item_to_command_list(self._set_ch_width,(channel_width,), 172 1, 900) 173 174 175 def _set_ch_width(self, channel_width): 176 channel_choice = ['20MHz', '20/40MHz'] 177 xpath = '//select[@name="wl_cwmmode"]' 178 self.select_item_from_popup_by_xpath(channel_choice[channel_width], 179 xpath) 180 181 182 def set_radio(self, enabled=True): 183 logging.debug('This router (%s) does not support radio', self.name) 184 return None 185 186 187 def set_band(self, band): 188 logging.debug('This router (%s) does not support multiple bands.', 189 self.name) 190 return None 191 192 193 def set_security_disabled(self): 194 self.add_item_to_command_list(self._set_security_disabled, (), 2, 1000) 195 196 197 def _set_security_disabled(self): 198 xpath = '//select[@name="wl_sec_mode"]' 199 self.select_item_from_popup_by_xpath('Disabled', xpath) 200 201 202 def set_security_wep(self, key_value, authentication): 203 self.add_item_to_command_list(self._set_security_wep, 204 (key_value, authentication), 2, 1000) 205 206 207 def _set_security_wep(self, key_value, authentication): 208 popup = '//select[@name="wl_sec_mode"]' 209 self.wait_for_object_by_xpath(popup) 210 text_field = '//input[@name="wep64pp"]' 211 self.select_item_from_popup_by_xpath('64bit WEP', popup, 212 wait_for_xpath=text_field) 213 self.set_content_of_text_field_by_xpath(key_value, text_field, 214 abort_check=True) 215 self.click_button_by_id('submitBtn_generate') 216 217 218 def set_security_wpapsk(self, security, shared_key, update_interval=None): 219 self.add_item_to_command_list(self._set_security_wpapsk, 220 (shared_key, update_interval), 2, 900) 221 222 223 def _set_security_wpapsk(self, security, shared_key, update_interval=None): 224 popup = '//select[@name="wl_sec_mode"]' 225 self.wait_for_object_by_xpath(popup) 226 key_field = '//input[@name="wl_wpa_psk1"]' 227 psk = '//select[@name="wl_auth"]' 228 self.select_item_from_popup_by_xpath('WPA-PSK(no server)', popup, 229 wait_for_xpath=key_field) 230 self.select_item_from_popup_by_xpath('psk', psk) 231 self.set_content_of_text_field_by_xpath(shared_key, key_field, 232 abort_check=False) 233 234 235 def is_visibility_supported(self): 236 """ 237 Returns if AP supports setting the visibility (SSID broadcast). 238 239 @return True if supported; False otherwise. 240 """ 241 return False 242 243 244 def is_update_interval_supported(self): 245 """ 246 Returns True if setting the PSK refresh interval is supported. 247 248 @return True is supported; False otherwise 249 """ 250 return False 251