1# Copyright 2013 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"""Finds desktop browsers that can be controlled by telemetry.""" 5 6import logging 7import os 8import subprocess 9import sys 10 11from telemetry.core import platform as platform_module 12from telemetry.core import browser 13from telemetry.core import possible_browser 14from telemetry.core.backends.chrome import desktop_browser_backend 15from telemetry.util import path 16 17 18class PossibleDesktopBrowser(possible_browser.PossibleBrowser): 19 """A desktop browser that can be controlled.""" 20 21 def __init__(self, browser_type, finder_options, executable, flash_path, 22 is_content_shell, browser_directory, is_local_build=False): 23 target_os = sys.platform.lower() 24 super(PossibleDesktopBrowser, self).__init__(browser_type, target_os, 25 finder_options, not is_content_shell) 26 assert browser_type in FindAllBrowserTypes(finder_options), \ 27 ('Please add %s to desktop_browser_finder.FindAllBrowserTypes' % 28 browser_type) 29 self._local_executable = executable 30 self._flash_path = flash_path 31 self._is_content_shell = is_content_shell 32 self._browser_directory = browser_directory 33 self.is_local_build = is_local_build 34 35 def __repr__(self): 36 return 'PossibleDesktopBrowser(type=%s, executable=%s, flash=%s)' % ( 37 self.browser_type, self._local_executable, self._flash_path) 38 39 def _InitPlatformIfNeeded(self): 40 if self._platform: 41 return 42 43 self._platform = platform_module.GetHostPlatform() 44 45 # pylint: disable=W0212 46 self._platform_backend = self._platform._platform_backend 47 48 def Create(self): 49 if self._flash_path and not os.path.exists(self._flash_path): 50 logging.warning( 51 'Could not find Flash at %s. Continuing without Flash.\n' 52 'To run with Flash, check it out via http://go/read-src-internal', 53 self._flash_path) 54 self._flash_path = None 55 56 self._InitPlatformIfNeeded() 57 58 backend = desktop_browser_backend.DesktopBrowserBackend( 59 self.finder_options.browser_options, self._local_executable, 60 self._flash_path, self._is_content_shell, self._browser_directory, 61 output_profile_path=self.finder_options.output_profile_path, 62 extensions_to_load=self.finder_options.extensions_to_load) 63 return browser.Browser(backend, 64 self._platform_backend, 65 self._archive_path, 66 self._append_to_existing_wpr, 67 self._make_javascript_deterministic, 68 self._credentials_path) 69 70 def SupportsOptions(self, finder_options): 71 if (len(finder_options.extensions_to_load) != 0) and self._is_content_shell: 72 return False 73 return True 74 75 def UpdateExecutableIfNeeded(self): 76 pass 77 78 def last_modification_time(self): 79 if os.path.exists(self._local_executable): 80 return os.path.getmtime(self._local_executable) 81 return -1 82 83def SelectDefaultBrowser(possible_browsers): 84 local_builds_by_date = [ 85 b for b in sorted(possible_browsers, 86 key=lambda b: b.last_modification_time()) 87 if b.is_local_build] 88 if local_builds_by_date: 89 return local_builds_by_date[-1] 90 return None 91 92def CanFindAvailableBrowsers(): 93 return not platform_module.GetHostPlatform().GetOSName() == 'chromeos' 94 95def FindAllBrowserTypes(_): 96 return [ 97 'exact', 98 'reference', 99 'release', 100 'release_x64', 101 'debug', 102 'debug_x64', 103 'canary', 104 'content-shell-debug', 105 'content-shell-debug_x64', 106 'content-shell-release', 107 'content-shell-release_x64', 108 'system'] 109 110def FindAllAvailableBrowsers(finder_options): 111 """Finds all the desktop browsers available on this machine.""" 112 browsers = [] 113 114 if not CanFindAvailableBrowsers(): 115 return [] 116 117 has_display = True 118 if (sys.platform.startswith('linux') and 119 os.getenv('DISPLAY') == None): 120 has_display = False 121 122 # Look for a browser in the standard chrome build locations. 123 if finder_options.chrome_root: 124 chrome_root = finder_options.chrome_root 125 else: 126 chrome_root = path.GetChromiumSrcDir() 127 128 flash_bin_dir = os.path.join( 129 chrome_root, 'third_party', 'adobe', 'flash', 'binaries', 'ppapi') 130 131 chromium_app_names = [] 132 if sys.platform == 'darwin': 133 chromium_app_names.append('Chromium.app/Contents/MacOS/Chromium') 134 chromium_app_names.append('Google Chrome.app/Contents/MacOS/Google Chrome') 135 content_shell_app_name = 'Content Shell.app/Contents/MacOS/Content Shell' 136 flash_bin = 'PepperFlashPlayer.plugin' 137 flash_path = os.path.join(flash_bin_dir, 'mac', flash_bin) 138 flash_path_64 = os.path.join(flash_bin_dir, 'mac_64', flash_bin) 139 elif sys.platform.startswith('linux'): 140 chromium_app_names.append('chrome') 141 content_shell_app_name = 'content_shell' 142 flash_bin = 'libpepflashplayer.so' 143 flash_path = os.path.join(flash_bin_dir, 'linux', flash_bin) 144 flash_path_64 = os.path.join(flash_bin_dir, 'linux_x64', flash_bin) 145 elif sys.platform.startswith('win'): 146 chromium_app_names.append('chrome.exe') 147 content_shell_app_name = 'content_shell.exe' 148 flash_bin = 'pepflashplayer.dll' 149 flash_path = os.path.join(flash_bin_dir, 'win', flash_bin) 150 flash_path_64 = os.path.join(flash_bin_dir, 'win_x64', flash_bin) 151 else: 152 raise Exception('Platform not recognized') 153 154 # Add the explicit browser executable if given. 155 if finder_options.browser_executable: 156 normalized_executable = os.path.expanduser( 157 finder_options.browser_executable) 158 if path.IsExecutable(normalized_executable): 159 browser_directory = os.path.dirname(finder_options.browser_executable) 160 browsers.append(PossibleDesktopBrowser('exact', finder_options, 161 normalized_executable, flash_path, 162 False, browser_directory)) 163 else: 164 raise Exception('%s specified by --browser-executable does not exist', 165 normalized_executable) 166 167 def AddIfFound(browser_type, build_dir, type_dir, app_name, content_shell): 168 browser_directory = os.path.join(chrome_root, build_dir, type_dir) 169 app = os.path.join(browser_directory, app_name) 170 if path.IsExecutable(app): 171 is_64 = browser_type.endswith('_x64') 172 browsers.append(PossibleDesktopBrowser( 173 browser_type, finder_options, app, 174 flash_path_64 if is_64 else flash_path, 175 content_shell, browser_directory, is_local_build=True)) 176 return True 177 return False 178 179 # Add local builds 180 for build_dir, build_type in path.GetBuildDirectories(): 181 for chromium_app_name in chromium_app_names: 182 AddIfFound(build_type.lower(), build_dir, build_type, 183 chromium_app_name, False) 184 AddIfFound('content-shell-' + build_type.lower(), build_dir, build_type, 185 content_shell_app_name, True) 186 187 reference_build_root = os.path.join( 188 chrome_root, 'chrome', 'tools', 'test', 'reference_build') 189 190 # Mac-specific options. 191 if sys.platform == 'darwin': 192 mac_canary_root = '/Applications/Google Chrome Canary.app/' 193 mac_canary = mac_canary_root + 'Contents/MacOS/Google Chrome Canary' 194 mac_system_root = '/Applications/Google Chrome.app' 195 mac_system = mac_system_root + '/Contents/MacOS/Google Chrome' 196 mac_reference_root = reference_build_root + '/chrome_mac/Google Chrome.app/' 197 mac_reference = mac_reference_root + 'Contents/MacOS/Google Chrome' 198 if path.IsExecutable(mac_canary): 199 browsers.append(PossibleDesktopBrowser('canary', finder_options, 200 mac_canary, None, False, 201 mac_canary_root)) 202 203 if path.IsExecutable(mac_system): 204 browsers.append(PossibleDesktopBrowser('system', finder_options, 205 mac_system, None, False, 206 mac_system_root)) 207 if path.IsExecutable(mac_reference): 208 browsers.append(PossibleDesktopBrowser('reference', finder_options, 209 mac_reference, None, False, 210 mac_reference_root)) 211 212 # Linux specific options. 213 if sys.platform.startswith('linux'): 214 # Look for a google-chrome instance. 215 found = False 216 try: 217 with open(os.devnull, 'w') as devnull: 218 found = subprocess.call(['google-chrome', '--version'], 219 stdout=devnull, stderr=devnull) == 0 220 except OSError: 221 pass 222 if found: 223 browsers.append(PossibleDesktopBrowser('system', finder_options, 224 'google-chrome', None, False, 225 '/opt/google/chrome')) 226 linux_reference_root = os.path.join(reference_build_root, 'chrome_linux') 227 linux_reference = os.path.join(linux_reference_root, 'chrome') 228 if path.IsExecutable(linux_reference): 229 browsers.append(PossibleDesktopBrowser('reference', finder_options, 230 linux_reference, None, False, 231 linux_reference_root)) 232 233 # Win32-specific options. 234 if sys.platform.startswith('win'): 235 app_paths = ( 236 ('system', os.path.join('Google', 'Chrome', 'Application')), 237 ('canary', os.path.join('Google', 'Chrome SxS', 'Application')), 238 ('reference', os.path.join(reference_build_root, 'chrome_win')), 239 ) 240 241 for browser_name, app_path in app_paths: 242 for chromium_app_name in chromium_app_names: 243 app_path = os.path.join(app_path, chromium_app_name) 244 app_path = path.FindInstalledWindowsApplication(app_path) 245 if app_path: 246 browsers.append(PossibleDesktopBrowser( 247 browser_name, finder_options, app_path, 248 None, False, os.path.dirname(app_path))) 249 250 if len(browsers) and not has_display: 251 logging.warning( 252 'Found (%s), but you do not have a DISPLAY environment set.' % 253 ','.join([b.browser_type for b in browsers])) 254 return [] 255 256 return browsers 257