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.
9 import pyauto_ap_configurator
12 import selenium.common.exceptions
13 from selenium.webdriver.support.ui import WebDriverWait
16 class APConfigurator(object):
17 """Base class for objects to configure access points using webdriver."""
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)
26 self.band_2ghz = '2.4GHz'
27 self.band_5ghz = '5GHz'
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'
43 self.wep_authentication_open = 'Open'
44 self.wep_authentication_shared = 'Shared Key'
46 self._command_list = []
48 def _WaitForObjectByXPath(self, xpath):
49 """Waits for an object to appear."""
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))
56 def SelectItemFromPopupByID(self, item, element_id, wait_for_xpath=None):
57 """Selects an item from a popup, by passing the element ID.
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
64 xpath = 'id("%s")' % element_id
65 self.SelectItemFromPopupByXPath(item, xpath, wait_for_xpath)
67 def SelectItemFromPopupByXPath(self, item, xpath, wait_for_xpath=None):
68 """Selects an item from a popup, by passing the xpath of the popup.
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
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:
80 if wait_for_xpath: self._WaitForObjectByXPath(wait_for_xpath)
82 def SetContentOfTextFieldByID(self, content, text_field_id,
84 """Sets the content of a textfield, by passing the element ID.
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
91 xpath = 'id("%s")' % text_field_id
92 self.SetConentsOfTextFieldByXPath(content, xpath, wait_for_xpath)
94 def SetConentsOfTextFieldByXPath(self, content, xpath, wait_for_xpath=None):
95 """Sets the content of a textfield, by passing the xpath.
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
102 # When we can get the value we know the text field is ready.
103 text_field = self._driver.find_element_by_xpath(xpath)
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)
111 text_field.send_keys(content)
112 if wait_for_xpath: self._WaitForObjectByXPath(wait_for_xpath)
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.
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
123 xpath = 'id("%s")' % check_box_id
124 self.SetCheckBoxSelectedByXPath(xpath, selected, wait_for_xpath)
126 def SetCheckBoxSelectedByXPath(self, xpath, selected=True,
127 wait_for_xpath=None):
128 """Sets the state of a checkbox, by passing the xpath.
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
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):
139 if wait_for_xpath: self._WaitForObjectByXPath(wait_for_xpath)
141 def AddItemToCommandList(self, method, args, page, priority):
142 """Adds commands to be executed against the AP web UI.
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
150 self._command_list.append({'method': method,
151 'args': copy.copy(args),
153 'priority': priority})
155 def GetRouterName(self):
156 """Returns a string to describe the router.
158 Note: The derived class must implement this method.
160 raise NotImplementedError
162 def GetRouterShortName(self):
163 """Returns a short string to describe the router.
165 Note: The derived class must implement this method.
167 raise NotImplementedError
169 def GetNumberOfPages(self):
170 """Returns the number of web pages used to configure the router.
172 Note: This is used internally by applySettings, and this method must be
173 implemented by the derived class.
175 raise NotImplementedError
177 def GetSupportedBands(self):
178 """Returns a list of dictionaries describing the supported bands.
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
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]}]
190 A list of dictionaries as described above
192 Note: The derived class must implement this method.
194 raise NotImplementedError
196 def GetSupportedModes(self):
197 """Returns a list of dictionaries describing the supported modes.
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.
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]}]
209 A list of dictionaries as described above
211 Note: The derived class must implement this method.
213 raise NotImplementedError
215 def NavigateToPage(self, page_number):
216 """Navigates to the page corresponding to the given page number.
218 This method performs the translation between a page number and a url to
219 load. This is used internally by applySettings.
222 page_number: Page number of the page to load
225 True if navigation is successful; False otherwise.
227 Note: The derived class must implement this method.
229 raise NotImplementedError
231 def SavePage(self, page_number):
232 """Saves the given page.
235 page_number: Page number of the page to save.
238 True if navigation is successful; False otherwise.
240 Note: The derived class must implement this method.
242 raise NotImplementedError
244 def SetMode(self, mode, band=None):
248 mode: must be one of the modes listed in __init__()
249 band: the band to select
251 Note: The derived class must implement this method
253 raise NotImplementedError
255 def SetRadio(self, enabled=True):
256 """Turns the radio on and off.
259 enabled: True to turn on the radio; False otherwise
261 Note: The derived class must implement this method.
263 raise NotImplementedError
265 def SetSSID(self, ssid):
266 """Sets the SSID of the wireless network.
269 ssid: Name of the wireless network
271 Note: The derived class must implement this method.
273 raise NotImplementedError
275 def SetChannel(self, channel):
276 """Sets the channel of the wireless network.
279 channel: Integer value of the channel
281 Note: The derived class must implement this method.
283 raise NotImplementedError
285 def SetBand(self, band):
286 """Sets the band of the wireless network.
288 Currently there are only two possible values for band 2kGHz and 5kGHz.
291 band: Constant describing the band type
293 Note: The derived class must implement this method.
295 raise NotImplementedError
297 def SetSecurityDisabled(self):
298 """Disables the security of the wireless network.
300 Note: The derived class must implement this method.
302 raise NotImplementedError
304 def SetSecurityWEP(self, key_value, authentication):
305 """Enabled WEP security for the wireless network.
308 key_value: encryption key to use
309 authentication: one of two supported authentication types:
310 wep_authentication_open or wep_authentication_shared
312 Note: The derived class must implement this method.
314 raise NotImplementedError
316 def SetSecurityWPAPSK(self, shared_key, update_interval=1800):
317 """Enabled WPA using a private security key for the wireless network.
320 shared_key: shared encryption key to use
321 update_interval: number of seconds to wait before updating
323 Note: The derived class must implement this method.
325 raise NotImplementedError
327 def SetVisibility(self, visible=True):
328 """Set the visibility of the wireless network.
331 visible: True for visible; False otherwise
333 Note: The derived class must implement this method.
335 raise NotImplementedError
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)
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'])
354 self._command_list = []