Home | History | Annotate | Download | only in ap_lab
      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 import copy
      6 import logging
      7 import os
      8 
      9 import pyauto_ap_configurator
     10 import pyauto
     11 
     12 import selenium.common.exceptions
     13 from selenium.webdriver.support.ui import WebDriverWait
     14 
     15 
     16 class APConfigurator(object):
     17   """Base class for objects to configure access points using webdriver."""
     18 
     19   def __init__(self, pyauto_instance):
     20     self.pyauto_instance = pyauto_instance
     21     self._driver = pyauto_instance.NewWebDriver()
     22     # Any call to wait.until() will raise an exception if the timeout is hit.
     23     self._wait = WebDriverWait(self._driver, timeout=5)
     24 
     25     # Possible bands
     26     self.band_2ghz = '2.4GHz'
     27     self.band_5ghz = '5GHz'
     28 
     29     # Possible modes
     30     self.mode_a = 0x0001
     31     self.mode_b = 0x0010
     32     self.mode_g = 0x0100
     33     self.mode_n = 0x1000
     34 
     35     # Possible security settings
     36     self.security_disabled = 'Disabled'
     37     self.security_wep = 'WEP'
     38     self.security_wpawpsk = 'WPA-Personal'
     39     self.security_wpa2wpsk = 'WPA2-Personal'
     40     self.security_wpa8021x = 'WPA-Enterprise'
     41     self.security_wpa28021x = 'WPA2-Enterprise'
     42 
     43     self.wep_authentication_open = 'Open'
     44     self.wep_authentication_shared = 'Shared Key'
     45 
     46     self._command_list = []
     47 
     48   def _WaitForObjectByXPath(self, xpath):
     49     """Waits for an object to appear."""
     50     try:
     51       self._wait.until(lambda _: self._driver.find_element_by_xpath(xpath))
     52     except selenium.common.exceptions.TimeoutException, e:
     53       logging.exception('Unable to find the wait for object by xpath: %s\n'
     54                         'WebDriver exception: %s', xpath, str(e))
     55 
     56   def SelectItemFromPopupByID(self, item, element_id, wait_for_xpath=None):
     57     """Selects an item from a popup, by passing the element ID.
     58 
     59     Args:
     60       item: the item to select from the popup
     61       element_id: the html ID of the item
     62       wait_for_xpath: an item to wait for before returning
     63     """
     64     xpath = 'id("%s")' % element_id
     65     self.SelectItemFromPopupByXPath(item, xpath, wait_for_xpath)
     66 
     67   def SelectItemFromPopupByXPath(self, item, xpath, wait_for_xpath=None):
     68     """Selects an item from a popup, by passing the xpath of the popup.
     69 
     70     Args:
     71       item: the item to select from the popup
     72       xpath: the xpath of the popup
     73       wait_for_xpath: an item to wait for before returning
     74     """
     75     popup = self._driver.find_element_by_xpath(xpath)
     76     for option in popup.find_elements_by_tag_name('option'):
     77       if option.text == item:
     78         option.click()
     79         break
     80     if wait_for_xpath: self._WaitForObjectByXPath(wait_for_xpath)
     81 
     82   def SetContentOfTextFieldByID(self, content, text_field_id,
     83                                 wait_for_xpath=None):
     84     """Sets the content of a textfield, by passing the element ID.
     85 
     86     Args:
     87       content: the content to apply to the textfield
     88       text_field_id: the html ID of the textfield
     89       wait_for_xpath: an item to wait for before returning
     90     """
     91     xpath = 'id("%s")' % text_field_id
     92     self.SetConentsOfTextFieldByXPath(content, xpath, wait_for_xpath)
     93 
     94   def SetConentsOfTextFieldByXPath(self, content, xpath, wait_for_xpath=None):
     95     """Sets the content of a textfield, by passing the xpath.
     96 
     97     Args:
     98       content: the content to apply to the textfield
     99       xpath: the xpath of the textfield
    100       wait_for_xpath: an item to wait for before returning
    101     """
    102      # When we can get the value we know the text field is ready.
    103     text_field = self._driver.find_element_by_xpath(xpath)
    104     try:
    105       self._wait.until(lambda _: text_field.get_attribute('value'))
    106     except selenium.common.exceptions.TimeoutException, e:
    107       logging.exception('Unable to obtain the value of the text field %s.\n'
    108                         'WebDriver exception: %s', wait_for_xpath, str(e))
    109     text_field = self._driver.find_element_by_xpath(xpath)
    110     text_field.clear()
    111     text_field.send_keys(content)
    112     if wait_for_xpath: self._WaitForObjectByXPath(wait_for_xpath)
    113 
    114   def SetCheckBoxSelectedByID(self, check_box_id, selected=True,
    115                               wait_for_xpath=None):
    116     """Sets the state of a checkbox, by passing the ID.
    117 
    118     Args:
    119       check_box_id: the html id of the checkbox
    120       selected: True to enable the checkbox; False otherwise
    121       wait_for_xpath: an item to wait for before returning
    122     """
    123     xpath = 'id("%s")' % check_box_id
    124     self.SetCheckBoxSelectedByXPath(xpath, selected, wait_for_xpath)
    125 
    126   def SetCheckBoxSelectedByXPath(self, xpath, selected=True,
    127                                  wait_for_xpath=None):
    128     """Sets the state of a checkbox, by passing the xpath.
    129 
    130     Args:
    131       xpath: the xpath of the checkbox
    132       selected: True to enable the checkbox; False otherwise
    133       wait_for_xpath: an item to wait for before returning
    134     """
    135     check_box = self._driver.find_element_by_xpath(xpath)
    136     value = check_box.get_attribute('value')
    137     if (value == '1' and not selected) or (value == '0' and selected):
    138       check_box.click()
    139     if wait_for_xpath: self._WaitForObjectByXPath(wait_for_xpath)
    140 
    141   def AddItemToCommandList(self, method, args, page, priority):
    142     """Adds commands to be executed against the AP web UI.
    143 
    144     Args:
    145       method: the method to run
    146       args: the arguments for the method you want executed
    147       page: the page on the web ui where the method should be run against
    148       priority: the priority of the method
    149     """
    150     self._command_list.append({'method': method,
    151                                'args': copy.copy(args),
    152                                'page': page,
    153                                'priority': priority})
    154 
    155   def GetRouterName(self):
    156     """Returns a string to describe the router.
    157 
    158     Note: The derived class must implement this method.
    159     """
    160     raise NotImplementedError
    161 
    162   def GetRouterShortName(self):
    163     """Returns a short string to describe the router.
    164 
    165     Note: The derived class must implement this method.
    166     """
    167     raise NotImplementedError
    168 
    169   def GetNumberOfPages(self):
    170     """Returns the number of web pages used to configure the router.
    171 
    172     Note: This is used internally by applySettings, and this method must be
    173           implemented by the derived class.
    174     """
    175     raise NotImplementedError
    176 
    177   def GetSupportedBands(self):
    178     """Returns a list of dictionaries describing the supported bands.
    179 
    180     Example: returned is a dictionary of band and a list of channels.  The band
    181              object returned must be one of those defined in the __init___ of
    182              this class.
    183 
    184     supported_bands = [{'band' : self.band_2GHz,
    185                         'channels' : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]},
    186                        {'band' : self.band_5ghz,
    187                         'channels' : [26, 40, 44, 48, 149, 153, 157, 161, 165]}]
    188 
    189     Returns:
    190       A list of dictionaries as described above
    191 
    192     Note: The derived class must implement this method.
    193     """
    194     raise NotImplementedError
    195 
    196   def GetSupportedModes(self):
    197     """Returns a list of dictionaries describing the supported modes.
    198 
    199     Example: returned is a dictionary of band and a list of modess.  The band
    200              and modes objects returned must be one of those defined in the
    201              __init___ of this class.
    202 
    203     supported_modes = [{'band' : self.band_2GHz,
    204                         'modes' : [mode_b, mode_b | mode_g]},
    205                        {'band' : self.band_5ghz,
    206                         'modes' : [mode_a, mode_n, mode_a | mode_n]}]
    207 
    208     Returns:
    209       A list of dictionaries as described above
    210 
    211     Note: The derived class must implement this method.
    212     """
    213     raise NotImplementedError
    214 
    215   def NavigateToPage(self, page_number):
    216     """Navigates to the page corresponding to the given page number.
    217 
    218     This method performs the translation between a page number and a url to
    219     load.  This is used internally by applySettings.
    220 
    221     Args:
    222       page_number: Page number of the page to load
    223 
    224     Returns:
    225       True if navigation is successful; False otherwise.
    226 
    227     Note: The derived class must implement this method.
    228     """
    229     raise NotImplementedError
    230 
    231   def SavePage(self, page_number):
    232     """Saves the given page.
    233 
    234     Args:
    235       page_number: Page number of the page to save.
    236 
    237     Returns:
    238       True if navigation is successful; False otherwise.
    239 
    240     Note: The derived class must implement this method.
    241     """
    242     raise NotImplementedError
    243 
    244   def SetMode(self, mode, band=None):
    245     """Sets the mode.
    246 
    247     Args:
    248       mode: must be one of the modes listed in __init__()
    249       band: the band to select
    250 
    251     Note: The derived class must implement this method
    252     """
    253     raise NotImplementedError
    254 
    255   def SetRadio(self, enabled=True):
    256     """Turns the radio on and off.
    257 
    258     Args:
    259       enabled: True to turn on the radio; False otherwise
    260 
    261     Note: The derived class must implement this method.
    262     """
    263     raise NotImplementedError
    264 
    265   def SetSSID(self, ssid):
    266     """Sets the SSID of the wireless network.
    267 
    268     Args:
    269       ssid: Name of the wireless network
    270 
    271     Note: The derived class must implement this method.
    272     """
    273     raise NotImplementedError
    274 
    275   def SetChannel(self, channel):
    276     """Sets the channel of the wireless network.
    277 
    278     Args:
    279       channel: Integer value of the channel
    280 
    281     Note: The derived class must implement this method.
    282     """
    283     raise NotImplementedError
    284 
    285   def SetBand(self, band):
    286     """Sets the band of the wireless network.
    287 
    288     Currently there are only two possible values for band 2kGHz and 5kGHz.
    289 
    290     Args:
    291       band: Constant describing the band type
    292 
    293     Note: The derived class must implement this method.
    294     """
    295     raise NotImplementedError
    296 
    297   def SetSecurityDisabled(self):
    298     """Disables the security of the wireless network.
    299 
    300     Note: The derived class must implement this method.
    301     """
    302     raise NotImplementedError
    303 
    304   def SetSecurityWEP(self, key_value, authentication):
    305     """Enabled WEP security for the wireless network.
    306 
    307     Args:
    308       key_value: encryption key to use
    309       authentication: one of two supported authentication types:
    310                       wep_authentication_open or wep_authentication_shared
    311 
    312     Note: The derived class must implement this method.
    313     """
    314     raise NotImplementedError
    315 
    316   def SetSecurityWPAPSK(self, shared_key, update_interval=1800):
    317     """Enabled WPA using a private security key for the wireless network.
    318 
    319     Args:
    320       shared_key: shared encryption key to use
    321       update_interval: number of seconds to wait before updating
    322 
    323     Note: The derived class must implement this method.
    324     """
    325     raise NotImplementedError
    326 
    327   def SetVisibility(self, visible=True):
    328     """Set the visibility of the wireless network.
    329 
    330     Args:
    331       visible: True for visible; False otherwise
    332 
    333     Note: The derived class must implement this method.
    334     """
    335     raise NotImplementedError
    336 
    337   def ApplySettings(self):
    338     """Apply all settings to the access point."""
    339     # Pull items by page and then sort
    340     if self.GetNumberOfPages() == -1:
    341       self.fail(msg='Number of pages is not set.')
    342     page_range = range(1, self.GetNumberOfPages() + 1)
    343     for i in page_range:
    344       page_commands = []
    345       for command in self._command_list:
    346         if command['page'] == i:
    347           page_commands.append(command)
    348       # Sort the commands in this page by priority
    349       sorted_page_commands = sorted(page_commands, key=lambda k: k['priority'])
    350       if sorted_page_commands and self.NavigateToPage(i):
    351         for command in sorted_page_commands:
    352           command['method'](*command['args'])
    353         self.SavePage(i)
    354     self._command_list = []
    355 
    356