head.js (5748B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 const { Sqlite } = ChromeUtils.importESModule( 5 "resource://gre/modules/Sqlite.sys.mjs" 6 ); 7 8 XPCOMUtils.defineLazyServiceGetter( 9 this, 10 "TrackingDBService", 11 "@mozilla.org/tracking-db-service;1", 12 Ci.nsITrackingDBService 13 ); 14 15 ChromeUtils.defineLazyGetter(this, "TRACK_DB_PATH", function () { 16 return PathUtils.join(PathUtils.profileDir, "protections.sqlite"); 17 }); 18 19 ChromeUtils.defineESModuleGetters(this, { 20 ContentBlockingAllowList: 21 "resource://gre/modules/ContentBlockingAllowList.sys.mjs", 22 }); 23 24 var { UrlClassifierTestUtils } = ChromeUtils.importESModule( 25 "resource://testing-common/UrlClassifierTestUtils.sys.mjs" 26 ); 27 28 async function waitForProtectionsPanelToast() { 29 await BrowserTestUtils.waitForEvent( 30 gProtectionsHandler._protectionsPopup, 31 "popupshown" 32 ); 33 Assert.ok( 34 gProtectionsHandler._protectionsPopup.hasAttribute("toast"), 35 "Protections panel toast is shown." 36 ); 37 38 await BrowserTestUtils.waitForEvent( 39 gProtectionsHandler._protectionsPopup, 40 "popuphidden" 41 ); 42 } 43 44 async function openProtectionsPanel(toast, win = window) { 45 let popupShownPromise = BrowserTestUtils.waitForEvent( 46 win, 47 "popupshown", 48 true, 49 e => e.target.id == "protections-popup" 50 ); 51 let shieldIconContainer = win.document.getElementById( 52 "tracking-protection-icon-container" 53 ); 54 55 // Register a promise to wait for the tooltip to be shown. 56 let tooltip = win.document.getElementById("tracking-protection-icon-tooltip"); 57 let tooltipShownPromise = BrowserTestUtils.waitForPopupEvent( 58 tooltip, 59 "shown" 60 ); 61 62 // nsXULTooltipListener will fail silently if no drag service is available 63 Assert.ok( 64 !SpecialPowers.isHeadless, 65 "openProtectionsPanel cannot be used in headless mode." 66 ); 67 68 // Move out than move over the shield icon to trigger the hover event in 69 // order to fetch tracker count. 70 EventUtils.synthesizeMouseAtCenter( 71 win.gURLBar, 72 { 73 type: "mousemove", 74 }, 75 win 76 ); 77 EventUtils.synthesizeMouseAtCenter( 78 shieldIconContainer, 79 { 80 type: "mousemove", 81 }, 82 win 83 ); 84 85 // Wait for the tooltip to be shown. 86 await tooltipShownPromise; 87 88 if (!toast) { 89 EventUtils.synthesizeMouseAtCenter(shieldIconContainer, {}, win); 90 } else { 91 win.gProtectionsHandler.showProtectionsPopup({ toast }); 92 } 93 94 await popupShownPromise; 95 } 96 97 async function openProtectionsPanelWithKeyNav() { 98 let popupShownPromise = BrowserTestUtils.waitForEvent( 99 window, 100 "popupshown", 101 true, 102 e => e.target.id == "protections-popup" 103 ); 104 105 gURLBar.focus(); 106 107 // This will trigger the focus event for the shield icon for pre-fetching 108 // the tracker count. 109 EventUtils.synthesizeKey("KEY_Tab", { shiftKey: true }); 110 is(document.activeElement.id, "urlbar-searchmode-switcher"); 111 EventUtils.synthesizeKey("KEY_ArrowRight"); 112 EventUtils.synthesizeKey("KEY_Enter"); 113 114 await popupShownPromise; 115 } 116 117 async function closeProtectionsPanel(win = window) { 118 let protectionsPopup = win.document.getElementById("protections-popup"); 119 if (!protectionsPopup) { 120 return; 121 } 122 let popuphiddenPromise = BrowserTestUtils.waitForEvent( 123 protectionsPopup, 124 "popuphidden" 125 ); 126 127 PanelMultiView.hidePopup(protectionsPopup); 128 await popuphiddenPromise; 129 } 130 131 function checkClickTelemetry(objectName, value, source = "protectionspopup") { 132 let events = Services.telemetry.snapshotEvents( 133 Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS 134 ).parent; 135 let buttonEvents = events.filter( 136 e => 137 e[1] == `security.ui.${source}` && 138 e[2] == "click" && 139 e[3] == objectName && 140 e[4] === value 141 ); 142 is(buttonEvents.length, 1, `recorded ${objectName} telemetry event`); 143 } 144 145 async function addTrackerDataIntoDB(count) { 146 const insertSQL = 147 "INSERT INTO events (type, count, timestamp)" + 148 "VALUES (:type, :count, date(:timestamp));"; 149 150 let db = await Sqlite.openConnection({ path: TRACK_DB_PATH }); 151 let date = new Date().toISOString(); 152 153 await db.execute(insertSQL, { 154 type: TrackingDBService.TRACKERS_ID, 155 count, 156 timestamp: date, 157 }); 158 159 await db.close(); 160 } 161 162 async function waitForAboutProtectionsTab() { 163 let tab = await BrowserTestUtils.waitForNewTab( 164 gBrowser, 165 "about:protections", 166 true 167 ); 168 169 // When the graph is built it means the messaging has finished, 170 // we can close the tab. 171 await SpecialPowers.spawn(tab.linkedBrowser, [], async function () { 172 await ContentTaskUtils.waitForCondition(() => { 173 let bars = content.document.querySelectorAll(".graph-bar"); 174 return bars.length; 175 }, "The graph has been built"); 176 }); 177 178 return tab; 179 } 180 181 function waitForSecurityChange(numChanges = 1, win = null) { 182 if (!win) { 183 win = window; 184 } 185 return new Promise(resolve => { 186 let n = 0; 187 let listener = { 188 onSecurityChange() { 189 n = n + 1; 190 info("Received onSecurityChange event " + n + " of " + numChanges); 191 if (n >= numChanges) { 192 win.gBrowser.removeProgressListener(listener); 193 resolve(n); 194 } 195 }, 196 }; 197 win.gBrowser.addProgressListener(listener); 198 }); 199 } 200 201 function waitForContentBlockingEvent(numChanges = 1, win = null) { 202 if (!win) { 203 win = window; 204 } 205 return new Promise(resolve => { 206 let n = 0; 207 let listener = { 208 onContentBlockingEvent(webProgress, request, event) { 209 n = n + 1; 210 info( 211 `Received onContentBlockingEvent event: ${event} (${n} of ${numChanges})` 212 ); 213 if (n >= numChanges) { 214 win.gBrowser.removeProgressListener(listener); 215 resolve(n); 216 } 217 }, 218 }; 219 win.gBrowser.addProgressListener(listener); 220 }); 221 }