tor-browser

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

commit 6455b94447935dcd7cfb9f88fce66feb5d1b26c9
parent 01a75a80dab2e2154f744937f5832baa9abcba43
Author: Nazım Can Altınova <canaltinova@gmail.com>
Date:   Tue, 21 Oct 2025 23:59:09 +0000

Bug 1916785 - Add tests for the new webchannel request r=mstange,profiler-reviewers

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

Diffstat:
Mdevtools/client/performance-new/test/browser/browser.toml | 3+++
Adevtools/client/performance-new/test/browser/browser_webchannel-get-js-sources.js | 178+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adevtools/client/performance-new/test/browser/webchannel-js-sources.html | 186+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 367 insertions(+), 0 deletions(-)

diff --git a/devtools/client/performance-new/test/browser/browser.toml b/devtools/client/performance-new/test/browser/browser.toml @@ -9,6 +9,7 @@ support-files = [ "webchannel.html", "webchannel-favicons.html", "webchannel-open-script-in-debugger_assets/*", + "webchannel-js-sources.html", ] skip-if = [ "os == 'linux' && os_version == '18.04' && processor == 'x86_64' && tsan", # Bug 1804081, timeouts and data races in various tests @@ -65,6 +66,8 @@ skip-if = [ ["browser_webchannel-enable-menu-button.js"] +["browser_webchannel-get-js-sources.js"] + ["browser_webchannel-open-script-in-debugger.js"] ["browser_webchannel-page-favicon-data.js"] diff --git a/devtools/client/performance-new/test/browser/browser_webchannel-get-js-sources.js b/devtools/client/performance-new/test/browser/browser_webchannel-get-js-sources.js @@ -0,0 +1,178 @@ +/* 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/. */ + +"use strict"; + +const FRONTEND_URL = + "https://example.com/browser/devtools/client/performance-new/test/browser/webchannel-js-sources.html"; + +add_task(async function test_webchannel_get_js_sources() { + info("Test the WebChannel GET_JS_SOURCES request functionality"); + + // Register some mock JS sources for testing. We already test the logic that + // retrieves the sources in other tests. This test focuses on the webchannel + // itself only. + const mockJSSources = { + "uuid-12345-1": "function testFunction() { return 42; }", + "uuid-12345-2": "console.log('Hello from source 2');", + "uuid-67890-5": "function anotherFunction() { return 'test'; }", + "uuid-67890-6": "alert('Hello world');", + }; + + const sourcesToRequest = ["uuid-12345-1", "uuid-12345-2", "uuid-67890-5"]; + + const expectedResponse = [ + { sourceText: "function testFunction() { return 42; }" }, + { sourceText: "console.log('Hello from source 2');" }, + { sourceText: "function anotherFunction() { return 'test'; }" }, + ]; + + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "about:blank", + }, + async browser => { + // Register the mock sources for the current browser + BackgroundJSM.registerProfileCaptureForBrowser( + browser, + Promise.resolve(new ArrayBuffer(0)), // Mock profile result + null, // No symbolication service + mockJSSources + ); + + // Now navigate to the test HTML page + const url = + FRONTEND_URL + + "?testType=basic" + + "&sourceUuids=" + + encodeURIComponent(JSON.stringify(sourcesToRequest)) + + "&expectedResponse=" + + encodeURIComponent(JSON.stringify(expectedResponse)); + + const loaded = BrowserTestUtils.browserLoaded(browser); + BrowserTestUtils.startLoadingURIString(browser, url); + await loaded; + + await waitForTabTitle("JS sources received"); + ok(true, "The JS sources are successfully retrieved by the WebChannel."); + } + ); +}); + +add_task(async function test_webchannel_get_js_sources_nonexistent() { + info("Test GET_JS_SOURCES WebChannel request with non-existent sources"); + + // Register some mock JS sources + const mockJSSources = { + "uuid-12345-1": "function testFunction() { return 42; }", + }; + + // Request non-existent sources (should return null) + const sourcesToRequest = [ + "uuid-12345-999", // Non-existent UUID + "uuid-99999-1", // Non-existent UUID + ]; + + const expectedResponse = [ + { error: "Source not found in the browser" }, + { error: "Source not found in the browser" }, + ]; + + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "about:blank", + }, + async browser => { + // Register the mock sources for the current browser + BackgroundJSM.registerProfileCaptureForBrowser( + browser, + Promise.resolve(new ArrayBuffer(0)), + null, + mockJSSources + ); + + // Now navigate to the test HTML page + const url = + FRONTEND_URL + + "?testType=nonexistent" + + "&sourceUuids=" + + encodeURIComponent(JSON.stringify(sourcesToRequest)) + + "&expectedResponse=" + + encodeURIComponent(JSON.stringify(expectedResponse)); + + const loaded = BrowserTestUtils.browserLoaded(browser); + BrowserTestUtils.startLoadingURIString(browser, url); + await loaded; + + await waitForTabTitle("JS sources received"); + ok( + true, + "Successfully verified GET_JS_SOURCES with non-existent sources" + ); + } + ); +}); + +add_task(async function test_webchannel_get_js_sources_no_data() { + info("Test GET_JS_SOURCES WebChannel request when no data is registered"); + + const sourcesToRequest = ["uuid-12345-1"]; + + // Open a new tab without registering JS sources + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "about:blank", + }, + async browser => { + // Don't register any JS sources - this should cause an error + + // Now navigate to the test HTML page + const url = + FRONTEND_URL + + "?testType=no-data" + + "&sourceUuids=" + + encodeURIComponent(JSON.stringify(sourcesToRequest)) + + "&expectError=true"; + + const loaded = BrowserTestUtils.browserLoaded(browser); + BrowserTestUtils.startLoadingURIString(browser, url); + await loaded; + + await waitForTabTitle("JS sources received"); + ok(true, "Successfully verified GET_JS_SOURCES error handling"); + } + ); +}); + +add_task(async function test_webchannel_get_js_sources_invalid_request() { + info("Test GET_JS_SOURCES WebChannel request with invalid sources parameter"); + + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "about:blank", + }, + async browser => { + // Don't need to register JS sources for this test + + // For this test, we need to pass invalid sourceUuids directly in the HTML + // We'll use a special URL parameter that the HTML will use directly + const url = + FRONTEND_URL + + "?testType=invalid-request" + + "&sourceUuids=invalid_not_array" + // This is intentionally not JSON + "&expectError=true"; + + const loaded = BrowserTestUtils.browserLoaded(browser); + BrowserTestUtils.startLoadingURIString(browser, url); + await loaded; + + await waitForTabTitle("JS sources received"); + ok(true, "Successfully verified GET_JS_SOURCES invalid request handling"); + } + ); +}); diff --git a/devtools/client/performance-new/test/browser/webchannel-js-sources.html b/devtools/client/performance-new/test/browser/webchannel-js-sources.html @@ -0,0 +1,186 @@ +<!DOCTYPE html> +<!-- 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/. --> +<html> + <head> + <meta charset="utf-8"/> + <title></title> + </head> + <body> + <script> + "use strict"; + // This file is used to test the retrieval of JS sources from a front-end. + // Rather than using some kind of complicated message passing scheme to + // talk to the test harness, modify the title of the page. The tests can + // easily read the window title to see if things worked as expected. + + // The following are the titles used to communicate the page's state to the tests. + // Keep these in sync with any tests that read them. + const initialTitle = "Waiting for the JS sources"; + const successTitle = "JS sources received"; + const errorTitle = "Error" + + document.title = initialTitle; + + // A function which requests the JS sources from the browser using the GET_JS_SOURCES + // WebChannel message. + function getJSSources(sourceUuids, expectError = false) { + return new Promise((resolve, reject) => { + const requestId = Date.now(); + + function listener(event) { + window.removeEventListener( + "WebChannelMessageToContent", + listener, + true + ); + + const { id, message } = event.detail; + + dump(JSON.stringify(message)); + dump("\n"); + if (id !== "profiler.firefox.com" || + !message || + typeof message !== "object" + ) { + console.error(message); + reject(new Error("A malformed WebChannel event was received.")); + return; + } + + if (!message.type) { + console.error(message); + reject(new Error("The WebChannel event indicates an error.")); + return; + } + + if (message.requestId === requestId) { + if (message.type === "SUCCESS_RESPONSE") { + resolve(message.response); + } else if (message.type === "ERROR_RESPONSE") { + if (expectError) { + resolve({ error: message.error }); + } else { + reject(new Error(message.error)); + } + } else { + reject(new Error("Unknown response type: " + message.type)); + } + } + } + + window.addEventListener("WebChannelMessageToContent", listener, true); + + window.dispatchEvent( + new CustomEvent("WebChannelMessageToChrome", { + detail: JSON.stringify({ + id: "profiler.firefox.com", + message: { type: "GET_JS_SOURCES", requestId, sourceUuids }, + }), + }) + ); + }) + } + + async function runTest() { + try { + // Get test configuration from URL parameters + const params = new URLSearchParams(document.location.search); + const testType = params.get("testType") || "basic"; + const expectError = params.get("expectError") === "true"; + + let sourcesToRequest; + let expectedResponse; + + // Handle invalid-request test case where sourceUuids is intentionally not JSON + if (testType === "invalid-request") { + sourcesToRequest = params.get("sourceUuids"); // Keep as string for invalid test + expectedResponse = null; + } else { + sourcesToRequest = JSON.parse(params.get("sourceUuids") || "[]"); + expectedResponse = JSON.parse(params.get("expectedResponse") || "null"); + } + + let response; + if (expectError) { + response = await getJSSources(sourcesToRequest, true); + } else { + response = await getJSSources(sourcesToRequest, false); + } + + dump("response\n") + dump(JSON.stringify(response)); + + let testPassed = false; + + function deepEqual(obj1, obj2) { + return JSON.stringify(obj1) === JSON.stringify(obj2); + } + + switch (testType) { + case "basic": + // Test case: Request existing JS sources + testPassed = response && + Array.isArray(response) && + response.length === expectedResponse.length && + response.every((item, index) => deepEqual(item, expectedResponse[index])); + break; + + case "nonexistent": + // Test case: Request non-existent sources (should return error objects) + testPassed = response && + Array.isArray(response) && + response.length === expectedResponse.length && + response.every((item, index) => deepEqual(item, expectedResponse[index])); + break; + + case "no-data": + // Test case: No JS source data registered (should return error) + testPassed = response && + response.error && + response.error.includes("No JS source data found for this tab"); + break; + + case "invalid-request": + // Test case: Invalid sources parameter (should return error) + testPassed = response && + response.error && + response.error.includes("sourceUuids must be an array"); + break; + + default: + throw new Error("Unknown test type: " + testType); + } + + if (testPassed) { + document.title = successTitle; + } else { + dump('Test failed in webchannel-js-sources.html\n'); + dump(`Test type: ${testType}\n`); + dump(`Expected: ${JSON.stringify(expectedResponse)}\n`); + dump(`Actual: ${JSON.stringify(response)}\n`); + + console.error( + "Test failed in webchannel-js-sources.html", + { testType, expectedResponse, response } + ); + + document.title = errorTitle; + } + } catch (error) { + // Catch any error and notify the test. + document.title = errorTitle; + dump('An error was caught in webchannel-js-sources.html\n'); + dump(`${error}\n`); + console.error( + "An error was caught in webchannel-js-sources.html", + error + ); + } + } + + runTest(); + </script> + </body> +</html>