1424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# found in the LICENSE file. 490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import logging 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import os 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport pipes 8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import re 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import subprocess 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import sys 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import time 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.core import exceptions 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)from telemetry.core import forwarders 157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochfrom telemetry.core import util 16424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)from telemetry.core.backends import adb_commands 17a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)from telemetry.core.backends import browser_backend 18a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)from telemetry.core.backends.chrome import chrome_browser_backend 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)from telemetry.core.forwarders import android_forwarder 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdochutil.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'android') 22116680a4aac90f2aa7413d9095a592090648e557Ben Murdochfrom pylib.device import device_errors # pylint: disable=F0401 23116680a4aac90f2aa7413d9095a592090648e557Ben Murdochfrom pylib.device import intent # pylint: disable=F0401 24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 25a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 26a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)class AndroidBrowserBackendSettings(object): 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def __init__(self, activity, cmdline_file, package, pseudo_exec_name, 296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) supports_tab_control, relax_ssl_check=False): 30a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.activity = activity 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self._cmdline_file = cmdline_file 32a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.package = package 33a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.pseudo_exec_name = pseudo_exec_name 341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) self.supports_tab_control = supports_tab_control 356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) self.relax_ssl_check = relax_ssl_check 36a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def GetCommandLineFile(self, is_user_debug_build): # pylint: disable=W0613 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return self._cmdline_file 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def GetDevtoolsRemotePort(self, adb): 41a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) raise NotImplementedError() 42a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def RemoveProfile(self, adb): 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci files = adb.device().RunShellCommand( 45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 'ls "%s"' % self.profile_dir, as_root=True) 46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # Don't delete lib, since it is created by the installer. 47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) paths = ['"%s/%s"' % (self.profile_dir, f) for f in files if f != 'lib'] 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci adb.device().RunShellCommand('rm -r %s' % ' '.join(paths), as_root=True) 49a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def PushProfile(self, _new_profile_dir, _adb): 51a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) logging.critical('Profiles cannot be overriden with current configuration') 52a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) sys.exit(1) 53a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 54a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) @property 55bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch def profile_dir(self): 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return '/data/data/%s/' % self.package 57a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 58a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 59a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)class ChromeBackendSettings(AndroidBrowserBackendSettings): 60a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # Stores a default Preferences file, re-used to speed up "--page-repeat". 61a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) _default_preferences_file = None 62a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def GetCommandLineFile(self, is_user_debug_build): 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if is_user_debug_build: 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return '/data/local/tmp/chrome-command-line' 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) else: 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return '/data/local/chrome-command-line' 68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def __init__(self, package): 70a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) super(ChromeBackendSettings, self).__init__( 71a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) activity='com.google.android.apps.chrome.Main', 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cmdline_file=None, 73a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) package=package, 741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) pseudo_exec_name='chrome', 751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) supports_tab_control=True) 76a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def GetDevtoolsRemotePort(self, adb): 78a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return 'localabstract:chrome_devtools_remote' 79a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def PushProfile(self, new_profile_dir, adb): 81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # Pushing the profile is slow, so we don't want to do it every time. 82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch # Avoid this by pushing to a safe location using PushChangedFiles, and 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # then copying into the correct location on each test run. 84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) (profile_parent, profile_base) = os.path.split(new_profile_dir) 86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # If the path ends with a '/' python split will return an empty string for 87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # the base name; so we now need to get the base name from the directory. 88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if not profile_base: 89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) profile_base = os.path.basename(profile_parent) 90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) saved_profile_location = '/sdcard/profile/%s' % profile_base 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci adb.device().PushChangedFiles(new_profile_dir, saved_profile_location) 93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci adb.device().old_interface.EfficientDeviceDirectoryCopy( 955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu saved_profile_location, self.profile_dir) 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci dumpsys = adb.device().RunShellCommand( 97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'dumpsys package %s' % self.package) 98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) id_line = next(line for line in dumpsys if 'userId=' in line) 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) uid = re.search('\d+', id_line).group() 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci files = adb.device().RunShellCommand( 101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 'ls "%s"' % self.profile_dir, as_root=True) 102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) files.remove('lib') 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) paths = ['%s/%s' % (self.profile_dir, f) for f in files] 104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for path in paths: 105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extended_path = '%s %s/* %s/*/* %s/*/*/*' % (path, path, path, path) 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci adb.device().RunShellCommand( 107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'chown %s.%s %s' % (uid, uid, extended_path)) 108a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 109a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)class ContentShellBackendSettings(AndroidBrowserBackendSettings): 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def __init__(self, package): 111a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) super(ContentShellBackendSettings, self).__init__( 112a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) activity='org.chromium.content_shell_apk.ContentShellActivity', 113a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) cmdline_file='/data/local/tmp/content-shell-command-line', 114a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) package=package, 1151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) pseudo_exec_name='content_shell', 1161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) supports_tab_control=False) 117a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def GetDevtoolsRemotePort(self, adb): 119a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return 'localabstract:content_shell_devtools_remote' 120a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 121a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class ChromeShellBackendSettings(AndroidBrowserBackendSettings): 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def __init__(self, package): 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) super(ChromeShellBackendSettings, self).__init__( 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) activity='org.chromium.chrome.shell.ChromeShellActivity', 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) cmdline_file='/data/local/tmp/chrome-shell-command-line', 12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) package=package, 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pseudo_exec_name='chrome_shell', 1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) supports_tab_control=False) 13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def GetDevtoolsRemotePort(self, adb): 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return 'localabstract:chrome_shell_devtools_remote' 13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 134a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)class WebviewBackendSettings(AndroidBrowserBackendSettings): 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def __init__(self, package, 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci activity='org.chromium.telemetry_shell.TelemetryActivity'): 137a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) super(WebviewBackendSettings, self).__init__( 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci activity=activity, 139a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) cmdline_file='/data/local/tmp/webview-command-line', 140a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) package=package, 1411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) pseudo_exec_name='webview', 1421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) supports_tab_control=False) 143a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def GetDevtoolsRemotePort(self, adb): 145a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # The DevTools socket name for WebView depends on the activity PID's. 146a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) retries = 0 147a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) timeout = 1 148a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) pid = None 149a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) while True: 1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pids = adb.ExtractPid(self.package) 151a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (len(pids) > 0): 152a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) pid = pids[-1] 153a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break 154a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) time.sleep(timeout) 155a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) retries += 1 156a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) timeout *= 2 157a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if retries == 4: 158a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) logging.critical('android_browser_backend: Timeout while waiting for ' 159a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 'activity %s:%s to come up', 160a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.package, 161a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.activity) 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) raise exceptions.BrowserGoneException(self.browser, 163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 'Timeout waiting for PID.') 164a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return 'localabstract:webview_devtools_remote_%s' % str(pid) 165a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass WebviewShellBackendSettings(WebviewBackendSettings): 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def __init__(self, package): 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci super(WebviewShellBackendSettings, self).__init__( 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci activity='org.chromium.android_webview.shell.AwShellActivity', 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci package=package) 171a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 172a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend): 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """The backend for controlling a browser instance running on Android.""" 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def __init__(self, browser_options, backend_settings, use_rndis_forwarder, 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci output_profile_path, extensions_to_load, target_arch, 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci android_platform_backend): 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) super(AndroidBrowserBackend, self).__init__( 178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch supports_tab_control=backend_settings.supports_tab_control, 17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) supports_extensions=False, browser_options=browser_options, 18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) output_profile_path=output_profile_path, 18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) extensions_to_load=extensions_to_load) 18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if len(extensions_to_load) > 0: 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) raise browser_backend.ExtensionsNotSupportedException( 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'Android browser does not support extensions.') 18568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Initialize fields so that an explosion during init doesn't break in Close. 1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self._android_platform_backend = android_platform_backend 188a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self._backend_settings = backend_settings 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self._saved_cmdline = '' 1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._target_arch = target_arch 1916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) self._saved_sslflag = '' 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # TODO(tonyg): This is flaky because it doesn't reserve the port that it 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # allocates. Need to fix this. 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._port = adb_commands.AllocateTestServerPort() 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # Disables android.net SSL certificate check. This is necessary for 1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # applications using the android.net stack to work with proxy HTTPS server 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # created by telemetry 2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if self._backend_settings.relax_ssl_check: 2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self._saved_sslflag = self._adb.device().GetProp('socket.relaxsslcheck') 2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self._adb.device().SetProp('socket.relaxsslcheck', 'yes') 2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Kill old browser. 2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self._KillBrowser() 2067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if self._adb.device().old_interface.CanAccessProtectedFileContents(): 20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if self.browser_options.profile_dir: 2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self._backend_settings.PushProfile(self.browser_options.profile_dir, 2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self._adb) 211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) elif not self.browser_options.dont_override_profile: 2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self._backend_settings.RemoveProfile(self._adb) 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self._forwarder_factory = android_forwarder.AndroidForwarderFactory( 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self._adb, use_rndis_forwarder) 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if self.browser_options.netsim or use_rndis_forwarder: 2186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) assert use_rndis_forwarder, 'Netsim requires RNDIS forwarding.' 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.wpr_port_pairs = forwarders.PortPairs( 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) http=forwarders.PortPair(0, 80), 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) https=forwarders.PortPair(0, 443), 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dns=forwarders.PortPair(0, 53)) 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # Set the debug app if needed. 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if self._adb.IsUserBuild(): 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) logging.debug('User build device, setting debug app') 227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) self._adb.device().RunShellCommand( 228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'am set-debug-app --persistent %s' % self._backend_settings.package) 22958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci @property 2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def _adb(self): 2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return self._android_platform_backend.adb 2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def _KillBrowser(self): 2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # We use KillAll rather than ForceStop for efficiency reasons. 2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci try: 2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self._adb.device().KillAll(self._backend_settings.package, retries=0) 2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci except device_errors.CommandFailedError: 2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pass 2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 24158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) def _SetUpCommandLine(self): 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def QuoteIfNeeded(arg): 2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # Properly escape "key=valueA valueB" to "key='valueA valueB'" 2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # Values without spaces, or that seem to be quoted are left untouched. 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # This is required so CommandLine.java can parse valueB correctly rather 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # than as a separate switch. 247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) params = arg.split('=', 1) 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if len(params) != 2: 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return arg 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) key, values = params 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ' ' not in values: 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return arg 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if values[0] in '"\'' and values[-1] == values[0]: 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return arg 2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return '%s=%s' % (key, pipes.quote(values)) 25658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) args = [self._backend_settings.pseudo_exec_name] 25758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) args.extend(self.GetBrowserStartupArgs()) 2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content = ' '.join(QuoteIfNeeded(arg) for arg in args) 2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cmdline_file = self._backend_settings.GetCommandLineFile( 2601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self._adb.IsUserBuild()) 2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci as_root = self._adb.device().old_interface.CanAccessProtectedFileContents() 2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 263116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch try: 2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # Save the current command line to restore later, except if it appears to 2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # be a Telemetry created one. This is to prevent a common bug where 2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # --host-resolver-rules borks people's browsers if something goes wrong 2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # with Telemetry. 2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self._saved_cmdline = ''.join(self._adb.device().ReadFile(cmdline_file)) 2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if '--host-resolver-rules' in self._saved_cmdline: 2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self._saved_cmdline = '' 2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self._adb.device().WriteTextFile(cmdline_file, content, as_root=as_root) 272116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch except device_errors.CommandFailedError: 273116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch logging.critical('Cannot set Chrome command line. ' 274116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 'Fix this by flashing to a userdebug build.') 275116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sys.exit(1) 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def _RestoreCommandLine(self): 2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cmdline_file = self._backend_settings.GetCommandLineFile( 2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self._adb.IsUserBuild()) 2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci as_root = self._adb.device().old_interface.CanAccessProtectedFileContents() 2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self._adb.device().WriteTextFile(cmdline_file, self._saved_cmdline, 2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci as_root=as_root) 2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 284a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) def Start(self): 285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) self._SetUpCommandLine() 2866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) self._adb.device().RunShellCommand('logcat -c') 2881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if self.browser_options.startup_url: 2891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) url = self.browser_options.startup_url 290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) elif self.browser_options.profile_dir: 291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) url = None 2921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) else: 293f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # If we have no existing tabs start with a blank page since default 294f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # startup with the NTP can lead to race conditions with Telemetry 2951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) url = 'about:blank' 2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # Dismiss any error dialogs. Limit the number in case we have an error loop 2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # or we are failing to dismiss. 2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for _ in xrange(10): 2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not self._adb.device().old_interface.DismissCrashDialogIfNeeded(): 3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break 301116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch self._adb.device().StartActivity( 302116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch intent.Intent(package=self._backend_settings.package, 303116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch activity=self._backend_settings.activity, 304116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch action=None, data=url, category=None), 305116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blocking=True) 306a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 307a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self._adb.Forward('tcp:%d' % self._port, 3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self._backend_settings.GetDevtoolsRemotePort(self._adb)) 309a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) try: 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._WaitForBrowserToComeUp() 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) except exceptions.BrowserGoneException: 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.critical('Failed to connect to browser.') 3145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if not self._adb.device().old_interface.CanAccessProtectedFileContents(): 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.critical( 3162385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch 'Resolve this by either: ' 3172385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch '(1) Flashing to a userdebug build OR ' 3182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch '(2) Manually enabling web debugging in Chrome at ' 3192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch 'Settings > Developer tools > Enable USB Web debugging.') 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sys.exit(1) 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) except: 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) import traceback 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) traceback.print_exc() 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.Close() 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) raise 3260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) finally: 3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self._RestoreCommandLine() 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def GetBrowserStartupArgs(self): 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) args = super(AndroidBrowserBackend, self).GetBrowserStartupArgs() 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if self.forwarder_factory.does_forwarder_override_dns: 33258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) args = [arg for arg in args 33358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if not arg.startswith('--host-resolver-rules')] 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) args.append('--enable-remote-debugging') 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) args.append('--disable-fre') 336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) args.append('--disable-external-intent-requests') 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return args 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @property 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def forwarder_factory(self): 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return self._forwarder_factory 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) @property 34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) def adb(self): 34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return self._adb 34690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) @property 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def pid(self): 34968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) pids = self._adb.ExtractPid(self._backend_settings.package) 35068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if not pids: 351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) raise exceptions.BrowserGoneException(self.browser) 35268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return int(pids[0]) 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 354bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch @property 355bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch def browser_directory(self): 356bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch return None 357bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 358bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch @property 359bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch def profile_directory(self): 360bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch return self._backend_settings.profile_dir 361bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 362424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) @property 363424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) def package(self): 364424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return self._backend_settings.package 365424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 3664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) @property 3674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) def activity(self): 3684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return self._backend_settings.activity 3694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def __del__(self): 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.Close() 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def Close(self): 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) super(AndroidBrowserBackend, self).Close() 3751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self._KillBrowser() 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) # Restore android.net SSL check 3786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if self._backend_settings.relax_ssl_check: 3796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) self._adb.device().SetProp('socket.relaxsslcheck', self._saved_sslflag) 3806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 38158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if self._output_profile_path: 38258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) logging.info("Pulling profile directory from device: '%s'->'%s'.", 38358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) self._backend_settings.profile_dir, 38458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) self._output_profile_path) 385424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) # To minimize bandwidth it might be good to look at whether all the data 386424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) # pulled down is really needed e.g. .pak files. 387f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if not os.path.exists(self._output_profile_path): 388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) os.makedirs(self._output_profile_pathame) 389f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) files = self.adb.device().RunShellCommand( 390a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 'ls "%s"' % self._backend_settings.profile_dir) 391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for f in files: 392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # Don't pull lib, since it is created by the installer. 393f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if f != 'lib': 394f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) source = '%s%s' % (self._backend_settings.profile_dir, f) 395f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) dest = os.path.join(self._output_profile_path, f) 396f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # self._adb.Pull(source, dest) doesn't work because its timeout 397f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # is fixed in android's adb_interface at 60 seconds, which may 398f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # be too short to pull the cache. 399f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) cmd = 'pull %s %s' % (source, dest) 4005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu self._adb.device().old_interface.Adb().SendCommand( 4015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu cmd, timeout_time=240) 402424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def IsBrowserRunning(self): 404a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) pids = self._adb.ExtractPid(self._backend_settings.package) 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return len(pids) != 0 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def GetRemotePort(self, local_port): 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return local_port 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def GetStandardOutput(self): 411f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return '\n'.join(self._adb.device().RunShellCommand('logcat -d -t 500')) 4127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def GetStackTrace(self): 4147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def Decorate(title, content): 4157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return title + '\n' + content + '\n' + '*' * 80 + '\n' 4167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch # Get the last lines of logcat (large enough to contain stacktrace) 4177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch logcat = self.GetStandardOutput() 4187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ret = Decorate('Logcat', logcat) 4197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch stack = os.path.join(util.GetChromiumSrcDir(), 'third_party', 4207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 'android_platform', 'development', 'scripts', 'stack') 4217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch # Try to symbolize logcat. 4227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if os.path.exists(stack): 4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cmd = [stack] 4245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if self._target_arch: 4255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cmd.append('--arch=%s' % self._target_arch) 4265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE) 4277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ret += Decorate('Stack from Logcat', p.communicate(input=logcat)[0]) 4287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch # Try to get tombstones. 4307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch tombstones = os.path.join(util.GetChromiumSrcDir(), 'build', 'android', 4317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 'tombstones.py') 4327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if os.path.exists(tombstones): 4337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ret += Decorate('Tombstones', 4347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch subprocess.Popen([tombstones, '-w', '--device', 4355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu self._adb.device_serial()], 4367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch stdout=subprocess.PIPE).communicate()[0]) 4377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return ret 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 43958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) def AddReplayServerOptions(self, extra_wpr_args): 4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if not self.forwarder_factory.does_forwarder_override_dns: 44158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) extra_wpr_args.append('--no-dns_forwarding') 442f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if self.browser_options.netsim: 443f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extra_wpr_args.append('--net=%s' % self.browser_options.netsim) 444