tor-browser

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

commit 5b9a31d66c3b23e04534ba1b94f3546ec4bf5fbf
parent 19389430a0d4c73ecf991eeb6f27bb74f128a41a
Author: Sebastian Streich <sstreich@mozilla.com>
Date:   Tue, 30 Sep 2025 14:50:24 +0000

Bug 1990490 - Patch 1 - Allow enrollment into other experiment types r=ip-protection-reviewers,rking

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

Diffstat:
Mbrowser/components/ipprotection/GuardianClient.sys.mjs | 13+++++++++----
Mbrowser/components/ipprotection/tests/browser/browser_guardian_client.js | 27+++++++++++++++++++++++++--
2 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/browser/components/ipprotection/GuardianClient.sys.mjs b/browser/components/ipprotection/GuardianClient.sys.mjs @@ -73,12 +73,15 @@ export class GuardianClient { /** * Tries to enroll the user to the proxy service. * It will silently try to sign in the user into guardian using their FxA account. - * If the user already has a proxy entitlement, nothing will happen. + * If the user already has a proxy entitlement, the experiment type will update. + * + * @param { "alpha" | "beta" | "delta" | "gamma" } aExperimentType - The experiment type to enroll the user into. + * The experiment type controls which feature set the user will get in Firefox. * * @param { AbortSignal | null } aAbortSignal - An AbortSignal to cancel the operation. - * @returns {Promise<{error?: string, ok?: boolean}>} Re + * @returns {Promise<{error?: string, ok?: boolean}>} */ - async enroll(aAbortSignal) { + async enroll(aExperimentType = "alpha", aAbortSignal = null) { // We abort loading the page if the origion is not allowed. const allowedOrigins = [ new URL(this.guardianEndpoint).origin, @@ -111,7 +114,9 @@ export class GuardianClient { } return false; }); - browser.loadURI(Services.io.newURI(this.#loginURL.href), { + const loginURL = this.#loginURL; + loginURL.searchParams.set("experiment", aExperimentType); + browser.loadURI(Services.io.newURI(loginURL.href), { // TODO: Make sure this is the right principal to use? triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(), diff --git a/browser/components/ipprotection/tests/browser/browser_guardian_client.js b/browser/components/ipprotection/tests/browser/browser_guardian_client.js @@ -37,6 +37,16 @@ const testcases = [ ok: true, error: undefined, }, + experimentType: "alpha", + }, + { + name: "Successful enrollment with custom experiment", + responseURL: "/oauth/success?code=abc123", + expects: { + ok: true, + error: undefined, + }, + experimentType: "beta", }, { name: "Failed enrollment - error in success URL", @@ -45,12 +55,13 @@ const testcases = [ ok: false, error: "generic_error", }, + experimentType: "alpha", }, ]; // Run each test case as a separate task to ensure clean state testcases - .map(({ name, responseURL, expects }) => { + .map(({ name, responseURL, expects, experimentType }) => { return async () => { requestLongerTimeout(2); // Increase timeout for this test case info(`Running test case: ${name}`); @@ -60,6 +71,18 @@ testcases enroll: (request, response) => { info(`Handling enroll request, redirecting to ${responseURL}`); + // Assert that the experiment query parameter is present + const queryParams = new URLSearchParams(request.queryString); + Assert.ok( + queryParams.has("experiment"), + "Request should include 'experiment' query parameter" + ); + Assert.equal( + queryParams.get("experiment"), + experimentType, + `Experiment type should be '${experimentType}'` + ); + // Set up a proper HTTP redirect response.setStatusLine(request.httpVersion, 302, "Found"); @@ -77,7 +100,7 @@ testcases try { // Call the actual enroll method - no mocking! - const result = await client.enroll(); + const result = await client.enroll(experimentType); // Check the results Assert.equal(