diff options
Diffstat (limited to '')
-rw-r--r-- | toolkit/mozapps/extensions/test/browser/browser_html_discover_view_clientid.js | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/toolkit/mozapps/extensions/test/browser/browser_html_discover_view_clientid.js b/toolkit/mozapps/extensions/test/browser/browser_html_discover_view_clientid.js new file mode 100644 index 0000000000..034a42be5a --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_html_discover_view_clientid.js @@ -0,0 +1,219 @@ +/* eslint max-len: ["error", 80] */ +"use strict"; + +const { ClientID } = ChromeUtils.importESModule( + "resource://gre/modules/ClientID.sys.mjs" +); + +const { AddonTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/AddonTestUtils.sys.mjs" +); + +AddonTestUtils.initMochitest(this); +const server = AddonTestUtils.createHttpServer(); +const serverBaseUrl = `http://localhost:${server.identity.primaryPort}/`; +server.registerPathHandler("/sumo/personalized-addons", (request, response) => { + response.write("This is a SUMO page that explains personalized add-ons."); +}); + +// Before a discovery API request is triggered, this method should be called. +// Resolves with the value of the "telemetry-client-id" query parameter. +async function promiseOneDiscoveryApiRequest() { + return new Promise(resolve => { + let requestCount = 0; + // Overwrite previous request handler, if any. + server.registerPathHandler("/discoapi", (request, response) => { + is(++requestCount, 1, "Expecting one discovery API request"); + response.write(`{"results": []}`); + let searchParams = new URLSearchParams(request.queryString); + let clientId = searchParams.get("telemetry-client-id"); + resolve(clientId); + }); + }); +} + +function getNoticeButton(win) { + return win.document.querySelector("[action='notice-learn-more']"); +} + +function isNoticeVisible(win) { + let message = win.document.querySelector("taar-notice"); + return message && message.offsetHeight > 0; +} + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [ + // Enable clientid - see Discovery.jsm for the first two prefs. + ["browser.discovery.enabled", true], + // Enabling the Data Upload pref may upload data. + // Point data reporting services to localhost so the data doesn't escape. + ["toolkit.telemetry.server", "https://localhost:1337"], + ["telemetry.fog.test.localhost_port", -1], + ["datareporting.healthreport.uploadEnabled", true], + ["extensions.getAddons.discovery.api_url", `${serverBaseUrl}discoapi`], + ["app.support.baseURL", `${serverBaseUrl}sumo/`], + // Discovery API requests can be triggered by the discopane and the + // recommendations in the list view. To make sure that the every test + // checks the behavior of the view they're testing, ensure that only one + // of the two views is enabled at a time. + ["extensions.htmlaboutaddons.recommendations.enabled", false], + ], + }); +}); + +// Test that the clientid is passed to the API when enabled via prefs. +add_task(async function clientid_enabled() { + let EXPECTED_CLIENT_ID = await ClientID.getClientIdHash(); + ok(EXPECTED_CLIENT_ID, "ClientID should be available"); + + let requestPromise = promiseOneDiscoveryApiRequest(); + let win = await loadInitialView("discover"); + + ok(isNoticeVisible(win), "Notice about personalization should be visible"); + + // TODO: This should ideally check whether the result is the expected ID. + // But run with --verify, the test may fail with EXPECTED_CLIENT_ID being + // "baae8d197cf6b0865d7ba7ddf83829cd2d9844374d7271a5c704199d91059316", + // which is sha256(TelemetryUtils.knownClientId). + // This happens because at the end of the test, the pushPrefEnv from setup is + // reverted, which resets datareporting.healthreport.uploadEnabled to false. + // When TelemetryController.sys.mjs detects this, it asynchronously resets the + // ClientID to knownClientId - which may happen at the next run of the test. + // TODO: Fix this together with bug 1537933 + // + // is(await requestPromise, EXPECTED_CLIENT_ID, + ok( + await requestPromise, + "Moz-Client-Id should be set when telemetry & discovery are enabled" + ); + + let tabbrowser = win.windowRoot.ownerGlobal.gBrowser; + let expectedUrl = `${serverBaseUrl}sumo/personalized-addons`; + let tabPromise = BrowserTestUtils.waitForNewTab(tabbrowser, expectedUrl); + + getNoticeButton(win).click(); + + info(`Waiting for new tab with URL: ${expectedUrl}`); + let tab = await tabPromise; + BrowserTestUtils.removeTab(tab); + + await closeView(win); +}); + +// Test that the clientid is not sent when disabled via prefs. +add_task(async function clientid_disabled() { + // Temporarily override the prefs that we had set in setup. + await SpecialPowers.pushPrefEnv({ + set: [["browser.discovery.enabled", false]], + }); + let requestPromise = promiseOneDiscoveryApiRequest(); + let win = await loadInitialView("discover"); + ok(!isNoticeVisible(win), "Notice about personalization should be hidden"); + is( + await requestPromise, + null, + "Moz-Client-Id should not be sent when discovery is disabled" + ); + await closeView(win); + await SpecialPowers.popPrefEnv(); +}); + +// Test that the clientid is not sent from private windows. +add_task(async function clientid_from_private_window() { + let privateWindow = await BrowserTestUtils.openNewBrowserWindow({ + private: true, + }); + + let requestPromise = promiseOneDiscoveryApiRequest(); + let managerWindow = await open_manager( + "addons://discover/", + null, + null, + null, + privateWindow + ); + ok( + PrivateBrowsingUtils.isContentWindowPrivate(managerWindow), + "Addon-manager is in a private window" + ); + + is( + await requestPromise, + null, + "Moz-Client-Id should not be sent in private windows" + ); + + await close_manager(managerWindow); + await BrowserTestUtils.closeWindow(privateWindow); +}); + +add_task(async function clientid_enabled_from_extension_list() { + await SpecialPowers.pushPrefEnv({ + // Override prefs from setup to enable recommendations. + set: [ + ["extensions.htmlaboutaddons.recommendations.enabled", true], + ["extensions.getAddons.showPane", false], + ], + }); + + // Force the extension list to be the first load. This pref will be + // overwritten once the view loads. + Services.prefs.setCharPref(PREF_UI_LASTCATEGORY, "addons://list/extension"); + + let requestPromise = promiseOneDiscoveryApiRequest(); + let win = await loadInitialView("extension"); + + ok(isNoticeVisible(win), "Notice about personalization should be visible"); + + ok( + await requestPromise, + "Moz-Client-Id should be set when telemetry & discovery are enabled" + ); + + // Make sure switching to the theme view doesn't trigger another request. + await switchView(win, "theme"); + + // Wait until the request would have happened so promiseOneDiscoveryApiRequest + // can fail if it does. + let recommendations = win.document.querySelector("recommended-addon-list"); + await recommendations.loadCardsIfNeeded(); + + await closeView(win); + await SpecialPowers.popPrefEnv(); +}); + +add_task(async function clientid_enabled_from_theme_list() { + await SpecialPowers.pushPrefEnv({ + // Override prefs from setup to enable recommendations. + set: [ + ["extensions.htmlaboutaddons.recommendations.enabled", true], + ["extensions.getAddons.showPane", false], + ], + }); + + // Force the theme list to be the first load. This pref will be overwritten + // once the view loads. + Services.prefs.setCharPref(PREF_UI_LASTCATEGORY, "addons://list/theme"); + + let requestPromise = promiseOneDiscoveryApiRequest(); + let win = await loadInitialView("theme"); + + ok(!isNoticeVisible(win), "Notice about personalization should be hidden"); + + is( + await requestPromise, + null, + "Moz-Client-Id should not be sent when loading themes initially" + ); + + info("Load the extension list and verify the client ID is now sent"); + + requestPromise = promiseOneDiscoveryApiRequest(); + await switchView(win, "extension"); + + ok(await requestPromise, "Moz-Client-Id is now sent for extensions"); + + await closeView(win); + await SpecialPowers.popPrefEnv(); +}); |