Home | History | Annotate | Download | only in ap_configurators
      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 F9K router."""
      6 
      7 import logging
      8 import urlparse
      9 import time
     10 import dynamic_ap_configurator
     11 import ap_spec
     12 from selenium.webdriver.common.keys import Keys
     13 from selenium.common.exceptions import WebDriverException
     14 from selenium.common.exceptions import TimeoutException as \
     15     SeleniumTimeoutException
     16 
     17 
     18 class BelkinF9KAPConfigurator(
     19         dynamic_ap_configurator.DynamicAPConfigurator):
     20     """Class to configure Blekin f9k1002v4 router."""
     21 
     22 
     23     def __init__(self, ap_config):
     24         super(BelkinF9KAPConfigurator, self).__init__(ap_config)
     25         self._dhcp_delay = 30
     26 
     27 
     28     security_popup = '//select[@name="security_type"]'
     29 
     30     def _security_alert(self, alert):
     31         text = alert.text
     32         if 'Invalid character' in text:
     33             alert.accept()
     34         elif 'It is recommended to use WPA/WPA2 when WPS is enabled' in text:
     35             alert.accept()
     36         elif 'After changing to 11g mode' in text:
     37             alert.accept()
     38         elif 'After changing to 11b&g&n or 11n mode' in text:
     39             alert.accept()
     40         else:
     41             alert.accept()
     42             raise RuntimeError('Unhandeled modal dialog. %s' % text)
     43 
     44 
     45     def open_new_tab(self):
     46          """Re-Opens tab on the browser"""
     47          body = self.driver.find_element_by_tag_name("body")
     48          body.send_keys(Keys.CONTROL + 't')
     49 
     50 
     51     def _login(self):
     52         """Opens the login page and logs in using the password.
     53            We need to login before doing any other change to make sure that
     54            we have access to the router."""
     55         page_url = urlparse.urljoin(self.admin_interface_url,'login.stm')
     56         xpath = '//input[@name="pws"]'
     57         try:
     58             self.open_new_tab()
     59             self.get_url(page_url, page_title='login.stm')
     60             self.wait_for_object_by_xpath(xpath, wait_time=10)
     61         except WebDriverException as e:
     62             logging.info("Page did not load or %s", str(e))
     63             self.driver.refresh()
     64         self.wait_for_object_by_xpath(xpath, wait_time=10)
     65         self.set_content_of_text_field_by_xpath('password', xpath,
     66                                                 abort_check=True)
     67         self.click_button_by_xpath('//input[@value="Submit"]',
     68                                    alert_handler=self._security_alert)
     69 
     70 
     71     def get_supported_bands(self):
     72         return [{'band': ap_spec.BAND_2GHZ,
     73                  'channels': ['Auto', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]}]
     74 
     75 
     76     def get_supported_modes(self):
     77         return [{'band': ap_spec.BAND_2GHZ,
     78                  'modes': [ap_spec.MODE_G, ap_spec.MODE_N,
     79                            ap_spec.MODE_B | ap_spec.MODE_G | ap_spec.MODE_N]}]
     80 
     81 
     82     def get_number_of_pages(self):
     83         return 2
     84 
     85 
     86     def is_security_mode_supported(self, security_mode):
     87         """
     88         Returns if a given security_type is supported.
     89 
     90         @param security_mode: one security modes defined in the APSpec
     91 
     92         @return True if the security mode is supported; False otherwise.
     93 
     94         """
     95         return security_mode in (ap_spec.SECURITY_TYPE_DISABLED,
     96                                  ap_spec.SECURITY_TYPE_WPAPSK,
     97                                  ap_spec.SECURITY_TYPE_WPA2PSK,
     98                                  ap_spec.SECURITY_TYPE_WEP)
     99 
    100 
    101     def navigate_to_page(self, page_number):
    102         """
    103         Navigates to the page corresponding to the given page number.
    104 
    105         This method performs the translation between a page number and a url to
    106         load. This is used internally by apply_settings.
    107 
    108         @param page_number: page number of the page to load
    109 
    110         """
    111         self._login()
    112         if page_number == 1:
    113             page_url = urlparse.urljoin(self.admin_interface_url,
    114                                         'wireless_id.stm')
    115             self.get_url(page_url, page_title='wireless_id')
    116             self.wait_for_object_by_xpath('//input[@name="ssid"]')
    117         elif page_number == 2:
    118             page_url = urlparse.urljoin(self.admin_interface_url,
    119                                         'wireless_e.stm')
    120             try:
    121                 self.get_url(page_url, page_title='wireless')
    122                 self.wait_for_object_by_xpath(self.security_popup)
    123             except (WebDriverException, SeleniumTimeoutException), e:
    124                 message = str(e)
    125                 if 'Timed out receiving message from renderer' in message:
    126                     self.driver.refresh()
    127                     self.wait_for_object_by_xpath(self.security_popup)
    128                 elif (any(alert in message for alert in
    129                     ['unexpected alert open', 'An open modal dialog blocked'])):
    130                     self._security_alert(self.driver.switch_to_alert())
    131                 else:
    132                     raise RuntimeError(message)
    133         else:
    134             raise RuntimeError('Invalid page number passed. Number of pages '
    135                                '%d, page value sent was %d' %
    136                                (self.get_number_of_pages(), page_number))
    137 
    138 
    139     def save_page(self, page_number):
    140         """Save changes and logout from the router.
    141 
    142         @param page_number: the page number to save as an integer.
    143 
    144         """
    145         self.click_button_by_xpath('//input[@type="submit" and '
    146                                    '@value="Apply Changes"]',
    147                                    alert_handler=self._security_alert)
    148         try:
    149             self.wait_for_object_by_xpath_to_vanish('//input[@name= \
    150                                                     "timeRemain]"',wait_time=30)
    151             self.wait.until(lambda _:'setup.htm' in self.driver.title)
    152         except WebDriverException, e:
    153             logging.info("Driver title page did not load or %s", str(e))
    154             self.open_new_tab()
    155         finally:
    156             self.restore_default_wait_time()
    157 
    158 
    159     def set_ssid(self, ssid):
    160         self.add_item_to_command_list(self._set_ssid, (ssid,), 1, 900)
    161 
    162 
    163     def _set_ssid(self, ssid):
    164         xpath = '//input[@name="ssid"]'
    165         self.set_content_of_text_field_by_xpath(ssid, xpath, abort_check=True)
    166         self._ssid = ssid
    167 
    168 
    169     def set_channel(self, channel):
    170         self.add_item_to_command_list(self._set_channel, (channel,), 1, 900)
    171 
    172 
    173     def _set_channel(self, channel):
    174         position = self._get_channel_popup_position(channel)
    175         channel_choices = ['Auto', '1', '2', '3', '4', '5', '6', '7', '8',
    176                            '9', '10', '11']
    177         xpath = '//select[@name="wchan"]'
    178         self.select_item_from_popup_by_xpath(channel_choices[position], xpath)
    179 
    180 
    181     def set_mode(self, mode):
    182         self.add_item_to_command_list(self._set_mode, (mode,), 1, 900)
    183 
    184 
    185     def _set_mode(self, mode):
    186         mode_mapping = {ap_spec.MODE_G: '802.11g',
    187                         ap_spec.MODE_N: '802.11n',
    188                         ap_spec.MODE_B | ap_spec.MODE_G | ap_spec.MODE_N:
    189                         '802.11b&802.11g&802.11n'}
    190         mode_name = mode_mapping.get(mode)
    191         if not mode_name:
    192             raise RuntimeError('The mode %d not supported by router %s. ',
    193                                hex(mode), self.name)
    194         xpath = '//select[@name="wbr"]'
    195         self.wait_for_object_by_xpath(xpath)
    196         while self.number_of_items_in_popup_by_xpath(xpath) < 3:
    197             time.sleep(0.25)
    198         self.select_item_from_popup_by_xpath(mode_name, xpath,
    199                                              wait_for_xpath=None,
    200                                              alert_handler=self._security_alert)
    201 
    202 
    203     def set_ch_width(self, channel_width):
    204         """
    205         Adjusts the channel width.
    206 
    207         @param channel_width: the channel width
    208         """
    209         self.add_item_to_command_list(self._set_ch_width,(channel_width,),
    210                                       1, 900)
    211 
    212 
    213     def _set_ch_width(self, channel_width):
    214         channel_choice = ['20MHz', '20/40MHz']
    215         xpath = '//select[@name="bandwidth"]'
    216         self.select_item_from_popup_by_xpath(channel_choice[channel_width],
    217                                              xpath)
    218 
    219 
    220     def set_radio(self, enabled=True):
    221         logging.debug('This router (%s) does not support radio', self.name)
    222         return None
    223 
    224 
    225     def set_band(self, band):
    226         logging.debug('This router %s does not support multiple bands.',
    227                       self.name)
    228         return None
    229 
    230 
    231     def set_security_disabled(self):
    232         self.add_item_to_command_list(self._set_security_disabled, (), 2, 1000)
    233 
    234 
    235     def _set_security_disabled(self):
    236         self.select_item_from_popup_by_xpath('Disabled',
    237                                              self.security_popup,
    238                                              alert_handler=self._security_alert)
    239 
    240 
    241     def set_security_wep(self, key_value, authentication):
    242         self.add_item_to_command_list(self._set_security_wep,
    243                                       (key_value, authentication), 2, 1000)
    244 
    245 
    246     def _set_security_wep(self, key_value, authentication):
    247         text_field = '//input[@name="passphrase"]'
    248         try:
    249             self.select_item_from_popup_by_xpath('64bit WEP',
    250                     self.security_popup, wait_for_xpath=text_field,
    251                     alert_handler=self._security_alert)
    252         except WebDriverException, e:
    253             message = str(e)
    254             if message.find('An open modal dialog blocked') == -1:
    255                raise RuntimeError(message)
    256                return
    257             self._security_alert(self.driver.switch_to_alert())
    258         self.set_content_of_text_field_by_xpath(key_value, text_field,
    259                                                 abort_check=True)
    260         self.click_button_by_xpath('//input[@class="submitBtn" and '
    261                                    '@value="Generate"]',
    262                                    alert_handler=self._security_alert)
    263 
    264 
    265     def set_security_wpapsk(self, security, shared_key, update_interval=None):
    266         self.add_item_to_command_list(self._set_security_wpapsk,
    267                                       (security, shared_key, update_interval),
    268                                        2, 900)
    269 
    270 
    271     def _set_security_wpapsk(self, security, shared_key, update_interval=None):
    272         key_field = '//input[@name="wpa_key_pass"]'
    273         psk = '//select[@name="authentication"]'
    274         self.select_item_from_popup_by_xpath('WPA/WPA2-Personal (PSK)',
    275                                              self.security_popup,
    276                                              wait_for_xpath=key_field,
    277                                              alert_handler=self._security_alert)
    278         auth_type = 'WPA-PSK'
    279         if security == ap_spec.SECURITY_TYPE_WPA2PSK:
    280             auth_type = 'WPA2-PSK'
    281         self.select_item_from_popup_by_xpath(auth_type, psk,
    282                                              wait_for_xpath=key_field,
    283                                              alert_handler=self._security_alert)
    284         self.set_content_of_text_field_by_xpath(shared_key, key_field,
    285                                                 abort_check=True)
    286 
    287 
    288     def is_visibility_supported(self):
    289         """
    290         Returns if AP supports setting the visibility (SSID broadcast).
    291 
    292         @return True if supported; False otherwise.
    293         """
    294         return False
    295 
    296 
    297     def is_update_interval_supported(self):
    298         """
    299         Returns True if setting the PSK refresh interval is supported.
    300 
    301         @return True is supported; False otherwise
    302         """
    303         return False
    304