Bug 1950636 - Implement MarionetteWebExtensionsProtocolPart r=whimboo,jgraham,webdriver-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D244400
This commit is contained in:
committed by
tjovanovic@mozilla.com
parent
b6efacd0f5
commit
ac257fd33f
@@ -31,28 +31,34 @@ class Addons:
|
|||||||
def __init__(self, marionette):
|
def __init__(self, marionette):
|
||||||
self._mn = marionette
|
self._mn = marionette
|
||||||
|
|
||||||
def install(self, path, temp=False):
|
def install(self, path=None, temp=False, data=None):
|
||||||
"""Install a Firefox addon.
|
"""Install a Firefox addon, which can be used right away.
|
||||||
|
|
||||||
If the addon is restartless, it can be used right away. Otherwise
|
|
||||||
a restart using :func:`~marionette_driver.marionette.Marionette.restart`
|
|
||||||
will be needed.
|
|
||||||
|
|
||||||
:param path: A file path to the extension to be installed.
|
:param path: A file path to the extension to be installed.
|
||||||
:param temp: Install a temporary addon. Temporary addons will
|
:param temp: Install a temporary addon. Temporary addons will
|
||||||
automatically be uninstalled on shutdown and do not need
|
automatically be uninstalled on shutdown and do not need
|
||||||
to be signed, though they must be restartless.
|
to be signed.
|
||||||
|
:param data: A base64-encoded string of a zip-packed addon.
|
||||||
|
|
||||||
:returns: The addon ID string of the newly installed addon.
|
:returns: The addon ID string of the newly installed addon.
|
||||||
|
|
||||||
:raises: :exc:`AddonInstallException`
|
:raises: :exc:`AddonInstallException`
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# On windows we can end up with a path with mixed \ and /
|
|
||||||
# which Firefox doesn't like
|
|
||||||
path = path.replace("/", os.path.sep)
|
|
||||||
|
|
||||||
body = {"path": path, "temporary": temp}
|
if (path and data) or (not path and not data):
|
||||||
|
raise AddonInstallException("Must use either path or data argument.")
|
||||||
|
|
||||||
|
body = {"temporary": temp}
|
||||||
|
if path:
|
||||||
|
# On windows we can end up with a path with mixed \ and /
|
||||||
|
# which Firefox doesn't like
|
||||||
|
path = path.replace("/", os.path.sep)
|
||||||
|
body.update({"path": path})
|
||||||
|
|
||||||
|
if data:
|
||||||
|
body.update({"addon": data})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return self._mn._send_message("Addon:Install", body, key="value")
|
return self._mn._send_message("Addon:Install", body, key="value")
|
||||||
except errors.UnknownException as e:
|
except errors.UnknownException as e:
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ from .protocol import (AccessibilityProtocolPart,
|
|||||||
DevicePostureProtocolPart,
|
DevicePostureProtocolPart,
|
||||||
VirtualPressureSourceProtocolPart,
|
VirtualPressureSourceProtocolPart,
|
||||||
DisplayFeaturesProtocolPart,
|
DisplayFeaturesProtocolPart,
|
||||||
|
WebExtensionsProtocolPart,
|
||||||
merge_dicts)
|
merge_dicts)
|
||||||
|
|
||||||
|
|
||||||
@@ -738,6 +739,24 @@ class MarionetteDisplayFeaturesProtocolPart(DisplayFeaturesProtocolPart):
|
|||||||
def clear_display_features(self):
|
def clear_display_features(self):
|
||||||
raise NotImplementedError("clear_display_features not yet implemented")
|
raise NotImplementedError("clear_display_features not yet implemented")
|
||||||
|
|
||||||
|
|
||||||
|
class MarionetteWebExtensionsProtocolPart(WebExtensionsProtocolPart):
|
||||||
|
def setup(self):
|
||||||
|
self.addons = Addons(self.parent.marionette)
|
||||||
|
|
||||||
|
def install_web_extension(self, extension):
|
||||||
|
if extension["type"] == "base64":
|
||||||
|
extension_id = self.addons.install(data=extension["value"], temp=True)
|
||||||
|
else:
|
||||||
|
path = self.parent.test_dir + extension["path"]
|
||||||
|
extension_id = self.addons.install(path, temp=True)
|
||||||
|
|
||||||
|
return {'extension': extension_id}
|
||||||
|
|
||||||
|
def uninstall_web_extension(self, extension_id):
|
||||||
|
return self.addons.uninstall(extension_id)
|
||||||
|
|
||||||
|
|
||||||
class MarionetteProtocol(Protocol):
|
class MarionetteProtocol(Protocol):
|
||||||
implements = [MarionetteBaseProtocolPart,
|
implements = [MarionetteBaseProtocolPart,
|
||||||
MarionetteTestharnessProtocolPart,
|
MarionetteTestharnessProtocolPart,
|
||||||
@@ -761,7 +780,8 @@ class MarionetteProtocol(Protocol):
|
|||||||
MarionetteVirtualSensorProtocolPart,
|
MarionetteVirtualSensorProtocolPart,
|
||||||
MarionetteDevicePostureProtocolPart,
|
MarionetteDevicePostureProtocolPart,
|
||||||
MarionetteVirtualPressureSourceProtocolPart,
|
MarionetteVirtualPressureSourceProtocolPart,
|
||||||
MarionetteDisplayFeaturesProtocolPart]
|
MarionetteDisplayFeaturesProtocolPart,
|
||||||
|
MarionetteWebExtensionsProtocolPart]
|
||||||
|
|
||||||
def __init__(self, executor, browser, capabilities=None, timeout_multiplier=1, e10s=True, ccov=False):
|
def __init__(self, executor, browser, capabilities=None, timeout_multiplier=1, e10s=True, ccov=False):
|
||||||
do_delayed_imports()
|
do_delayed_imports()
|
||||||
@@ -955,6 +975,10 @@ class MarionetteTestharnessExecutor(TestharnessExecutor):
|
|||||||
self.protocol.testharness.load_runner(new_environment["protocol"])
|
self.protocol.testharness.load_runner(new_environment["protocol"])
|
||||||
|
|
||||||
def do_test(self, test):
|
def do_test(self, test):
|
||||||
|
# TODO: followup to do this properly, pass test as state on the CallbackHandler:
|
||||||
|
# https://phabricator.services.mozilla.com/D244400?id=1030480#inline-1369921
|
||||||
|
self.protocol.test_dir = os.path.dirname(test.path)
|
||||||
|
|
||||||
timeout = (test.timeout * self.timeout_multiplier if self.debug_info is None
|
timeout = (test.timeout * self.timeout_multiplier if self.debug_info is None
|
||||||
else None)
|
else None)
|
||||||
|
|
||||||
|
|||||||
@@ -335,6 +335,21 @@ class AccessibilityProtocolPart(ProtocolPart):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class WebExtensionsProtocolPart(ProtocolPart):
|
||||||
|
"""Protocol part for managing WebExtensions"""
|
||||||
|
__metaclass__ = ABCMeta
|
||||||
|
|
||||||
|
name = "web_extensions"
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def install_web_extension(self, extension):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def uninstall_web_extension(self, extension_id):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class BidiBluetoothProtocolPart(ProtocolPart):
|
class BidiBluetoothProtocolPart(ProtocolPart):
|
||||||
"""Protocol part for managing BiDi events"""
|
"""Protocol part for managing BiDi events"""
|
||||||
__metaclass__ = ABCMeta
|
__metaclass__ = ABCMeta
|
||||||
|
|||||||
Reference in New Issue
Block a user