browser_protectionsUI_cryptominers.js (8630B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const TRACKING_PAGE = 7 // eslint-disable-next-line @microsoft/sdl/no-insecure-url 8 "http://example.org/browser/browser/base/content/test/protectionsUI/trackingPage.html"; 9 const CM_PROTECTION_PREF = "privacy.trackingprotection.cryptomining.enabled"; 10 let cmHistogram; 11 12 add_setup(async function () { 13 await SpecialPowers.pushPrefEnv({ 14 set: [ 15 [ 16 "urlclassifier.features.cryptomining.blacklistHosts", 17 "cryptomining.example.com", 18 ], 19 [ 20 "urlclassifier.features.cryptomining.annotate.blacklistHosts", 21 "cryptomining.example.com", 22 ], 23 ["privacy.trackingprotection.enabled", false], 24 ["privacy.trackingprotection.annotate_channels", false], 25 ["privacy.trackingprotection.fingerprinting.enabled", false], 26 ["urlclassifier.features.fingerprinting.annotate.blacklistHosts", ""], 27 ], 28 }); 29 cmHistogram = Services.telemetry.getHistogramById( 30 "CRYPTOMINERS_BLOCKED_COUNT" 31 ); 32 registerCleanupFunction(() => { 33 cmHistogram.clear(); 34 }); 35 }); 36 37 async function testIdentityState(hasException) { 38 cmHistogram.clear(); 39 let promise = BrowserTestUtils.openNewForegroundTab({ 40 url: TRACKING_PAGE, 41 gBrowser, 42 }); 43 let [tab] = await Promise.all([promise, waitForContentBlockingEvent()]); 44 45 if (hasException) { 46 let loaded = BrowserTestUtils.browserLoaded( 47 tab.linkedBrowser, 48 false, 49 TRACKING_PAGE 50 ); 51 gProtectionsHandler.disableForCurrentPage(); 52 await loaded; 53 } 54 55 await openProtectionsPanel(); 56 57 ok( 58 !gProtectionsHandler._protectionsPopup.hasAttribute("detected"), 59 "cryptominers are not detected" 60 ); 61 62 ok( 63 BrowserTestUtils.isVisible(gProtectionsHandler.iconBox), 64 "icon box is visible regardless the exception" 65 ); 66 67 promise = waitForContentBlockingEvent(); 68 69 await SpecialPowers.spawn(tab.linkedBrowser, [], function () { 70 content.postMessage("cryptomining", "*"); 71 }); 72 73 await promise; 74 75 ok( 76 gProtectionsHandler._protectionsPopup.hasAttribute("detected"), 77 "trackers are detected" 78 ); 79 ok( 80 BrowserTestUtils.isVisible(gProtectionsHandler.iconBox), 81 "icon box is visible" 82 ); 83 is( 84 gProtectionsHandler.iconBox.hasAttribute("hasException"), 85 hasException, 86 "Shows an exception when appropriate" 87 ); 88 89 if (hasException) { 90 let loaded = BrowserTestUtils.browserLoaded( 91 tab.linkedBrowser, 92 false, 93 TRACKING_PAGE 94 ); 95 gProtectionsHandler.enableForCurrentPage(); 96 await loaded; 97 } 98 99 let loads = hasException ? 3 : 1; 100 testTelemetry(loads, 1, hasException); 101 102 BrowserTestUtils.removeTab(tab); 103 } 104 105 async function testSubview(hasException) { 106 cmHistogram.clear(); 107 let promise = BrowserTestUtils.openNewForegroundTab({ 108 url: TRACKING_PAGE, 109 gBrowser, 110 }); 111 let [tab] = await Promise.all([promise, waitForContentBlockingEvent()]); 112 113 if (hasException) { 114 let loaded = BrowserTestUtils.browserLoaded( 115 tab.linkedBrowser, 116 false, 117 TRACKING_PAGE 118 ); 119 gProtectionsHandler.disableForCurrentPage(); 120 await loaded; 121 } 122 123 promise = waitForContentBlockingEvent(); 124 await SpecialPowers.spawn(tab.linkedBrowser, [], function () { 125 content.postMessage("cryptomining", "*"); 126 }); 127 await promise; 128 129 await openProtectionsPanel(); 130 131 let categoryItem = document.getElementById( 132 "protections-popup-category-cryptominers" 133 ); 134 135 // Explicitly waiting for the category item becoming visible. 136 await TestUtils.waitForCondition(() => { 137 return BrowserTestUtils.isVisible(categoryItem); 138 }); 139 140 ok(BrowserTestUtils.isVisible(categoryItem), "TP category item is visible"); 141 142 /* eslint-disable mozilla/no-arbitrary-setTimeout */ 143 // We have to wait until the ContentBlockingLog gets updated in the content. 144 // Unfortunately, we need to use the setTimeout here since we don't have an 145 // easy to know whether the log is updated in the content. This should be 146 // removed after the log been removed in the content (Bug 1599046). 147 await new Promise(resolve => { 148 setTimeout(resolve, 500); 149 }); 150 /* eslint-enable mozilla/no-arbitrary-setTimeout */ 151 152 let subview = document.getElementById("protections-popup-cryptominersView"); 153 let viewShown = BrowserTestUtils.waitForEvent(subview, "ViewShown"); 154 categoryItem.click(); 155 await viewShown; 156 157 let trackersViewShimHint = document.getElementById( 158 "protections-popup-cryptominersView-shim-allow-hint" 159 ); 160 ok(trackersViewShimHint.hidden, "Shim hint is hidden"); 161 162 let listItems = subview.querySelectorAll(".protections-popup-list-item"); 163 is(listItems.length, 1, "We have 1 item in the list"); 164 let listItem = listItems[0]; 165 ok(BrowserTestUtils.isVisible(listItem), "List item is visible"); 166 is( 167 listItem.querySelector("label").value, 168 // eslint-disable-next-line @microsoft/sdl/no-insecure-url 169 "http://cryptomining.example.com", 170 "Has the correct host" 171 ); 172 is( 173 listItem.classList.contains("allowed"), 174 hasException, 175 "Indicates the miner was blocked or allowed" 176 ); 177 178 let mainView = document.getElementById("protections-popup-mainView"); 179 viewShown = BrowserTestUtils.waitForEvent(mainView, "ViewShown"); 180 let backButton = subview.querySelector(".subviewbutton-back"); 181 backButton.click(); 182 await viewShown; 183 184 ok(true, "Main view was shown"); 185 186 if (hasException) { 187 let loaded = BrowserTestUtils.browserLoaded( 188 tab.linkedBrowser, 189 false, 190 TRACKING_PAGE 191 ); 192 gProtectionsHandler.enableForCurrentPage(); 193 await loaded; 194 } 195 196 let loads = hasException ? 3 : 1; 197 testTelemetry(loads, 1, hasException); 198 199 BrowserTestUtils.removeTab(tab); 200 } 201 202 async function testCategoryItem() { 203 Services.prefs.setBoolPref(CM_PROTECTION_PREF, false); 204 let promise = BrowserTestUtils.openNewForegroundTab({ 205 url: TRACKING_PAGE, 206 gBrowser, 207 }); 208 let [tab] = await Promise.all([promise, waitForContentBlockingEvent()]); 209 210 await openProtectionsPanel(); 211 212 let categoryItem = document.getElementById( 213 "protections-popup-category-cryptominers" 214 ); 215 216 ok( 217 !categoryItem.classList.contains("blocked"), 218 "Category not marked as blocked" 219 ); 220 ok( 221 categoryItem.classList.contains("notFound"), 222 "Category marked as not found" 223 ); 224 Services.prefs.setBoolPref(CM_PROTECTION_PREF, true); 225 ok(categoryItem.classList.contains("blocked"), "Category marked as blocked"); 226 ok( 227 categoryItem.classList.contains("notFound"), 228 "Category marked as not found" 229 ); 230 Services.prefs.setBoolPref(CM_PROTECTION_PREF, false); 231 ok( 232 !categoryItem.classList.contains("blocked"), 233 "Category not marked as blocked" 234 ); 235 ok( 236 categoryItem.classList.contains("notFound"), 237 "Category marked as not found" 238 ); 239 await closeProtectionsPanel(); 240 241 promise = waitForContentBlockingEvent(); 242 243 await SpecialPowers.spawn(tab.linkedBrowser, [], function () { 244 content.postMessage("cryptomining", "*"); 245 }); 246 247 await promise; 248 249 await openProtectionsPanel(); 250 ok( 251 !categoryItem.classList.contains("blocked"), 252 "Category not marked as blocked" 253 ); 254 ok( 255 !categoryItem.classList.contains("notFound"), 256 "Category not marked as not found" 257 ); 258 Services.prefs.setBoolPref(CM_PROTECTION_PREF, true); 259 ok(categoryItem.classList.contains("blocked"), "Category marked as blocked"); 260 ok( 261 !categoryItem.classList.contains("notFound"), 262 "Category not marked as not found" 263 ); 264 Services.prefs.setBoolPref(CM_PROTECTION_PREF, false); 265 ok( 266 !categoryItem.classList.contains("blocked"), 267 "Category not marked as blocked" 268 ); 269 ok( 270 !categoryItem.classList.contains("notFound"), 271 "Category not marked as not found" 272 ); 273 await closeProtectionsPanel(); 274 275 BrowserTestUtils.removeTab(tab); 276 } 277 278 function testTelemetry(pagesVisited, pagesWithBlockableContent, hasException) { 279 let results = cmHistogram.snapshot(); 280 Assert.equal( 281 results.values[0], 282 pagesVisited, 283 "The correct number of page loads have been recorded" 284 ); 285 let expectedValue = hasException ? 2 : 1; 286 Assert.equal( 287 results.values[expectedValue], 288 pagesWithBlockableContent, 289 "The correct number of cryptominers have been recorded as blocked or allowed." 290 ); 291 } 292 293 add_task(async function test() { 294 Services.prefs.setBoolPref(CM_PROTECTION_PREF, true); 295 296 await testIdentityState(false); 297 await testIdentityState(true); 298 299 await testSubview(false); 300 await testSubview(true); 301 302 await testCategoryItem(); 303 304 Services.prefs.clearUserPref(CM_PROTECTION_PREF); 305 Services.prefs.setStringPref("browser.contentblocking.category", "standard"); 306 });