blob: f1782af1454668d0de8ec355d86e3c1240841810 [file] [log] [blame]
# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import copy
from telemetry.core import platform
from telemetry.util import wpr_modes
from telemetry.internal.browser import browser_finder
from telemetry.internal.browser import browser_finder_exceptions
class ProfileExtender(object):
"""Abstract base class for an object that constructs a Chrome profile."""
def __init__(self, finder_options):
"""Initializer.
|finder_options| is an instance of BrowserFinderOptions. When subclass
implementations of this method inevitably attempt to find and launch a
browser, they should pass |finder_options| to the relevant methods.
Several properties of |finder_options| might require direct manipulation by
subclasses. These are:
|finder_options.output_profile_path|: The path at which the profile
should be created.
|finder_options.browser_options.profile_dir|: If this property is None,
then a new profile is created. Otherwise, the existing profile is
appended on to.
"""
self._finder_options = copy.deepcopy(finder_options)
# Since profile extenders are not supported on remote platforms,
# this should be the same as target platform.
self._os_name = platform.GetHostPlatform().GetOSName()
# A reference to the browser that will be performing all of the tab
# navigations.
# This member is initialized during SetUpBrowser().
self._browser = None
# We only need to close network controller if we opened it before.
# If it was already open, we should not close it.
self._should_close_network_controller = False
def Run(self):
"""Creates or extends the profile."""
raise NotImplementedError()
def WebPageReplayArchivePath(self):
"""Returns the path to the WPR archive.
Can be overridden by subclasses.
"""
return None
@property
def finder_options(self):
"""The options to use to find and run the browser."""
return self._finder_options
@property
def profile_path(self):
"""The path of the profile that the browser will use while it's running."""
# TODO(eakuefner): Remove this after crrev.com/1874473006 rolls in.
return getattr(self.finder_options, 'output_profile_path',
self.finder_options.browser_options.output_profile_path)
@property
def browser(self):
return self._browser
@property
def os_name(self):
"""Name of OS that extender is currently running on."""
return self._os_name
def EnabledOSList(self):
"""Returns a list of OSes that this extender can run on.
Can be overridden by subclasses.
Returns:
List of OS ('win', 'mac', or 'linux') that this extender can run on.
"""
return ['win', 'mac', 'linux']
def SetUpBrowser(self):
"""Finds and starts the browser.
Can be overridden by subclasses. The subclass implementation must call the
super class implementation.
Subclasses do not need to call this method. This method is only necessary
if the subclass needs to start a browser. If a subclass does call this
method, the subclass must also call TearDownBrowser().
"""
possible_browser = self._GetPossibleBrowser(self.finder_options)
enabled_os_list = self.EnabledOSList()
if self._os_name not in enabled_os_list:
raise NotImplementedError(
'This profile extender on %s is not yet supported'
% self._os_name)
if possible_browser.IsRemote():
raise NotImplementedError(
'Profile extenders are not yet supported on remote platforms.')
assert possible_browser.supports_tab_control
self._SetUpWebPageReplay(self.finder_options, possible_browser)
self._browser = possible_browser.Create(self.finder_options)
def TearDownBrowser(self):
"""Tears down the browser.
Can be overridden by subclasses. The subclass implementation must call the
super class implementation.
"""
if self._browser:
if self._should_close_network_controller:
self._browser.platform.network_controller.Close()
self._browser.Close()
self._browser = None
def FetchWebPageReplayArchives(self):
"""Fetches the web page replay archives.
Can be overridden by subclasses.
"""
pass
def _SetUpWebPageReplay(self, finder_options, possible_browser):
"""Sets up Web Page Replay, if necessary."""
wpr_archive_path = self.WebPageReplayArchivePath()
if not wpr_archive_path:
return
self.FetchWebPageReplayArchives()
if finder_options.use_live_sites:
wpr_mode = wpr_modes.WPR_OFF
else:
wpr_mode = wpr_modes.WPR_REPLAY
network_controller = possible_browser.platform.network_controller
if not network_controller.is_open:
self._should_close_network_controller = True
network_controller.Open(wpr_mode,
finder_options.browser_options.extra_wpr_args)
network_controller.StartReplay(
wpr_archive_path, make_javascript_deterministic=True)
def _GetPossibleBrowser(self, finder_options):
"""Return a possible_browser with the given options."""
possible_browser = browser_finder.FindBrowser(finder_options)
if not possible_browser:
raise browser_finder_exceptions.BrowserFinderException(
'No browser found.\n\nAvailable browsers:\n%s\n' %
'\n'.join(browser_finder.GetAllAvailableBrowserTypes(finder_options)))
finder_options.browser_options.browser_type = (
possible_browser.browser_type)
return possible_browser