Bug 1950636 - Implement MarionetteWebExtensionsProtocolPart r=whimboo,jgraham,webdriver-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D244400
This commit is contained in:
Tomislav Jovanovic
2025-05-20 14:37:33 +00:00
committed by tjovanovic@mozilla.com
parent b6efacd0f5
commit ac257fd33f
3 changed files with 57 additions and 12 deletions

View File

@@ -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:

View File

@@ -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)

View File

@@ -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