/* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; requestLongerTimeout(2); const BAD_CERT = "https://expired.example.com/"; const BAD_STS_CERT = "https://badchain.include-subdomains.pinning.example.com:443"; add_task(async function checkTelemetryClickEvents() { info("Loading a bad cert page and verifying telemetry click events arrive."); let oldCanRecord = Services.telemetry.canRecordExtended; Services.telemetry.canRecordExtended = true; registerCleanupFunction(() => { Services.telemetry.canRecordExtended = oldCanRecord; }); // For obvious reasons event telemetry in the content processes updates with // the main processs asynchronously, so we need to wait for the main process // to catch up through the entire test. // There's an arbitrary interval of 2 seconds in which the content // processes sync their event data with the parent process, we wait // this out to ensure that we clear everything that is left over from // previous tests and don't receive random events in the middle of our tests. // eslint-disable-next-line mozilla/no-arbitrary-setTimeout await new Promise(c => setTimeout(c, 2000)); // Clear everything. Services.telemetry.clearEvents(); await TestUtils.waitForCondition(() => { let events = Services.telemetry.snapshotEvents( Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS, true ).content; return !events || !events.length; }); // Now enable recording our telemetry. Even if this is disabled, content // processes will send event telemetry to the parent, thus we needed to ensure // we waited and cleared first. Sigh. Services.telemetry.setEventRecordingEnabled("security.ui.certerror", true); for (let useFrame of [false, true]) { let recordedObjects = [ "advanced_button", "learn_more_link", "error_code_link", "clipboard_button_top", "clipboard_button_bot", "return_button_top", ]; recordedObjects.push("return_button_adv"); if (!useFrame) { recordedObjects.push("exception_button"); } for (let object of recordedObjects) { let tab = await openErrorPage(BAD_CERT, useFrame); let browser = tab.linkedBrowser; let loadEvents = await TestUtils.waitForCondition(() => { let events = Services.telemetry.snapshotEvents( Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS, true ).content; if (events && events.length) { events = events.filter( e => e[1] == "security.ui.certerror" && e[2] == "load" ); if ( events.length == 1 && events[0][5].is_frame == useFrame.toString() ) { return events; } } return null; }, "recorded telemetry for the load"); is( loadEvents.length, 1, `recorded telemetry for the load testing ${object}, useFrame: ${useFrame}` ); let bc = browser.browsingContext; if (useFrame) { bc = bc.children[0]; } await SpecialPowers.spawn(bc, [object], async function (objectId) { let doc = content.document; await ContentTaskUtils.waitForCondition( () => doc.body.classList.contains("certerror"), "Wait for certerror to be loaded" ); let domElement = doc.querySelector(`[data-telemetry-id='${objectId}']`); domElement.click(); }); let clickEvents = await TestUtils.waitForCondition(() => { let events = Services.telemetry.snapshotEvents( Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS, true ).content; if (events && events.length) { events = events.filter( e => e[1] == "security.ui.certerror" && e[2] == "click" && e[3] == object ); if ( events.length == 1 && events[0][5].is_frame == useFrame.toString() ) { return events; } } return null; }, "Has captured telemetry events."); is( clickEvents.length, 1, `recorded telemetry for the click on ${object}, useFrame: ${useFrame}` ); // We opened an extra tab for the SUMO page, need to close it. if (object == "learn_more_link") { BrowserTestUtils.removeTab(gBrowser.selectedTab); } if (object == "exception_button") { let certOverrideService = Cc[ "@mozilla.org/security/certoverride;1" ].getService(Ci.nsICertOverrideService); certOverrideService.clearValidityOverride( "expired.example.com", -1, {} ); } BrowserTestUtils.removeTab(gBrowser.selectedTab); } } let enableCertErrorUITelemetry = Services.prefs.getBoolPref( "security.certerrors.recordEventTelemetry" ); Services.telemetry.setEventRecordingEnabled( "security.ui.certerror", enableCertErrorUITelemetry ); });