tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit d59b96a25802ada359064d35e763cde943c80e5d
parent c5fef7ff2b99bd5b0d3d45ecdccfda55392e5249
Author: Freya LaLuna <freyalaluna@outlook.com>
Date:   Sat,  3 Jan 2026 20:00:42 +0000

Bug 1909662 - Marionette server/client implementation of generate_test_report command r=whimboo,jgraham

This is an implementation of a Marionette version of the WebDriver extension command outlined in Part 7.1 of the Reporting API spec: https://w3c.github.io/reporting/#generate-test-report-command
This command simulates the generation of a report for the purpose of testing, which is observed by any registered Reporting Observers and sent off to a specified endpoint.

The platform logic for this command lives in D250373.

Differential Revision: https://phabricator.services.mozilla.com/D275985

Diffstat:
Mremote/marionette/actors/MarionetteCommandsChild.sys.mjs | 14++++++++++++++
Mremote/marionette/actors/MarionetteCommandsParent.sys.mjs | 7+++++++
Mremote/marionette/driver.sys.mjs | 38++++++++++++++++++++++++++++++++++++++
Mtesting/marionette/client/marionette_driver/marionette.py | 12++++++++++++
Atesting/marionette/harness/marionette_harness/tests/unit/test_generate_test_report.py | 19+++++++++++++++++++
Mtesting/marionette/harness/marionette_harness/tests/unit/unit-tests.toml | 2++
Dtesting/web-platform/meta/infrastructure/testdriver/generate_test_report.html.ini | 4----
Dtesting/web-platform/meta/reporting/bufferSize.html.ini | 4----
Dtesting/web-platform/meta/reporting/disconnect.html.ini | 5-----
Dtesting/web-platform/meta/reporting/generateTestReport-honors-endpoint.https.sub.html.ini | 8--------
Dtesting/web-platform/meta/reporting/generateTestReport.html.ini | 5-----
Dtesting/web-platform/meta/reporting/nestedReport.html.ini | 7-------
Dtesting/web-platform/meta/reporting/order.html.ini | 7-------
Mtesting/web-platform/meta/reporting/reporting-api-honors-limits.https.sub.html.ini | 12++++++++----
Mtesting/web-platform/tests/tools/wptrunner/wptrunner/executors/executormarionette.py | 4++--
15 files changed, 102 insertions(+), 46 deletions(-)

diff --git a/remote/marionette/actors/MarionetteCommandsChild.sys.mjs b/remote/marionette/actors/MarionetteCommandsChild.sys.mjs @@ -220,6 +220,9 @@ export class MarionetteCommandsChild extends JSWindowActorChild { case "MarionetteCommandsParent:findElements": result = await this.findElements(data); break; + case "MarionetteCommandsParent:generateTestReport": + result = await this.generateTestReport(data); + break; case "MarionetteCommandsParent:getActiveElement": result = await this.getActiveElement(); break; @@ -387,6 +390,17 @@ export class MarionetteCommandsChild extends JSWindowActorChild { } /** + * Generates and sends a test report to be observed by any registered reporting observers + */ + async generateTestReport(options = {}) { + const { message, group } = options; + return this.browsingContext.window.TestReportGenerator.generateReport({ + message, + group, + }); + } + + /** * Return the active element in the document. */ async getActiveElement() { diff --git a/remote/marionette/actors/MarionetteCommandsParent.sys.mjs b/remote/marionette/actors/MarionetteCommandsParent.sys.mjs @@ -188,6 +188,13 @@ export class MarionetteCommandsParent extends JSWindowActorParent { }); } + generateTestReport(messageBody, messageGroup) { + return this.sendQuery("MarionetteCommandsParent:generateTestReport", { + message: messageBody, + group: messageGroup, + }); + } + async getShadowRoot(webEl) { return this.sendQuery("MarionetteCommandsParent:getShadowRoot", { elem: webEl, diff --git a/remote/marionette/driver.sys.mjs b/remote/marionette/driver.sys.mjs @@ -3647,6 +3647,41 @@ GeckoDriver.prototype.teardownReftest = function () { }; /** + * Implements the GenerateTestReport functionality of the Reporting API. + * + * @see https://w3c.github.io/reporting/#generate-test-report-command * + * + * @param {object} cmd + * @param {string} cmd.parameters.message + * The message contents of the report being generated. + * @param {string=} cmd.parameters.group + * The name of the reporting endpoint that the report should be sent to. + * @see https://www.w3.org/TR/reporting-1/#endpoint + * + * @throws {InvalidArgumentError} + * If a message argument wasn't passed in the parameters. + */ + +GeckoDriver.prototype.generateTestReport = async function (cmd) { + const { message, group = "default" } = cmd.parameters; + + lazy.assert.open(this.getBrowsingContext()); + await this._handleUserPrompts(); + + lazy.assert.string( + message, + lazy.pprint(`Expected "message" to be a string, got ${message}`) + ); + + lazy.assert.string( + group, + lazy.pprint(`Expected "group" to be a string, got ${group}`) + ); + + await this.getActor().generateTestReport(message, group); +}; + +/** * Print page as PDF. * * @param {object} cmd @@ -4109,6 +4144,9 @@ GeckoDriver.prototype.commands = { "GPC:GetGlobalPrivacyControl": GeckoDriver.prototype.getGlobalPrivacyControl, "GPC:SetGlobalPrivacyControl": GeckoDriver.prototype.setGlobalPrivacyControl, + // Reporting API test generation of reports + "Reporting:GenerateTestReport": GeckoDriver.prototype.generateTestReport, + // WebAuthn "WebAuthn:AddVirtualAuthenticator": GeckoDriver.prototype.addVirtualAuthenticator, diff --git a/testing/marionette/client/marionette_driver/marionette.py b/testing/marionette/client/marionette_driver/marionette.py @@ -2010,6 +2010,18 @@ class Marionette: return self._send_message("WebDriver:FindElements", body) + def generate_test_report(self, message, group=None): + """Generates a test report to be observed by registered reporting observers + + :param message: The message string to be used as the body of the generated report + :param group: The name of the endpoint that will receive the report + """ + body = {"message": message} + if group is not None: + body["group"] = group + + self._send_message("Reporting:GenerateTestReport", body) + def get_active_element(self): el_or_ref = self._send_message("WebDriver:GetActiveElement", key="value") return el_or_ref diff --git a/testing/marionette/harness/marionette_harness/tests/unit/test_generate_test_report.py b/testing/marionette/harness/marionette_harness/tests/unit/test_generate_test_report.py @@ -0,0 +1,19 @@ +from marionette_harness import MarionetteTestCase + + +class TestGenerateTestReport(MarionetteTestCase): + def setUp(self): + MarionetteTestCase.setUp(self) + self.prefsToSet = ["dom.reporting.enabled", "dom.reporting.testing.enabled"] + for pref in self.prefsToSet: + self.marionette.set_pref(pref, True) + + def tearDown(self): + for pref in self.prefsToSet: + self.marionette.clear_pref(pref) + + def test_generate_test_report(self): + self.marionette.generate_test_report("Test") + + def test_generate_test_report_different_group(self): + self.marionette.generate_test_report("Test", "different") diff --git a/testing/marionette/harness/marionette_harness/tests/unit/unit-tests.toml b/testing/marionette/harness/marionette_harness/tests/unit/unit-tests.toml @@ -104,6 +104,8 @@ skip-if = [ ["test_geckoinstance.py"] +["test_generate_test_report.py"] + ["test_get_computed_label.py"] ["test_get_computed_role.py"] diff --git a/testing/web-platform/meta/infrastructure/testdriver/generate_test_report.html.ini b/testing/web-platform/meta/infrastructure/testdriver/generate_test_report.html.ini @@ -1,4 +0,0 @@ -[generate_test_report.html] - [TestDriver generate_test_report method] - expected: FAIL - diff --git a/testing/web-platform/meta/reporting/bufferSize.html.ini b/testing/web-platform/meta/reporting/bufferSize.html.ini @@ -1,4 +0,0 @@ -[bufferSize.html] - [Buffer size] - expected: FAIL - diff --git a/testing/web-platform/meta/reporting/disconnect.html.ini b/testing/web-platform/meta/reporting/disconnect.html.ini @@ -1,5 +0,0 @@ -[disconnect.html] - expected: - if (os == "android") and fission: [OK, TIMEOUT] - [Disconnect] - expected: FAIL diff --git a/testing/web-platform/meta/reporting/generateTestReport-honors-endpoint.https.sub.html.ini b/testing/web-platform/meta/reporting/generateTestReport-honors-endpoint.https.sub.html.ini @@ -1,8 +0,0 @@ -[generateTestReport-honors-endpoint.https.sub.html] - expected: - if (os == "android") and fission: [OK, TIMEOUT] - [Generate Test Report] - expected: FAIL - - [Reporting-Endpoints target received the test report.] - expected: FAIL diff --git a/testing/web-platform/meta/reporting/generateTestReport.html.ini b/testing/web-platform/meta/reporting/generateTestReport.html.ini @@ -1,5 +0,0 @@ -[generateTestReport.html] - expected: - if (os == "android") and fission: [OK, TIMEOUT] - [Generate Test Report] - expected: FAIL diff --git a/testing/web-platform/meta/reporting/nestedReport.html.ini b/testing/web-platform/meta/reporting/nestedReport.html.ini @@ -1,7 +0,0 @@ -[nestedReport.html] - expected: - if (os == "android") and debug and fission: [ERROR, TIMEOUT] - if (os == "android") and debug and not fission: [ERROR, TIMEOUT] - ERROR - [Nested report] - expected: TIMEOUT diff --git a/testing/web-platform/meta/reporting/order.html.ini b/testing/web-platform/meta/reporting/order.html.ini @@ -1,7 +0,0 @@ -[order.html] - expected: - if (os == "android") and debug and not fission: [ERROR, TIMEOUT] - if (os == "android") and debug and fission: [ERROR, TIMEOUT] - ERROR - [Order] - expected: TIMEOUT diff --git a/testing/web-platform/meta/reporting/reporting-api-honors-limits.https.sub.html.ini b/testing/web-platform/meta/reporting/reporting-api-honors-limits.https.sub.html.ini @@ -1,10 +1,14 @@ [reporting-api-honors-limits.https.sub.html] expected: TIMEOUT - [Buffer filled] - expected: FAIL - [Test Report limits were honored] - expected: TIMEOUT # see bug 1909662 + [CSP Report limits were honored] + expected: TIMEOUT + bug: 2003729 [Combined report limits were honored] expected: NOTRUN + bug: 2003729 + + [Test Report limits were honored] + expected: NOTRUN + bug: 2003729 diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executormarionette.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executormarionette.py @@ -577,8 +577,8 @@ class MarionetteGenerateTestReportProtocolPart(GenerateTestReportProtocolPart): def setup(self): self.marionette = self.parent.marionette - def generate_test_report(self, config): - raise NotImplementedError("generate_test_report not yet implemented") + def generate_test_report(self, message): + self.marionette.generate_test_report(message) class MarionetteVirtualAuthenticatorProtocolPart(VirtualAuthenticatorProtocolPart): def setup(self):