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 5import logging 6import collections 7import os 8 9from telemetry.core import util 10 11from devil.android.sdk import version_codes 12 13import py_utils 14 15 16_BackendSettingsTuple = collections.namedtuple('_BackendSettingsTuple', [ 17 'browser_type', 'package', 'activity', 'command_line_name', 18 'devtools_port', 'apk_name', 'embedder_apk_name', 19 'supports_tab_control', 'supports_spki_list', 'additional_apk_name']) 20 21 22class AndroidBrowserBackendSettings(_BackendSettingsTuple): 23 """Base class for backend settings of Android browsers. 24 25 These abstract away the differences that may exist between different 26 browsers that may be installed or controlled on Android. 27 28 Args: 29 browser_type: The short browser name used by Telemetry to identify 30 this from, e.g., the --browser command line argument. 31 package: The package name used to identify the browser on Android. 32 Each browser_type must match to a single package name and viceversa. 33 activity: The activity name used to launch this browser via an intent. 34 command_line_name: File name where the browser reads command line flags. 35 devtools_port: Default remote port used to set up a DevTools conneciton. 36 Subclasses may override how this value is interpreted. 37 apk_name: Default apk name as built on a chromium checkout, used to 38 find local apks on the host platform. Subclasses may override 39 how this value is interpreted. 40 embedder_apk_name: Name of an additional apk needed, also expected to be 41 found in the chromium checkout, used as an app which embbeds e.g. 42 the WebView implementation given by the apk_name above. 43 supports_tab_control: Whether this browser variant supports the concept 44 of tabs. 45 supports_spki_list: Whether this browser supports spki-list for ignoring 46 certificate errors. See: crbug.com/753948 47 """ 48 __slots__ = () 49 50 def __str__(self): 51 return '%s (%s)' % (self.browser_type, self.package) 52 53 @property 54 def profile_ignore_list(self): 55 # Don't delete lib, since it is created by the installer. 56 return ('lib', ) 57 58 @property 59 def requires_embedder(self): 60 return self.embedder_apk_name is not None 61 62 def GetDevtoolsRemotePort(self, device): 63 del device 64 # By default return the devtools_port defined in the constructor. 65 return self.devtools_port 66 67 def GetApkName(self, device): 68 # Subclasses may override this method to pick the correct apk based on 69 # specific device features. 70 del device # Unused. 71 return self.apk_name 72 73 def FindLocalApk(self, device, chrome_root): 74 apk_name = self.GetApkName(device) 75 logging.info('Picked apk name %s for browser_type %s', 76 apk_name, self.browser_type) 77 if apk_name is None: 78 return None 79 else: 80 return util.FindLatestApkOnHost(chrome_root, apk_name) 81 82 # returns True if this is a WebView browser and WebView-specific 83 # field trial configurations should apply. 84 def IsWebView(self): 85 return False 86 87 88class GenericChromeBackendSettings(AndroidBrowserBackendSettings): 89 def __new__(cls, **kwargs): 90 # Provide some defaults common to Chrome based backends. 91 kwargs.setdefault('activity', 'com.google.android.apps.chrome.Main') 92 kwargs.setdefault('command_line_name', 'chrome-command-line') 93 kwargs.setdefault('devtools_port', 'localabstract:chrome_devtools_remote') 94 kwargs.setdefault('apk_name', None) 95 kwargs.setdefault('embedder_apk_name', None) 96 kwargs.setdefault('supports_tab_control', True) 97 kwargs.setdefault('supports_spki_list', True) 98 kwargs.setdefault('additional_apk_name', None) 99 return super(GenericChromeBackendSettings, cls).__new__(cls, **kwargs) 100 101 102class GenericChromeBundleBackendSettings(GenericChromeBackendSettings): 103 def GetApkName(self, device): 104 assert self.apk_name.endswith('_bundle') 105 del device # unused 106 # Bundles are created using the generated tool in the output directory's 107 # bin directory instead of being output to the apk directory at compile 108 # time like a normal APK. 109 return os.path.join('..', 'bin', self.apk_name) 110 111 112class ChromeBackendSettings(GenericChromeBackendSettings): 113 def GetApkName(self, device): 114 assert self.apk_name is None 115 # The APK to install depends on the OS version of the deivce. 116 if device.build_version_sdk >= version_codes.NOUGAT: 117 return 'Monochrome.apk' 118 else: 119 return 'Chrome.apk' 120 121 122class WebViewBasedBackendSettings(AndroidBrowserBackendSettings): 123 def __new__(cls, **kwargs): 124 # Provide some defaults common to WebView based backends. 125 kwargs.setdefault('devtools_port', 126 'localabstract:webview_devtools_remote_{pid}') 127 kwargs.setdefault('apk_name', None) 128 kwargs.setdefault('embedder_apk_name', None) 129 kwargs.setdefault('supports_tab_control', False) 130 # TODO(crbug.com/753948): Switch to True when spki-list support is 131 # implemented on WebView. 132 kwargs.setdefault('supports_spki_list', False) 133 kwargs.setdefault('additional_apk_name', None) 134 return super(WebViewBasedBackendSettings, cls).__new__(cls, **kwargs) 135 136 def GetDevtoolsRemotePort(self, device): 137 # The DevTools port for WebView based backends depends on the browser PID. 138 def get_activity_pid(): 139 return device.GetApplicationPids(self.package, at_most_one=True) 140 141 pid = py_utils.WaitFor(get_activity_pid, timeout=30) 142 return self.devtools_port.format(pid=pid) 143 144 145class WebViewBackendSettings(WebViewBasedBackendSettings): 146 def __new__(cls, **kwargs): 147 # Provide some defaults for backends that work via system_webview_shell, 148 # a testing app with source code available at: 149 # https://cs.chromium.org/chromium/src/android_webview/tools/system_webview_shell 150 kwargs.setdefault('package', 'org.chromium.webview_shell') 151 kwargs.setdefault('activity', 152 'org.chromium.webview_shell.TelemetryActivity') 153 kwargs.setdefault('embedder_apk_name', 'SystemWebViewShell.apk') 154 kwargs.setdefault('command_line_name', 'webview-command-line') 155 return super(WebViewBackendSettings, cls).__new__(cls, **kwargs) 156 157 def GetApkName(self, device): 158 if self.apk_name is not None: 159 return self.apk_name 160 # The APK to install depends on the OS version of the deivce unless 161 # explicitly overridden. 162 if device.build_version_sdk >= version_codes.NOUGAT: 163 return 'MonochromePublic.apk' 164 else: 165 return 'SystemWebView.apk' 166 167 def FindSupportApks(self, apk_path, chrome_root): 168 del chrome_root 169 all_apks = [] 170 # Try to find the WebView embedder next to the local APK found. 171 if apk_path is not None: 172 embedder_apk_path = os.path.join( 173 os.path.dirname(apk_path), self.embedder_apk_name) 174 if os.path.exists(embedder_apk_path): 175 all_apks.append(embedder_apk_path) 176 if self.additional_apk_name is not None: 177 additional_apk_path = os.path.join( 178 os.path.dirname(apk_path), self.additional_apk_name) 179 if os.path.exists(additional_apk_path): 180 all_apks.append(additional_apk_path) 181 return all_apks 182 183 def IsWebView(self): 184 return True 185 186 187class WebViewGoogleBackendSettings(WebViewBackendSettings): 188 def GetApkName(self, device): 189 assert self.apk_name is None 190 # The APK to install depends on the OS version of the deivce. 191 if device.build_version_sdk >= version_codes.NOUGAT: 192 return 'Monochrome.apk' 193 else: 194 return 'SystemWebViewGoogle.apk' 195 196 197class WebViewBundleBackendSettings(WebViewBackendSettings): 198 def GetApkName(self, device): 199 assert self.apk_name.endswith('_bundle') 200 del device # unused 201 # Bundles are created using the generated tool in the output directory's 202 # bin directory instead of being output to the apk directory at compile 203 # time like a normal APK. 204 return os.path.join('..', 'bin', self.apk_name) 205 206 def FindSupportApks(self, apk_path, chrome_root): 207 del chrome_root 208 # Try to find the WebView embedder in apk directory 209 if apk_path is not None: 210 embedder_apk_path = os.path.join( 211 os.path.dirname(apk_path), '..', 'apks', self.embedder_apk_name) 212 if os.path.exists(embedder_apk_path): 213 return [embedder_apk_path] 214 return [] 215 216 217class WebLayerBackendSettings(WebViewBackendSettings): 218 def __new__(cls, **kwargs): 219 # Provide some defaults for backends that work via weblayer_shell, 220 # a testing app with source code available at: 221 # https://cs.chromium.org/chromium/src/weblayer/shell 222 kwargs.setdefault('devtools_port', 223 'localabstract:weblayer_devtools_remote_{pid}') 224 kwargs.setdefault('package', 'org.chromium.weblayer.shell') 225 kwargs.setdefault('activity', 226 'org.chromium.weblayer.shell.TelemetryActivity') 227 kwargs.setdefault('embedder_apk_name', 'WebLayerShellSystemWebView.apk') 228 kwargs.setdefault('command_line_name', 'weblayer-command-line') 229 return super(WebLayerBackendSettings, cls).__new__(cls, **kwargs) 230 231 def GetApkName(self, device): 232 del device # Unused 233 assert self.apk_name is None 234 return 'Monochrome.apk' 235 236 def IsWebView(self): 237 return False 238 239class WebLayerBundleBackendSettings(WebLayerBackendSettings): 240 def GetApkName(self, device): 241 assert self.apk_name.endswith('_bundle') 242 del device # unused 243 # Bundles are created using the generated tool in the output directory's 244 # bin directory instead of being output to the apk directory at compile 245 # time like a normal APK. 246 return os.path.join('..', 'bin', self.apk_name) 247 248 def FindSupportApks(self, apk_path, chrome_root): 249 del chrome_root 250 # Try to find the WebLayer embedder in apk directory. 251 if apk_path is not None: 252 embedder_apk_path = os.path.join( 253 os.path.dirname(apk_path), '..', 'apks', self.embedder_apk_name) 254 if os.path.exists(embedder_apk_path): 255 return [embedder_apk_path] 256 return [] 257 258 259ANDROID_CONTENT_SHELL = AndroidBrowserBackendSettings( 260 browser_type='android-content-shell', 261 package='org.chromium.content_shell_apk', 262 activity='org.chromium.content_shell_apk.ContentShellActivity', 263 command_line_name='content-shell-command-line', 264 devtools_port='localabstract:content_shell_devtools_remote', 265 apk_name='ContentShell.apk', 266 embedder_apk_name=None, 267 supports_tab_control=False, 268 supports_spki_list=True, 269 additional_apk_name=None) 270 271# TODO(crbug.com/1038137): Add reference setting for android-weblayer 272ANDROID_WEBLAYER = WebLayerBackendSettings( 273 browser_type='android-weblayer') 274 275# TODO(crbug.com/1038137): Add reference setting for android-weblayer 276ANDROID_WEBLAYER_GOOGLE_BUNDLE = WebLayerBundleBackendSettings( 277 browser_type='android-weblayer-google-bundle', 278 apk_name='monochrome_bundle') 279 280# TODO(crbug.com/1038137): Add reference setting for android-weblayer 281ANDROID_WEBLAYER_STANDALONE_GOOGLE_BUNDLE = WebLayerBundleBackendSettings( 282 browser_type='android-weblayer-standalone-google-bundle', 283 apk_name='system_webview_google_bundle') 284 285# TODO(crbug.com/1038137): Add reference setting for android-webview 286ANDROID_WEBVIEW = WebViewBackendSettings( 287 browser_type='android-webview') 288 289# TODO(crbug.com/1038137): Add reference setting for android-webview 290ANDROID_WEBVIEW_STANDALONE = WebViewBackendSettings( 291 apk_name='SystemWebView.apk', 292 browser_type='android-webview-standalone') 293 294# TODO(crbug.com/1038137): Add reference setting for android-webview 295ANDROID_WEBVIEW_STANDALONE_BUNDLE = WebViewBundleBackendSettings( 296 browser_type='android-webview-standalone-bundle', 297 apk_name='system_webview_bundle') 298 299# TODO(crbug.com/1038137): Add reference setting for android-webview 300ANDROID_WEBVIEW_TRICHROME = WebViewBackendSettings( 301 apk_name='TrichromeWebView.apk', 302 additional_apk_name='TrichromeLibrary.apk', 303 browser_type='android-webview-trichrome') 304 305# TODO(crbug.com/1038137): Add reference setting for android-webview 306ANDROID_WEBVIEW_TRICHROME_BUNDLE = WebViewBackendSettings( 307 apk_name='trichrome_webview_bundle', 308 additional_apk_name='TrichromeLibrary.apk', 309 browser_type='android-webview-trichrome-bundle') 310 311# TODO(crbug.com/1038137): Add reference setting for android-webview-bundle 312ANDROID_WEBVIEW_BUNDLE = WebViewBundleBackendSettings( 313 browser_type='android-webview-bundle', 314 apk_name='monochrome_public_bundle') 315 316# TODO(crbug.com/1038137): Add reference setting for android-webview-google 317ANDROID_WEBVIEW_GOOGLE = WebViewGoogleBackendSettings( 318 browser_type='android-webview-google') 319 320# TODO(crbug.com/1038137): Add reference setting for 321# android-webview-google-bundle 322ANDROID_WEBVIEW_GOOGLE_BUNDLE = WebViewBundleBackendSettings( 323 browser_type='android-webview-google-bundle', 324 apk_name='monochrome_bundle') 325 326# TODO(crbug.com/1038137): Add reference setting for android-webview 327ANDROID_WEBVIEW_STANDALONE_GOOGLE = WebViewBackendSettings( 328 apk_name='SystemWebViewGoogle.apk', 329 browser_type='android-webview-standalone-google') 330 331# TODO(crbug.com/1038137): Add reference setting for android-webview 332ANDROID_WEBVIEW_STANDALONE_GOOGLE_BUNDLE = WebViewBundleBackendSettings( 333 browser_type='android-webview-standalone-google-bundle', 334 apk_name='system_webview_google_bundle') 335 336# TODO(crbug.com/1038137): Add reference setting for android-webview 337ANDROID_WEBVIEW_TRICHROME_GOOGLE = WebViewBackendSettings( 338 apk_name='TrichromeWebViewGoogle.apk', 339 additional_apk_name='TrichromeLibraryGoogle.apk', 340 browser_type='android-webview-trichrome-google') 341 342# TODO(crbug.com/1038137): Add reference setting for android-webview 343ANDROID_WEBVIEW_TRICHROME_GOOGLE_BUNDLE = WebViewBackendSettings( 344 apk_name='trichrome_webview_google_bundle', 345 additional_apk_name='TrichromeLibraryGoogle.apk', 346 browser_type='android-webview-trichrome-google-bundle') 347 348ANDROID_WEBVIEW_INSTRUMENTATION = WebViewBasedBackendSettings( 349 browser_type='android-webview-instrumentation', 350 package='org.chromium.android_webview.shell', 351 activity='org.chromium.android_webview.shell.AwShellActivity', 352 command_line_name='android-webview-command-line', 353 apk_name='WebViewInstrumentation.apk') 354 355ANDROID_CHROMIUM = GenericChromeBackendSettings( 356 browser_type='android-chromium', 357 package='org.chromium.chrome', 358 apk_name='ChromePublic.apk') 359 360ANDROID_CHROMIUM_BUNDLE = GenericChromeBundleBackendSettings( 361 browser_type='android-chromium-bundle', 362 package='org.chromium.chrome', 363 apk_name='chrome_modern_public_bundle') 364 365ANDROID_CHROMIUM_MONOCHROME = GenericChromeBackendSettings( 366 browser_type='android-chromium-monochrome', 367 package='org.chromium.chrome', 368 apk_name='MonochromePublic.apk' 369) 370 371# TODO(crbug.com/1038137): Add reference setting for android-chrome 372ANDROID_CHROME = ChromeBackendSettings( 373 browser_type='android-chrome', 374 package='com.google.android.apps.chrome') 375 376ANDROID_CHROME_BUNDLE = GenericChromeBundleBackendSettings( 377 browser_type='android-chrome-bundle', 378 package='com.google.android.apps.chrome', 379 apk_name='monochrome_bundle') 380 381REFERENCE_ANDROID_CHROME_BUNDLE = GenericChromeBackendSettings( 382 browser_type='reference-android-chrome-bundle', 383 package='com.google.android.apps.chrome') 384 385# TODO(crbug.com/1038137): Add reference setting for android-chrome-64-bundle 386ANDROID_CHROME_64_BUNDLE = GenericChromeBundleBackendSettings( 387 browser_type='android-chrome-64-bundle', 388 package='com.google.android.apps.chrome', 389 apk_name='monochrome_64_32_bundle') 390 391ANDROID_CHROME_BETA = GenericChromeBackendSettings( 392 browser_type='android-chrome-beta', 393 package='com.chrome.beta') 394 395ANDROID_CHROME_DEV = GenericChromeBackendSettings( 396 browser_type='android-chrome-dev', 397 package='com.chrome.dev') 398 399ANDROID_CHROME_CANARY = GenericChromeBackendSettings( 400 browser_type='android-chrome-canary', 401 package='com.chrome.canary') 402 403ANDROID_SYSTEM_CHROME = GenericChromeBackendSettings( 404 browser_type='android-system-chrome', 405 package='com.android.chrome') 406 407 408ANDROID_BACKEND_SETTINGS = ( 409 ANDROID_CONTENT_SHELL, 410 ANDROID_WEBLAYER, 411 ANDROID_WEBLAYER_GOOGLE_BUNDLE, 412 ANDROID_WEBLAYER_STANDALONE_GOOGLE_BUNDLE, 413 ANDROID_WEBVIEW, 414 ANDROID_WEBVIEW_BUNDLE, 415 ANDROID_WEBVIEW_GOOGLE, 416 ANDROID_WEBVIEW_GOOGLE_BUNDLE, 417 ANDROID_WEBVIEW_INSTRUMENTATION, 418 ANDROID_WEBVIEW_STANDALONE, 419 ANDROID_WEBVIEW_STANDALONE_BUNDLE, 420 ANDROID_WEBVIEW_STANDALONE_GOOGLE, 421 ANDROID_WEBVIEW_STANDALONE_GOOGLE_BUNDLE, 422 ANDROID_WEBVIEW_TRICHROME, 423 ANDROID_WEBVIEW_TRICHROME_BUNDLE, 424 ANDROID_WEBVIEW_TRICHROME_GOOGLE, 425 ANDROID_WEBVIEW_TRICHROME_GOOGLE_BUNDLE, 426 ANDROID_CHROMIUM, 427 ANDROID_CHROMIUM_BUNDLE, 428 ANDROID_CHROMIUM_MONOCHROME, 429 REFERENCE_ANDROID_CHROME_BUNDLE, 430 ANDROID_CHROME, 431 ANDROID_CHROME_64_BUNDLE, 432 ANDROID_CHROME_BUNDLE, 433 ANDROID_CHROME_BETA, 434 ANDROID_CHROME_DEV, 435 ANDROID_CHROME_CANARY, 436 ANDROID_SYSTEM_CHROME 437) 438