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