commit 4dcfde8752c07dfd8cd8d3ed763609863d3f857f
parent 6718d0601807b1b4e080c93329519ee3eb25a30c
Author: Freya LaLuna <freyalaluna@outlook.com>
Date: Thu, 18 Dec 2025 08:52:04 +0000
Bug 1955682 - C++ platform implementation of generate_test_report command r=webidl,smaug
This is the platform implementation for 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.
Differential Revision: https://phabricator.services.mozilla.com/D250373
Diffstat:
9 files changed, 244 insertions(+), 2 deletions(-)
diff --git a/dom/reporting/CSPViolationReportBody.cpp b/dom/reporting/CSPViolationReportBody.cpp
@@ -35,11 +35,11 @@ JSObject* CSPViolationReportBody::WrapObject(
}
void CSPViolationReportBody::GetBlockedURL(nsAString& aURL) const {
- aURL = mDocumentURL;
+ aURL = mBlockedURL;
}
void CSPViolationReportBody::GetDocumentURL(nsAString& aURL) const {
- aURL = mBlockedURL;
+ aURL = mDocumentURL;
}
void CSPViolationReportBody::GetReferrer(nsAString& aReferrer) const {
diff --git a/dom/reporting/TestReportBody.cpp b/dom/reporting/TestReportBody.cpp
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/TestReportBody.h"
+
+#include "mozilla/JSONWriter.h"
+#include "mozilla/dom/ReportingBinding.h"
+
+namespace mozilla::dom {
+
+TestReportBody::TestReportBody(nsIGlobalObject* aGlobal,
+ const nsString& aMessage)
+ : ReportBody(aGlobal), mMessage(aMessage) {}
+
+JSObject* TestReportBody::WrapObject(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto) {
+ return TestReportBody_Binding::Wrap(aCx, this, aGivenProto);
+}
+
+TestReportBody::~TestReportBody() = default;
+
+void TestReportBody::GetMessage(nsAString& aMessage) const {
+ aMessage = mMessage;
+}
+
+void TestReportBody::ToJSON(JSONWriter& aJSONWriter) const {
+ if (mMessage.IsEmpty()) {
+ aJSONWriter.NullProperty("message");
+ } else {
+ aJSONWriter.StringProperty("message", NS_ConvertUTF16toUTF8(mMessage));
+ }
+}
+} // namespace mozilla::dom
diff --git a/dom/reporting/TestReportBody.h b/dom/reporting/TestReportBody.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_TestReportBody_h
+#define mozilla_dom_TestReportBody_h
+
+#include "mozilla/dom/Nullable.h"
+#include "mozilla/dom/ReportBody.h"
+#include "mozilla/dom/SecurityPolicyViolationEvent.h"
+
+namespace mozilla::dom {
+
+class TestReportBody final : public ReportBody {
+ public:
+ TestReportBody(nsIGlobalObject* aGlobal, const nsString& aBody);
+
+ JSObject* WrapObject(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto) override;
+
+ void GetMessage(nsAString& aMessage) const;
+
+ protected:
+ void ToJSON(JSONWriter& aJSONWriter) const override;
+
+ private:
+ ~TestReportBody();
+
+ const nsString mMessage;
+};
+
+} // namespace mozilla::dom
+
+#endif // mozilla_dom_TestReportBody_h
diff --git a/dom/reporting/TestReportGenerator.cpp b/dom/reporting/TestReportGenerator.cpp
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/TestReportGenerator.h"
+
+#include "mozilla/dom/ReportingBinding.h"
+
+namespace mozilla::dom {
+
+/* static */
+already_AddRefed<Promise> TestReportGenerator::GenerateReport(
+ const GlobalObject& aGlobal, const GenerateTestReportParameters& aParams,
+ ErrorResult& aRv) {
+ nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
+ MOZ_ASSERT(global);
+
+ RefPtr<Promise> promise = Promise::Create(global, aRv);
+ if (NS_WARN_IF(aRv.Failed())) {
+ return nullptr;
+ }
+ MOZ_ASSERT(promise);
+
+ nsString messageBody = aParams.mMessage;
+ if (messageBody.IsEmpty()) {
+ promise->MaybeRejectWithNotSupportedError(
+ "Report must have a message string");
+ return promise.forget();
+ }
+
+ nsString reportGroup = aParams.mGroup;
+
+ nsPIDOMWindowInner* window = global->GetAsInnerWindow();
+ if (NS_WARN_IF(!window)) {
+ promise->MaybeRejectWithNotSupportedError(
+ "Failed to convert global object to window");
+ return promise.forget();
+ }
+
+ RefPtr<TestReportBody> reportBody = new TestReportBody(global, messageBody);
+
+ nsCOMPtr<nsIURI> docURI = window->GetDocumentURI();
+ nsAutoCString spec;
+ if (!docURI || NS_FAILED(docURI->GetSpec(spec))) {
+ promise->MaybeRejectWithNotSupportedError(
+ "Failed to retrieve active document's URI from window");
+ return promise.forget();
+ }
+
+ NS_ConvertUTF8toUTF16 docURIString(spec);
+
+ ReportingUtils::Report(global, nsGkAtoms::test, reportGroup, docURIString,
+ reportBody);
+
+ AutoJSAPI jsapi;
+ if (!jsapi.Init(global)) {
+ promise->MaybeRejectWithNotSupportedError(
+ "Failed to initialize JS context");
+ return promise.forget();
+ }
+
+ promise->MaybeResolveWithUndefined();
+ return promise.forget();
+}
+
+} // namespace mozilla::dom
diff --git a/dom/reporting/TestReportGenerator.h b/dom/reporting/TestReportGenerator.h
@@ -0,0 +1,24 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_TestReportGenerator_h
+#define mozilla_dom_TestReportGenerator_h
+
+#include "mozilla/dom/Promise.h"
+
+namespace mozilla::dom {
+
+struct GenerateTestReportParameters;
+
+class TestReportGenerator {
+ public:
+ static already_AddRefed<Promise> GenerateReport(
+ const GlobalObject& aGlobal, const GenerateTestReportParameters& aParams,
+ ErrorResult& aRv);
+};
+} // namespace mozilla::dom
+
+#endif // mozilla_dom_TestReportGenerator_h
diff --git a/dom/reporting/moz.build b/dom/reporting/moz.build
@@ -18,6 +18,8 @@ EXPORTS.mozilla.dom = [
"ReportingObserver.h",
"ReportingUtils.h",
"TestingDeprecatedInterface.h",
+ "TestReportBody.h",
+ "TestReportGenerator.h",
]
UNIFIED_SOURCES += [
@@ -34,6 +36,8 @@ UNIFIED_SOURCES += [
"ReportingObserver.cpp",
"ReportingUtils.cpp",
"TestingDeprecatedInterface.cpp",
+ "TestReportBody.cpp",
+ "TestReportGenerator.cpp",
]
IPDL_SOURCES += [
diff --git a/dom/reporting/tests/browser.toml b/dom/reporting/tests/browser.toml
@@ -5,3 +5,5 @@ support-files = [
]
["browser_cleanup.js"]
+
+["browser_reportGeneration.js"]
diff --git a/dom/reporting/tests/browser_reportGeneration.js b/dom/reporting/tests/browser_reportGeneration.js
@@ -0,0 +1,52 @@
+/* Any copyright is dedicated to the Public Domain.
+ https://creativecommons.org/publicdomain/zero/1.0/ */
+
+add_task(async function () {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["dom.reporting.enabled", true],
+ ["dom.reporting.header.enabled", true],
+ ["dom.reporting.testing.enabled", true],
+ ],
+ });
+});
+
+add_task(async function () {
+ let o = new ReportingObserver(() => {});
+ o.observe();
+
+ await window.TestReportGenerator.generateReport({
+ message: "test",
+ group: "test",
+ });
+
+ let r = o.takeRecords();
+ is(r.length, 1, "Report delivery was observed");
+ is(r[0].body.message, "test", "Message is correct");
+
+ await window.TestReportGenerator.generateReport({ message: "test" });
+
+ r = o.takeRecords();
+ is(r.length, 1, "Report delivery was observed when no group was provided");
+
+ await Assert.rejects(
+ window.TestReportGenerator.generateReport(),
+ /TypeError/,
+ "generateReport emits a TypeError when message isn't provided"
+ );
+});
+
+// test serialization of message as null property
+add_task(async function () {
+ let o = new ReportingObserver(() => {});
+ o.observe();
+
+ await window.TestReportGenerator.generateReport({
+ message: null,
+ group: "test",
+ });
+
+ let r = o.takeRecords();
+ is(r.length, 1, "Report delivery was observed");
+ is(r[0].body.message, "null", "Message is correct");
+});
diff --git a/dom/webidl/Reporting.webidl b/dom/webidl/Reporting.webidl
@@ -7,6 +7,8 @@
* https://w3c.github.io/reporting/#interface-reporting-observer
*/
+interface nsISupports;
+
[Pref="dom.reporting.enabled",
Exposed=(Window,Worker)]
interface ReportBody {
@@ -112,3 +114,21 @@ dictionary ReportingEndpoint {
// This is an unsigned long.
any weight;
};
+
+dictionary GenerateTestReportParameters
+{
+ required DOMString message;
+ DOMString group = "default";
+};
+
+[ChromeOnly, Pref="dom.reporting.enabled", Exposed=Window]
+namespace TestReportGenerator {
+ [Throws]
+ Promise<undefined> generateReport(GenerateTestReportParameters params);
+};
+
+[LegacyNoInterfaceObject, Exposed=Window]
+interface TestReportBody : ReportBody {
+ [Default] object toJSON();
+ readonly attribute DOMString message;
+};