browser_permissions_dialog.js (20336B)
1 "use strict"; 2 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 const PERMISSIONS_URL = 8 "chrome://browser/content/preferences/dialogs/sitePermissions.xhtml"; 9 const URL = "http://www.example.com"; 10 const URI = Services.io.newURI(URL); 11 var sitePermissionsDialog; 12 let settingsButtonMap = { 13 "desktop-notification": "notificationSettingsButton", 14 speaker: "speakerSettingsButton", 15 }; 16 17 function checkMenulistPermissionItem(origin, state) { 18 let doc = sitePermissionsDialog.document; 19 20 let label = doc.getElementsByTagName("label")[3]; 21 Assert.equal(label.textContent, origin); 22 23 let menulist = doc.getElementsByTagName("menulist")[0]; 24 Assert.equal(menulist.value, state); 25 } 26 27 async function openPermissionsDialog(permissionType) { 28 let dialogOpened = promiseLoadSubDialog(PERMISSIONS_URL); 29 await SpecialPowers.spawn( 30 gBrowser.selectedBrowser, 31 [settingsButtonMap[permissionType]], 32 function (settingsButtonId) { 33 let doc = content.document; 34 let settingsButton = doc.getElementById(settingsButtonId); 35 settingsButton.click(); 36 } 37 ); 38 39 sitePermissionsDialog = await dialogOpened; 40 await sitePermissionsDialog.document.mozSubdialogReady; 41 } 42 43 add_task(async function openSitePermissionsDialog() { 44 await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); 45 await openPermissionsDialog("desktop-notification"); 46 }); 47 48 add_task(async function addPermission() { 49 let doc = sitePermissionsDialog.document; 50 let richlistbox = doc.getElementById("permissionsBox"); 51 52 // First item in the richlistbox contains column headers. 53 Assert.equal( 54 richlistbox.itemCount, 55 0, 56 "Number of permission items is 0 initially" 57 ); 58 59 // Add notification permission for a website. 60 PermissionTestUtils.add( 61 URI, 62 "desktop-notification", 63 Services.perms.ALLOW_ACTION 64 ); 65 66 // Observe the added permission changes in the dialog UI. 67 Assert.equal(richlistbox.itemCount, 1); 68 checkMenulistPermissionItem(URL, Services.perms.ALLOW_ACTION); 69 70 PermissionTestUtils.remove(URI, "desktop-notification"); 71 }); 72 73 add_task(async function addPermissionPrivateBrowsing() { 74 let privateBrowsingPrincipal = 75 Services.scriptSecurityManager.createContentPrincipal(URI, { 76 privateBrowsingId: 1, 77 }); 78 let doc = sitePermissionsDialog.document; 79 let richlistbox = doc.getElementById("permissionsBox"); 80 81 Assert.equal( 82 richlistbox.itemCount, 83 0, 84 "Number of permission items is 0 initially" 85 ); 86 87 // Add a session permission for private browsing. 88 PermissionTestUtils.add( 89 privateBrowsingPrincipal, 90 "desktop-notification", 91 Services.perms.ALLOW_ACTION, 92 Services.perms.EXPIRE_SESSION 93 ); 94 95 // The permission should not show in the dialog UI. 96 Assert.equal(richlistbox.itemCount, 0); 97 98 PermissionTestUtils.remove(privateBrowsingPrincipal, "desktop-notification"); 99 100 // Add a permanent permission for private browsing 101 // The permission manager will store it as EXPIRE_SESSION 102 PermissionTestUtils.add( 103 privateBrowsingPrincipal, 104 "desktop-notification", 105 Services.perms.ALLOW_ACTION 106 ); 107 108 // The permission should not show in the dialog UI. 109 Assert.equal(richlistbox.itemCount, 0); 110 111 PermissionTestUtils.remove(privateBrowsingPrincipal, "desktop-notification"); 112 }); 113 114 add_task(async function observePermissionChange() { 115 PermissionTestUtils.add( 116 URI, 117 "desktop-notification", 118 Services.perms.ALLOW_ACTION 119 ); 120 121 // Change the permission. 122 PermissionTestUtils.add( 123 URI, 124 "desktop-notification", 125 Services.perms.DENY_ACTION 126 ); 127 128 checkMenulistPermissionItem(URL, Services.perms.DENY_ACTION); 129 130 PermissionTestUtils.remove(URI, "desktop-notification"); 131 }); 132 133 add_task(async function observePermissionDelete() { 134 let doc = sitePermissionsDialog.document; 135 let richlistbox = doc.getElementById("permissionsBox"); 136 137 PermissionTestUtils.add( 138 URI, 139 "desktop-notification", 140 Services.perms.ALLOW_ACTION 141 ); 142 143 Assert.equal( 144 richlistbox.itemCount, 145 1, 146 "The box contains one permission item initially" 147 ); 148 149 PermissionTestUtils.remove(URI, "desktop-notification"); 150 151 Assert.equal(richlistbox.itemCount, 0); 152 }); 153 154 add_task(async function onPermissionChange() { 155 let doc = sitePermissionsDialog.document; 156 PermissionTestUtils.add( 157 URI, 158 "desktop-notification", 159 Services.perms.ALLOW_ACTION 160 ); 161 162 // Change the permission state in the UI. 163 doc.getElementsByAttribute("value", SitePermissions.BLOCK)[0].click(); 164 165 Assert.equal( 166 PermissionTestUtils.getPermissionObject(URI, "desktop-notification") 167 .capability, 168 Services.perms.ALLOW_ACTION, 169 "Permission state does not change before saving changes" 170 ); 171 172 doc.querySelector("dialog").getButton("accept").click(); 173 174 await TestUtils.waitForCondition( 175 () => 176 PermissionTestUtils.getPermissionObject(URI, "desktop-notification") 177 .capability == Services.perms.DENY_ACTION 178 ); 179 180 PermissionTestUtils.remove(URI, "desktop-notification"); 181 }); 182 183 add_task(async function onPermissionDelete() { 184 await openPermissionsDialog("desktop-notification"); 185 186 let doc = sitePermissionsDialog.document; 187 let richlistbox = doc.getElementById("permissionsBox"); 188 189 PermissionTestUtils.add( 190 URI, 191 "desktop-notification", 192 Services.perms.ALLOW_ACTION 193 ); 194 195 richlistbox.selectItem(richlistbox.getItemAtIndex(0)); 196 doc.getElementById("removePermission").click(); 197 198 await TestUtils.waitForCondition(() => richlistbox.itemCount == 0); 199 200 Assert.equal( 201 PermissionTestUtils.getPermissionObject(URI, "desktop-notification") 202 .capability, 203 Services.perms.ALLOW_ACTION, 204 "Permission is not deleted before saving changes" 205 ); 206 207 doc.querySelector("dialog").getButton("accept").click(); 208 209 await TestUtils.waitForCondition( 210 () => 211 PermissionTestUtils.getPermissionObject(URI, "desktop-notification") == 212 null 213 ); 214 }); 215 216 add_task(async function onAllPermissionsDelete() { 217 await openPermissionsDialog("desktop-notification"); 218 219 let doc = sitePermissionsDialog.document; 220 let richlistbox = doc.getElementById("permissionsBox"); 221 222 PermissionTestUtils.add( 223 URI, 224 "desktop-notification", 225 Services.perms.ALLOW_ACTION 226 ); 227 let u = Services.io.newURI("http://www.test.com"); 228 PermissionTestUtils.add( 229 u, 230 "desktop-notification", 231 Services.perms.ALLOW_ACTION 232 ); 233 234 doc.getElementById("removeAllPermissions").click(); 235 await TestUtils.waitForCondition(() => richlistbox.itemCount == 0); 236 237 Assert.equal( 238 PermissionTestUtils.getPermissionObject(URI, "desktop-notification") 239 .capability, 240 Services.perms.ALLOW_ACTION 241 ); 242 Assert.equal( 243 PermissionTestUtils.getPermissionObject(u, "desktop-notification") 244 .capability, 245 Services.perms.ALLOW_ACTION, 246 "Permissions are not deleted before saving changes" 247 ); 248 249 doc.querySelector("dialog").getButton("accept").click(); 250 251 await TestUtils.waitForCondition( 252 () => 253 PermissionTestUtils.getPermissionObject(URI, "desktop-notification") == 254 null && 255 PermissionTestUtils.getPermissionObject(u, "desktop-notification") == null 256 ); 257 }); 258 259 add_task(async function onPermissionChangeAndDelete() { 260 await openPermissionsDialog("desktop-notification"); 261 262 let doc = sitePermissionsDialog.document; 263 let richlistbox = doc.getElementById("permissionsBox"); 264 265 PermissionTestUtils.add( 266 URI, 267 "desktop-notification", 268 Services.perms.ALLOW_ACTION 269 ); 270 271 // Change the permission state in the UI. 272 doc.getElementsByAttribute("value", SitePermissions.BLOCK)[0].click(); 273 274 // Remove that permission by clicking the "Remove" button. 275 richlistbox.selectItem(richlistbox.getItemAtIndex(0)); 276 doc.getElementById("removePermission").click(); 277 278 await TestUtils.waitForCondition(() => richlistbox.itemCount == 0); 279 280 doc.querySelector("dialog").getButton("accept").click(); 281 282 await TestUtils.waitForCondition( 283 () => 284 PermissionTestUtils.getPermissionObject(URI, "desktop-notification") == 285 null 286 ); 287 }); 288 289 add_task(async function onPermissionChangeCancel() { 290 await openPermissionsDialog("desktop-notification"); 291 292 let doc = sitePermissionsDialog.document; 293 PermissionTestUtils.add( 294 URI, 295 "desktop-notification", 296 Services.perms.ALLOW_ACTION 297 ); 298 299 // Change the permission state in the UI. 300 doc.getElementsByAttribute("value", SitePermissions.BLOCK)[0].click(); 301 302 doc.querySelector("dialog").getButton("cancel").click(); 303 304 Assert.equal( 305 PermissionTestUtils.getPermissionObject(URI, "desktop-notification") 306 .capability, 307 Services.perms.ALLOW_ACTION, 308 "Permission state does not change on clicking cancel" 309 ); 310 311 PermissionTestUtils.remove(URI, "desktop-notification"); 312 }); 313 314 add_task(async function onPermissionDeleteCancel() { 315 await openPermissionsDialog("desktop-notification"); 316 317 let doc = sitePermissionsDialog.document; 318 let richlistbox = doc.getElementById("permissionsBox"); 319 PermissionTestUtils.add( 320 URI, 321 "desktop-notification", 322 Services.perms.ALLOW_ACTION 323 ); 324 325 // Remove that permission by clicking the "Remove" button. 326 richlistbox.selectItem(richlistbox.getItemAtIndex(0)); 327 doc.getElementById("removePermission").click(); 328 329 await TestUtils.waitForCondition(() => richlistbox.itemCount == 0); 330 331 doc.querySelector("dialog").getButton("cancel").click(); 332 333 Assert.equal( 334 PermissionTestUtils.getPermissionObject(URI, "desktop-notification") 335 .capability, 336 Services.perms.ALLOW_ACTION, 337 "Permission state does not change on clicking cancel" 338 ); 339 340 PermissionTestUtils.remove(URI, "desktop-notification"); 341 }); 342 343 add_task(async function onSearch() { 344 await openPermissionsDialog("desktop-notification"); 345 let doc = sitePermissionsDialog.document; 346 let richlistbox = doc.getElementById("permissionsBox"); 347 let searchBox = doc.getElementById("searchBox"); 348 349 PermissionTestUtils.add( 350 URI, 351 "desktop-notification", 352 Services.perms.ALLOW_ACTION 353 ); 354 searchBox.value = "www.example.com"; 355 356 let u = Services.io.newURI("http://www.test.com"); 357 PermissionTestUtils.add( 358 u, 359 "desktop-notification", 360 Services.perms.ALLOW_ACTION 361 ); 362 363 Assert.equal( 364 doc.getElementsByAttribute("origin", "http://www.test.com")[0], 365 null 366 ); 367 Assert.equal( 368 doc.getElementsByAttribute("origin", "http://www.example.com")[0], 369 richlistbox.getItemAtIndex(0) 370 ); 371 372 PermissionTestUtils.remove(URI, "desktop-notification"); 373 PermissionTestUtils.remove(u, "desktop-notification"); 374 375 doc.querySelector("dialog").getButton("cancel").click(); 376 }); 377 378 add_task(async function onPermissionsSort() { 379 PermissionTestUtils.add( 380 URI, 381 "desktop-notification", 382 Services.perms.ALLOW_ACTION 383 ); 384 let u = Services.io.newURI("http://www.test.com"); 385 PermissionTestUtils.add( 386 u, 387 "desktop-notification", 388 Services.perms.DENY_ACTION 389 ); 390 391 await openPermissionsDialog("desktop-notification"); 392 let doc = sitePermissionsDialog.document; 393 let richlistbox = doc.getElementById("permissionsBox"); 394 395 // Test default arrangement(Allow followed by Block). 396 Assert.equal( 397 richlistbox.getItemAtIndex(0).getAttribute("origin"), 398 "http://www.example.com" 399 ); 400 Assert.equal( 401 richlistbox.getItemAtIndex(1).getAttribute("origin"), 402 "http://www.test.com" 403 ); 404 405 doc.getElementById("statusCol").click(); 406 407 // Test the rearrangement(Block followed by Allow). 408 Assert.equal( 409 richlistbox.getItemAtIndex(0).getAttribute("origin"), 410 "http://www.test.com" 411 ); 412 Assert.equal( 413 richlistbox.getItemAtIndex(1).getAttribute("origin"), 414 "http://www.example.com" 415 ); 416 417 doc.getElementById("siteCol").click(); 418 419 // Test the rearrangement(Website names arranged in alphabhetical order). 420 Assert.equal( 421 richlistbox.getItemAtIndex(0).getAttribute("origin"), 422 "http://www.example.com" 423 ); 424 Assert.equal( 425 richlistbox.getItemAtIndex(1).getAttribute("origin"), 426 "http://www.test.com" 427 ); 428 429 doc.getElementById("siteCol").click(); 430 431 // Test the rearrangement(Website names arranged in reverse alphabhetical order). 432 Assert.equal( 433 richlistbox.getItemAtIndex(0).getAttribute("origin"), 434 "http://www.test.com" 435 ); 436 Assert.equal( 437 richlistbox.getItemAtIndex(1).getAttribute("origin"), 438 "http://www.example.com" 439 ); 440 441 PermissionTestUtils.remove(URI, "desktop-notification"); 442 PermissionTestUtils.remove(u, "desktop-notification"); 443 444 doc.querySelector("dialog").getButton("cancel").click(); 445 }); 446 447 add_task(async function onPermissionDisable() { 448 // Enable desktop-notification permission prompts. 449 Services.prefs.setIntPref( 450 "permissions.default.desktop-notification", 451 SitePermissions.UNKNOWN 452 ); 453 454 await openPermissionsDialog("desktop-notification"); 455 let doc = sitePermissionsDialog.document; 456 457 // Check if the enabled state is reflected in the checkbox. 458 let checkbox = doc.getElementById("permissionsDisableCheckbox"); 459 Assert.equal(checkbox.checked, false); 460 461 // Disable permission and click on "Cancel". 462 checkbox.checked = true; 463 doc.querySelector("dialog").getButton("cancel").click(); 464 465 // Check that the permission is not disabled yet. 466 let perm = Services.prefs.getIntPref( 467 "permissions.default.desktop-notification" 468 ); 469 Assert.equal(perm, SitePermissions.UNKNOWN); 470 471 // Open the dialog once again. 472 await openPermissionsDialog("desktop-notification"); 473 doc = sitePermissionsDialog.document; 474 475 // Disable permission and save changes. 476 checkbox = doc.getElementById("permissionsDisableCheckbox"); 477 checkbox.checked = true; 478 doc.querySelector("dialog").getButton("accept").click(); 479 480 // Check if the permission is now disabled. 481 perm = Services.prefs.getIntPref("permissions.default.desktop-notification"); 482 Assert.equal(perm, SitePermissions.BLOCK); 483 484 // Open the dialog once again and check if the disabled state is still reflected in the checkbox. 485 await openPermissionsDialog("desktop-notification"); 486 doc = sitePermissionsDialog.document; 487 checkbox = doc.getElementById("permissionsDisableCheckbox"); 488 Assert.equal(checkbox.checked, true); 489 490 // Close the dialog and clean up. 491 doc.querySelector("dialog").getButton("cancel").click(); 492 Services.prefs.setIntPref( 493 "permissions.default.desktop-notification", 494 SitePermissions.UNKNOWN 495 ); 496 }); 497 498 add_task(async function checkDefaultPermissionState() { 499 // Set default permission state to ALLOW. 500 Services.prefs.setIntPref( 501 "permissions.default.desktop-notification", 502 SitePermissions.ALLOW 503 ); 504 505 await openPermissionsDialog("desktop-notification"); 506 let doc = sitePermissionsDialog.document; 507 508 // Check if the enabled state is reflected in the checkbox. 509 let checkbox = doc.getElementById("permissionsDisableCheckbox"); 510 Assert.equal(checkbox.checked, false); 511 512 // Check the checkbox and then uncheck it. 513 checkbox.checked = true; 514 checkbox.checked = false; 515 516 // Save changes. 517 doc.querySelector("dialog").getButton("accept").click(); 518 519 // Check if the default permission state is retained (and not automatically set to SitePermissions.UNKNOWN). 520 let state = Services.prefs.getIntPref( 521 "permissions.default.desktop-notification" 522 ); 523 Assert.equal(state, SitePermissions.ALLOW); 524 525 // Clean up. 526 Services.prefs.setIntPref( 527 "permissions.default.desktop-notification", 528 SitePermissions.UNKNOWN 529 ); 530 }); 531 532 add_task(async function testTabBehaviour() { 533 // Test tab behaviour inside the permissions setting dialog when site permissions are selected. 534 // Only selected items in the richlistbox should be tabable for accessibility reasons. 535 536 // Force tabfocus for all elements on OSX. 537 SpecialPowers.pushPrefEnv({ set: [["accessibility.tabfocus", 7]] }); 538 539 PermissionTestUtils.add( 540 URI, 541 "desktop-notification", 542 Services.perms.ALLOW_ACTION 543 ); 544 let u = Services.io.newURI("http://www.test.com"); 545 PermissionTestUtils.add( 546 u, 547 "desktop-notification", 548 Services.perms.ALLOW_ACTION 549 ); 550 551 await openPermissionsDialog("desktop-notification"); 552 let doc = sitePermissionsDialog.document; 553 554 EventUtils.synthesizeKey("KEY_Tab", {}, sitePermissionsDialog); 555 let richlistbox = doc.getElementById("permissionsBox"); 556 is( 557 richlistbox, 558 doc.activeElement.closest("#permissionsBox"), 559 "The richlistbox is focused after pressing tab once." 560 ); 561 562 EventUtils.synthesizeKey("KEY_ArrowDown", {}, sitePermissionsDialog); 563 EventUtils.synthesizeKey("KEY_Tab", {}, sitePermissionsDialog); 564 let menulist = doc 565 .getElementById("permissionsBox") 566 .itemChildren[1].getElementsByTagName("menulist")[0]; 567 is( 568 menulist, 569 doc.activeElement, 570 "The menulist inside the selected richlistitem is focused now" 571 ); 572 573 EventUtils.synthesizeKey("KEY_Tab", {}, sitePermissionsDialog); 574 let removeButton = doc.getElementById("removePermission"); 575 is( 576 removeButton, 577 doc.activeElement, 578 "The focus moves outside the richlistbox and onto the remove button" 579 ); 580 581 PermissionTestUtils.remove(URI, "desktop-notification"); 582 PermissionTestUtils.remove(u, "desktop-notification"); 583 584 doc.querySelector("dialog").getButton("cancel").click(); 585 }); 586 587 add_task(async function addSpeakerPermission() { 588 let enabled = Services.prefs.getBoolPref("media.setsinkid.enabled", false); 589 let speakerButton = gBrowser.contentDocument.getElementById( 590 "speakerSettingsButton" 591 ); 592 Assert.equal( 593 BrowserTestUtils.isVisible(speakerButton), 594 enabled, 595 "speakerButton visible" 596 ); 597 if (!enabled) { 598 return; 599 } 600 601 await openPermissionsDialog("speaker"); 602 let doc = sitePermissionsDialog.document; 603 let richlistbox = doc.getElementById("permissionsBox"); 604 Assert.equal( 605 richlistbox.itemCount, 606 0, 607 "Number of permission items is 0 initially" 608 ); 609 // Add an allow permission for a device. 610 let deviceId = "DEVICE-ID"; 611 let devicePermissionId = `speaker^${deviceId}`; 612 PermissionTestUtils.add(URI, devicePermissionId, Services.perms.ALLOW_ACTION); 613 614 // Observe the added permission changes in the dialog UI. 615 Assert.equal(richlistbox.itemCount, 1, "itemCount with allow"); 616 checkMenulistPermissionItem(URL, Services.perms.ALLOW_ACTION); 617 618 // Check that an all-device deny permission overrides the device-specific 619 // allow permission. 620 PermissionTestUtils.add(URI, "speaker", Services.perms.DENY_ACTION); 621 622 Assert.equal(richlistbox.itemCount, 1, "itemCount with deny and allow"); 623 let richlistitem = richlistbox.itemChildren[0]; 624 let siteStatus = richlistitem.querySelector(".website-status"); 625 Assert.equal( 626 siteStatus.value, 627 Services.perms.DENY_ACTION, 628 "website status with deny and allow" 629 ); 630 // The website status element is not a menulist because all-device allow is 631 // not an option. 632 Assert.equal(siteStatus.tagName, "label"); 633 634 PermissionTestUtils.remove(URI, devicePermissionId); 635 PermissionTestUtils.remove(URI, "speaker"); 636 637 doc.querySelector("dialog").getButton("cancel").click(); 638 }); 639 640 add_task(async function testLocalNetworkAccessPermissionVisibility() { 641 let enabled = Services.prefs.getBoolPref("network.lna.blocking", false); 642 let localHostSettingsButton = gBrowser.contentDocument.getElementById( 643 "localHostSettingsButton" 644 ); 645 let localNetworkSettingsButton = gBrowser.contentDocument.getElementById( 646 "localNetworkSettingsButton" 647 ); 648 649 Assert.equal( 650 BrowserTestUtils.isVisible(localNetworkSettingsButton), 651 enabled, 652 "localhost permissions visible" 653 ); 654 Assert.equal( 655 BrowserTestUtils.isVisible(localHostSettingsButton), 656 enabled, 657 "localhost permissions visible" 658 ); 659 660 let changeLocalHostButton = waitForSettingControlChange( 661 localHostSettingsButton 662 ); 663 let changeLocalNetworkButton = waitForSettingControlChange( 664 localNetworkSettingsButton 665 ); 666 667 enabled = !enabled; 668 Services.prefs.setBoolPref("network.lna.blocking", enabled); 669 670 await changeLocalHostButton; 671 await changeLocalNetworkButton; 672 673 Assert.equal( 674 BrowserTestUtils.isVisible(localHostSettingsButton), 675 enabled, 676 "localhost permissions toggle" 677 ); 678 679 Assert.equal( 680 BrowserTestUtils.isVisible(localNetworkSettingsButton), 681 enabled, 682 "localhost permissions toggle" 683 ); 684 685 Services.prefs.setBoolPref("network.lna.blocking", !enabled); 686 }); 687 688 add_task(async function removeTab() { 689 gBrowser.removeCurrentTab(); 690 });