diff --git a/testing/marionette/client/marionette_driver/addons.py b/testing/marionette/client/marionette_driver/addons.py index ebbe6fed4992..836be27ae4ae 100644 --- a/testing/marionette/client/marionette_driver/addons.py +++ b/testing/marionette/client/marionette_driver/addons.py @@ -31,28 +31,34 @@ class Addons: def __init__(self, marionette): self._mn = marionette - def install(self, path, temp=False): - """Install a Firefox addon. - - If the addon is restartless, it can be used right away. Otherwise - a restart using :func:`~marionette_driver.marionette.Marionette.restart` - will be needed. + def install(self, path=None, temp=False, data=None): + """Install a Firefox addon, which can be used right away. :param path: A file path to the extension to be installed. :param temp: Install a temporary addon. Temporary addons will 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. :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: return self._mn._send_message("Addon:Install", body, key="value") except errors.UnknownException as e: diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executormarionette.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executormarionette.py index 08bc02cbc3c0..93b26a73c837 100644 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executormarionette.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executormarionette.py @@ -47,6 +47,7 @@ from .protocol import (AccessibilityProtocolPart, DevicePostureProtocolPart, VirtualPressureSourceProtocolPart, DisplayFeaturesProtocolPart, + WebExtensionsProtocolPart, merge_dicts) @@ -738,6 +739,24 @@ class MarionetteDisplayFeaturesProtocolPart(DisplayFeaturesProtocolPart): def clear_display_features(self): 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): implements = [MarionetteBaseProtocolPart, MarionetteTestharnessProtocolPart, @@ -761,7 +780,8 @@ class MarionetteProtocol(Protocol): MarionetteVirtualSensorProtocolPart, MarionetteDevicePostureProtocolPart, MarionetteVirtualPressureSourceProtocolPart, - MarionetteDisplayFeaturesProtocolPart] + MarionetteDisplayFeaturesProtocolPart, + MarionetteWebExtensionsProtocolPart] def __init__(self, executor, browser, capabilities=None, timeout_multiplier=1, e10s=True, ccov=False): do_delayed_imports() @@ -955,6 +975,10 @@ class MarionetteTestharnessExecutor(TestharnessExecutor): self.protocol.testharness.load_runner(new_environment["protocol"]) 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 else None) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/protocol.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/protocol.py index 6b9a0de9bb24..af32f487c953 100644 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/protocol.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/protocol.py @@ -335,6 +335,21 @@ class AccessibilityProtocolPart(ProtocolPart): 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): """Protocol part for managing BiDi events""" __metaclass__ = ABCMeta