Source code

Revision control

Copy as Markdown

Other Tools

# 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 shutil import which
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 = [which("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 which(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