browser_privacy_ipprotection.js (11897B)
1 /* Any copyright is dedicated to the Public Domain. 2 * https://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 // This file tests the Privacy pane's Firefox VPN UI. 5 6 "use strict"; 7 8 const FEATURE_PREF = "browser.ipProtection.enabled"; 9 const SITE_EXCEPTIONS_FEATURE_PREF = 10 "browser.ipProtection.features.siteExceptions"; 11 const AUTOSTART_FEATURE_ENABLED_PREF = 12 "browser.ipProtection.features.autoStart"; 13 const AUTOSTART_PREF = "browser.ipProtection.autoStartEnabled"; 14 const AUTOSTART_PRIVATE_PREF = "browser.ipProtection.autoStartPrivateEnabled"; 15 const ONBOARDING_MESSAGE_MASK_PREF = 16 "browser.ipProtection.onboardingMessageMask"; 17 18 const SECTION_ID = "dataIPProtectionGroup"; 19 20 async function setupVpnPrefs({ 21 feature = false, 22 siteExceptions = false, 23 autostartFeatureEnabled = false, 24 autostart = false, 25 autostartprivate = false, 26 }) { 27 return SpecialPowers.pushPrefEnv({ 28 set: [ 29 [FEATURE_PREF, feature], 30 [SITE_EXCEPTIONS_FEATURE_PREF, siteExceptions], 31 [AUTOSTART_FEATURE_ENABLED_PREF, autostartFeatureEnabled], 32 [AUTOSTART_PREF, autostart], 33 [AUTOSTART_PRIVATE_PREF, autostartprivate], 34 ], 35 }); 36 } 37 38 function testSettingsGroupVisible(browser, sectionId) { 39 let section = browser.contentDocument.getElementById(sectionId); 40 let settingGroup = section.querySelector( 41 `setting-group[groupid="ipprotection"]` 42 ); 43 is_element_visible(section, "#dataIPProtectionGroup is shown"); 44 is_element_visible(settingGroup, "ipprotection setting group is shown"); 45 46 return settingGroup; 47 } 48 49 // Test the section is hidden on page load if the feature pref is disabled. 50 add_task( 51 async function test_section_removed_when_set_to_ineligible_experiment_pref() { 52 await setupVpnPrefs({ feature: false }); 53 54 await BrowserTestUtils.withNewTab( 55 { gBrowser, url: "about:preferences#privacy" }, 56 async function (browser) { 57 let section = browser.contentDocument.getElementById(SECTION_ID); 58 is_element_hidden(section, "#dataIPProtectionGroup is hidden"); 59 } 60 ); 61 62 await SpecialPowers.popPrefEnv(); 63 } 64 ); 65 66 // Test the section is shown on page load if the feature pref is enabled 67 add_task( 68 async function test_section_shown_when_set_to_eligible_experiment_pref() { 69 await setupVpnPrefs({ feature: true }); 70 71 await BrowserTestUtils.withNewTab( 72 { gBrowser, url: "about:preferences#privacy" }, 73 async function (browser) { 74 testSettingsGroupVisible(browser, SECTION_ID); 75 } 76 ); 77 } 78 ); 79 80 // Test the site exceptions controls load correctly. 81 add_task(async function test_exceptions_settings() { 82 await setupVpnPrefs({ feature: true, siteExceptions: true }); 83 84 await BrowserTestUtils.withNewTab( 85 { gBrowser, url: "about:preferences#privacy" }, 86 async function (browser) { 87 let settingGroup = testSettingsGroupVisible(browser, SECTION_ID); 88 let siteExceptionsGroup = settingGroup?.querySelector( 89 "#ipProtectionExceptions" 90 ); 91 is_element_visible(siteExceptionsGroup, "Site exceptions group is shown"); 92 93 let exceptionAllListButton = siteExceptionsGroup?.querySelector( 94 "#ipProtectionExceptionAllListButton" 95 ); 96 is_element_visible( 97 exceptionAllListButton, 98 "Button for list of exclusions is shown" 99 ); 100 } 101 ); 102 }); 103 104 // Test that we show the "Add" button in the site exceptions permission dialog 105 // and correctly add site exclusions. 106 add_task(async function test_exclusions_add_button() { 107 const PERM_NAME = "ipp-vpn"; 108 await setupVpnPrefs({ feature: "beta", siteExceptions: true }); 109 110 await BrowserTestUtils.withNewTab( 111 { gBrowser, url: "about:preferences#privacy" }, 112 async function (browser) { 113 let settingGroup = testSettingsGroupVisible(browser, SECTION_ID); 114 let siteExceptionsGroup = settingGroup?.querySelector( 115 "#ipProtectionExceptions" 116 ); 117 let exceptionAllListButton = siteExceptionsGroup?.querySelector( 118 "#ipProtectionExceptionAllListButton" 119 ); 120 is_element_visible( 121 exceptionAllListButton, 122 "Button for list of exclusions is shown" 123 ); 124 125 // Clear ipp-vpn to start with 0 exclusions 126 Services.perms.removeByType(PERM_NAME); 127 128 // Let's load the dialog 129 let promiseSubDialogLoaded = promiseLoadSubDialog( 130 "chrome://browser/content/preferences/dialogs/permissions.xhtml" 131 ); 132 133 exceptionAllListButton.click(); 134 135 const win = await promiseSubDialogLoaded; 136 137 let addButton = win.document.getElementById("btnAdd"); 138 Assert.ok(addButton, "Add button exists"); 139 Assert.ok(BrowserTestUtils.isVisible(addButton), "Add button is visible"); 140 Assert.ok(addButton.disabled, "Add button is disabled"); 141 142 // Now let's click the Add button to add a new exclusion 143 let permissionsBox = win.document.getElementById("permissionsBox"); 144 let siteListUpdatedPromise = BrowserTestUtils.waitForMutationCondition( 145 permissionsBox, 146 { subtree: true, childList: true }, 147 () => { 148 return permissionsBox.children.length; 149 } 150 ); 151 152 // Set up a mock url input value 153 let urlField = win.document.getElementById("url"); 154 Assert.ok(urlField, "Dialog url field exists"); 155 const site1 = "https://example.com"; 156 urlField.focus(); 157 158 EventUtils.sendString(site1, win); 159 Assert.ok(!addButton.disabled, "Add button is enabled"); 160 161 addButton.click(); 162 163 await siteListUpdatedPromise; 164 165 permissionsBox = win.document.getElementById("permissionsBox"); 166 Assert.equal( 167 permissionsBox.children.length, 168 1, 169 "Should have 1 site listed as an exclusion" 170 ); 171 172 let shownSite1 = permissionsBox.children[0]; 173 Assert.equal( 174 shownSite1.getAttribute("origin"), 175 site1, 176 "Should match inputted site in the list of sites" 177 ); 178 179 // Apply the changes 180 let saveButton = win.document.querySelector("dialog").getButton("accept"); 181 Assert.ok(saveButton, "Save button is shown"); 182 183 saveButton.click(); 184 185 let exclusions = Services.perms.getAllByTypes([PERM_NAME]); 186 Assert.equal( 187 exclusions.length, 188 1, 189 "Should have 1 exclusion after pressing the Add button" 190 ); 191 Assert.equal( 192 exclusions[0]?.principal.siteOrigin, 193 site1, 194 "Should match the inputted site" 195 ); 196 197 // Clean up 198 Services.perms.removeByType(PERM_NAME); 199 Services.prefs.clearUserPref(ONBOARDING_MESSAGE_MASK_PREF); 200 } 201 ); 202 }); 203 204 // Test that we show the correct number of site exclusions 205 add_task(async function test_exclusions_count() { 206 const PERM_NAME = "ipp-vpn"; 207 await setupVpnPrefs({ feature: "beta", siteExceptions: true }); 208 209 await BrowserTestUtils.withNewTab( 210 { gBrowser, url: "about:preferences#privacy" }, 211 async function (browser) { 212 let section = browser.contentDocument.getElementById(SECTION_ID); 213 let settingGroup = section.querySelector( 214 `setting-group[groupid="ipprotection"]` 215 ); 216 is_element_visible(section, "#dataIPProtectionGroup is shown"); 217 is_element_visible(settingGroup, "ipprotection setting group is shown"); 218 219 let siteExceptionsGroup = settingGroup?.querySelector( 220 "#ipProtectionExceptions" 221 ); 222 is_element_visible(siteExceptionsGroup, "Site exceptions group is shown"); 223 224 let exceptionAllListButton = siteExceptionsGroup?.querySelector( 225 "#ipProtectionExceptionAllListButton" 226 ); 227 is_element_visible( 228 exceptionAllListButton, 229 "Button for list of exclusions is shown" 230 ); 231 232 let sitesCountUpdatedPromise = BrowserTestUtils.waitForMutationCondition( 233 exceptionAllListButton, 234 { attributes: true, attributeFilter: ["data-l10n-args"] }, 235 () => { 236 let args = exceptionAllListButton.getAttribute("data-l10n-args"); 237 return args && JSON.parse(args)?.count === 0; 238 } 239 ); 240 241 // Clear ipp-vpn to start with 0 exclusions 242 Services.perms.removeByType(PERM_NAME); 243 244 await sitesCountUpdatedPromise; 245 246 Assert.ok(true, "Should show 0 exclusions initially"); 247 248 // Now test with 1 exclusion 249 sitesCountUpdatedPromise = BrowserTestUtils.waitForMutationCondition( 250 exceptionAllListButton, 251 { attributes: true, attributeFilter: ["data-l10n-args"] }, 252 () => { 253 let args = exceptionAllListButton.getAttribute("data-l10n-args"); 254 return args && JSON.parse(args)?.count === 1; 255 } 256 ); 257 let site1 = "https://example.com"; 258 let principal1 = 259 Services.scriptSecurityManager.createContentPrincipalFromOrigin(site1); 260 Services.perms.addFromPrincipal( 261 principal1, 262 PERM_NAME, 263 Services.perms.DENY_ACTION 264 ); 265 266 await sitesCountUpdatedPromise; 267 268 Assert.ok(true, "Should show 1 exclusion after adding the first site"); 269 270 // Now test with 2 exclusions 271 sitesCountUpdatedPromise = BrowserTestUtils.waitForMutationCondition( 272 exceptionAllListButton, 273 { attributes: true, attributeFilter: ["data-l10n-args"] }, 274 () => { 275 let args = exceptionAllListButton.getAttribute("data-l10n-args"); 276 return args && JSON.parse(args)?.count === 2; 277 } 278 ); 279 let site2 = "https://example.org"; 280 let principal2 = 281 Services.scriptSecurityManager.createContentPrincipalFromOrigin(site2); 282 Services.perms.addFromPrincipal( 283 principal2, 284 PERM_NAME, 285 Services.perms.DENY_ACTION 286 ); 287 288 await sitesCountUpdatedPromise; 289 290 Assert.ok(true, "Should show 2 exclusions after adding the second site"); 291 292 // Clean up 293 Services.perms.removeByType(PERM_NAME); 294 Services.prefs.clearUserPref(ONBOARDING_MESSAGE_MASK_PREF); 295 } 296 ); 297 }); 298 299 // Test that autostart checkboxes exist and map to the correct preferences 300 add_task(async function test_autostart_checkboxes() { 301 await setupVpnPrefs({ 302 feature: true, 303 autostartFeatureEnabled: true, 304 autostart: true, 305 autostartprivate: true, 306 }); 307 308 await BrowserTestUtils.withNewTab( 309 { gBrowser, url: "about:preferences#privacy" }, 310 async function (browser) { 311 let settingGroup = testSettingsGroupVisible(browser, SECTION_ID); 312 let autoStartSettings = settingGroup?.querySelector( 313 "#ipProtectionAutoStart" 314 ); 315 is_element_visible( 316 autoStartSettings, 317 "autoStart settings group is shown" 318 ); 319 320 let autoStartCheckbox = autoStartSettings?.querySelector( 321 "#ipProtectionAutoStartCheckbox" 322 ); 323 let autoStartPrivateCheckbox = autoStartSettings?.querySelector( 324 "#ipProtectionAutoStartPrivateCheckbox" 325 ); 326 327 Assert.ok( 328 autoStartCheckbox.checked, 329 "Autostart checkbox should be checked" 330 ); 331 Assert.ok( 332 autoStartPrivateCheckbox.checked, 333 "Autostart in private browsing checkbox should be checked" 334 ); 335 } 336 ); 337 }); 338 339 // Test that additional links exist 340 add_task(async function test_additional_links() { 341 await setupVpnPrefs({ 342 feature: true, 343 }); 344 345 await BrowserTestUtils.withNewTab( 346 { gBrowser, url: "about:preferences#privacy" }, 347 async function (browser) { 348 let settingGroup = testSettingsGroupVisible(browser, SECTION_ID); 349 let additionalLinks = settingGroup?.querySelector( 350 "#ipProtectionAdditionalLinks" 351 ); 352 is_element_visible(additionalLinks, "Additional links section is shown"); 353 354 let ipProtectionSupportLink = additionalLinks?.querySelector( 355 "#ipProtectionSupportLink" 356 ); 357 let ipProtectionUpgradeLink = additionalLinks?.querySelector( 358 "#ipProtectionUpgradeLink" 359 ); 360 is_element_visible(ipProtectionSupportLink, "Support link is shown"); 361 is_element_visible(ipProtectionUpgradeLink, "Upgrade link is shown"); 362 } 363 ); 364 });