1# Copyright (c) 2013 The Chromium OS 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 5from autotest_lib.client.cros import constants 6from autotest_lib.server import autotest 7 8 9class InteractiveClient(object): 10 """InteractiveClient represents a remote host for interactive tests. 11 12 An XML-RPC server is deployed to the remote host and a set of methods 13 exposed that allow you to open a browser window on that device, write 14 output and receive button clicks in order to develop interactive tests. 15 """ 16 17 XMLRPC_BRINGUP_TIMEOUT_SECONDS = 60 18 19 def __init__(self, client_host): 20 """Construct a InteractiveClient. 21 22 @param client_host: host object representing a remote host. 23 24 """ 25 self._host = client_host 26 # Make sure the client library is on the device so that the proxy code 27 # is there when we try to call it. 28 client_at = autotest.Autotest(self._host) 29 client_at.install() 30 # Start up the XML-RPC proxy on the client. 31 self._proxy = self._host.rpc_server_tracker.xmlrpc_connect( 32 constants.INTERACTIVE_XMLRPC_SERVER_COMMAND, 33 constants.INTERACTIVE_XMLRPC_SERVER_PORT, 34 command_name= 35 constants.INTERACTIVE_XMLRPC_SERVER_CLEANUP_PATTERN, 36 ready_test_name= 37 constants.INTERACTIVE_XMLRPC_SERVER_READY_METHOD, 38 timeout_seconds=self.XMLRPC_BRINGUP_TIMEOUT_SECONDS) 39 40 41 def login(self): 42 """Login to the system and open a tab. 43 44 The tab opened is used by other methods on this server to interact 45 with the user. 46 47 @return True on success, False otherwise. 48 49 """ 50 return self._proxy.login() 51 52 53 def set_output(self, html): 54 """Replace the contents of the tab. 55 56 @param html: HTML document to replace tab contents with. 57 58 @return True on success, False otherwise. 59 60 """ 61 return self._proxy.set_output(html) 62 63 64 def append_output(self, html): 65 """Append HTML to the contents of the tab. 66 67 @param html: HTML to append to the existing tab contents. 68 69 @return True on success, False otherwise. 70 71 """ 72 return self._proxy.append_output(html) 73 74 75 def append_buttons(self, *args): 76 """Append confirmation buttons to the tab. 77 78 Each button is given an index, 0 for the first button, 1 for the second, 79 and so on. 80 81 @param title...: Title of button to append. 82 83 @return True on success, False otherwise. 84 85 """ 86 return self._proxy.append_buttons(*args) 87 88 89 def wait_for_button(self, timeout): 90 """Wait for a button to be clicked. 91 92 Call append_buttons() before this to add buttons to the document. 93 94 @param timeout: Maximum time, in seconds, to wait for a click. 95 96 @return index of button that was clicked, or -1 on timeout. 97 98 """ 99 return self._proxy.wait_for_button(timeout) 100 101 102 def check_for_button(self): 103 """Check whether a button has been clicked. 104 105 Call append_buttons() before this to add buttons to the document. 106 107 @return index of button that was clicked or -1 if no button 108 has been clicked. 109 110 """ 111 return self._proxy.check_for_button() 112 113 114 def append_list(self, name): 115 """Append a results list to the contents of the tab. 116 117 @param name: Name to use for making modifications to the list. 118 119 @return True. 120 121 """ 122 return self._proxy.append_list(name) 123 124 125 def append_list_item(self, list_name, item_name, html): 126 """Append an item to a results list. 127 128 @param list_name: Name of list provided to append_list(). 129 @param item_name: Name to use for making modifications to the item. 130 @param html: HTML to place in the list item. 131 132 @return True. 133 134 """ 135 return self._proxy.append_list_item(list_name, item_name, html) 136 137 138 def replace_list_item(self, item_name, html): 139 """Replace an item in a results list. 140 141 @param item_name: Name of item provided to append_list_item(). 142 @param html: HTML to place in the list item. 143 144 @return True. 145 146 """ 147 return self._proxy.replace_list_item(item_name, html) 148 149 150 def close(self): 151 """Tear down state associated with the client.""" 152 # Log out the browser. 153 self._proxy.close() 154 # This does not close the host because it's shared with the client. 155