summaryrefslogtreecommitdiffstats
path: root/testing/mozbase/mozrunner/mozrunner/application.py
diff options
context:
space:
mode:
Diffstat (limited to 'testing/mozbase/mozrunner/mozrunner/application.py')
-rw-r--r--testing/mozbase/mozrunner/mozrunner/application.py156
1 files changed, 156 insertions, 0 deletions
diff --git a/testing/mozbase/mozrunner/mozrunner/application.py b/testing/mozbase/mozrunner/mozrunner/application.py
new file mode 100644
index 0000000000..d1dd91e4c0
--- /dev/null
+++ b/testing/mozbase/mozrunner/mozrunner/application.py
@@ -0,0 +1,156 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import os
+import posixpath
+from abc import ABCMeta, abstractmethod
+from distutils.spawn import find_executable
+
+import six
+from mozdevice import ADBDeviceFactory
+from mozprofile import (
+ ChromeProfile,
+ ChromiumProfile,
+ FirefoxProfile,
+ Profile,
+ ThunderbirdProfile,
+)
+
+here = os.path.abspath(os.path.dirname(__file__))
+
+
+def get_app_context(appname):
+ context_map = {
+ "chrome": ChromeContext,
+ "chromium": ChromiumContext,
+ "default": DefaultContext,
+ "fennec": FennecContext,
+ "firefox": FirefoxContext,
+ "thunderbird": ThunderbirdContext,
+ }
+ if appname not in context_map:
+ raise KeyError("Application '%s' not supported!" % appname)
+ return context_map[appname]
+
+
+class DefaultContext(object):
+ profile_class = Profile
+
+
+@six.add_metaclass(ABCMeta)
+class RemoteContext(object):
+ device = None
+ _remote_profile = None
+ _adb = None
+ profile_class = Profile
+ _bindir = None
+ remote_test_root = ""
+ remote_process = None
+
+ @property
+ def bindir(self):
+ if self._bindir is None:
+ paths = [find_executable("emulator")]
+ paths = [p for p in paths if p is not None if os.path.isfile(p)]
+ if not paths:
+ self._bindir = ""
+ else:
+ self._bindir = os.path.dirname(paths[0])
+ return self._bindir
+
+ @property
+ def adb(self):
+ if not self._adb:
+ paths = [
+ os.environ.get("ADB"),
+ os.environ.get("ADB_PATH"),
+ self.which("adb"),
+ ]
+ paths = [p for p in paths if p is not None if os.path.isfile(p)]
+ if not paths:
+ raise OSError(
+ "Could not find the adb binary, make sure it is on your"
+ "path or set the $ADB_PATH environment variable."
+ )
+ self._adb = paths[0]
+ return self._adb
+
+ @property
+ def remote_profile(self):
+ if not self._remote_profile:
+ self._remote_profile = posixpath.join(self.remote_test_root, "profile")
+ return self._remote_profile
+
+ def which(self, binary):
+ paths = os.environ.get("PATH", {}).split(os.pathsep)
+ if self.bindir is not None and os.path.abspath(self.bindir) not in paths:
+ paths.insert(0, os.path.abspath(self.bindir))
+ os.environ["PATH"] = os.pathsep.join(paths)
+
+ return find_executable(binary)
+
+ @abstractmethod
+ def stop_application(self):
+ """Run (device manager) command to stop application."""
+ pass
+
+
+devices = {}
+
+
+class FennecContext(RemoteContext):
+ _remote_profiles_ini = None
+ _remote_test_root = None
+
+ def __init__(self, app=None, adb_path=None, avd_home=None, device_serial=None):
+ self._adb = adb_path
+ self.avd_home = avd_home
+ self.remote_process = app
+ self.device_serial = device_serial
+ self.device = self.get_device(self.adb, device_serial)
+
+ def get_device(self, adb_path, device_serial):
+ # Create a mozdevice.ADBDevice object for the specified device_serial
+ # and cache it for future use. If the same device_serial is subsequently
+ # requested, retrieve it from the cache to avoid costly re-initialization.
+ global devices
+ if device_serial in devices:
+ device = devices[device_serial]
+ else:
+ device = ADBDeviceFactory(adb=adb_path, device=device_serial)
+ devices[device_serial] = device
+ return device
+
+ def stop_application(self):
+ self.device.stop_application(self.remote_process)
+
+ @property
+ def remote_test_root(self):
+ if not self._remote_test_root:
+ self._remote_test_root = self.device.test_root
+ return self._remote_test_root
+
+ @property
+ def remote_profiles_ini(self):
+ if not self._remote_profiles_ini:
+ self._remote_profiles_ini = posixpath.join(
+ "/data", "data", self.remote_process, "files", "mozilla", "profiles.ini"
+ )
+ return self._remote_profiles_ini
+
+
+class FirefoxContext(object):
+ profile_class = FirefoxProfile
+
+
+class ThunderbirdContext(object):
+ profile_class = ThunderbirdProfile
+
+
+class ChromeContext(object):
+ profile_class = ChromeProfile
+
+
+class ChromiumContext(object):
+ profile_class = ChromiumProfile