OLD | NEW |
| (Empty) |
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 | |
OLD | NEW |