browser_aboutCertError_telemetry.js (6928B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 requestLongerTimeout(4); 7 8 const BAD_CERT = "https://expired.example.com/"; 9 const BAD_STS_CERT = 10 "https://badchain.include-subdomains.pinning.example.com:443"; 11 12 async function checkTelemetryClickEvents(useFelt) { 13 info("Loading a bad cert page and verifying telemetry click events arrive."); 14 await SpecialPowers.pushPrefEnv({ 15 set: [["security.certerrors.felt-privacy-v1", useFelt]], 16 }); 17 18 let oldCanRecord = Services.telemetry.canRecordExtended; 19 Services.telemetry.canRecordExtended = true; 20 21 registerCleanupFunction(() => { 22 Services.telemetry.canRecordExtended = oldCanRecord; 23 }); 24 25 // For obvious reasons event telemetry in the content processes updates with 26 // the main processs asynchronously, so we need to wait for the main process 27 // to catch up through the entire test. 28 29 // There's an arbitrary interval of 2 seconds in which the content 30 // processes sync their event data with the parent process, we wait 31 // this out to ensure that we clear everything that is left over from 32 // previous tests and don't receive random events in the middle of our tests. 33 // eslint-disable-next-line mozilla/no-arbitrary-setTimeout 34 await new Promise(c => setTimeout(c, 2000)); 35 36 // Clear everything. 37 Services.telemetry.clearEvents(); 38 await TestUtils.waitForCondition(() => { 39 let events = Services.telemetry.snapshotEvents( 40 Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS, 41 true 42 ).content; 43 return !events || !events.length; 44 }); 45 46 for (let useFrame of [false, true]) { 47 let recordedObjects = [ 48 "advanced_button", 49 "learn_more_link", 50 "error_code_link", 51 "clipboard_button_top", 52 "clipboard_button_bot", 53 ]; 54 55 const mapRecordObjectsFelt = { 56 advanced_button: "advancedButton", 57 learn_more_link: "learnMoreLink", 58 error_code_link: "errorCode", 59 clipboard_button_top: "copyButtonTop", 60 clipboard_button_bot: "copyButtonBot", 61 return_button_adv: "returnButton", 62 exception_button: "exceptionButton", 63 }; 64 65 recordedObjects.push("return_button_adv"); 66 if (!useFrame) { 67 recordedObjects.push("exception_button"); 68 } 69 if (!useFelt) { 70 recordedObjects.push("return_button_top"); 71 } 72 73 for (let object of recordedObjects) { 74 let tab = await openErrorPage(BAD_CERT, useFrame); 75 let browser = tab.linkedBrowser; 76 77 let loadEvents = await TestUtils.waitForCondition(() => { 78 let events = Services.telemetry.snapshotEvents( 79 Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS, 80 true 81 ).content; 82 if (events && events.length) { 83 events = events.filter( 84 e => e[1] == "security.ui.certerror" && e[2] == "load" 85 ); 86 if ( 87 events.length == 1 && 88 events[0][5].is_frame == useFrame.toString() 89 ) { 90 return events; 91 } 92 } 93 return null; 94 }, "recorded telemetry for the load"); 95 96 is( 97 loadEvents.length, 98 1, 99 `recorded telemetry for the load testing ${object}, useFrame: ${useFrame}` 100 ); 101 102 let bc = browser.browsingContext; 103 if (useFrame) { 104 bc = bc.children[0]; 105 } 106 107 await SpecialPowers.spawn( 108 bc, 109 [object, useFelt, mapRecordObjectsFelt], 110 async function (objectId, use_felt, mapFelt) { 111 let doc = content.document; 112 113 if (use_felt) { 114 const netErrorCard = 115 doc.querySelector("net-error-card").wrappedJSObject; 116 const advancedButton = netErrorCard.advancedButton; 117 if ( 118 !netErrorCard.advancedContainer && 119 objectId !== "advanced_button" 120 ) { 121 advancedButton.scrollIntoView(true); 122 EventUtils.synthesizeMouseAtCenter(advancedButton, {}, content); 123 124 await ContentTaskUtils.waitForCondition( 125 () => netErrorCard.advancedContainer, 126 "Advanced section should be rendered for revoked certificate" 127 ); 128 } 129 if ( 130 ["clipboard_button_top", "clipboard_button_bot"].includes( 131 objectId 132 ) 133 ) { 134 netErrorCard.errorCode.click(); 135 await ContentTaskUtils.waitForCondition( 136 () => netErrorCard[mapFelt[objectId]], 137 "Wait for component to render." 138 ); 139 } 140 if (objectId === "exception_button") { 141 await ContentTaskUtils.waitForCondition( 142 () => 143 netErrorCard.exceptionButton && 144 !netErrorCard.exceptionButton.disabled, 145 "Wait for the exception button to be created." 146 ); 147 } 148 const el = netErrorCard[mapFelt[objectId]]; 149 el.scrollIntoView(true); 150 EventUtils.synthesizeMouseAtCenter(el, {}, content); 151 } else { 152 await ContentTaskUtils.waitForCondition( 153 () => doc.body.classList.contains("certerror"), 154 "Wait for certerror to be loaded" 155 ); 156 let domElement = doc.querySelector( 157 `[data-telemetry-id='${objectId}']` 158 ); 159 domElement.click(); 160 } 161 } 162 ); 163 164 let clickEvents = await TestUtils.waitForCondition(() => { 165 let events = Services.telemetry.snapshotEvents( 166 Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS, 167 true 168 ).content; 169 if (events && events.length) { 170 events = events.filter( 171 e => 172 e[1] == "security.ui.certerror" && 173 e[2] == "click" && 174 e[3] == object 175 ); 176 if ( 177 events.length == 1 && 178 events[0][5].is_frame == useFrame.toString() 179 ) { 180 return events; 181 } 182 } 183 return null; 184 }, "Has captured telemetry events."); 185 186 is( 187 clickEvents.length, 188 1, 189 `recorded telemetry for the click on ${object}, useFrame: ${useFrame}` 190 ); 191 192 // We opened an extra tab for the SUMO page, need to close it. 193 if (object == "learn_more_link") { 194 BrowserTestUtils.removeTab(gBrowser.selectedTab); 195 } 196 197 if (object == "exception_button") { 198 let certOverrideService = Cc[ 199 "@mozilla.org/security/certoverride;1" 200 ].getService(Ci.nsICertOverrideService); 201 certOverrideService.clearValidityOverride( 202 "expired.example.com", 203 -1, 204 {} 205 ); 206 } 207 208 BrowserTestUtils.removeTab(gBrowser.selectedTab); 209 } 210 } 211 } 212 213 add_task(async function runCheckTelemetryClickEvents() { 214 for (const useFelt of [true, false]) { 215 await checkTelemetryClickEvents(useFelt); 216 } 217 });