blob: 61abc64108babebaf2a3a8ec3e5eb7b909da5931 [file] [log] [blame]
# Copyright (C) 2016 Igalia S.L. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os
import sys
import tempfile
import logging
import subprocess
try:
import psutil
except ImportError:
pass
from webkitpy.benchmark_runner.utils import force_remove
from browser_driver import BrowserDriver
_log = logging.getLogger(__name__)
class LinuxBrowserDriver(BrowserDriver):
browser_name = None
process_search_list = []
platform = 'linux'
def __init__(self):
self.process_name = self._get_first_executable_path_from_list(self.process_search_list)
if self.process_name is None:
raise ValueError('Cant find executable for browser {browser_name}. Searched list: {browser_process_list}'.format(
browser_name=self.browser_name, browser_process_list=self.process_search_list))
def prepare_env(self, config):
self._browser_process = None
self._browser_arguments = None
self._temp_profiledir = tempfile.mkdtemp()
self._test_environ = dict(os.environ)
self._test_environ['HOME'] = self._temp_profiledir
def prepare_initial_env(self, config):
pass
def restore_env(self):
force_remove(self._temp_profiledir)
def restore_env_after_all_testing(self):
pass
def close_browsers(self):
if self._browser_process:
if self._browser_process.poll() is None: # still running
if 'psutil' in sys.modules:
main_browser_process = psutil.Process(self._browser_process.pid)
browser_children = main_browser_process.children(recursive=True)
_log.info('Killing browser {browser_name} with pid {browser_pid} and cmd: {browser_cmd}'.format(
browser_name=self.browser_name, browser_pid=self._browser_process.pid,
browser_cmd=' '.join(main_browser_process.cmdline()).strip() or main_browser_process.name()))
main_browser_process.kill()
for browser_child in browser_children:
if browser_child.is_running():
_log.info('Killing still alive {browser_name} child with pid {browser_pid} and cmd: {browser_cmd}'.format(
browser_name=self.browser_name, browser_pid=browser_child.pid,
browser_cmd=' '.join(browser_child.cmdline()).strip() or browser_child.name()))
browser_child.kill()
else:
_log.info('Killing browser {browser_name} with pid {browser_pid}'.format(
browser_name=self.browser_name, browser_pid=self._browser_process.pid))
self._browser_process.kill()
_log.warning('python psutil not found, cant check for '
'still-alive browser childs to kill.')
else:
_log.error('Browser {browser_name} with pid {browser_pid} ended prematurely with return code {browser_retcode}.'.format(
browser_name=self.browser_name, browser_pid=self._browser_process.pid,
browser_retcode=self._browser_process.returncode))
def launch_url(self, url, options, browser_build_path, browser_path):
if not self._browser_arguments:
self._browser_arguments = [url]
exec_args = [self.process_name] + self._browser_arguments
_log.info('Executing: {browser_cmdline}'.format(browser_cmdline=' '.join(exec_args)))
self._browser_process = subprocess.Popen(exec_args, env=self._test_environ,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
def launch_webdriver(self, url, driver):
try:
driver.maximize_window()
except Exception as error:
_log.error('Failed to maximize {browser} window - Error: {error}'.format(browser=driver.name, error=error))
_log.info('Launching "%s" with url "%s"' % (driver.name, url))
driver.get(url)
def _get_first_executable_path_from_list(self, searchlist):
searchpath = [os.path.curdir] + os.environ['PATH'].split(os.pathsep)
for program in searchlist:
for path in searchpath:
fullpath = os.path.abspath(os.path.join(path, program))
if os.path.isfile(fullpath) and os.access(fullpath, os.X_OK):
return fullpath
return None
def _screen_size(self):
# load_subclasses() from __init__.py will load this file to
# check the platform defined. Do here a lazy import instead of
# trying to import the Gtk module on the global scope of this
# file to avoid ImportError errors on other platforms.
# Python imports are cached and only run once, so this should be ok.
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
from gi.repository import Gtk, Gdk
if Gtk.get_major_version() == 3 and Gtk.get_minor_version() < 22:
screen = Gtk.Window().get_screen()
return screen.get_monitor_geometry(screen.get_primary_monitor())
else:
display = Gdk.Display.get_default()
monitor = display.get_primary_monitor()
return monitor.get_geometry()