| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 | 2 |
| 3 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 3 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 """PyAuto: Python Interface to Chromium's Automation Proxy. | 7 """PyAuto: Python Interface to Chromium's Automation Proxy. |
| 8 | 8 |
| 9 PyAuto uses swig to expose Automation Proxy interfaces to Python. | 9 PyAuto uses swig to expose Automation Proxy interfaces to Python. |
| 10 For complete documentation on the functionality available, | 10 For complete documentation on the functionality available, |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 while timeout is None or time.time() - begin <= timeout: | 415 while timeout is None or time.time() - begin <= timeout: |
| 416 retval = function(*args) | 416 retval = function(*args) |
| 417 if (expect_retval is None and retval) or expect_retval == retval: | 417 if (expect_retval is None and retval) or expect_retval == retval: |
| 418 return True | 418 return True |
| 419 logging.debug('WaitUntil(%s) still waiting. ' | 419 logging.debug('WaitUntil(%s) still waiting. ' |
| 420 'Expecting %s. Last returned %s.' % ( | 420 'Expecting %s. Last returned %s.' % ( |
| 421 function, expect_retval, retval)) | 421 function, expect_retval, retval)) |
| 422 time.sleep(retry_sleep) | 422 time.sleep(retry_sleep) |
| 423 return False | 423 return False |
| 424 | 424 |
| 425 class CmdExecutionTimeoutChanger(object): | 425 |
| 426 """Facilitate temporary changes to command_execution_timeout_ms. | 426 class ActionTimeoutChanger(object): |
| 427 """Facilitate temporary changes to action_timeout_ms. |
| 427 | 428 |
| 428 Automatically resets to original timeout when object is destroyed. | 429 Automatically resets to original timeout when object is destroyed. |
| 429 """ | 430 """ |
| 430 _saved_timeout = -1 # Saved value for command_execution_timeout_ms | 431 _saved_timeout = -1 # Saved value for action_timeout_ms |
| 431 | 432 |
| 432 def __init__(self, ui_test, new_timeout): | 433 def __init__(self, ui_test, new_timeout): |
| 433 """Initialize. | 434 """Initialize. |
| 434 | 435 |
| 435 Args: | 436 Args: |
| 436 ui_test: a PyUITest object | 437 ui_test: a PyUITest object |
| 437 new_timeout: new timeout to use (in milli secs) | 438 new_timeout: new timeout to use (in milli secs) |
| 438 """ | 439 """ |
| 439 self._saved_timeout = ui_test.command_execution_timeout_ms() | 440 self._saved_timeout = ui_test.action_timeout_ms() |
| 440 if new_timeout != self._saved_timeout: | 441 if new_timeout != self._saved_timeout: |
| 441 ui_test.set_command_execution_timeout_ms(new_timeout) | 442 ui_test.set_action_timeout_ms(new_timeout) |
| 442 self._ui_test = ui_test | 443 self._ui_test = ui_test |
| 443 | 444 |
| 444 def __del__(self): | 445 def __del__(self): |
| 445 """Reset command_execution_timeout_ms to original value.""" | 446 """Reset command_execution_timeout_ms to original value.""" |
| 446 if self._ui_test.command_execution_timeout_ms() != self._saved_timeout: | 447 if self._ui_test.action_timeout_ms() != self._saved_timeout: |
| 447 self._ui_test.set_command_execution_timeout_ms(self._saved_timeout) | 448 self._ui_test.set_action_timeout_ms(self._saved_timeout) |
| 448 | 449 |
| 449 | 450 |
| 450 def _GetResultFromJSONRequest(self, cmd_dict, windex=0): | 451 def _GetResultFromJSONRequest(self, cmd_dict, windex=0, timeout=-1): |
| 451 """Issue call over the JSON automation channel and fetch output. | 452 """Issue call over the JSON automation channel and fetch output. |
| 452 | 453 |
| 453 This method packages the given dictionary into a json string, sends it | 454 This method packages the given dictionary into a json string, sends it |
| 454 over the JSON automation channel, loads the json output string returned, | 455 over the JSON automation channel, loads the json output string returned, |
| 455 and returns it back as a dictionary. | 456 and returns it back as a dictionary. |
| 456 | 457 |
| 457 Args: | 458 Args: |
| 458 cmd_dict: the command dictionary. It must have a 'command' key | 459 cmd_dict: the command dictionary. It must have a 'command' key |
| 459 Sample: | 460 Sample: |
| 460 { | 461 { |
| 461 'command': 'SetOmniboxText', | 462 'command': 'SetOmniboxText', |
| 462 'text': text, | 463 'text': text, |
| 463 } | 464 } |
| 464 windex: 0-based window index on which to work. Default: 0 (first window) | 465 windex: 0-based window index on which to work. Default: 0 (first window) |
| 465 Use -ve windex if the automation command does not apply to a | 466 Use -ve windex if the automation command does not apply to a |
| 466 browser window. example: chromeos login | 467 browser window. example: chromeos login |
| 467 | 468 |
| 469 timeout: request timeout (in milliseconds) |
| 470 |
| 468 Returns: | 471 Returns: |
| 469 a dictionary for the output returned by the automation channel. | 472 a dictionary for the output returned by the automation channel. |
| 470 | 473 |
| 471 Raises: | 474 Raises: |
| 472 pyauto_errors.JSONInterfaceError if the automation call returns an error. | 475 pyauto_errors.JSONInterfaceError if the automation call returns an error. |
| 473 """ | 476 """ |
| 474 result = self._SendJSONRequest(windex, json.dumps(cmd_dict)) | 477 if timeout == -1: # Default |
| 478 timeout = self.action_max_timeout_ms() |
| 479 result = self._SendJSONRequest(windex, json.dumps(cmd_dict), timeout) |
| 475 if len(result) == 0: | 480 if len(result) == 0: |
| 476 raise JSONInterfaceError('Automation call received no response.') | 481 raise JSONInterfaceError('Automation call received no response.') |
| 477 ret_dict = json.loads(result) | 482 ret_dict = json.loads(result) |
| 478 if ret_dict.has_key('error'): | 483 if ret_dict.has_key('error'): |
| 479 raise JSONInterfaceError(ret_dict['error']) | 484 raise JSONInterfaceError(ret_dict['error']) |
| 480 return ret_dict | 485 return ret_dict |
| 481 | 486 |
| 482 def GetBookmarkModel(self): | 487 def GetBookmarkModel(self): |
| 483 """Return the bookmark model as a BookmarkModel object. | 488 """Return the bookmark model as a BookmarkModel object. |
| 484 | 489 |
| 485 This is a snapshot of the bookmark model; it is not a proxy and | 490 This is a snapshot of the bookmark model; it is not a proxy and |
| 486 does not get updated as the bookmark model changes. | 491 does not get updated as the bookmark model changes. |
| 487 """ | 492 """ |
| 488 return bookmark_model.BookmarkModel(self._GetBookmarksAsJSON()) | 493 return bookmark_model.BookmarkModel(self._GetBookmarksAsJSON()) |
| 489 | 494 |
| 490 def GetDownloadsInfo(self, windex=0): | 495 def GetDownloadsInfo(self, windex=0): |
| 491 """Return info about downloads. | 496 """Return info about downloads. |
| 492 | 497 |
| 493 This includes all the downloads recognized by the history system. | 498 This includes all the downloads recognized by the history system. |
| 494 | 499 |
| 495 Returns: | 500 Returns: |
| 496 an instance of downloads_info.DownloadInfo | 501 an instance of downloads_info.DownloadInfo |
| 497 """ | 502 """ |
| 498 return download_info.DownloadInfo( | 503 return download_info.DownloadInfo( |
| 499 self._SendJSONRequest( | 504 self._SendJSONRequest( |
| 500 windex, json.dumps({'command': 'GetDownloadsInfo'}))) | 505 windex, json.dumps({'command': 'GetDownloadsInfo'}), |
| 506 self.action_max_timeout_ms())) |
| 501 | 507 |
| 502 def GetOmniboxInfo(self, windex=0): | 508 def GetOmniboxInfo(self, windex=0): |
| 503 """Return info about Omnibox. | 509 """Return info about Omnibox. |
| 504 | 510 |
| 505 This represents a snapshot of the omnibox. If you expect changes | 511 This represents a snapshot of the omnibox. If you expect changes |
| 506 you need to call this method again to get a fresh snapshot. | 512 you need to call this method again to get a fresh snapshot. |
| 507 Note that this DOES NOT shift focus to the omnibox; you've to ensure that | 513 Note that this DOES NOT shift focus to the omnibox; you've to ensure that |
| 508 the omnibox is in focus or else you won't get any interesting info. | 514 the omnibox is in focus or else you won't get any interesting info. |
| 509 | 515 |
| 510 It's OK to call this even when the omnibox popup is not showing. In this | 516 It's OK to call this even when the omnibox popup is not showing. In this |
| 511 case however, there won't be any matches, but other properties (like the | 517 case however, there won't be any matches, but other properties (like the |
| 512 current text in the omnibox) will still be fetched. | 518 current text in the omnibox) will still be fetched. |
| 513 | 519 |
| 514 Due to the nature of the omnibox, this function is sensitive to mouse | 520 Due to the nature of the omnibox, this function is sensitive to mouse |
| 515 focus. DO NOT HOVER MOUSE OVER OMNIBOX OR CHANGE WINDOW FOCUS WHEN USING | 521 focus. DO NOT HOVER MOUSE OVER OMNIBOX OR CHANGE WINDOW FOCUS WHEN USING |
| 516 THIS METHOD. | 522 THIS METHOD. |
| 517 | 523 |
| 518 Args: | 524 Args: |
| 519 windex: the index of the browser window to work on. | 525 windex: the index of the browser window to work on. |
| 520 Default: 0 (first window) | 526 Default: 0 (first window) |
| 521 | 527 |
| 522 Returns: | 528 Returns: |
| 523 an instance of omnibox_info.OmniboxInfo | 529 an instance of omnibox_info.OmniboxInfo |
| 524 """ | 530 """ |
| 525 return omnibox_info.OmniboxInfo( | 531 return omnibox_info.OmniboxInfo( |
| 526 self._SendJSONRequest(windex, | 532 self._SendJSONRequest(windex, |
| 527 json.dumps({'command': 'GetOmniboxInfo'}))) | 533 json.dumps({'command': 'GetOmniboxInfo'}), |
| 534 self.action_max_timeout_ms())) |
| 528 | 535 |
| 529 def SetOmniboxText(self, text, windex=0): | 536 def SetOmniboxText(self, text, windex=0): |
| 530 """Enter text into the omnibox. This shifts focus to the omnibox. | 537 """Enter text into the omnibox. This shifts focus to the omnibox. |
| 531 | 538 |
| 532 Args: | 539 Args: |
| 533 text: the text to be set. | 540 text: the text to be set. |
| 534 windex: the index of the browser window to work on. | 541 windex: the index of the browser window to work on. |
| 535 Default: 0 (first window) | 542 Default: 0 (first window) |
| 536 """ | 543 """ |
| 537 # Ensure that keyword data is loaded from the profile. | 544 # Ensure that keyword data is loaded from the profile. |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 719 """Return info about preferences. | 726 """Return info about preferences. |
| 720 | 727 |
| 721 This represents a snapshot of the preferences. If you expect preferences | 728 This represents a snapshot of the preferences. If you expect preferences |
| 722 to have changed, you need to call this method again to get a fresh | 729 to have changed, you need to call this method again to get a fresh |
| 723 snapshot. | 730 snapshot. |
| 724 | 731 |
| 725 Returns: | 732 Returns: |
| 726 an instance of prefs_info.PrefsInfo | 733 an instance of prefs_info.PrefsInfo |
| 727 """ | 734 """ |
| 728 return prefs_info.PrefsInfo( | 735 return prefs_info.PrefsInfo( |
| 729 self._SendJSONRequest(0, json.dumps({'command': 'GetPrefsInfo'}))) | 736 self._SendJSONRequest(0, json.dumps({'command': 'GetPrefsInfo'}), |
| 737 self.action_max_timeout_ms())) |
| 730 | 738 |
| 731 def SetPrefs(self, path, value): | 739 def SetPrefs(self, path, value): |
| 732 """Set preference for the given path. | 740 """Set preference for the given path. |
| 733 | 741 |
| 734 Preferences are stored by Chromium as a hierarchical dictionary. | 742 Preferences are stored by Chromium as a hierarchical dictionary. |
| 735 dot-separated paths can be used to refer to a particular preference. | 743 dot-separated paths can be used to refer to a particular preference. |
| 736 example: "session.restore_on_startup" | 744 example: "session.restore_on_startup" |
| 737 | 745 |
| 738 Some preferences are managed, that is, they cannot be changed by the | 746 Some preferences are managed, that is, they cannot be changed by the |
| 739 user. It's upto the user to know which ones can be changed. Typically, | 747 user. It's upto the user to know which ones can be changed. Typically, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 777 'windowsKeyCode': key_code, | 785 'windowsKeyCode': key_code, |
| 778 'modifiers': 0, | 786 'modifiers': 0, |
| 779 'windex': windex, | 787 'windex': windex, |
| 780 'tab_index': tab_index, | 788 'tab_index': tab_index, |
| 781 } | 789 } |
| 782 # Sending two requests, one each for "key down" and "key up". | 790 # Sending two requests, one each for "key down" and "key up". |
| 783 self._GetResultFromJSONRequest(cmd_dict) | 791 self._GetResultFromJSONRequest(cmd_dict) |
| 784 cmd_dict['type'] = 3 # kKeyUpType | 792 cmd_dict['type'] = 3 # kKeyUpType |
| 785 self._GetResultFromJSONRequest(cmd_dict) | 793 self._GetResultFromJSONRequest(cmd_dict) |
| 786 | 794 |
| 787 def WaitForAllDownloadsToComplete(self, windex=0): | 795 def WaitForAllDownloadsToComplete(self, windex=0, timeout=-1): |
| 788 """Wait for all downloads to complete. | 796 """Wait for all downloads to complete. |
| 789 | 797 |
| 790 Note: This method does not work for dangerous downloads. Use | 798 Note: This method does not work for dangerous downloads. Use |
| 791 WaitForGivenDownloadsToComplete (below) instead. | 799 WaitForGivenDownloadsToComplete (below) instead. |
| 792 """ | 800 """ |
| 793 cmd_dict = {'command': 'WaitForAllDownloadsToComplete'} | 801 cmd_dict = {'command': 'WaitForAllDownloadsToComplete'} |
| 794 self._GetResultFromJSONRequest(cmd_dict, windex=windex) | 802 self._GetResultFromJSONRequest(cmd_dict, windex=windex, timeout=timeout) |
| 795 | 803 |
| 796 def WaitForDownloadToComplete(self, download_path, timeout=-1): | 804 def WaitForDownloadToComplete(self, download_path, timeout=-1): |
| 797 """Wait for the given downloads to complete. | 805 """Wait for the given downloads to complete. |
| 798 | 806 |
| 799 This method works for dangerous downloads as well as regular downloads. | 807 This method works for dangerous downloads as well as regular downloads. |
| 800 | 808 |
| 801 Args: | 809 Args: |
| 802 download_path: The path to the final download. This is only necessary for | 810 download_path: The path to the final download. This is only necessary for |
| 803 the workaround described in the comments below and should | 811 the workaround described in the comments below and should |
| 804 be removed when downloads are re-implemented. | 812 be removed when downloads are re-implemented. |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1079 the chrome://history/ UI. | 1087 the chrome://history/ UI. |
| 1080 | 1088 |
| 1081 Returns: | 1089 Returns: |
| 1082 an instance of history_info.HistoryInfo | 1090 an instance of history_info.HistoryInfo |
| 1083 """ | 1091 """ |
| 1084 cmd_dict = { # Prepare command for the json interface | 1092 cmd_dict = { # Prepare command for the json interface |
| 1085 'command': 'GetHistoryInfo', | 1093 'command': 'GetHistoryInfo', |
| 1086 'search_text': search_text, | 1094 'search_text': search_text, |
| 1087 } | 1095 } |
| 1088 return history_info.HistoryInfo( | 1096 return history_info.HistoryInfo( |
| 1089 self._SendJSONRequest(0, json.dumps(cmd_dict))) | 1097 self._SendJSONRequest(0, json.dumps(cmd_dict), |
| 1098 self.action_max_timeout_ms())) |
| 1090 | 1099 |
| 1091 def GetTranslateInfo(self, tab_index=0, window_index=0): | 1100 def GetTranslateInfo(self, tab_index=0, window_index=0): |
| 1092 """Returns info about translate for the given page. | 1101 """Returns info about translate for the given page. |
| 1093 | 1102 |
| 1094 If the translate bar is showing, also returns information about the bar. | 1103 If the translate bar is showing, also returns information about the bar. |
| 1095 | 1104 |
| 1096 Args: | 1105 Args: |
| 1097 tab_index: The tab index, default is 0. | 1106 tab_index: The tab index, default is 0. |
| 1098 window_index: The window index, default is 0. | 1107 window_index: The window index, default is 0. |
| 1099 | 1108 |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1416 | 1425 |
| 1417 def GetPluginsInfo(self): | 1426 def GetPluginsInfo(self): |
| 1418 """Return info about plugins. | 1427 """Return info about plugins. |
| 1419 | 1428 |
| 1420 This is the info available from about:plugins | 1429 This is the info available from about:plugins |
| 1421 | 1430 |
| 1422 Returns: | 1431 Returns: |
| 1423 an instance of plugins_info.PluginsInfo | 1432 an instance of plugins_info.PluginsInfo |
| 1424 """ | 1433 """ |
| 1425 return plugins_info.PluginsInfo( | 1434 return plugins_info.PluginsInfo( |
| 1426 self._SendJSONRequest(0, json.dumps({'command': 'GetPluginsInfo'}))) | 1435 self._SendJSONRequest(0, json.dumps({'command': 'GetPluginsInfo'}), |
| 1436 self.action_max_timeout_ms())) |
| 1427 | 1437 |
| 1428 def EnablePlugin(self, path): | 1438 def EnablePlugin(self, path): |
| 1429 """Enable the plugin at the given path. | 1439 """Enable the plugin at the given path. |
| 1430 | 1440 |
| 1431 Use GetPluginsInfo() to fetch path info about a plugin. | 1441 Use GetPluginsInfo() to fetch path info about a plugin. |
| 1432 | 1442 |
| 1433 Raises: | 1443 Raises: |
| 1434 pyauto_errors.JSONInterfaceError if the automation call returns an error. | 1444 pyauto_errors.JSONInterfaceError if the automation call returns an error. |
| 1435 """ | 1445 """ |
| 1436 cmd_dict = { | 1446 cmd_dict = { |
| (...skipping 1609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3046 if self._options.verbose: | 3056 if self._options.verbose: |
| 3047 verbosity = 2 | 3057 verbosity = 2 |
| 3048 result = PyAutoTextTestRuner(verbosity=verbosity).run(pyauto_suite) | 3058 result = PyAutoTextTestRuner(verbosity=verbosity).run(pyauto_suite) |
| 3049 del loaded_tests # Need to destroy test cases before the suite | 3059 del loaded_tests # Need to destroy test cases before the suite |
| 3050 del pyauto_suite | 3060 del pyauto_suite |
| 3051 sys.exit(not result.wasSuccessful()) | 3061 sys.exit(not result.wasSuccessful()) |
| 3052 | 3062 |
| 3053 | 3063 |
| 3054 if __name__ == '__main__': | 3064 if __name__ == '__main__': |
| 3055 Main() | 3065 Main() |
| OLD | NEW |