def __init__(self, browser_type, finder_options, android_platform, backend_settings, apk_name): super(PossibleAndroidBrowser, self).__init__(browser_type, 'android', backend_settings.supports_tab_control) assert browser_type in FindAllBrowserTypes(finder_options), ( 'Please add %s to android_browser_finder.FindAllBrowserTypes' % browser_type) self._platform = android_platform self._platform_backend = (android_platform._platform_backend) # pylint: disable=protected-access self._backend_settings = backend_settings self._local_apk = None if browser_type == 'exact': if not os.path.exists(apk_name): raise exceptions.PathMissingError( 'Unable to find exact apk %s specified by --browser-executable' % apk_name) self._local_apk = apk_name elif apk_name: assert finder_options.chrome_root, ( 'Must specify Chromium source to use apk_name') chrome_root = finder_options.chrome_root candidate_apks = [] for build_dir, build_type in util.GetBuildDirectories(): apk_full_name = os.path.join(chrome_root, build_dir, build_type, 'apks', apk_name) if os.path.exists(apk_full_name): last_changed = os.path.getmtime(apk_full_name) candidate_apks.append((last_changed, apk_full_name)) if candidate_apks: # Find the candidate .apk with the latest modification time. newest_apk_path = sorted(candidate_apks)[-1][1] self._local_apk = newest_apk_path
def GetBuildTypeOfPath(path): if not path: return None for build_dir, build_type in util.GetBuildDirectories(): if os.path.join(build_dir, build_type) in path: return build_type return None
def __init__(self, browser_type, finder_options, android_platform, backend_settings, apk_name): super(PossibleAndroidBrowser, self).__init__(browser_type, 'android', backend_settings.supports_tab_control) assert browser_type in FindAllBrowserTypes(finder_options), ( 'Please add %s to android_browser_finder.FindAllBrowserTypes' % browser_type) self._platform = android_platform self._platform_backend = (android_platform._platform_backend) # pylint: disable=W0212 self._backend_settings = backend_settings self._local_apk = None chrome_root = util.GetChromiumSrcDir() if apk_name: candidate_apks = [] for build_dir, build_type in util.GetBuildDirectories(): apk_full_name = os.path.join(chrome_root, build_dir, build_type, 'apks', apk_name) if os.path.exists(apk_full_name): last_changed = os.path.getmtime(apk_full_name) candidate_apks.append((last_changed, apk_full_name)) if candidate_apks: # Find the canadidate .apk with the latest modification time. newest_apk_path = sorted(candidate_apks)[-1][1] self._local_apk = newest_apk_path
def _FindMatchingUnstrippedLibraryOnHost(device, lib): lib_base = os.path.basename(lib) device_md5sums = md5sum.CalculateDeviceMd5Sums([lib], device) if lib not in device_md5sums: return None device_md5 = device_md5sums[lib] def FindMatchingStrippedLibrary(out_path): # First find a matching stripped library on the host. This avoids the need # to pull the stripped library from the device, which can take tens of # seconds. # Check the GN stripped lib path first, and the GYP ones afterwards. host_lib_path = os.path.join(out_path, lib_base) host_lib_pattern = os.path.join(out_path, '*_apk', 'libs', '*', lib_base) for stripped_host_lib in [host_lib_path] + glob.glob(host_lib_pattern): if os.path.exists(stripped_host_lib): with open(stripped_host_lib) as f: host_md5 = hashlib.md5(f.read()).hexdigest() if host_md5 == device_md5: return stripped_host_lib return None out_path = None stripped_host_lib = None for out_path in util.GetBuildDirectories(): stripped_host_lib = FindMatchingStrippedLibrary(out_path) if stripped_host_lib: break if not stripped_host_lib: return None # The corresponding unstripped library will be under lib.unstripped for GN, or # lib for GYP. unstripped_host_lib_paths = [ os.path.join(out_path, 'lib.unstripped', lib_base), os.path.join(out_path, 'lib', lib_base) ] unstripped_host_lib = next( (lib for lib in unstripped_host_lib_paths if os.path.exists(lib)), None) if unstripped_host_lib is None: return None # Make sure the unstripped library matches the stripped one. We do this # by comparing the hashes of text sections in both libraries. This isn't an # exact guarantee, but should still give reasonable confidence that the # libraries are compatible. # TODO(skyostil): Check .note.gnu.build-id instead once we're using # --build-id=sha1. # pylint: disable=undefined-loop-variable if (_ElfSectionMd5Sum(unstripped_host_lib, _TEXT_SECTION) != _ElfSectionMd5Sum(stripped_host_lib, _TEXT_SECTION)): return None return unstripped_host_lib
def _FindLocalApk(chrome_root, apk_name): found_apk_path = None found_last_changed = None for build_path in util.GetBuildDirectories(chrome_root): apk_path = os.path.join(build_path, 'apks', apk_name) if os.path.exists(apk_path): last_changed = os.path.getmtime(apk_path) # Keep the most recently updated apk only. if last_changed is None or last_changed > found_last_changed: found_apk_path = apk_path found_last_changed = last_changed return found_apk_path
def GetStackTrace(self): """Returns stack trace. The stack trace consists of raw logcat dump, logcat dump with symbols, and stack info from tomstone files. """ def Decorate(title, content): return "%s\n%s\n%s\n" % (title, content, '*' * 80) # Get the UI nodes that can be found on the screen ret = Decorate('UI dump', '\n'.join(self.GetSystemUi().ScreenDump())) # Get the last lines of logcat (large enough to contain stacktrace) logcat = self.GetLogCat() ret += Decorate('Logcat', logcat) stack = os.path.join(util.GetChromiumSrcDir(), 'third_party', 'android_platform', 'development', 'scripts', 'stack') # Try to symbolize logcat. if os.path.exists(stack): cmd = [stack] arch = self.GetArchName() arch = _ARCH_TO_STACK_TOOL_ARCH.get(arch, arch) cmd.append('--arch=%s' % arch) for build_path in util.GetBuildDirectories(): if os.path.exists(build_path): cmd.append('--output-directory=%s' % build_path) break p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE) ret += Decorate('Stack from Logcat', p.communicate(input=logcat)[0]) # Try to get tombstones. tombstones = os.path.join(util.GetChromiumSrcDir(), 'build', 'android', 'tombstones.py') if os.path.exists(tombstones): tombstones_cmd = [ tombstones, '-w', '--device', self._device.adb.GetDeviceSerial(), '--adb-path', self._device.adb.GetAdbPath(), ] ret += Decorate( 'Tombstones', subprocess.Popen(tombstones_cmd, stdout=subprocess.PIPE).communicate()[0]) return (True, ret)
def _FindNewestFlushUtility(self): flush_command = None flush_command_mtime = 0 chrome_root = util.GetChromiumSrcDir() for build_dir, build_type in util.GetBuildDirectories(): candidate = os.path.join(chrome_root, build_dir, build_type, self.GetFlushUtilityName()) if os.access(candidate, os.X_OK): candidate_mtime = os.stat(candidate).st_mtime if candidate_mtime > flush_command_mtime: flush_command = candidate flush_command_mtime = candidate_mtime return flush_command
def _FindLocallyBuiltPath(binary_name): """Finds the most recently built |binary_name|.""" command = None command_mtime = 0 required_mode = os.X_OK if binary_name.endswith('.apk'): required_mode = os.R_OK for build_path in util.GetBuildDirectories(): candidate = os.path.join(build_path, binary_name) if os.path.isfile(candidate) and os.access(candidate, required_mode): candidate_mtime = os.stat(candidate).st_mtime if candidate_mtime > command_mtime: command = candidate command_mtime = candidate_mtime return command
def FindLocallyBuiltPath(binary_name): """Finds the most recently built |binary_name|.""" command = None command_mtime = 0 chrome_root = util.GetChromiumSrcDir() required_mode = os.X_OK if binary_name.endswith('.apk'): required_mode = os.R_OK for build_dir, build_type in util.GetBuildDirectories(): candidate = os.path.join(chrome_root, build_dir, build_type, binary_name) if os.path.isfile(candidate) and os.access(candidate, required_mode): candidate_mtime = os.stat(candidate).st_mtime if candidate_mtime > command_mtime: command = candidate command_mtime = candidate_mtime return command
def _InstallNfcApk(self): """Installs the APK that allows VR tests to simulate a headset NFC scan.""" chromium_root = path_util.GetChromiumSrcDir() # Find the most recently build APK candidate_apks = [] for build_path in util.GetBuildDirectories(chromium_root): apk_path = os.path.join(build_path, 'apks', 'VrNfcSimulator.apk') if os.path.exists(apk_path): last_changed = os.path.getmtime(apk_path) candidate_apks.append((last_changed, apk_path)) if not candidate_apks: raise RuntimeError( 'Could not find VrNfcSimulator.apk in a build output directory') newest_apk_path = sorted(candidate_apks)[-1][1] self._platform.InstallApplication( os.path.join(chromium_root, newest_apk_path))
def _FindMatchingUnstrippedLibraryOnHost(device, lib): lib_base = os.path.basename(lib) device_md5 = device.RunShellCommand('md5 "%s"' % lib, as_root=True)[0] device_md5 = device_md5.split(' ', 1)[0] def FindMatchingStrippedLibrary(out_path): # First find a matching stripped library on the host. This avoids the need # to pull the stripped library from the device, which can take tens of # seconds. host_lib_pattern = os.path.join(out_path, '*_apk', 'libs', '*', lib_base) for stripped_host_lib in glob.glob(host_lib_pattern): with open(stripped_host_lib) as f: host_md5 = hashlib.md5(f.read()).hexdigest() if host_md5 == device_md5: return stripped_host_lib return None out_path = None stripped_host_lib = None for out_path in util.GetBuildDirectories(): stripped_host_lib = FindMatchingStrippedLibrary(out_path) if stripped_host_lib: break if not stripped_host_lib: return None # The corresponding unstripped library will be under out/Release/lib. unstripped_host_lib = os.path.join(out_path, 'lib', lib_base) # Make sure the unstripped library matches the stripped one. We do this # by comparing the hashes of text sections in both libraries. This isn't an # exact guarantee, but should still give reasonable confidence that the # libraries are compatible. # TODO(skyostil): Check .note.gnu.build-id instead once we're using # --build-id=sha1. # pylint: disable=undefined-loop-variable if (_ElfSectionMd5Sum(unstripped_host_lib, _TEXT_SECTION) != _ElfSectionMd5Sum(stripped_host_lib, _TEXT_SECTION)): return None return unstripped_host_lib
def __init__(self, browser_type, finder_options, backend_settings, apk_name): super(PossibleAndroidBrowser, self).__init__(browser_type, finder_options) self._backend_settings = backend_settings self._local_apk = None chrome_root = util.GetChromiumSrcDir() if apk_name: candidate_apks = [] for build_dir, build_type in util.GetBuildDirectories(): apk_full_name = os.path.join(chrome_root, build_dir, build_type, 'apks', apk_name) if os.path.exists(apk_full_name): last_changed = os.path.getmtime(apk_full_name) candidate_apks.append((last_changed, apk_full_name)) if candidate_apks: # Find the canadidate .apk with the latest modification time. newest_apk_path = sorted(candidate_apks)[-1][1] self._local_apk = newest_apk_path
def testNoAdTaggingRuleset(self): # This tests (badly) assumes that util.GetBuildDirectories() will always # return a list of multiple directories, with Debug ordered before Release. # This is not the case if CHROMIUM_OUTPUT_DIR is set or a build.ninja file # exists in the current working directory - in those cases, only a single # directory is returned. So, abort early if we only get back one directory. num_dirs = 0 for _ in util.GetBuildDirectories(self._chrome_root): num_dirs += 1 if num_dirs < 2: return benchmark = perf_benchmark.PerfBenchmark() options = options_for_unittests.GetCopy() # Set the chrome root to avoid using a ruleset from an existing "Release" # out dir. options.chrome_root = self._output_dir benchmark.CustomizeOptions(options) self._ExpectAdTaggingProfileFiles(options.browser_options, False)
def testAdTaggingRulesetOutputDirNotFound(self): # Same as the above test but use Debug instead of Release. This should # cause the benchmark to fail to find the ruleset because we only check # directories matching the browser_type. self._PopulateGenFiles(os.path.join(self._chrome_root, 'out', 'Debug')) # This tests (badly) assumes that util.GetBuildDirectories() will always # return a list of multiple directories, with Debug ordered before Release. # This is not the case if CHROMIUM_OUTPUT_DIR is set or a build.ninja file # exists in the current working directory - in those cases, only a single # directory is returned. So, abort early if we only get back one directory. num_dirs = 0 for _ in util.GetBuildDirectories(self._chrome_root): num_dirs += 1 if num_dirs < 2: return benchmark = perf_benchmark.PerfBenchmark() options = options_for_unittests.GetCopy() options.chrome_root = self._chrome_root options.browser_options.browser_type = "release" benchmark.CustomizeOptions(options) self._ExpectAdTaggingProfileFiles(options.browser_options, False)
# to pull the stripped library from the presentation.device, which can take tens of # seconds. # Check the GN stripped lib path first, and the GYP ones afterwards. host_lib_path = os.path.join(out_path, lib_base) host_lib_pattern = os.path.join(out_path, '*_apk', 'libs', '*', lib_base) for stripped_host_lib in [host_lib_path] + glob.glob(host_lib_pattern): if os.path.exists(stripped_host_lib): with open(stripped_host_lib) as f: host_md5 = hashlib.md5(f.read()).hexdigest() if host_md5 == device_md5: return stripped_host_lib return None out_path = None stripped_host_lib = None for out_path in util.GetBuildDirectories(): stripped_host_lib = FindMatchingStrippedLibrary(out_path) if stripped_host_lib: break if not stripped_host_lib: return None # The corresponding unstripped library will be under lib.unstripped for GN, or # lib for GYP. unstripped_host_lib_paths = [ os.path.join(out_path, 'lib.unstripped', lib_base), os.path.join(out_path, 'lib', lib_base) ] unstripped_host_lib = next( (lib for lib in unstripped_host_lib_paths if os.path.exists(lib)), None)
def FindAllAvailableBrowsers(finder_options): """Finds all the desktop browsers available on this machine.""" browsers = [] if not CanFindAvailableBrowsers(): return [] has_display = True if (sys.platform.startswith('linux') and os.getenv('DISPLAY') == None): has_display = False # Look for a browser in the standard chrome build locations. if finder_options.chrome_root: chrome_root = finder_options.chrome_root else: chrome_root = util.GetChromiumSrcDir() flash_bin_dir = os.path.join(chrome_root, 'third_party', 'adobe', 'flash', 'binaries', 'ppapi') chromium_app_names = [] if sys.platform == 'darwin': chromium_app_names.append('Chromium.app/Contents/MacOS/Chromium') chromium_app_names.append( 'Google Chrome.app/Contents/MacOS/Google Chrome') content_shell_app_name = 'Content Shell.app/Contents/MacOS/Content Shell' flash_bin = 'PepperFlashPlayer.plugin' flash_path = os.path.join(flash_bin_dir, 'mac', flash_bin) flash_path_64 = os.path.join(flash_bin_dir, 'mac_64', flash_bin) elif sys.platform.startswith('linux'): chromium_app_names.append('chrome') content_shell_app_name = 'content_shell' flash_bin = 'libpepflashplayer.so' flash_path = os.path.join(flash_bin_dir, 'linux', flash_bin) flash_path_64 = os.path.join(flash_bin_dir, 'linux_x64', flash_bin) elif sys.platform.startswith('win'): chromium_app_names.append('chrome.exe') content_shell_app_name = 'content_shell.exe' flash_bin = 'pepflashplayer.dll' flash_path = os.path.join(flash_bin_dir, 'win', flash_bin) flash_path_64 = os.path.join(flash_bin_dir, 'win_x64', flash_bin) else: raise Exception('Platform not recognized') def IsExecutable(path): return os.path.isfile(path) and os.access(path, os.X_OK) # Add the explicit browser executable if given. if finder_options.browser_executable: normalized_executable = os.path.expanduser( finder_options.browser_executable) if IsExecutable(normalized_executable): browser_directory = os.path.dirname( finder_options.browser_executable) browsers.append( PossibleDesktopBrowser('exact', finder_options, normalized_executable, flash_path, False, browser_directory)) else: raise Exception( '%s specified by --browser-executable does not exist', normalized_executable) def AddIfFound(browser_type, build_dir, type_dir, app_name, content_shell): browser_directory = os.path.join(chrome_root, build_dir, type_dir) app = os.path.join(browser_directory, app_name) if IsExecutable(app): is_64 = browser_type.endswith('_x64') browsers.append( PossibleDesktopBrowser(browser_type, finder_options, app, flash_path_64 if is_64 else flash_path, content_shell, browser_directory, is_local_build=True)) return True return False # Add local builds for build_dir, build_type in util.GetBuildDirectories(): for chromium_app_name in chromium_app_names: AddIfFound(build_type.lower(), build_dir, build_type, chromium_app_name, False) AddIfFound('content-shell-' + build_type.lower(), build_dir, build_type, content_shell_app_name, True) # Mac-specific options. if sys.platform == 'darwin': mac_canary_root = '/Applications/Google Chrome Canary.app/' mac_canary = mac_canary_root + 'Contents/MacOS/Google Chrome Canary' mac_system_root = '/Applications/Google Chrome.app' mac_system = mac_system_root + '/Contents/MacOS/Google Chrome' if IsExecutable(mac_canary): browsers.append( PossibleDesktopBrowser('canary', finder_options, mac_canary, None, False, mac_canary_root)) if IsExecutable(mac_system): browsers.append( PossibleDesktopBrowser('system', finder_options, mac_system, None, False, mac_system_root)) # Linux specific options. if sys.platform.startswith('linux'): # Look for a google-chrome instance. found = False try: with open(os.devnull, 'w') as devnull: found = subprocess.call(['google-chrome', '--version'], stdout=devnull, stderr=devnull) == 0 except OSError: pass if found: browsers.append( PossibleDesktopBrowser('system', finder_options, 'google-chrome', None, False, '/opt/google/chrome')) # Win32-specific options. if sys.platform.startswith('win'): system_path = os.path.join('Google', 'Chrome', 'Application') canary_path = os.path.join('Google', 'Chrome SxS', 'Application') win_search_paths = [ os.getenv('PROGRAMFILES(X86)'), os.getenv('PROGRAMFILES'), os.getenv('LOCALAPPDATA') ] def AddIfFoundWin(browser_name, search_path, app_path): browser_directory = os.path.join(search_path, app_path) for chromium_app_name in chromium_app_names: app = os.path.join(browser_directory, chromium_app_name) if IsExecutable(app): browsers.append( PossibleDesktopBrowser(browser_name, finder_options, app, None, False, browser_directory)) return True return False for path in win_search_paths: if not path: continue if AddIfFoundWin('canary', path, canary_path): break for path in win_search_paths: if not path: continue if AddIfFoundWin('system', path, system_path): break if len(browsers) and not has_display: logging.warning( 'Found (%s), but you do not have a DISPLAY environment set.' % ','.join([b.browser_type for b in browsers])) return [] return browsers
def GetStackTrace(self): """Returns a recent stack trace from a crash. The stack trace consists of raw logcat dump, logcat dump with symbols, and stack info from tombstone files, all concatenated into one string. """ def Decorate(title, content): if not content or content.isspace(): content = ('**EMPTY** - could be explained by log messages ' 'preceding the previous python Traceback - best wishes') return "%s\n%s\n%s\n" % (title, content, '*' * 80) # Get the UI nodes that can be found on the screen ret = Decorate('UI dump', '\n'.join(self.GetSystemUi().ScreenDump())) # Get the last lines of logcat (large enough to contain stacktrace) logcat = self.GetLogCat() ret += Decorate('Logcat', logcat) # Determine the build directory. build_path = '.' for b in util.GetBuildDirectories(): if os.path.exists(b): build_path = b break # Try to symbolize logcat. chromium_src_dir = util.GetChromiumSrcDir() stack = os.path.join(chromium_src_dir, 'third_party', 'android_platform', 'development', 'scripts', 'stack') if _ExecutableExists(stack): cmd = [stack] arch = self.GetArchName() arch = _ARCH_TO_STACK_TOOL_ARCH.get(arch, arch) cmd.append('--arch=%s' % arch) cmd.append('--output-directory=%s' % build_path) p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE) ret += Decorate('Stack from Logcat', p.communicate(input=logcat)[0]) # Try to get tombstones. tombstones = os.path.join(chromium_src_dir, 'build', 'android', 'tombstones.py') if _ExecutableExists(tombstones): tombstones_cmd = [ tombstones, '-w', '--device', self._device.adb.GetDeviceSerial(), '--adb-path', self._device.adb.GetAdbPath(), ] ret += Decorate('Tombstones', subprocess.Popen(tombstones_cmd, stdout=subprocess.PIPE).communicate()[0]) # Attempt to get detailed stack traces with Crashpad. stackwalker_path = os.path.join(chromium_src_dir, 'build', 'android', 'stacktrace', 'crashpad_stackwalker.py') minidump_stackwalk_path = os.path.join(build_path, 'minidump_stackwalk') if (_ExecutableExists(stackwalker_path) and _ExecutableExists(minidump_stackwalk_path)): crashpad_cmd = [ stackwalker_path, '--device', self._device.adb.GetDeviceSerial(), '--adb-path', self._device.adb.GetAdbPath(), '--build-path', build_path, '--chrome-cache-path', os.path.join( self.GetProfileDir( self._ExtractLastNativeCrashPackageFromLogcat(logcat)), 'cache'), ] ret += Decorate('Crashpad stackwalk', subprocess.Popen(crashpad_cmd, stdout=subprocess.PIPE).communicate()[0]) return (True, ret)