OLD | NEW |
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Includes different methods to drive chromoting UI.""" | |
6 | |
7 import os | 5 import os |
8 import subprocess | |
9 import sys | |
10 import time | |
11 | |
12 from pyauto_errors import JSONInterfaceError | |
13 | 6 |
14 | 7 |
15 class ChromotingMixIn(object): | 8 class ChromotingMixIn(object): |
16 """MixIn for PyUITest that adds Chromoting-specific methods. | 9 """MixIn for PyUITest that adds Chromoting-specific methods. |
17 | 10 |
18 Prepend it as a base class of a test to enable Chromoting functionality. | 11 Prepend it as a base class of a test to enable Chromoting functionality. |
19 This is a separate class from PyUITest to avoid namespace collisions. | 12 This is a separate class from PyUITest to avoid namespace collisions. |
20 | 13 |
21 Example usage: | 14 Example usage: |
22 class ChromotingExample(chromoting.ChromotingMixIn, pyauto.PyUITest): | 15 class ChromotingExample(chromoting.ChromotingMixIn, pyauto.PyUITest): |
23 def testShare(self): | 16 def testShare(self): |
24 app = self.InstallApp(self.GetWebappPath()) | 17 app = self.InstallApp(self.GetWebappPath()) |
25 self.LaunchApp(app) | 18 self.LaunchApp(app) |
26 self.Authenticate() | 19 self.Authenticate() |
27 self.assertTrue(self.Share()) | 20 self.assertTrue(self.Share()) |
28 """ | 21 """ |
29 | 22 |
30 def _ExecuteJavascript(self, command, tab_index, windex): | 23 def _ExecuteJavascript(self, command, tab_index, windex): |
31 """Helper that returns immediately after running a Javascript command. | 24 """Helper that returns immediately after running a Javascript command.""" |
32 """ | 25 return self.ExecuteJavascript( |
33 try: | 26 '%s; window.domAutomationController.send("done");' % command, |
34 self.ExecuteJavascript( | 27 tab_index, windex) |
35 '%s; window.domAutomationController.send("done");' % command, | |
36 tab_index, windex) | |
37 return True | |
38 except JSONInterfaceError: | |
39 print '_ExecuteJavascript threw JSONInterfaceError' | |
40 return False | |
41 | 28 |
42 def _WaitForJavascriptCondition(self, condition, tab_index, windex): | 29 def _WaitForJavascriptCondition(self, condition, tab_index, windex): |
43 """Waits until the Javascript condition is true. | 30 """Waits until the Javascript condition is true. |
44 | 31 |
45 This is different from a naive self.WaitUntil(lambda: self.GetDOMValue()) | 32 This is different from a naive self.WaitUntil(lambda: self.GetDOMValue()) |
46 because it uses Javascript to check the condition instead of Python. | 33 because it uses Javascript to check the condition instead of Python. |
47 | |
48 Returns: True if condition is satisfied or otherwise False. | |
49 """ | 34 """ |
50 try: | 35 return self.WaitUntil(lambda: self.GetDOMValue( |
51 return self.WaitUntil(lambda: self.GetDOMValue( | 36 '(%s) ? "1" : ""' % condition, tab_index, windex)) |
52 '(%s) ? "1" : ""' % condition, tab_index, windex)) | |
53 except JSONInterfaceError: | |
54 print '_WaitForJavascriptCondition threw JSONInterfaceError' | |
55 return False | |
56 | 37 |
57 def _ExecuteAndWaitForMode(self, command, mode, tab_index, windex): | 38 def _ExecuteAndWaitForMode(self, command, mode, tab_index, windex): |
58 """ Executes JavaScript and wait for remoting app mode equal to | 39 self.assertTrue(self._ExecuteJavascript(command, tab_index, windex), |
59 the given mode. | 40 'Javascript command did not return anything.') |
60 | |
61 Returns: True if condition is satisfied or otherwise False. | |
62 """ | |
63 if not self._ExecuteJavascript(command, tab_index, windex): | |
64 return False | |
65 return self._WaitForJavascriptCondition( | 41 return self._WaitForJavascriptCondition( |
66 'remoting.currentMode == remoting.AppMode.%s' % mode, | 42 'remoting.currentMode == remoting.AppMode.%s' % mode, |
67 tab_index, windex) | 43 tab_index, windex) |
68 | 44 |
69 def _ExecuteAndWaitForMajorMode(self, command, mode, tab_index, windex): | 45 def _ExecuteAndWaitForMajorMode(self, command, mode, tab_index, windex): |
70 """ Executes JavaScript and wait for remoting app major mode equal to | 46 self.assertTrue(self._ExecuteJavascript(command, tab_index, windex), |
71 the given mode. | 47 'Javascript command did not return anything.') |
72 | |
73 Returns: True if condition is satisfied or otherwise False. | |
74 """ | |
75 if not self._ExecuteJavascript(command, tab_index, windex): | |
76 return False | |
77 return self._WaitForJavascriptCondition( | 48 return self._WaitForJavascriptCondition( |
78 'remoting.getMajorMode() == remoting.AppMode.%s' % mode, | 49 'remoting.getMajorMode() == remoting.AppMode.%s' % mode, |
79 tab_index, windex) | 50 tab_index, windex) |
80 | 51 |
81 def GetWebappPath(self): | 52 def GetWebappPath(self): |
82 """Returns the path to the webapp. | 53 """Returns the path to the webapp. |
83 | 54 |
84 Expects the webapp to be in the same place as the pyautolib binaries. | 55 Expects the webapp to be in the same place as the pyautolib binaries. |
85 """ | 56 """ |
86 return os.path.join(self.BrowserPath(), 'remoting', 'remoting.webapp') | 57 return os.path.join(self.BrowserPath(), 'remoting', 'remoting.webapp') |
87 | 58 |
88 def _GetHelperRunner(self): | 59 def Authenticate(self, email=None, password=None, otp=None, |
89 """Returns the python binary name that runs chromoting_helper.py.""" | 60 tab_index=1, windex=0): |
90 if sys.platform.startswith('win'): | 61 """Logs a user in for Chromoting and accepts permissions for the app. |
91 return 'python' | |
92 else: | |
93 return 'suid-python' | |
94 | 62 |
95 def _GetHelper(self): | 63 PyAuto tests start with a clean profile, so Chromoting tests should call |
96 """Get chromoting_helper.py.""" | 64 this for every run after launching the app. If email or password is omitted, |
97 return os.path.join('chrome', 'test', 'pyautolib', 'chromoting_helper.py') | 65 the user can type it into the browser window manually. |
98 | 66 |
99 def InstallHostDaemon(self): | 67 Raises: |
100 """Installs the host daemon.""" | 68 AssertionError if the authentication flow changes or |
101 subprocess.call([self._GetHelperRunner(), self._GetHelper(), | 69 the credentials are incorrect. |
102 'install', self.BrowserPath()]) | 70 """ |
103 | |
104 def UninstallHostDaemon(self): | |
105 """Uninstalls the host daemon.""" | |
106 subprocess.call([self._GetHelperRunner(), self._GetHelper(), | |
107 'uninstall', self.BrowserPath()]) | |
108 | |
109 def ContinueAuth(self, tab_index=1, windex=0): | |
110 """Starts authentication.""" | |
111 self.assertTrue( | 71 self.assertTrue( |
112 self._WaitForJavascriptCondition('window.remoting && remoting.oauth2', | 72 self._WaitForJavascriptCondition('window.remoting && remoting.oauth2', |
113 tab_index, windex), | 73 tab_index, windex), |
114 msg='Timed out while waiting for remoting app to finish loading.') | 74 msg='Timed out while waiting for remoting app to finish loading.') |
115 self._ExecuteJavascript('remoting.oauth2.doAuthRedirect();', | 75 self._ExecuteJavascript('remoting.oauth2.doAuthRedirect();', |
116 tab_index, windex) | 76 tab_index, windex) |
117 | |
118 def SignIn(self, email=None, password=None, otp=None, | |
119 tab_index=1, windex=0): | |
120 """Logs a user in. | |
121 | |
122 PyAuto tests start with a clean profile, so Chromoting tests should call | |
123 this for every run after launching the app. If email or password is | |
124 omitted, the user can type it into the browser window manually. | |
125 """ | |
126 self.assertTrue( | 77 self.assertTrue( |
127 self._WaitForJavascriptCondition('document.getElementById("signIn")', | 78 self._WaitForJavascriptCondition('document.getElementById("signIn")', |
128 tab_index, windex), | 79 tab_index, windex), |
129 msg='Unable to redirect for authentication.') | 80 msg='Unable to redirect for authentication.') |
130 | 81 |
131 if email: | 82 if email: |
132 self._ExecuteJavascript('document.getElementById("Email").value = "%s";' | 83 self._ExecuteJavascript('document.getElementById("Email").value = "%s";' |
133 'document.getElementById("Passwd").focus();' | 84 'document.getElementById("Passwd").focus();' |
134 % email, tab_index, windex) | 85 % email, tab_index, windex) |
135 | 86 |
136 if password: | 87 if password: |
137 self._ExecuteJavascript('document.getElementById("Passwd").value = "%s";' | 88 self._ExecuteJavascript('document.getElementById("Passwd").value = "%s";' |
138 'document.getElementById("signIn").click();' | 89 'document.getElementById("signIn").click();' |
139 % password, tab_index, windex) | 90 % password, tab_index, windex) |
140 | 91 |
141 if otp: | 92 if otp: |
142 self.assertTrue( | 93 self.assertTrue( |
143 self._WaitForJavascriptCondition( | 94 self._WaitForJavascriptCondition( |
144 'document.getElementById("smsVerifyPin")', | 95 'document.getElementById("smsVerifyPin")', |
145 tab_index, windex), | 96 tab_index, windex), |
146 msg='Invalid username or password.') | 97 msg='Invalid username or password.') |
147 self._ExecuteJavascript( | 98 self._ExecuteJavascript('document.getElementById("smsUserPin").value = ' |
148 'document.getElementById("smsUserPin").value = "%s";' | 99 '"%s";' |
149 'document.getElementById("smsVerifyPin").click();' % otp, | 100 'document.getElementById("smsVerifyPin").click();' |
150 tab_index, windex) | 101 % otp, tab_index, windex) |
151 | 102 |
152 # If the account adder screen appears, then skip it. | 103 # If the account adder screen appears, then skip it. |
153 self.assertTrue( | 104 self.assertTrue( |
154 self._WaitForJavascriptCondition( | 105 self._WaitForJavascriptCondition( |
155 'document.getElementById("skip") || ' | 106 'document.getElementById("skip") || ' |
156 'document.getElementById("submit_approve_access")', | 107 'document.getElementById("submit_approve_access")', |
157 tab_index, windex), | 108 tab_index, windex), |
158 msg='No "skip adding account" or "approve access" link.') | 109 msg='No "skip adding account" or "approve access" link.') |
159 self._ExecuteJavascript( | 110 self._ExecuteJavascript( |
160 'if (document.getElementById("skip")) ' | 111 'if (document.getElementById("skip")) ' |
161 '{ document.getElementById("skip").click(); }', | 112 '{ document.getElementById("skip").click(); }', |
162 tab_index, windex) | 113 tab_index, windex) |
163 | 114 |
164 def AllowAccess(self, tab_index=1, windex=0): | |
165 """Allows access to chromoting webapp.""" | |
166 # Approve access. | 115 # Approve access. |
167 self.assertTrue( | 116 self.assertTrue( |
168 self._WaitForJavascriptCondition( | 117 self._WaitForJavascriptCondition( |
169 'document.getElementById("submit_approve_access")', | 118 'document.getElementById("submit_approve_access")', |
170 tab_index, windex), | 119 tab_index, windex), |
171 msg='Did not go to permission page.') | 120 msg='Authentication failed. The username, password, or otp is invalid.') |
172 self._ExecuteJavascript( | 121 self._ExecuteJavascript( |
173 'document.getElementById("submit_approve_access").click();', | 122 'document.getElementById("submit_approve_access").click();', |
174 tab_index, windex) | 123 tab_index, windex) |
175 | 124 |
176 # Wait for some things to be ready. | 125 # Wait for some things to be ready. |
177 self.assertTrue( | 126 self.assertTrue( |
178 self._WaitForJavascriptCondition( | 127 self._WaitForJavascriptCondition( |
179 'window.remoting && remoting.oauth2 && ' | 128 'window.remoting && remoting.oauth2 && ' |
180 'remoting.oauth2.isAuthenticated()', | 129 'remoting.oauth2.isAuthenticated()', |
181 tab_index, windex), | 130 tab_index, windex), |
182 msg='OAuth2 authentication failed.') | 131 msg='OAuth2 authentication failed.') |
183 self.assertTrue( | 132 self.assertTrue( |
184 self._WaitForJavascriptCondition( | 133 self._WaitForJavascriptCondition( |
185 'window.localStorage.getItem("remoting-email")', | 134 'window.localStorage.getItem("remoting-email")', |
186 tab_index, windex), | 135 tab_index, windex), |
187 msg='Chromoting app did not reload after authentication.') | 136 msg='Chromoting app did not reload after authentication.') |
188 | 137 |
189 def DenyAccess(self, tab_index=1, windex=0): | |
190 """Deny and then allow access to chromoting webapp.""" | |
191 self.assertTrue( | |
192 self._WaitForJavascriptCondition( | |
193 'document.getElementById("submit_deny_access")', | |
194 tab_index, windex), | |
195 msg='Did not go to permission page.') | |
196 self._ExecuteJavascript( | |
197 'document.getElementById("submit_deny_access").click();', | |
198 tab_index, windex) | |
199 | |
200 def SignOut(self, tab_index=1, windex=0): | |
201 """Signs out from chromoting and signs back in.""" | |
202 self._ExecuteAndWaitForMode( | |
203 'document.getElementById("sign-out").click();', | |
204 'UNAUTHENTICATED', tab_index, windex) | |
205 | |
206 def Authenticate(self, tab_index=1, windex=0): | |
207 """Finishes authentication flow for user.""" | |
208 self.ContinueAuth(tab_index, windex) | |
209 account = self.GetPrivateInfo()['test_chromoting_account'] | |
210 self.host.SignIn(account['username'], account['password'], None, | |
211 tab_index, windex) | |
212 self.host.AllowAccess(tab_index, windex) | |
213 | |
214 def StartMe2Me(self, tab_index=1, windex=0): | |
215 """Starts Me2Me. """ | |
216 self._ExecuteJavascript( | |
217 'document.getElementById("get-started-me2me").click();', | |
218 tab_index, windex) | |
219 | |
220 def Share(self, tab_index=1, windex=0): | 138 def Share(self, tab_index=1, windex=0): |
221 """Generates an access code and waits for incoming connections. | 139 """Generates an access code and waits for incoming connections. |
222 | 140 |
223 Returns: | 141 Returns: |
224 The access code on success; None otherwise. | 142 The access code on success; None otherwise. |
225 """ | 143 """ |
226 self._ExecuteAndWaitForMode( | 144 self._ExecuteAndWaitForMode( |
227 'remoting.tryShare();', | 145 'remoting.tryShare();', |
228 'HOST_WAITING_FOR_CONNECTION', tab_index, windex) | 146 'HOST_WAITING_FOR_CONNECTION', tab_index, windex) |
229 return self.GetDOMValue( | 147 return self.GetDOMValue( |
230 'document.getElementById("access-code-display").innerText', | 148 'document.getElementById("access-code-display").innerText', |
231 tab_index, windex) | 149 tab_index, windex) |
232 | 150 |
| 151 def Connect(self, access_code, wait_for_frame, tab_index=1, windex=0): |
| 152 """Connects to a Chromoting host and starts the session. |
| 153 |
| 154 Returns: |
| 155 True on success; False otherwise. |
| 156 """ |
| 157 if not self._ExecuteAndWaitForMode( |
| 158 'document.getElementById("access-code-entry").value = "%s";' |
| 159 'remoting.connectIt2Me();' % access_code, |
| 160 'IN_SESSION', tab_index, windex): |
| 161 return False |
| 162 |
| 163 if wait_for_frame and not self._WaitForJavascriptCondition( |
| 164 'remoting.clientSession && remoting.clientSession.hasReceivedFrame()', |
| 165 tab_index, windex): |
| 166 return False |
| 167 return True |
| 168 |
233 def CancelShare(self, tab_index=1, windex=0): | 169 def CancelShare(self, tab_index=1, windex=0): |
234 """Stops sharing the desktop on the host side.""" | 170 """Stops sharing the desktop on the host side. |
235 self.assertTrue( | |
236 self._ExecuteAndWaitForMode( | |
237 'remoting.cancelShare();', | |
238 'HOST_SHARE_FINISHED', tab_index, windex), | |
239 msg='Stopping sharing from the host side failed') | |
240 | 171 |
241 def EnableConnectionsInstalled(self, pin_exercise=False, | 172 Returns: |
242 tab_index=1, windex=0): | 173 True on success; False otherwise. |
243 """Enables the remote connections on the host side.""" | 174 """ |
244 subprocess.call([self._GetHelperRunner(), self._GetHelper(), 'enable']) | 175 return self._ExecuteAndWaitForMode( |
245 | 176 'remoting.cancelShare();', |
246 self.assertTrue( | 177 'HOST_SHARE_FINISHED', tab_index, windex) |
247 self._ExecuteAndWaitForMode( | |
248 'document.getElementById("start-daemon").click();', | |
249 'HOST_SETUP_ASK_PIN', tab_index, windex), | |
250 msg='Cannot start host setup') | |
251 self.assertTrue( | |
252 self._WaitForJavascriptCondition( | |
253 'document.getElementById("ask-pin-form").hidden == false', | |
254 tab_index, windex), | |
255 msg='No ask pin dialog') | |
256 | |
257 if pin_exercise: | |
258 # Cancels the pin prompt | |
259 self._ExecuteJavascript( | |
260 'document.getElementById("daemon-pin-cancel").click();', | |
261 tab_index, windex) | |
262 | |
263 # Enables again | |
264 self.assertTrue( | |
265 self._ExecuteAndWaitForMode( | |
266 'document.getElementById("start-daemon").click();', | |
267 'HOST_SETUP_ASK_PIN', tab_index, windex), | |
268 msg='Cannot start host setup') | |
269 | |
270 # Click ok without typing in pins | |
271 self._ExecuteJavascript( | |
272 'document.getElementById("daemon-pin-ok").click();', | |
273 tab_index, windex) | |
274 self.assertTrue( | |
275 self._WaitForJavascriptCondition( | |
276 'document.getElementById("daemon-pin-error-message")', | |
277 tab_index, windex), | |
278 msg='No pin error message') | |
279 | |
280 # Mis-matching pins | |
281 self._ExecuteJavascript( | |
282 'document.getElementById("daemon-pin-entry").value = "111111";', | |
283 tab_index, windex) | |
284 self._ExecuteJavascript( | |
285 'document.getElementById("daemon-pin-confirm").value = "123456";', | |
286 tab_index, windex) | |
287 self.assertTrue( | |
288 self._WaitForJavascriptCondition( | |
289 'document.getElementById("daemon-pin-error-message")', | |
290 tab_index, windex), | |
291 msg='No pin error message') | |
292 | |
293 # Types in correct pins | |
294 self._ExecuteJavascript( | |
295 'document.getElementById("daemon-pin-entry").value = "111111";', | |
296 tab_index, windex) | |
297 self._ExecuteJavascript( | |
298 'document.getElementById("daemon-pin-confirm").value = "111111";', | |
299 tab_index, windex) | |
300 self.assertTrue( | |
301 self._ExecuteAndWaitForMode( | |
302 'document.getElementById("daemon-pin-ok").click();', | |
303 'HOST_SETUP_PROCESSING', tab_index, windex), | |
304 msg='Host setup was not started') | |
305 | |
306 # Handles preference panes | |
307 self.assertTrue( | |
308 self._WaitForJavascriptCondition( | |
309 'remoting.currentMode == remoting.AppMode.HOST_SETUP_DONE', | |
310 tab_index, windex), | |
311 msg='Host setup was not done') | |
312 | |
313 # Dismisses the host config done dialog | |
314 self.assertTrue( | |
315 self._WaitForJavascriptCondition( | |
316 'document.getElementById("host-setup-dialog")' | |
317 '.childNodes[5].hidden == false', | |
318 tab_index, windex), | |
319 msg='No host setup done dialog') | |
320 self.assertTrue( | |
321 self._ExecuteAndWaitForMode( | |
322 'document.getElementById("host-config-done-dismiss").click();', | |
323 'HOME', tab_index, windex), | |
324 msg='Failed to dismiss host setup confirmation dialog') | |
325 | |
326 def EnableConnectionsUninstalledAndCancel(self, tab_index=1, windex=0): | |
327 """Enables remote connections while host is not installed yet.""" | |
328 self.assertTrue( | |
329 self._ExecuteAndWaitForMode( | |
330 'document.getElementById("start-daemon").click();', | |
331 'HOST_SETUP_INSTALL', tab_index, windex), | |
332 msg='Cannot start host install') | |
333 self.assertTrue( | |
334 self._ExecuteAndWaitForMode( | |
335 'document.getElementById("host-config-install-dismiss").click();', | |
336 'HOME', tab_index, windex), | |
337 msg='Failed to dismiss host install dialog') | |
338 | |
339 def DisableConnections(self, tab_index=1, windex=0): | |
340 """Disables the remote connections on the host side.""" | |
341 subprocess.call([self._GetHelperRunner(), self._GetHelper(), 'disable']) | |
342 | |
343 self._ExecuteJavascript( | |
344 'document.getElementById("stop-daemon").click();', | |
345 tab_index, windex) | |
346 self.assertTrue( | |
347 self._ExecuteAndWaitForMode( | |
348 'document.getElementById("host-config-done-dismiss").click();', | |
349 'HOME', tab_index, windex), | |
350 msg='Failed to dismiss host setup confirmation dialog') | |
351 | |
352 def Connect(self, access_code, tab_index=1, windex=0): | |
353 """Connects to a Chromoting host and starts the session.""" | |
354 self.assertTrue( | |
355 self._ExecuteAndWaitForMode( | |
356 'document.getElementById("access-code-entry").value = "%s";' | |
357 'remoting.connectIt2Me();' % access_code, | |
358 'IN_SESSION', tab_index, windex), | |
359 msg='Cannot connect it2me session') | |
360 | |
361 def ChangePin(self, pin='222222', tab_index=1, windex=0): | |
362 """Changes pin for enabled host.""" | |
363 subprocess.call([self._GetHelperRunner(), self._GetHelper(), 'changepin']) | |
364 | |
365 self.assertTrue( | |
366 self._ExecuteAndWaitForMode( | |
367 'document.getElementById("change-daemon-pin").click();', | |
368 'HOST_SETUP_ASK_PIN', tab_index, windex), | |
369 msg='Cannot change daemon pin') | |
370 self.assertTrue( | |
371 self._WaitForJavascriptCondition( | |
372 'document.getElementById("ask-pin-form").hidden == false', | |
373 tab_index, windex), | |
374 msg='No ask pin dialog') | |
375 | |
376 self._ExecuteJavascript( | |
377 'document.getElementById("daemon-pin-entry").value = "' + pin + '";', | |
378 tab_index, windex) | |
379 self._ExecuteJavascript( | |
380 'document.getElementById("daemon-pin-confirm").value = "' + | |
381 pin + '";', tab_index, windex) | |
382 self.assertTrue( | |
383 self._ExecuteAndWaitForMode( | |
384 'document.getElementById("daemon-pin-ok").click();', | |
385 'HOST_SETUP_PROCESSING', tab_index, windex), | |
386 msg='Host setup was not started') | |
387 | |
388 # Handles preference panes | |
389 self.assertTrue( | |
390 self._WaitForJavascriptCondition( | |
391 'remoting.currentMode == remoting.AppMode.HOST_SETUP_DONE', | |
392 tab_index, windex), | |
393 msg='Host setup was not done') | |
394 | |
395 # Dismisses the host config done dialog | |
396 self.assertTrue( | |
397 self._WaitForJavascriptCondition( | |
398 'document.getElementById("host-setup-dialog")' | |
399 '.childNodes[5].hidden == false', | |
400 tab_index, windex), | |
401 msg='No host setup done dialog') | |
402 self.assertTrue( | |
403 self._ExecuteAndWaitForMode( | |
404 'document.getElementById("host-config-done-dismiss").click();', | |
405 'HOME', tab_index, windex), | |
406 msg='Failed to dismiss host setup confirmation dialog') | |
407 | |
408 def ChangeName(self, new_name='Changed', tab_index=1, windex=0): | |
409 """Changes the host name.""" | |
410 self._ExecuteJavascript( | |
411 'document.getElementById("this-host-rename").click();', | |
412 tab_index, windex) | |
413 self._ExecuteJavascript( | |
414 'document.getElementById("this-host-name").childNodes[0].value = "' + | |
415 new_name + '";', tab_index, windex) | |
416 self._ExecuteJavascript( | |
417 'document.getElementById("this-host-rename").click();', | |
418 tab_index, windex) | |
419 | |
420 def ConnectMe2Me(self, pin='111111', mode='IN_SESSION', | |
421 tab_index=1, windex=0): | |
422 """Connects to a Chromoting host and starts the session.""" | |
423 | |
424 # There is delay from the enabling remote connections to the host | |
425 # showing up in the host list. We need to reload the web app to get | |
426 # the host to show up. We will repeat this a few times to make sure | |
427 # eventually host appears. | |
428 for _ in range(1, 3): | |
429 self._ExecuteJavascript( | |
430 'window.location.reload();', | |
431 tab_index, windex) | |
432 | |
433 # pyauto _GetResultFromJSONRequest throws JSONInterfaceError after | |
434 # ~60 seconds if ExecuteJavascript is called right after reload. | |
435 # Waiting 2s here can avoid this. So instead of getting the error and | |
436 # wait ~60s, we wait 2s here. If the error still happens, the following | |
437 # retry will handle that. | |
438 time.sleep(2) | |
439 | |
440 # If this-host-connect is still not enabled, let's retry 3 times here. | |
441 this_host_connect_enabled = False | |
442 for _ in range(1, 3): | |
443 this_host_connect_enabled = self._WaitForJavascriptCondition( | |
444 'document.getElementById("this-host-connect")' | |
445 '.getAttribute("data-daemon-state") == "enabled"', | |
446 tab_index, windex) | |
447 if this_host_connect_enabled: | |
448 break | |
449 if this_host_connect_enabled: | |
450 break; | |
451 | |
452 # Clicking this-host-connect does work right after this-host-connect | |
453 # is enabled. Need to retry. | |
454 for _ in range(1, 3): | |
455 self._ExecuteJavascript( | |
456 'document.getElementById("this-host-connect").click();', | |
457 tab_index, windex) | |
458 | |
459 # pyauto _GetResultFromJSONRequest throws JSONInterfaceError after | |
460 # a long time out if WaitUntil is called right after click. | |
461 # Waiting 2s here can avoid this. | |
462 time.sleep(2) | |
463 | |
464 # If cannot detect that pin-form appears, try 3 times. | |
465 pin_form_exposed = False | |
466 for _ in range(1, 3): | |
467 pin_form_exposed = self._WaitForJavascriptCondition( | |
468 'document.getElementById("client-dialog")' | |
469 '.childNodes[9].hidden == false', | |
470 tab_index, windex) | |
471 if pin_form_exposed: | |
472 break | |
473 if pin_form_exposed: | |
474 break | |
475 | |
476 self._ExecuteJavascript( | |
477 'document.getElementById("pin-entry").value = "' + pin + '";', | |
478 tab_index, windex) | |
479 self.assertTrue( | |
480 self._ExecuteAndWaitForMode( | |
481 'document.getElementById("pin-form").childNodes[5].click();', | |
482 mode, tab_index, windex), | |
483 msg='Session was not started') | |
484 | 178 |
485 def Disconnect(self, tab_index=1, windex=0): | 179 def Disconnect(self, tab_index=1, windex=0): |
486 """Disconnects from the Chromoting it2me session on the client side.""" | 180 """Disconnects from the Chromoting session on the client side. |
487 self.assertTrue( | |
488 self._ExecuteAndWaitForMode( | |
489 'remoting.disconnect();', | |
490 'CLIENT_SESSION_FINISHED_IT2ME', tab_index, windex), | |
491 msg='Disconnecting it2me session from the client side failed') | |
492 | 181 |
493 def DisconnectMe2Me(self, confirmation=True, tab_index=1, windex=0): | 182 Returns: |
494 """Disconnects from the Chromoting me2me session on the client side.""" | 183 True on success; False otherwise. |
495 self.assertTrue( | 184 """ |
496 self._ExecuteAndWaitForMode( | 185 return self._ExecuteAndWaitForMode( |
497 'remoting.disconnect();', | 186 'remoting.disconnect();', |
498 'CLIENT_SESSION_FINISHED_ME2ME', tab_index, windex), | 187 'CLIENT_SESSION_FINISHED_IT2ME', tab_index, windex) |
499 msg='Disconnecting me2me session from the client side failed') | |
500 | |
501 if confirmation: | |
502 self.assertTrue( | |
503 self._ExecuteAndWaitForMode( | |
504 'document.getElementById("client-finished-me2me-button")' | |
505 '.click();', 'HOME', tab_index, windex), | |
506 msg='Failed to dismiss session finished dialog') | |
507 | |
508 def ReconnectMe2Me(self, pin='111111', tab_index=1, windex=0): | |
509 """Reconnects the me2me session.""" | |
510 self._ExecuteJavascript( | |
511 'document.getElementById("client-reconnect-button").click();', | |
512 tab_index, windex) | |
513 | |
514 # pyauto _GetResultFromJSONRequest throws JSONInterfaceError after | |
515 # a long time out if WaitUntil is called right after click. | |
516 time.sleep(2) | |
517 | |
518 # If cannot detect that pin-form appears, try 3 times. | |
519 for _ in range(1, 3): | |
520 pin_form_exposed = self._WaitForJavascriptCondition( | |
521 'document.getElementById("client-dialog")' | |
522 '.childNodes[9].hidden == false', | |
523 tab_index, windex) | |
524 if pin_form_exposed: | |
525 break | |
526 | |
527 self._ExecuteJavascript( | |
528 'document.getElementById("pin-entry").value = "' + pin + '";', | |
529 tab_index, windex) | |
530 self.assertTrue( | |
531 self._ExecuteAndWaitForMode( | |
532 'document.getElementById("pin-form").childNodes[5].click();', | |
533 'IN_SESSION', tab_index, windex), | |
534 msg='Session was not started') | |
OLD | NEW |