From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../browser/browser_server_side_redirection.js | 260 +++++++++++++++++++++ 1 file changed, 260 insertions(+) create mode 100644 browser/extensions/search-detection/tests/browser/browser_server_side_redirection.js (limited to 'browser/extensions/search-detection/tests/browser/browser_server_side_redirection.js') diff --git a/browser/extensions/search-detection/tests/browser/browser_server_side_redirection.js b/browser/extensions/search-detection/tests/browser/browser_server_side_redirection.js new file mode 100644 index 0000000000..ea235406a4 --- /dev/null +++ b/browser/extensions/search-detection/tests/browser/browser_server_side_redirection.js @@ -0,0 +1,260 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { AddonTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/AddonTestUtils.sys.mjs" +); + +const { TelemetryTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/TelemetryTestUtils.sys.mjs" +); + +AddonTestUtils.initMochitest(this); + +const TELEMETRY_EVENTS_FILTERS = { + category: "addonsSearchDetection", + method: "etld_change", +}; + +// The search-detection built-in add-on registers dynamic events. +const TELEMETRY_TEST_UTILS_OPTIONS = { clear: true, process: "dynamic" }; + +const REDIRECT_SJS = + "browser/browser/extensions/search-detection/tests/browser/redirect.sjs?q={searchTerms}"; +// This URL will redirect to `example.net`, which is different than +// `*.example.com`. That will be the final URL of a redirect chain: +// www.example.com -> example.net +const SEARCH_URL_WWW = `https://www.example.com/${REDIRECT_SJS}`; +// This URL will redirect to `www.example.com`, which will create a redirect +// chain with two hops: +// test2.example.com -> www.example.com -> example.net +const SEARCH_URL_TEST2 = `https://test2.example.com/${REDIRECT_SJS}`; +// This URL will redirect to `test2.example.com`, which will create a redirect +// chain with three hops: +// test1.example.com -> test2.example.com -> www.example.com -> example.net +const SEARCH_URL_TEST1 = `https://test1.example.com/${REDIRECT_SJS}`; + +const TEST_SEARCH_ENGINE_ADDON_ID = "some@addon-id"; +const TEST_SEARCH_ENGINE_ADDON_VERSION = "4.5.6"; + +const testServerSideRedirect = async ({ + searchURL, + expectedEvents, + tabURL, +}) => { + Services.telemetry.clearEvents(); + + const searchEngineName = "test search engine"; + // Load a default search engine because the add-on we are testing here + // monitors the search engines. + const searchEngine = ExtensionTestUtils.loadExtension({ + manifest: { + version: TEST_SEARCH_ENGINE_ADDON_VERSION, + browser_specific_settings: { + gecko: { id: TEST_SEARCH_ENGINE_ADDON_ID }, + }, + chrome_settings_overrides: { + search_provider: { + name: searchEngineName, + keyword: "test", + search_url: searchURL, + }, + }, + }, + useAddonManager: "temporary", + }); + + await searchEngine.startup(); + ok( + Services.search.getEngineByName(searchEngineName), + "test search engine registered" + ); + await AddonTestUtils.waitForSearchProviderStartup(searchEngine); + + // Simulate a search (with the test search engine) by navigating to it. + const url = tabURL || searchURL.replace("{searchTerms}", "some terms"); + await BrowserTestUtils.withNewTab("about:blank", async browser => { + // Wait for the tab to be fully loaded. + let loaded = BrowserTestUtils.browserLoaded(browser); + BrowserTestUtils.loadURIString(browser, url); + await loaded; + }); + + await searchEngine.unload(); + ok( + !Services.search.getEngineByName(searchEngineName), + "test search engine unregistered" + ); + + TelemetryTestUtils.assertEvents( + expectedEvents, + TELEMETRY_EVENTS_FILTERS, + TELEMETRY_TEST_UTILS_OPTIONS + ); +}; + +add_task(function test_redirect_final() { + return testServerSideRedirect({ + // www.example.com -> example.net + searchURL: SEARCH_URL_WWW, + expectedEvents: [ + { + object: "other", + value: "server", + extra: { + addonId: TEST_SEARCH_ENGINE_ADDON_ID, + addonVersion: TEST_SEARCH_ENGINE_ADDON_VERSION, + from: "example.com", + to: "example.net", + }, + }, + ], + }); +}); + +add_task(function test_redirect_two_hops() { + return testServerSideRedirect({ + // test2.example.com -> www.example.com -> example.net + searchURL: SEARCH_URL_TEST2, + expectedEvents: [ + { + object: "other", + value: "server", + extra: { + addonId: TEST_SEARCH_ENGINE_ADDON_ID, + addonVersion: TEST_SEARCH_ENGINE_ADDON_VERSION, + from: "example.com", + to: "example.net", + }, + }, + ], + }); +}); + +add_task(function test_redirect_three_hops() { + return testServerSideRedirect({ + // test1.example.com -> test2.example.com -> www.example.com -> example.net + searchURL: SEARCH_URL_TEST1, + expectedEvents: [ + { + object: "other", + value: "server", + extra: { + addonId: TEST_SEARCH_ENGINE_ADDON_ID, + addonVersion: TEST_SEARCH_ENGINE_ADDON_VERSION, + from: "example.com", + to: "example.net", + }, + }, + ], + }); +}); + +add_task(function test_no_event_when_search_engine_not_used() { + return testServerSideRedirect({ + // www.example.com -> example.net + searchURL: SEARCH_URL_WWW, + // We do not expect any events because the user is not using the search + // engine that was registered. + tabURL: "http://mochi.test:8888/search?q=foobar", + expectedEvents: [], + }); +}); + +add_task(function test_redirect_chain_does_not_start_on_first_request() { + return testServerSideRedirect({ + // www.example.com -> example.net + searchURL: SEARCH_URL_WWW, + // User first navigates to an URL that isn't monitored and will be + // redirected to another URL that is monitored. + tabURL: `http://mochi.test:8888/browser/browser/extensions/search-detection/tests/browser/redirect.sjs?q={searchTerms}`, + expectedEvents: [ + { + object: "other", + value: "server", + extra: { + addonId: TEST_SEARCH_ENGINE_ADDON_ID, + addonVersion: TEST_SEARCH_ENGINE_ADDON_VERSION, + // We expect this and not `mochi.test` because we do not monitor + // `mochi.test`, only `example.com`, which is coming from the search + // engine registered in the test setup. + from: "example.com", + to: "example.net", + }, + }, + ], + }); +}); + +add_task(async function test_two_extensions_reported() { + Services.telemetry.clearEvents(); + + const searchEngines = []; + for (const [addonId, addonVersion, isDefault] of [ + ["1-addon@guid", "1.2", false], + ["2-addon@guid", "3.4", true], + ]) { + const searchEngine = ExtensionTestUtils.loadExtension({ + manifest: { + version: addonVersion, + browser_specific_settings: { + gecko: { id: addonId }, + }, + chrome_settings_overrides: { + search_provider: { + is_default: isDefault, + name: `test search engine - ${addonId}`, + keyword: "test", + search_url: `${SEARCH_URL_WWW}&id=${addonId}`, + }, + }, + }, + useAddonManager: "temporary", + }); + + await searchEngine.startup(); + await AddonTestUtils.waitForSearchProviderStartup(searchEngine); + + searchEngines.push(searchEngine); + } + + // Simulate a search by navigating to it. + const url = SEARCH_URL_WWW.replace("{searchTerms}", "some terms"); + await BrowserTestUtils.withNewTab("about:blank", async browser => { + // Wait for the tab to be fully loaded. + let loaded = BrowserTestUtils.browserLoaded(browser); + BrowserTestUtils.loadURIString(browser, url); + await loaded; + }); + + await Promise.all(searchEngines.map(engine => engine.unload())); + + TelemetryTestUtils.assertEvents( + [ + { + object: "other", + value: "server", + extra: { + addonId: "1-addon@guid", + addonVersion: "1.2", + from: "example.com", + to: "example.net", + }, + }, + { + object: "other", + value: "server", + extra: { + addonId: "2-addon@guid", + addonVersion: "3.4", + from: "example.com", + to: "example.net", + }, + }, + ], + TELEMETRY_EVENTS_FILTERS, + TELEMETRY_TEST_UTILS_OPTIONS + ); +}); -- cgit v1.2.3