# 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