Home | History | Annotate | Download | only in chrome
      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 """Finds android browsers that can be controlled by telemetry."""
      5 
      6 import os
      7 import logging as real_logging
      8 import re
      9 import subprocess
     10 import sys
     11 
     12 from telemetry.core import browser
     13 from telemetry.core import possible_browser
     14 from telemetry.core import profile_types
     15 from telemetry.core.chrome import adb_commands
     16 from telemetry.core.chrome import android_browser_backend
     17 from telemetry.core.platform import android_platform_backend
     18 
     19 CHROME_PACKAGE_NAMES = {
     20   'android-chrome': 'com.google.android.apps.chrome',
     21   'android-chrome-beta': 'com.chrome.beta',
     22   'android-chrome-dev': 'com.google.android.apps.chrome_dev',
     23   'android-jb-system-chrome': 'com.android.chrome'
     24 }
     25 
     26 ALL_BROWSER_TYPES = ','.join([
     27                                 'android-chromium-testshell',
     28                                 'android-content-shell',
     29                                 'android-webview',
     30                              ] + CHROME_PACKAGE_NAMES.keys())
     31 
     32 CONTENT_SHELL_PACKAGE = 'org.chromium.content_shell_apk'
     33 CHROMIUM_TESTSHELL_PACKAGE = 'org.chromium.chrome.testshell'
     34 WEBVIEW_PACKAGE = 'com.android.webview.chromium.shell'
     35 
     36 
     37 # adb shell pm list packages
     38 # adb
     39 # intents to run (pass -D url for the rest)
     40 #   com.android.chrome/.Main
     41 #   com.google.android.apps.chrome/.Main
     42 
     43 class PossibleAndroidBrowser(possible_browser.PossibleBrowser):
     44   """A launchable android browser instance."""
     45   def __init__(self, browser_type, options, backend_settings):
     46     super(PossibleAndroidBrowser, self).__init__(browser_type, options)
     47     self._backend_settings = backend_settings
     48 
     49   def __repr__(self):
     50     return 'PossibleAndroidBrowser(browser_type=%s)' % self.browser_type
     51 
     52   def Create(self):
     53     if profile_types.GetProfileCreator(self.options.profile_type):
     54       raise Exception("Profile creation not currently supported on Android")
     55 
     56     backend = android_browser_backend.AndroidBrowserBackend(
     57         self._options, self._backend_settings)
     58     platform_backend = android_platform_backend.AndroidPlatformBackend(
     59         self._backend_settings.adb.Adb(), self._options.no_performance_mode)
     60     b = browser.Browser(backend, platform_backend)
     61     return b
     62 
     63   def SupportsOptions(self, options):
     64     if len(options.extensions_to_load) != 0:
     65       return False
     66     return True
     67 
     68 def SelectDefaultBrowser(_):
     69   return None
     70 
     71 adb_works = None
     72 def CanFindAvailableBrowsers(logging=real_logging):
     73   if not adb_commands.IsAndroidSupported():
     74     return False
     75 
     76   global adb_works
     77 
     78   if adb_works == None:
     79     try:
     80       with open(os.devnull, 'w') as devnull:
     81         proc = subprocess.Popen(['adb', 'devices'],
     82                                 stdout=subprocess.PIPE,
     83                                 stderr=subprocess.PIPE,
     84                                 stdin=devnull)
     85         stdout, _ = proc.communicate()
     86         if re.search(re.escape('????????????\tno permissions'), stdout) != None:
     87           logging.warn(
     88               ('adb devices reported a permissions error. Consider '
     89                'restarting adb as root:'))
     90           logging.warn('  adb kill-server')
     91           logging.warn('  sudo `which adb` devices\n\n')
     92         adb_works = True
     93     except OSError:
     94       platform_tools_path = os.path.join(
     95           os.path.dirname(__file__), '..', '..', '..', '..', '..'
     96           'third_party', 'android_tools', 'sdk', 'platform-tools')
     97       if (sys.platform.startswith('linux') and
     98           os.path.exists(os.path.join(platform_tools_path, 'adb'))):
     99         os.environ['PATH'] = os.pathsep.join([platform_tools_path,
    100                                               os.environ['PATH']])
    101         adb_works = True
    102       else:
    103         adb_works = False
    104 
    105   return adb_works
    106 
    107 def FindAllAvailableBrowsers(options, logging=real_logging):
    108   """Finds all the desktop browsers available on this machine."""
    109   if not CanFindAvailableBrowsers(logging=logging):
    110     logging.info('No adb command found. ' +
    111                  'Will not try searching for Android browsers.')
    112     return []
    113 
    114   device = None
    115   if options.android_device:
    116     devices = [options.android_device]
    117   else:
    118     devices = adb_commands.GetAttachedDevices()
    119 
    120   if len(devices) == 0:
    121     logging.info('No android devices found.')
    122     return []
    123 
    124   if len(devices) > 1:
    125     logging.warn('Multiple devices attached. ' +
    126                  'Please specify a device explicitly.')
    127     return []
    128 
    129   device = devices[0]
    130 
    131   adb = adb_commands.AdbCommands(device=device)
    132 
    133   packages = adb.RunShellCommand('pm list packages')
    134   possible_browsers = []
    135   if 'package:' + CONTENT_SHELL_PACKAGE in packages:
    136     b = PossibleAndroidBrowser(
    137         'android-content-shell',
    138         options, android_browser_backend.ContentShellBackendSettings(
    139             adb, CONTENT_SHELL_PACKAGE))
    140     possible_browsers.append(b)
    141 
    142   if 'package:' + CHROMIUM_TESTSHELL_PACKAGE in packages:
    143     b = PossibleAndroidBrowser(
    144         'android-chromium-testshell',
    145         options, android_browser_backend.ChromiumTestShellBackendSettings(
    146             adb, CHROMIUM_TESTSHELL_PACKAGE))
    147     possible_browsers.append(b)
    148 
    149   if 'package:' + WEBVIEW_PACKAGE in packages:
    150     b = PossibleAndroidBrowser(
    151         'android-webview',
    152         options,
    153         android_browser_backend.WebviewBackendSettings(adb, WEBVIEW_PACKAGE))
    154     possible_browsers.append(b)
    155 
    156   for name, package in CHROME_PACKAGE_NAMES.iteritems():
    157     if 'package:' + package in packages:
    158       b = PossibleAndroidBrowser(
    159           name,
    160           options,
    161           android_browser_backend.ChromeBackendSettings(adb, package))
    162       possible_browsers.append(b)
    163 
    164   # See if the "forwarder" is installed -- we need this to host content locally
    165   # but make it accessible to the device.
    166   if len(possible_browsers) and not adb_commands.HasForwarder():
    167     logging.warn('telemetry detected an android device. However,')
    168     logging.warn('Chrome\'s port-forwarder app is not available.')
    169     logging.warn('To build:')
    170     logging.warn('  ninja -C out/Release forwarder2 md5sum')
    171     logging.warn('')
    172     logging.warn('')
    173     return []
    174   return possible_browsers
    175