OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """PyAuto: Python Interface to Chromium's Automation Proxy. | 6 """PyAuto: Python Interface to Chromium's Automation Proxy. |
7 | 7 |
8 PyAuto uses swig to expose Automation Proxy interfaces to Python. | 8 PyAuto uses swig to expose Automation Proxy interfaces to Python. |
9 For complete documentation on the functionality available, | 9 For complete documentation on the functionality available, |
10 run pydoc on this file. | 10 run pydoc on this file. |
(...skipping 3196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3207 """ | 3207 """ |
3208 def _IsExtensionViewClosed(): | 3208 def _IsExtensionViewClosed(): |
3209 extension_views = self.GetBrowserInfo()['extension_views'] | 3209 extension_views = self.GetBrowserInfo()['extension_views'] |
3210 for extension_view in extension_views: | 3210 for extension_view in extension_views: |
3211 if view == extension_view['view']: | 3211 if view == extension_view['view']: |
3212 return False | 3212 return False |
3213 return True | 3213 return True |
3214 | 3214 |
3215 return self.WaitUntil(lambda: _IsExtensionViewClosed()) | 3215 return self.WaitUntil(lambda: _IsExtensionViewClosed()) |
3216 | 3216 |
3217 def FillAutofillProfile(self, profiles=None, credit_cards=None, | |
3218 tab_index=0, window_index=0): | |
3219 """Set the autofill profile to contain the given profiles and credit cards. | |
3220 | |
3221 If profiles or credit_cards are specified, they will overwrite existing | |
3222 profiles and credit cards. To update profiles and credit cards, get the | |
3223 existing ones with the GetAutofillProfile function and then append new | |
3224 profiles to the list and call this function. | |
3225 | |
3226 Autofill profiles (not credit cards) support multiple values for some of the | |
3227 fields. To account for this, all values in a profile must be specified as | |
3228 a list of strings. If a form field only has a single value associated with | |
3229 it, that value must still be specified as a list containing a single string. | |
3230 | |
3231 Args: | |
3232 profiles: (optional) a list of dictionaries representing each profile to | |
3233 add. Example: | |
3234 [{ | |
3235 'NAME_FIRST': ['Bob',], | |
3236 'NAME_LAST': ['Smith',], | |
3237 'ADDRESS_HOME_ZIP': ['94043',], | |
3238 }, | |
3239 { | |
3240 'EMAIL_ADDRESS': ['sue@example.com',], | |
3241 'COMPANY_NAME': ['Company X',], | |
3242 }] | |
3243 | |
3244 Other possible keys are: | |
3245 'NAME_FIRST', 'NAME_MIDDLE', 'NAME_LAST', 'EMAIL_ADDRESS', | |
3246 'COMPANY_NAME', 'ADDRESS_HOME_LINE1', 'ADDRESS_HOME_LINE2', | |
3247 'ADDRESS_HOME_CITY', 'ADDRESS_HOME_STATE', 'ADDRESS_HOME_ZIP', | |
3248 'ADDRESS_HOME_COUNTRY', 'PHONE_HOME_WHOLE_NUMBER' | |
3249 | |
3250 credit_cards: (optional) a list of dictionaries representing each credit | |
3251 card to add. Example: | |
3252 [{ | |
3253 'CREDIT_CARD_NAME': 'Bob C. Smith', | |
3254 'CREDIT_CARD_NUMBER': '5555555555554444', | |
3255 'CREDIT_CARD_EXP_MONTH': '12', | |
3256 'CREDIT_CARD_EXP_4_DIGIT_YEAR': '2011' | |
3257 }, | |
3258 { | |
3259 'CREDIT_CARD_NAME': 'Bob C. Smith', | |
3260 'CREDIT_CARD_NUMBER': '4111111111111111', | |
3261 'CREDIT_CARD_TYPE': 'Visa' | |
3262 } | |
3263 | |
3264 Other possible keys are: | |
3265 'CREDIT_CARD_NAME', 'CREDIT_CARD_NUMBER', 'CREDIT_CARD_EXP_MONTH', | |
3266 'CREDIT_CARD_EXP_4_DIGIT_YEAR' | |
3267 | |
3268 All values must be strings. | |
3269 | |
3270 tab_index: tab index, defaults to 0. | |
3271 | |
3272 window_index: window index, defaults to 0. | |
3273 | |
3274 Raises: | |
3275 pyauto_errors.JSONInterfaceError if the automation call returns an error. | |
3276 """ | |
3277 cmd_dict = { # Prepare command for the json interface | |
3278 'command': 'FillAutofillProfile', | |
3279 'tab_index': tab_index, | |
3280 'profiles': profiles, | |
3281 'credit_cards': credit_cards | |
3282 } | |
3283 self._GetResultFromJSONRequest(cmd_dict, windex=window_index) | |
3284 | |
3285 def GetAutofillProfile(self, tab_index=0, window_index=0): | |
3286 """Returns all autofill profile and credit card information. | |
3287 | |
3288 The format of the returned dictionary is described above in | |
3289 FillAutofillProfile. The general format is: | |
3290 {'profiles': [list of profile dictionaries as described above], | |
3291 'credit_cards': [list of credit card dictionaries as described above]} | |
3292 | |
3293 Args: | |
3294 tab_index: tab index, defaults to 0. | |
3295 window_index: window index, defaults to 0. | |
3296 | |
3297 Raises: | |
3298 pyauto_errors.JSONInterfaceError if the automation call returns an error. | |
3299 """ | |
3300 cmd_dict = { # Prepare command for the json interface | |
3301 'command': 'GetAutofillProfile', | |
3302 'tab_index': tab_index | |
3303 } | |
3304 return self._GetResultFromJSONRequest(cmd_dict, windex=window_index) | |
3305 | |
3306 def SubmitAutofillForm(self, js, frame_xpath='', tab_index=0, windex=0): | |
3307 """Submits a webpage autofill form and waits for autofill to be updated. | |
3308 | |
3309 This function should be called when submitting autofill profiles via | |
3310 webpage forms. It waits until the autofill data has been updated internally | |
3311 before returning. | |
3312 | |
3313 Args: | |
3314 js: The string Javascript code that can be injected into the given webpage | |
3315 to submit an autofill form. This Javascript MUST submit the form. | |
3316 frame_xpath: The string xpath for the frame in which to inject javascript. | |
3317 tab_index: Integer index of the tab to work on; defaults to 0 (first tab). | |
3318 windex: Integer index of the browser window to use; defaults to 0 | |
3319 (first window). | |
3320 """ | |
3321 cmd_dict = { # Prepare command for the json interface. | |
3322 'command': 'SubmitAutofillForm', | |
3323 'javascript': js, | |
3324 'frame_xpath': frame_xpath, | |
3325 'tab_index': tab_index, | |
3326 } | |
3327 self._GetResultFromJSONRequest(cmd_dict, windex=windex) | |
3328 | |
3329 def AutofillTriggerSuggestions(self, field_id=None, tab_index=0, windex=0): | |
3330 """Focuses a webpage form field and triggers the autofill popup in it. | |
3331 | |
3332 This function focuses the specified input field in a webpage form, then | |
3333 causes the autofill popup to appear in that field. The underlying | |
3334 automation hook sends a "down arrow" keypress event to trigger the autofill | |
3335 popup. This function waits until the popup is displayed before returning. | |
3336 | |
3337 Args: | |
3338 field_id: The string ID of the webpage form field to focus. Can be | |
3339 'None' (the default), in which case nothing is focused. This | |
3340 can be useful if the field has already been focused by other | |
3341 means. | |
3342 tab_index: Integer index of the tab to work on; defaults to 0 (first tab). | |
3343 windex: Integer index of the browser window to work on; defaults to 0 | |
3344 (first window). | |
3345 | |
3346 Returns: | |
3347 True, if no errors were encountered, or False otherwise. | |
3348 | |
3349 Raises: | |
3350 pyauto_errors.JSONInterfaceError if the automation call returns an error. | |
3351 """ | |
3352 # Focus the field with the specified ID, if necessary. | |
3353 if field_id: | |
3354 if not self.JavascriptFocusElementById(field_id, tab_index, windex): | |
3355 return False | |
3356 | |
3357 # Cause the autofill popup to be shown in the focused form field. | |
3358 cmd_dict = { | |
3359 'command': 'AutofillTriggerSuggestions', | |
3360 'tab_index': tab_index, | |
3361 } | |
3362 self._GetResultFromJSONRequest(cmd_dict, windex=windex) | |
3363 return True | |
3364 | |
3365 def AutofillHighlightSuggestion(self, direction, tab_index=0, windex=0): | |
3366 """Highlights the previous or next suggestion in an existing autofill popup. | |
3367 | |
3368 This function assumes that an existing autofill popup is currently displayed | |
3369 in a webpage form. The underlying automation hook sends either a | |
3370 "down arrow" or an "up arrow" keypress event to cause the next or previous | |
3371 suggestion to be highlighted, respectively. This function waits until | |
3372 autofill displays a preview of the form's filled state before returning. | |
3373 | |
3374 Use AutofillTriggerSuggestions() to trigger the autofill popup before | |
3375 calling this function. Use AutofillAcceptSelection() after calling this | |
3376 function to accept a selection. | |
3377 | |
3378 Args: | |
3379 direction: The string direction in which to highlight an autofill | |
3380 suggestion. Must be either "up" or "down". | |
3381 tab_index: Integer index of the tab to work on; defaults to 0 (first tab). | |
3382 windex: Integer index of the browser window to work on; defaults to 0 | |
3383 (first window). | |
3384 | |
3385 Raises: | |
3386 pyauto_errors.JSONInterfaceError if the automation call returns an error. | |
3387 """ | |
3388 assert direction in ('up', 'down') | |
3389 cmd_dict = { | |
3390 'command': 'AutofillHighlightSuggestion', | |
3391 'direction': direction, | |
3392 'tab_index': tab_index, | |
3393 } | |
3394 self._GetResultFromJSONRequest(cmd_dict, windex=windex) | |
3395 | |
3396 def AutofillAcceptSelection(self, tab_index=0, windex=0): | |
3397 """Accepts the current selection in an already-displayed autofill popup. | |
3398 | |
3399 This function assumes that a profile is already highlighted in an existing | |
3400 autofill popup in a webpage form. The underlying automation hook sends a | |
3401 "return" keypress event to cause the highlighted profile to be accepted. | |
3402 This function waits for the webpage form to be filled in with autofill data | |
3403 before returning. This function does not submit the webpage form. | |
3404 | |
3405 Raises: | |
3406 pyauto_errors.JSONInterfaceError if the automation call returns an error. | |
3407 """ | |
3408 cmd_dict = { | |
3409 'command': 'AutofillAcceptSelection', | |
3410 'tab_index': tab_index, | |
3411 } | |
3412 self._GetResultFromJSONRequest(cmd_dict, windex=windex) | |
3413 | |
3414 def AutofillPopulateForm(self, field_id, profile_index=0, tab_index=0, | |
3415 windex=0): | |
3416 """Populates a webpage form using autofill data and keypress events. | |
3417 | |
3418 This function focuses the specified input field in the form, and then | |
3419 sends keypress events to the associated tab to cause the form to be | |
3420 populated with information from the requested autofill profile. | |
3421 | |
3422 Args: | |
3423 field_id: The string ID of the webpage form field to focus for autofill | |
3424 purposes. | |
3425 profile_index: The index of the profile in the autofill popup to use to | |
3426 populate the form; defaults to 0 (first profile). | |
3427 tab_index: Integer index of the tab to work on; defaults to 0 (first tab). | |
3428 windex: Integer index of the browser window to work on; defaults to 0 | |
3429 (first window). | |
3430 | |
3431 Returns: | |
3432 True, if the webpage form is populated successfully, or False if not. | |
3433 | |
3434 Raises: | |
3435 pyauto_errors.JSONInterfaceError if an automation call returns an error. | |
3436 """ | |
3437 if not self.AutofillTriggerSuggestions(field_id, tab_index, windex): | |
3438 return False | |
3439 | |
3440 for _ in range(profile_index + 1): | |
3441 self.AutofillHighlightSuggestion('down', tab_index, windex) | |
3442 | |
3443 self.AutofillAcceptSelection(tab_index, windex) | |
3444 return True | |
3445 | |
3446 def AddHistoryItem(self, item): | 3217 def AddHistoryItem(self, item): |
3447 """Forge a history item for Chrome. | 3218 """Forge a history item for Chrome. |
3448 | 3219 |
3449 Args: | 3220 Args: |
3450 item: a python dictionary representing the history item. Example: | 3221 item: a python dictionary representing the history item. Example: |
3451 { | 3222 { |
3452 # URL is the only mandatory item. | 3223 # URL is the only mandatory item. |
3453 'url': 'http://news.google.com', | 3224 'url': 'http://news.google.com', |
3454 # Title is optional. | 3225 # Title is optional. |
3455 'title': 'Google News', | 3226 'title': 'Google News', |
(...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4296 windex: index of the window. | 4067 windex: index of the window. |
4297 | 4068 |
4298 Returns: | 4069 Returns: |
4299 a string that was sent back via the domAutomationController.send method | 4070 a string that was sent back via the domAutomationController.send method |
4300 """ | 4071 """ |
4301 converted_args = map(lambda arg: json.dumps(arg), args) | 4072 converted_args = map(lambda arg: json.dumps(arg), args) |
4302 js = '%s(%s)' % (function, ', '.join(converted_args)) | 4073 js = '%s(%s)' % (function, ', '.join(converted_args)) |
4303 logging.debug('Executing javascript: %s', js) | 4074 logging.debug('Executing javascript: %s', js) |
4304 return self.ExecuteJavascript(js, tab_index, windex) | 4075 return self.ExecuteJavascript(js, tab_index, windex) |
4305 | 4076 |
4306 def JavascriptFocusElementById(self, field_id, tab_index=0, windex=0): | |
4307 """Uses Javascript to focus an element with the given ID in a webpage. | |
4308 | |
4309 Args: | |
4310 field_id: The string ID of the webpage form field to focus. | |
4311 tab_index: Integer index of the tab to work on; defaults to 0 (first tab). | |
4312 windex: Integer index of the browser window to work on; defaults to 0 | |
4313 (first window). | |
4314 | |
4315 Returns: | |
4316 True, on success, or False on failure. | |
4317 """ | |
4318 focus_field_js = """ | |
4319 var field = document.getElementById("%s"); | |
4320 if (!field) { | |
4321 window.domAutomationController.send("error"); | |
4322 } else { | |
4323 field.focus(); | |
4324 window.domAutomationController.send("done"); | |
4325 } | |
4326 """ % field_id | |
4327 return self.ExecuteJavascript(focus_field_js, tab_index, windex) == 'done' | |
4328 | |
4329 def SignInToSync(self, username, password): | 4077 def SignInToSync(self, username, password): |
4330 """Signs in to sync using the given username and password. | 4078 """Signs in to sync using the given username and password. |
4331 | 4079 |
4332 Args: | 4080 Args: |
4333 username: The account with which to sign in. Example: "user@gmail.com". | 4081 username: The account with which to sign in. Example: "user@gmail.com". |
4334 password: Password for the above account. Example: "pa$$w0rd". | 4082 password: Password for the above account. Example: "pa$$w0rd". |
4335 | 4083 |
4336 Returns: | 4084 Returns: |
4337 True, on success. | 4085 True, on success. |
4338 | 4086 |
(...skipping 2659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6998 successful = result.wasSuccessful() | 6746 successful = result.wasSuccessful() |
6999 if not successful: | 6747 if not successful: |
7000 pyauto_tests_file = os.path.join(self.TestsDir(), self._tests_filename) | 6748 pyauto_tests_file = os.path.join(self.TestsDir(), self._tests_filename) |
7001 print >>sys.stderr, 'Tests can be disabled by editing %s. ' \ | 6749 print >>sys.stderr, 'Tests can be disabled by editing %s. ' \ |
7002 'Ref: %s' % (pyauto_tests_file, _PYAUTO_DOC_URL) | 6750 'Ref: %s' % (pyauto_tests_file, _PYAUTO_DOC_URL) |
7003 sys.exit(not successful) | 6751 sys.exit(not successful) |
7004 | 6752 |
7005 | 6753 |
7006 if __name__ == '__main__': | 6754 if __name__ == '__main__': |
7007 Main() | 6755 Main() |
OLD | NEW |