Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / core / backends / chrome / android_browser_backend.py
index c2a6249..3234909 100644 (file)
@@ -17,36 +17,39 @@ from telemetry.core.backends import browser_backend
 from telemetry.core.backends.chrome import chrome_browser_backend
 from telemetry.core.forwarders import android_forwarder
 
+util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'android')
+from pylib.device import device_errors  # pylint: disable=F0401
+from pylib.device import intent  # pylint: disable=F0401
+
 
 class AndroidBrowserBackendSettings(object):
 
   def __init__(self, adb, activity, cmdline_file, package, pseudo_exec_name,
-               supports_tab_control):
+               supports_tab_control, relax_ssl_check=False):
     self.adb = adb
     self.activity = activity
     self.cmdline_file = cmdline_file
     self.package = package
     self.pseudo_exec_name = pseudo_exec_name
     self.supports_tab_control = supports_tab_control
+    self.relax_ssl_check = relax_ssl_check
 
   def GetDevtoolsRemotePort(self):
     raise NotImplementedError()
 
   def RemoveProfile(self):
-    files = self.adb.RunShellCommandWithSU('ls "%s"' % self.profile_dir)
+    files = self.adb.device().RunShellCommand(
+        'ls "%s"' % self.profile_dir, as_root=True)
     # Don't delete lib, since it is created by the installer.
     paths = ['"%s/%s"' % (self.profile_dir, f) for f in files if f != 'lib']
-    self.adb.RunShellCommandWithSU('rm -r %s' % ' '.join(paths))
+    self.adb.device().RunShellCommand('rm -r %s' % ' '.join(paths),
+                                      as_root=True)
 
   def PushProfile(self, _):
     logging.critical('Profiles cannot be overriden with current configuration')
     sys.exit(1)
 
   @property
-  def is_content_shell(self):
-    return False
-
-  @property
   def profile_dir(self):
     return '/data/data/%s/' % self.package
 
@@ -75,11 +78,8 @@ class ChromeBackendSettings(AndroidBrowserBackendSettings):
     return 'localabstract:chrome_devtools_remote'
 
   def PushProfile(self, new_profile_dir):
-    # Clear the old profile first, since copying won't delete files.
-    self.RemoveProfile()
-
     # Pushing the profile is slow, so we don't want to do it every time.
-    # Avoid this by pushing to a safe location using PushIfNeeded, and
+    # Avoid this by pushing to a safe location using PushChangedFiles, and
     # then copying into the correct location on each test run.
 
     (profile_parent, profile_base) = os.path.split(new_profile_dir)
@@ -89,23 +89,22 @@ class ChromeBackendSettings(AndroidBrowserBackendSettings):
       profile_base = os.path.basename(profile_parent)
 
     saved_profile_location = '/sdcard/profile/%s' % profile_base
-    self.adb.Adb().PushIfNeeded(new_profile_dir, saved_profile_location)
-    self.adb.RunShellCommand('cp -r %s/* %s' % (saved_profile_location,
-                                                self.profile_dir),
-                             timeout_time = 60)
+    self.adb.device().PushChangedFiles(new_profile_dir, saved_profile_location)
 
-    # We now need to give the ownership back to the browser UID
-    dumpsys = self.adb.RunShellCommand('dumpsys package %s' % self.package)
+    self.adb.device().old_interface.EfficientDeviceDirectoryCopy(
+        saved_profile_location, self.profile_dir)
+    dumpsys = self.adb.device().RunShellCommand(
+        'dumpsys package %s' % self.package)
     id_line = next(line for line in dumpsys if 'userId=' in line)
     uid = re.search('\d+', id_line).group()
-    files = self.adb.RunShellCommandWithSU('ls "%s"' % self.profile_dir)
+    files = self.adb.device().RunShellCommand(
+        'ls "%s"' % self.profile_dir, as_root=True)
     files.remove('lib')
     paths = ['%s/%s' % (self.profile_dir, f) for f in files]
     for path in paths:
       extended_path = '%s %s/* %s/*/* %s/*/*/*' % (path, path, path, path)
-      self.adb.RunShellCommand('chown %s.%s %s' %
-                             (uid, uid, extended_path))
-
+      self.adb.device().RunShellCommand(
+          'chown %s.%s %s' % (uid, uid, extended_path))
 
 class ContentShellBackendSettings(AndroidBrowserBackendSettings):
   def __init__(self, adb, package):
@@ -120,34 +119,26 @@ class ContentShellBackendSettings(AndroidBrowserBackendSettings):
   def GetDevtoolsRemotePort(self):
     return 'localabstract:content_shell_devtools_remote'
 
-  @property
-  def is_content_shell(self):
-    return True
 
-
-class ChromiumTestShellBackendSettings(AndroidBrowserBackendSettings):
+class ChromeShellBackendSettings(AndroidBrowserBackendSettings):
   def __init__(self, adb, package):
-    super(ChromiumTestShellBackendSettings, self).__init__(
+    super(ChromeShellBackendSettings, self).__init__(
           adb=adb,
-          activity='org.chromium.chrome.testshell.ChromiumTestShellActivity',
-          cmdline_file='/data/local/tmp/chromium-testshell-command-line',
+          activity='org.chromium.chrome.shell.ChromeShellActivity',
+          cmdline_file='/data/local/tmp/chrome-shell-command-line',
           package=package,
-          pseudo_exec_name='chromium_testshell',
+          pseudo_exec_name='chrome_shell',
           supports_tab_control=False)
 
   def GetDevtoolsRemotePort(self):
-    return 'localabstract:chromium_testshell_devtools_remote'
-
-  @property
-  def is_content_shell(self):
-    return True
+    return 'localabstract:chrome_shell_devtools_remote'
 
 
 class WebviewBackendSettings(AndroidBrowserBackendSettings):
   def __init__(self, adb, package):
     super(WebviewBackendSettings, self).__init__(
         adb=adb,
-        activity='com.android.webview.chromium.shell.TelemetryActivity',
+        activity='org.chromium.telemetry_shell.TelemetryActivity',
         cmdline_file='/data/local/tmp/webview-command-line',
         package=package,
         pseudo_exec_name='webview',
@@ -171,16 +162,17 @@ class WebviewBackendSettings(AndroidBrowserBackendSettings):
                          'activity %s:%s to come up',
                          self.package,
                          self.activity)
-        raise exceptions.BrowserGoneException('Timeout waiting for PID.')
+        raise exceptions.BrowserGoneException(self.browser,
+                                              'Timeout waiting for PID.')
     return 'localabstract:webview_devtools_remote_%s' % str(pid)
 
 
 class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
   """The backend for controlling a browser instance running on Android."""
   def __init__(self, browser_options, backend_settings, use_rndis_forwarder,
-               output_profile_path, extensions_to_load):
+               output_profile_path, extensions_to_load, target_arch):
     super(AndroidBrowserBackend, self).__init__(
-        is_content_shell=backend_settings.is_content_shell,
+        supports_tab_control=backend_settings.supports_tab_control,
         supports_extensions=False, browser_options=browser_options,
         output_profile_path=output_profile_path,
         extensions_to_load=extensions_to_load)
@@ -192,24 +184,26 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
     self._adb = backend_settings.adb
     self._backend_settings = backend_settings
     self._saved_cmdline = ''
+    self._target_arch = target_arch
+    self._saved_sslflag = ''
 
     # TODO(tonyg): This is flaky because it doesn't reserve the port that it
     # allocates. Need to fix this.
     self._port = adb_commands.AllocateTestServerPort()
 
     # Kill old browser.
-    self._adb.CloseApplication(self._backend_settings.package)
+    self._adb.device().ForceStop(self._backend_settings.package)
 
-    if self._adb.Adb().CanAccessProtectedFileContents():
-      if not self.browser_options.dont_override_profile:
-        self._backend_settings.RemoveProfile()
+    if self._adb.device().old_interface.CanAccessProtectedFileContents():
       if self.browser_options.profile_dir:
         self._backend_settings.PushProfile(self.browser_options.profile_dir)
+      elif not self.browser_options.dont_override_profile:
+        self._backend_settings.RemoveProfile()
 
     self._forwarder_factory = android_forwarder.AndroidForwarderFactory(
         self._adb, use_rndis_forwarder)
 
-    if self.browser_options.netsim:
+    if self.browser_options.netsim or use_rndis_forwarder:
       assert use_rndis_forwarder, 'Netsim requires RNDIS forwarding.'
       self.wpr_port_pairs = forwarders.PortPairs(
           http=forwarders.PortPair(0, 80),
@@ -219,8 +213,8 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
     # Set the debug app if needed.
     if self._adb.IsUserBuild():
       logging.debug('User build device, setting debug app')
-      self._adb.RunShellCommand('am set-debug-app --persistent %s' %
-                                self._backend_settings.package)
+      self._adb.device().RunShellCommand(
+          'am set-debug-app --persistent %s' % self._backend_settings.package)
 
   def _SetUpCommandLine(self):
     def QuoteIfNeeded(arg):
@@ -246,8 +240,8 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
   def _SetCommandLineFile(self, file_contents):
     logging.debug('Using command line: ' + file_contents)
     def IsProtectedFile(name):
-      if self._adb.Adb().FileExistsOnDevice(name):
-        return not self._adb.Adb().IsFileWritableOnDevice(name)
+      if self._adb.device().old_interface.FileExistsOnDevice(name):
+        return not self._adb.device().old_interface.IsFileWritableOnDevice(name)
       else:
         parent_name = os.path.dirname(name)
         if parent_name != '':
@@ -255,24 +249,31 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
         else:
           return True
 
-    if IsProtectedFile(self._backend_settings.cmdline_file):
-      if not self._adb.Adb().CanAccessProtectedFileContents():
-        logging.critical('Cannot set Chrome command line. '
-                         'Fix this by flashing to a userdebug build.')
-        sys.exit(1)
-      self._saved_cmdline = ''.join(self._adb.Adb().GetProtectedFileContents(
-          self._backend_settings.cmdline_file) or [])
-      self._adb.Adb().SetProtectedFileContents(
-          self._backend_settings.cmdline_file, file_contents)
-    else:
-      self._saved_cmdline = ''.join(self._adb.Adb().GetFileContents(
-          self._backend_settings.cmdline_file) or [])
-      self._adb.Adb().SetFileContents(self._backend_settings.cmdline_file,
-                                      file_contents)
+    protected = IsProtectedFile(self._backend_settings.cmdline_file)
+    try:
+      self._saved_cmdline = ''.join(
+          self._adb.device().ReadFile(
+              self._backend_settings.cmdline_file, as_root=protected)
+          or [])
+      self._adb.device().WriteFile(
+          self._backend_settings.cmdline_file, file_contents,
+          as_root=protected)
+    except device_errors.CommandFailedError:
+      logging.critical('Cannot set Chrome command line. '
+                       'Fix this by flashing to a userdebug build.')
+      sys.exit(1)
 
   def Start(self):
     self._SetUpCommandLine()
-    self._adb.RunShellCommand('logcat -c')
+
+    # Disables android.net SSL certificate check.  This is necessary for
+    # applications using the android.net stack to work with proxy HTTPS server
+    # created by telemetry
+    if self._backend_settings.relax_ssl_check:
+      self._saved_sslflag = self._adb.device().GetProp('socket.relaxsslcheck')
+      self._adb.device().SetProp('socket.relaxsslcheck', 'yes')
+
+    self._adb.device().RunShellCommand('logcat -c')
     if self.browser_options.startup_url:
       url = self.browser_options.startup_url
     elif self.browser_options.profile_dir:
@@ -281,23 +282,25 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
       # If we have no existing tabs start with a blank page since default
       # startup with the NTP can lead to race conditions with Telemetry
       url = 'about:blank'
-    self._adb.Adb().DismissCrashDialogIfNeeded()
-    self._adb.StartActivity(self._backend_settings.package,
-                            self._backend_settings.activity,
-                            True,
-                            None,
-                            None,
-                            url)
+    # Dismiss any error dialogs. Limit the number in case we have an error loop
+    # or we are failing to dismiss.
+    for _ in xrange(10):
+      if not self._adb.device().old_interface.DismissCrashDialogIfNeeded():
+        break
+    self._adb.device().StartActivity(
+        intent.Intent(package=self._backend_settings.package,
+                      activity=self._backend_settings.activity,
+                      action=None, data=url, category=None),
+        blocking=True)
 
     self._adb.Forward('tcp:%d' % self._port,
                       self._backend_settings.GetDevtoolsRemotePort())
 
     try:
       self._WaitForBrowserToComeUp()
-      self._PostBrowserStartupInitialization()
     except exceptions.BrowserGoneException:
       logging.critical('Failed to connect to browser.')
-      if not self._adb.Adb().CanAccessProtectedFileContents():
+      if not self._adb.device().old_interface.CanAccessProtectedFileContents():
         logging.critical(
           'Resolve this by either: '
           '(1) Flashing to a userdebug build OR '
@@ -340,7 +343,7 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
   def pid(self):
     pids = self._adb.ExtractPid(self._backend_settings.package)
     if not pids:
-      raise exceptions.BrowserGoneException(self.GetStackTrace())
+      raise exceptions.BrowserGoneException(self.browser)
     return int(pids[0])
 
   @property
@@ -359,16 +362,16 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
   def activity(self):
     return self._backend_settings.activity
 
-  @property
-  def supports_tab_control(self):
-    return self._backend_settings.supports_tab_control
-
   def __del__(self):
     self.Close()
 
   def Close(self):
     super(AndroidBrowserBackend, self).Close()
-    self._adb.CloseApplication(self._backend_settings.package)
+    self._adb.device().ForceStop(self._backend_settings.package)
+
+    # Restore android.net SSL check
+    if self._backend_settings.relax_ssl_check:
+      self._adb.device().SetProp('socket.relaxsslcheck', self._saved_sslflag)
 
     if self._output_profile_path:
       logging.info("Pulling profile directory from device: '%s'->'%s'.",
@@ -378,7 +381,7 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
       # pulled down is really needed e.g. .pak files.
       if not os.path.exists(self._output_profile_path):
         os.makedirs(self._output_profile_pathame)
-      files = self.adb.RunShellCommandWithSU(
+      files = self.adb.device().RunShellCommand(
           'ls "%s"' % self._backend_settings.profile_dir)
       for f in files:
         # Don't pull lib, since it is created by the installer.
@@ -389,7 +392,8 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
           # is fixed in android's adb_interface at 60 seconds, which may
           # be too short to pull the cache.
           cmd = 'pull %s %s' % (source, dest)
-          self._adb.Adb().Adb().SendCommand(cmd, timeout_time=240)
+          self._adb.device().old_interface.Adb().SendCommand(
+              cmd, timeout_time=240)
 
   def IsBrowserRunning(self):
     pids = self._adb.ExtractPid(self._backend_settings.package)
@@ -399,7 +403,7 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
     return local_port
 
   def GetStandardOutput(self):
-    return '\n'.join(self._adb.RunShellCommand('logcat -d -t 500'))
+    return '\n'.join(self._adb.device().RunShellCommand('logcat -d -t 500'))
 
   def GetStackTrace(self):
     def Decorate(title, content):
@@ -411,8 +415,10 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
                          'android_platform', 'development', 'scripts', 'stack')
     # Try to symbolize logcat.
     if os.path.exists(stack):
-      p = subprocess.Popen([stack], stdin=subprocess.PIPE,
-                           stdout=subprocess.PIPE)
+      cmd = [stack]
+      if self._target_arch:
+        cmd.append('--arch=%s' % self._target_arch)
+      p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
       ret += Decorate('Stack from Logcat', p.communicate(input=logcat)[0])
 
     # Try to get tombstones.
@@ -421,7 +427,7 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
     if os.path.exists(tombstones):
       ret += Decorate('Tombstones',
                       subprocess.Popen([tombstones, '-w', '--device',
-                                        self._adb.device()],
+                                        self._adb.device_serial()],
                                        stdout=subprocess.PIPE).communicate()[0])
     return ret