browser_extension_controlled.js (43714B)
1 /* eslint-env webextensions */ 2 3 const PROXY_PREF = "network.proxy.type"; 4 const HOMEPAGE_URL_PREF = "browser.startup.homepage"; 5 const HOMEPAGE_OVERRIDE_KEY = "homepage_override"; 6 const URL_OVERRIDES_TYPE = "url_overrides"; 7 const NEW_TAB_KEY = "newTabURL"; 8 const PREF_SETTING_TYPE = "prefs"; 9 10 ChromeUtils.defineESModuleGetters(this, { 11 AboutNewTab: "resource:///modules/AboutNewTab.sys.mjs", 12 ExtensionSettingsStore: 13 "resource://gre/modules/ExtensionSettingsStore.sys.mjs", 14 }); 15 16 XPCOMUtils.defineLazyPreferenceGetter(this, "proxyType", PROXY_PREF); 17 18 const { AddonTestUtils } = ChromeUtils.importESModule( 19 "resource://testing-common/AddonTestUtils.sys.mjs" 20 ); 21 AddonTestUtils.initMochitest(this); 22 23 const { ExtensionPreferencesManager } = ChromeUtils.importESModule( 24 "resource://gre/modules/ExtensionPreferencesManager.sys.mjs" 25 ); 26 27 const TEST_DIR = gTestPath.substr(0, gTestPath.lastIndexOf("/")); 28 const CHROME_URL_ROOT = TEST_DIR + "/"; 29 const PERMISSIONS_URL = 30 "chrome://browser/content/preferences/dialogs/sitePermissions.xhtml"; 31 let sitePermissionsDialog; 32 33 function getSupportsFile(path) { 34 let cr = Cc["@mozilla.org/chrome/chrome-registry;1"].getService( 35 Ci.nsIChromeRegistry 36 ); 37 let uri = Services.io.newURI(CHROME_URL_ROOT + path); 38 let fileurl = cr.convertChromeURL(uri); 39 return fileurl.QueryInterface(Ci.nsIFileURL); 40 } 41 42 function waitForMessageChange( 43 element, 44 cb, 45 opts = { attributes: true, attributeFilter: ["hidden"] } 46 ) { 47 return waitForMutation(element, opts, cb); 48 } 49 50 function getElement(id, doc = gBrowser.contentDocument) { 51 return doc.getElementById(id); 52 } 53 54 function waitForMessageHidden(messageId, doc) { 55 return waitForMessageChange( 56 getElement(messageId, doc), 57 target => target.hidden 58 ); 59 } 60 61 function waitForMessageShown(messageId, doc) { 62 return waitForMessageChange( 63 getElement(messageId, doc), 64 target => !target.hidden 65 ); 66 } 67 68 function waitForEnableMessage(messageId, doc) { 69 return waitForMessageChange( 70 getElement(messageId, doc), 71 target => target.classList.contains("extension-controlled-disabled"), 72 { attributeFilter: ["class"], attributes: true } 73 ); 74 } 75 76 function waitForMessageContent(messageId, l10nId, doc) { 77 return waitForMessageChange( 78 getElement(messageId, doc), 79 target => doc.l10n.getAttributes(target).id === l10nId, 80 { childList: true } 81 ); 82 } 83 84 async function openNotificationsPermissionDialog() { 85 let dialogOpened = promiseLoadSubDialog(PERMISSIONS_URL); 86 87 await SpecialPowers.spawn(gBrowser.selectedBrowser, [], function () { 88 let doc = content.document; 89 let settingsButton = doc.getElementById("notificationSettingsButton"); 90 settingsButton.click(); 91 }); 92 93 sitePermissionsDialog = await dialogOpened; 94 await sitePermissionsDialog.document.mozSubdialogReady; 95 } 96 97 async function disableExtensionViaClick(labelId, disableButtonId, doc) { 98 let controlledLabel = doc.getElementById(labelId); 99 100 let enableMessageShown = waitForEnableMessage(labelId, doc); 101 doc.getElementById(disableButtonId).click(); 102 await enableMessageShown; 103 104 let controlledDescription = controlledLabel.querySelector("description"); 105 is( 106 doc.l10n.getAttributes(controlledDescription.querySelector("label")).id, 107 "extension-controlled-enable", 108 "The user is notified of how to enable the extension again." 109 ); 110 111 // The user can dismiss the enable instructions. 112 let hidden = waitForMessageHidden(labelId, doc); 113 controlledLabel.querySelector("image:last-of-type").click(); 114 await hidden; 115 } 116 117 async function reEnableExtension(addon, labelId) { 118 let controlledMessageShown = waitForMessageShown(labelId); 119 await addon.enable(); 120 await controlledMessageShown; 121 } 122 123 add_task(async function testExtensionControlledHomepage() { 124 const ADDON_ID = "@set_homepage"; 125 const SECOND_ADDON_ID = "@second_set_homepage"; 126 127 await openPreferencesViaOpenPreferencesAPI("paneHome", { leaveOpen: true }); 128 let homepagePref = () => Services.prefs.getCharPref(HOMEPAGE_URL_PREF); 129 let originalHomepagePref = homepagePref(); 130 is( 131 gBrowser.currentURI.spec, 132 "about:preferences#home", 133 "#home should be in the URI for about:preferences" 134 ); 135 let doc = gBrowser.contentDocument; 136 let homeModeEl = doc.getElementById("homeMode"); 137 let customSettingsSection = doc.getElementById("customSettings"); 138 139 is(homeModeEl.itemCount, 3, "The menu list starts with 3 options"); 140 141 let promise = TestUtils.waitForCondition( 142 () => homeModeEl.itemCount === 4, 143 "wait for the addon option to be added as an option in the menu list" 144 ); 145 let extension = ExtensionTestUtils.loadExtension({ 146 useAddonManager: "permanent", 147 manifest: { 148 version: "1.0", 149 name: "set_homepage", 150 browser_specific_settings: { 151 gecko: { 152 id: ADDON_ID, 153 }, 154 }, 155 chrome_settings_overrides: { homepage: "/home.html" }, 156 }, 157 }); 158 await extension.startup(); 159 await promise; 160 161 // The homepage is set to the default and the custom settings section is hidden 162 is(homeModeEl.disabled, false, "The homepage menulist is enabled"); 163 is( 164 customSettingsSection.hidden, 165 true, 166 "The custom settings element is hidden" 167 ); 168 169 let addon = await AddonManager.getAddonByID(ADDON_ID); 170 is( 171 homeModeEl.value, 172 addon.id, 173 "the home select menu's value is set to the addon" 174 ); 175 176 promise = TestUtils.waitForPrefChange(HOMEPAGE_URL_PREF); 177 // Set the Menu to the default value 178 homeModeEl.value = "0"; 179 homeModeEl.dispatchEvent(new Event("command")); 180 await promise; 181 is(homepagePref(), originalHomepagePref, "homepage is set back to default"); 182 let levelOfControl = await ExtensionPreferencesManager.getLevelOfControl( 183 addon.id, 184 HOMEPAGE_OVERRIDE_KEY, 185 PREF_SETTING_TYPE 186 ); 187 is( 188 levelOfControl, 189 "not_controllable", 190 "getLevelOfControl returns not_controllable." 191 ); 192 let setting = await ExtensionPreferencesManager.getSetting( 193 HOMEPAGE_OVERRIDE_KEY 194 ); 195 ok(!setting.value, "the setting is not set."); 196 197 promise = TestUtils.waitForPrefChange(HOMEPAGE_URL_PREF); 198 // Set the menu to the addon value 199 homeModeEl.value = ADDON_ID; 200 homeModeEl.dispatchEvent(new Event("command")); 201 await promise; 202 ok( 203 homepagePref().startsWith("moz-extension") && 204 homepagePref().endsWith("home.html"), 205 "Home url should be provided by the extension." 206 ); 207 levelOfControl = await ExtensionPreferencesManager.getLevelOfControl( 208 addon.id, 209 HOMEPAGE_OVERRIDE_KEY, 210 PREF_SETTING_TYPE 211 ); 212 is( 213 levelOfControl, 214 "controlled_by_this_extension", 215 "getLevelOfControl returns controlled_by_this_extension." 216 ); 217 setting = await ExtensionPreferencesManager.getSetting(HOMEPAGE_OVERRIDE_KEY); 218 ok( 219 setting.value.startsWith("moz-extension") && 220 setting.value.endsWith("home.html"), 221 "The setting value is the same as the extension." 222 ); 223 224 // Add a second extension, ensure it is added to the menulist and selected. 225 promise = TestUtils.waitForCondition( 226 () => homeModeEl.itemCount == 5, 227 "addon option is added as an option in the menu list" 228 ); 229 let secondExtension = ExtensionTestUtils.loadExtension({ 230 useAddonManager: "permanent", 231 manifest: { 232 version: "1.0", 233 name: "second_set_homepage", 234 browser_specific_settings: { 235 gecko: { 236 id: SECOND_ADDON_ID, 237 }, 238 }, 239 chrome_settings_overrides: { homepage: "/home2.html" }, 240 }, 241 }); 242 await secondExtension.startup(); 243 await promise; 244 245 let secondAddon = await AddonManager.getAddonByID(SECOND_ADDON_ID); 246 is(homeModeEl.value, SECOND_ADDON_ID, "home menulist is set to the add-on"); 247 248 levelOfControl = await ExtensionPreferencesManager.getLevelOfControl( 249 secondAddon.id, 250 HOMEPAGE_OVERRIDE_KEY, 251 PREF_SETTING_TYPE 252 ); 253 is( 254 levelOfControl, 255 "controlled_by_this_extension", 256 "getLevelOfControl returns controlled_by_this_extension." 257 ); 258 setting = await ExtensionPreferencesManager.getSetting(HOMEPAGE_OVERRIDE_KEY); 259 ok( 260 setting.value.startsWith("moz-extension") && 261 setting.value.endsWith("home2.html"), 262 "The setting value is the same as the extension." 263 ); 264 265 promise = TestUtils.waitForCondition( 266 () => homeModeEl.itemCount == 4, 267 "addon option is no longer an option in the menu list after disable, even if it was not selected" 268 ); 269 await addon.disable(); 270 await promise; 271 272 // Ensure that re-enabling an addon adds it back to the menulist 273 promise = TestUtils.waitForCondition( 274 () => homeModeEl.itemCount == 5, 275 "addon option is added again to the menulist when enabled" 276 ); 277 await addon.enable(); 278 await promise; 279 280 promise = TestUtils.waitForCondition( 281 () => homeModeEl.itemCount == 4, 282 "addon option is no longer an option in the menu list after disable" 283 ); 284 await secondAddon.disable(); 285 await promise; 286 287 promise = TestUtils.waitForCondition( 288 () => homeModeEl.itemCount == 5, 289 "addon option is added again to the menulist when enabled" 290 ); 291 await secondAddon.enable(); 292 await promise; 293 294 promise = TestUtils.waitForCondition( 295 () => homeModeEl.itemCount == 3, 296 "addon options are no longer an option in the menu list after disabling all addons" 297 ); 298 await secondAddon.disable(); 299 await addon.disable(); 300 await promise; 301 302 is(homeModeEl.value, "0", "addon option is not selected in the menu list"); 303 304 levelOfControl = await ExtensionPreferencesManager.getLevelOfControl( 305 secondAddon.id, 306 HOMEPAGE_OVERRIDE_KEY, 307 PREF_SETTING_TYPE 308 ); 309 is( 310 levelOfControl, 311 "controllable_by_this_extension", 312 "getLevelOfControl returns controllable_by_this_extension." 313 ); 314 setting = await ExtensionPreferencesManager.getSetting(HOMEPAGE_OVERRIDE_KEY); 315 ok(!setting.value, "The setting value is back to default."); 316 317 // The homepage elements are reset to their original state. 318 is(homepagePref(), originalHomepagePref, "homepage is set back to default"); 319 is(homeModeEl.disabled, false, "The homepage menulist is enabled"); 320 BrowserTestUtils.removeTab(gBrowser.selectedTab); 321 await extension.unload(); 322 await secondExtension.unload(); 323 }); 324 325 add_task(async function testPrefLockedHomepage() { 326 const ADDON_ID = "@set_homepage"; 327 await openPreferencesViaOpenPreferencesAPI("paneHome", { leaveOpen: true }); 328 let doc = gBrowser.contentDocument; 329 is( 330 gBrowser.currentURI.spec, 331 "about:preferences#home", 332 "#home should be in the URI for about:preferences" 333 ); 334 335 let homePagePref = "browser.startup.homepage"; 336 let buttonPrefs = [ 337 "pref.browser.homepage.disable_button.current_page", 338 "pref.browser.homepage.disable_button.bookmark_page", 339 "pref.browser.homepage.disable_button.restore_default", 340 ]; 341 let homeModeEl = doc.getElementById("homeMode"); 342 let homePageInput = doc.getElementById("homePageUrl"); 343 let prefs = Services.prefs.getDefaultBranch(null); 344 let mutationOpts = { attributes: true, attributeFilter: ["disabled"] }; 345 346 // Helper functions. 347 let getButton = pref => 348 doc.querySelector(`.homepage-button[preference="${pref}"`); 349 let waitForAllMutations = () => 350 Promise.all( 351 buttonPrefs 352 .map(pref => waitForMutation(getButton(pref), mutationOpts)) 353 .concat([ 354 waitForMutation(homeModeEl, mutationOpts), 355 waitForMutation(homePageInput, mutationOpts), 356 ]) 357 ); 358 let getHomepage = () => 359 Services.prefs.getCharPref("browser.startup.homepage"); 360 361 let originalHomepage = getHomepage(); 362 let extensionHomepage = "https://developer.mozilla.org/"; 363 let lockedHomepage = "http://www.yahoo.com"; 364 365 let lockPrefs = () => { 366 buttonPrefs.forEach(pref => { 367 prefs.setBoolPref(pref, true); 368 prefs.lockPref(pref); 369 }); 370 // Do the homepage last since that's the only pref that triggers a UI update. 371 prefs.setCharPref(homePagePref, lockedHomepage); 372 prefs.lockPref(homePagePref); 373 }; 374 let unlockPrefs = () => { 375 buttonPrefs.forEach(pref => { 376 prefs.unlockPref(pref); 377 prefs.setBoolPref(pref, false); 378 }); 379 // Do the homepage last since that's the only pref that triggers a UI update. 380 prefs.unlockPref(homePagePref); 381 prefs.setCharPref(homePagePref, originalHomepage); 382 }; 383 384 // Lock or unlock prefs then wait for all mutations to finish. 385 // Expects a bool indicating if we should lock or unlock. 386 let waitForLockMutations = lock => { 387 let mutationsDone = waitForAllMutations(); 388 if (lock) { 389 lockPrefs(); 390 } else { 391 unlockPrefs(); 392 } 393 return mutationsDone; 394 }; 395 396 Assert.notEqual( 397 originalHomepage, 398 extensionHomepage, 399 "The extension will change the homepage" 400 ); 401 402 // Install an extension that sets the homepage to MDN. 403 let promise = TestUtils.waitForPrefChange(HOMEPAGE_URL_PREF); 404 let extension = ExtensionTestUtils.loadExtension({ 405 useAddonManager: "permanent", 406 manifest: { 407 version: "1.0", 408 name: "set_homepage", 409 browser_specific_settings: { 410 gecko: { 411 id: ADDON_ID, 412 }, 413 }, 414 chrome_settings_overrides: { homepage: "https://developer.mozilla.org/" }, 415 }, 416 }); 417 await extension.startup(); 418 await promise; 419 420 // Check that everything is still disabled, homepage didn't change. 421 is( 422 getHomepage(), 423 extensionHomepage, 424 "The reported homepage is set by the extension" 425 ); 426 is( 427 homePageInput.value, 428 extensionHomepage, 429 "The homepage is set by the extension" 430 ); 431 432 // Lock all of the prefs, wait for the UI to update. 433 await waitForLockMutations(true); 434 435 // Check that everything is now disabled. 436 is(getHomepage(), lockedHomepage, "The reported homepage is set by the pref"); 437 is(homePageInput.value, lockedHomepage, "The homepage is set by the pref"); 438 is( 439 homePageInput.disabled, 440 true, 441 "The homepage is disabed when the pref is locked" 442 ); 443 444 buttonPrefs.forEach(pref => { 445 is( 446 getButton(pref).disabled, 447 true, 448 `The ${pref} button is disabled when locked` 449 ); 450 }); 451 452 let levelOfControl = await ExtensionPreferencesManager.getLevelOfControl( 453 ADDON_ID, 454 HOMEPAGE_OVERRIDE_KEY, 455 PREF_SETTING_TYPE 456 ); 457 is( 458 levelOfControl, 459 "not_controllable", 460 "getLevelOfControl returns not_controllable, the pref is locked." 461 ); 462 463 // Verify that the UI is selecting the extension's Id in the menulist 464 let unlockedPromise = TestUtils.waitForCondition( 465 () => homeModeEl.value == ADDON_ID, 466 "Homepage menulist value is equal to the extension ID" 467 ); 468 // Unlock the prefs, wait for the UI to update. 469 unlockPrefs(); 470 await unlockedPromise; 471 472 is( 473 homeModeEl.disabled, 474 false, 475 "the home select element is not disabled when the pref is not locked" 476 ); 477 is( 478 homePageInput.disabled, 479 false, 480 "The homepage is enabled when the pref is unlocked" 481 ); 482 is( 483 getHomepage(), 484 extensionHomepage, 485 "The homepage is reset to extension page" 486 ); 487 488 levelOfControl = await ExtensionPreferencesManager.getLevelOfControl( 489 ADDON_ID, 490 HOMEPAGE_OVERRIDE_KEY, 491 PREF_SETTING_TYPE 492 ); 493 is( 494 levelOfControl, 495 "controlled_by_this_extension", 496 "getLevelOfControl returns controlled_by_this_extension after prefs are unlocked." 497 ); 498 let setting = await ExtensionPreferencesManager.getSetting( 499 HOMEPAGE_OVERRIDE_KEY 500 ); 501 is( 502 setting.value, 503 extensionHomepage, 504 "The setting value is equal to the extensionHomepage." 505 ); 506 507 // Uninstall the add-on. 508 promise = TestUtils.waitForPrefChange(HOMEPAGE_URL_PREF); 509 await extension.unload(); 510 await promise; 511 512 setting = await ExtensionPreferencesManager.getSetting(HOMEPAGE_OVERRIDE_KEY); 513 ok(!setting, "The setting is gone after the addon is uninstalled."); 514 515 // Check that everything is now enabled again. 516 is( 517 getHomepage(), 518 originalHomepage, 519 "The reported homepage is reset to original value" 520 ); 521 is(homePageInput.value, "", "The homepage is empty"); 522 is( 523 homePageInput.disabled, 524 false, 525 "The homepage is enabled after clearing lock" 526 ); 527 is( 528 homeModeEl.disabled, 529 false, 530 "Homepage menulist is enabled after clearing lock" 531 ); 532 buttonPrefs.forEach(pref => { 533 is( 534 getButton(pref).disabled, 535 false, 536 `The ${pref} button is enabled when unlocked` 537 ); 538 }); 539 540 // Lock the prefs without an extension. 541 await waitForLockMutations(true); 542 543 // Check that everything is now disabled. 544 is(getHomepage(), lockedHomepage, "The reported homepage is set by the pref"); 545 is(homePageInput.value, lockedHomepage, "The homepage is set by the pref"); 546 is( 547 homePageInput.disabled, 548 true, 549 "The homepage is disabed when the pref is locked" 550 ); 551 is( 552 homeModeEl.disabled, 553 true, 554 "Homepage menulist is disabled when pref is locked" 555 ); 556 buttonPrefs.forEach(pref => { 557 is( 558 getButton(pref).disabled, 559 true, 560 `The ${pref} button is disabled when locked` 561 ); 562 }); 563 564 // Unlock the prefs without an extension. 565 await waitForLockMutations(false); 566 567 // Check that everything is enabled again. 568 is( 569 getHomepage(), 570 originalHomepage, 571 "The homepage is reset to the original value" 572 ); 573 is(homePageInput.value, "", "The homepage is clear after being unlocked"); 574 is( 575 homePageInput.disabled, 576 false, 577 "The homepage is enabled after clearing lock" 578 ); 579 is( 580 homeModeEl.disabled, 581 false, 582 "Homepage menulist is enabled after clearing lock" 583 ); 584 buttonPrefs.forEach(pref => { 585 is( 586 getButton(pref).disabled, 587 false, 588 `The ${pref} button is enabled when unlocked` 589 ); 590 }); 591 592 BrowserTestUtils.removeTab(gBrowser.selectedTab); 593 }); 594 595 add_task(async function testExtensionControlledNewTab() { 596 const ADDON_ID = "@set_newtab"; 597 const SECOND_ADDON_ID = "@second_set_newtab"; 598 const DEFAULT_NEWTAB = "about:newtab"; 599 const NEWTAB_CONTROLLED_PREF = "browser.newtab.extensionControlled"; 600 601 await openPreferencesViaOpenPreferencesAPI("paneHome", { leaveOpen: true }); 602 is( 603 gBrowser.currentURI.spec, 604 "about:preferences#home", 605 "#home should be in the URI for about:preferences" 606 ); 607 608 let doc = gBrowser.contentDocument; 609 let newTabMenuList = doc.getElementById("newTabMode"); 610 // The new tab page is set to the default. 611 is(AboutNewTab.newTabURL, DEFAULT_NEWTAB, "new tab is set to default"); 612 613 let promise = TestUtils.waitForCondition( 614 () => newTabMenuList.itemCount == 3, 615 "addon option is added as an option in the menu list" 616 ); 617 // Install an extension that will set the new tab page. 618 let extension = ExtensionTestUtils.loadExtension({ 619 useAddonManager: "permanent", 620 manifest: { 621 version: "1.0", 622 name: "set_newtab", 623 browser_specific_settings: { 624 gecko: { 625 id: ADDON_ID, 626 }, 627 }, 628 chrome_url_overrides: { newtab: "/newtab.html" }, 629 }, 630 }); 631 await extension.startup(); 632 633 await promise; 634 let addon = await AddonManager.getAddonByID(ADDON_ID); 635 636 is(newTabMenuList.value, ADDON_ID, "New tab menulist is set to the add-on"); 637 638 let levelOfControl = await ExtensionPreferencesManager.getLevelOfControl( 639 addon.id, 640 NEW_TAB_KEY, 641 URL_OVERRIDES_TYPE 642 ); 643 is( 644 levelOfControl, 645 "controlled_by_this_extension", 646 "getLevelOfControl returns controlled_by_this_extension." 647 ); 648 let setting = ExtensionSettingsStore.getSetting( 649 URL_OVERRIDES_TYPE, 650 NEW_TAB_KEY 651 ); 652 ok( 653 setting.value.startsWith("moz-extension") && 654 setting.value.endsWith("newtab.html"), 655 "The url_overrides is set by this extension" 656 ); 657 658 promise = TestUtils.waitForPrefChange(NEWTAB_CONTROLLED_PREF); 659 // Set the menu to the default value 660 newTabMenuList.value = "0"; 661 newTabMenuList.dispatchEvent(new Event("command")); 662 await promise; 663 let newTabPref = Services.prefs.getBoolPref(NEWTAB_CONTROLLED_PREF, false); 664 is(newTabPref, false, "the new tab is not controlled"); 665 666 levelOfControl = await ExtensionPreferencesManager.getLevelOfControl( 667 addon.id, 668 NEW_TAB_KEY, 669 URL_OVERRIDES_TYPE 670 ); 671 is( 672 levelOfControl, 673 "not_controllable", 674 "getLevelOfControl returns not_controllable." 675 ); 676 setting = ExtensionSettingsStore.getSetting(URL_OVERRIDES_TYPE, NEW_TAB_KEY); 677 ok(!setting.value, "The url_overrides is not set by this extension"); 678 679 promise = TestUtils.waitForPrefChange(NEWTAB_CONTROLLED_PREF); 680 // Set the menu to a the addon value 681 newTabMenuList.value = ADDON_ID; 682 newTabMenuList.dispatchEvent(new Event("command")); 683 await promise; 684 newTabPref = Services.prefs.getBoolPref(NEWTAB_CONTROLLED_PREF, false); 685 is(newTabPref, true, "the new tab is controlled"); 686 687 // Add a second extension, ensure it is added to the menulist and selected. 688 promise = TestUtils.waitForCondition( 689 () => newTabMenuList.itemCount == 4, 690 "addon option is added as an option in the menu list" 691 ); 692 let secondExtension = ExtensionTestUtils.loadExtension({ 693 useAddonManager: "permanent", 694 manifest: { 695 version: "1.0", 696 name: "second_set_newtab", 697 browser_specific_settings: { 698 gecko: { 699 id: SECOND_ADDON_ID, 700 }, 701 }, 702 chrome_url_overrides: { newtab: "/newtab2.html" }, 703 }, 704 }); 705 await secondExtension.startup(); 706 await promise; 707 let secondAddon = await AddonManager.getAddonByID(SECOND_ADDON_ID); 708 is( 709 newTabMenuList.value, 710 SECOND_ADDON_ID, 711 "New tab menulist is set to the add-on" 712 ); 713 714 levelOfControl = await ExtensionPreferencesManager.getLevelOfControl( 715 secondAddon.id, 716 NEW_TAB_KEY, 717 URL_OVERRIDES_TYPE 718 ); 719 is( 720 levelOfControl, 721 "controlled_by_this_extension", 722 "getLevelOfControl returns controlled_by_this_extension." 723 ); 724 setting = ExtensionSettingsStore.getSetting(URL_OVERRIDES_TYPE, NEW_TAB_KEY); 725 ok( 726 setting.value.startsWith("moz-extension") && 727 setting.value.endsWith("newtab2.html"), 728 "The url_overrides is set by the second extension" 729 ); 730 731 promise = TestUtils.waitForCondition( 732 () => newTabMenuList.itemCount == 3, 733 "addon option is no longer an option in the menu list after disable, even if it was not selected" 734 ); 735 await addon.disable(); 736 await promise; 737 738 // Ensure that re-enabling an addon adds it back to the menulist 739 promise = TestUtils.waitForCondition( 740 () => newTabMenuList.itemCount == 4, 741 "addon option is added again to the menulist when enabled" 742 ); 743 await addon.enable(); 744 await promise; 745 746 promise = TestUtils.waitForCondition( 747 () => newTabMenuList.itemCount == 3, 748 "addon option is no longer an option in the menu list after disable" 749 ); 750 await secondAddon.disable(); 751 await promise; 752 753 promise = TestUtils.waitForCondition( 754 () => newTabMenuList.itemCount == 4, 755 "addon option is added again to the menulist when enabled" 756 ); 757 await secondAddon.enable(); 758 await promise; 759 760 promise = TestUtils.waitForCondition( 761 () => newTabMenuList.itemCount == 2, 762 "addon options are all removed after disabling all" 763 ); 764 await addon.disable(); 765 await secondAddon.disable(); 766 await promise; 767 is( 768 AboutNewTab.newTabURL, 769 DEFAULT_NEWTAB, 770 "new tab page is set back to default" 771 ); 772 773 // Cleanup the tabs and add-on. 774 BrowserTestUtils.removeTab(gBrowser.selectedTab); 775 await extension.unload(); 776 await secondExtension.unload(); 777 }); 778 779 add_task(async function testExtensionControlledWebNotificationsPermission() { 780 let manifest = { 781 manifest_version: 2, 782 name: "TestExtension", 783 version: "1.0", 784 description: "Testing WebNotificationsDisable", 785 browser_specific_settings: { gecko: { id: "@web_notifications_disable" } }, 786 permissions: ["browserSettings"], 787 browser_action: { 788 default_title: "Testing", 789 }, 790 }; 791 792 await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); 793 await openNotificationsPermissionDialog(); 794 795 let doc = sitePermissionsDialog.document; 796 let extensionControlledContent = doc.getElementById( 797 "browserNotificationsPermissionExtensionContent" 798 ); 799 800 // Test that extension content is initially hidden. 801 ok( 802 extensionControlledContent.hidden, 803 "Extension content is initially hidden" 804 ); 805 806 // Install an extension that will disable web notifications permission. 807 let messageShown = waitForMessageShown( 808 "browserNotificationsPermissionExtensionContent", 809 doc 810 ); 811 let extension = ExtensionTestUtils.loadExtension({ 812 manifest, 813 useAddonManager: "permanent", 814 background() { 815 browser.browserSettings.webNotificationsDisabled.set({ value: true }); 816 browser.test.sendMessage("load-extension"); 817 }, 818 }); 819 await extension.startup(); 820 await extension.awaitMessage("load-extension"); 821 await messageShown; 822 823 let controlledDesc = extensionControlledContent.querySelector("description"); 824 Assert.deepEqual( 825 doc.l10n.getAttributes(controlledDesc), 826 { 827 id: "extension-controlling-web-notifications", 828 args: { 829 name: "TestExtension", 830 }, 831 }, 832 "The user is notified that an extension is controlling the web notifications permission" 833 ); 834 is( 835 extensionControlledContent.hidden, 836 false, 837 "The extension controlled row is not hidden" 838 ); 839 840 // Disable the extension. 841 doc.getElementById("disableNotificationsPermissionExtension").click(); 842 843 // Verify the user is notified how to enable the extension. 844 await waitForEnableMessage(extensionControlledContent.id, doc); 845 is( 846 doc.l10n.getAttributes(controlledDesc.querySelector("label")).id, 847 "extension-controlled-enable", 848 "The user is notified of how to enable the extension again" 849 ); 850 851 // Verify the enable message can be dismissed. 852 let hidden = waitForMessageHidden(extensionControlledContent.id, doc); 853 let dismissButton = controlledDesc.querySelector("image:last-of-type"); 854 dismissButton.click(); 855 await hidden; 856 857 // Verify that the extension controlled content in hidden again. 858 is( 859 extensionControlledContent.hidden, 860 true, 861 "The extension controlled row is now hidden" 862 ); 863 864 await extension.unload(); 865 BrowserTestUtils.removeTab(gBrowser.selectedTab); 866 }); 867 868 add_task(async function testExtensionControlledHomepageUninstalledAddon() { 869 async function checkHomepageEnabled() { 870 await openPreferencesViaOpenPreferencesAPI("paneHome", { leaveOpen: true }); 871 let doc = gBrowser.contentDocument; 872 is( 873 gBrowser.currentURI.spec, 874 "about:preferences#home", 875 "#home should be in the URI for about:preferences" 876 ); 877 878 // The homepage is enabled. 879 let homepageInput = doc.getElementById("homePageUrl"); 880 is(homepageInput.disabled, false, "The homepage input is enabled"); 881 is(homepageInput.value, "", "The homepage input is empty"); 882 883 BrowserTestUtils.removeTab(gBrowser.selectedTab); 884 } 885 886 await ExtensionSettingsStore.initialize(); 887 888 // Verify the setting isn't reported as controlled and the inputs are enabled. 889 is( 890 ExtensionSettingsStore.getSetting("prefs", "homepage_override"), 891 null, 892 "The homepage_override is not set" 893 ); 894 await checkHomepageEnabled(); 895 896 // Disarm any pending writes before we modify the JSONFile directly. 897 await ExtensionSettingsStore._reloadFile(false); 898 899 // Write out a bad store file. 900 let storeData = { 901 prefs: { 902 homepage_override: { 903 initialValue: "", 904 precedenceList: [ 905 { 906 id: "bad@mochi.test", 907 installDate: 1508802672, 908 value: "https://developer.mozilla.org", 909 enabled: true, 910 }, 911 ], 912 }, 913 }, 914 }; 915 let jsonFileName = "extension-settings.json"; 916 let storePath = PathUtils.join(PathUtils.profileDir, jsonFileName); 917 918 await IOUtils.writeUTF8(storePath, JSON.stringify(storeData)); 919 920 // Reload the ExtensionSettingsStore so it will read the file on disk. Don't 921 // finalize the current store since it will overwrite our file. 922 await ExtensionSettingsStore._reloadFile(false); 923 924 // Verify that the setting is reported as set, but the homepage is still enabled 925 // since there is no matching installed extension. 926 is( 927 ExtensionSettingsStore.getSetting("prefs", "homepage_override").value, 928 "https://developer.mozilla.org", 929 "The homepage_override appears to be set" 930 ); 931 await checkHomepageEnabled(); 932 933 // Remove the bad store file that we used. 934 await IOUtils.remove(storePath); 935 936 // Reload the ExtensionSettingsStore again so it clears the data we added. 937 // Don't finalize the current store since it will write out the bad data. 938 await ExtensionSettingsStore._reloadFile(false); 939 940 is( 941 ExtensionSettingsStore.getSetting("prefs", "homepage_override"), 942 null, 943 "The ExtensionSettingsStore is left empty." 944 ); 945 }); 946 947 add_task(async function testExtensionControlledTrackingProtection() { 948 const TP_PREF = "privacy.trackingprotection.enabled"; 949 const TP_DEFAULT = false; 950 const EXTENSION_ID = "@set_tp"; 951 const CONTROLLED_LABEL_ID = 952 "contentBlockingTrackingProtectionExtensionContentLabel"; 953 const CONTROLLED_BUTTON_ID = 954 "contentBlockingDisableTrackingProtectionExtension"; 955 956 let tpEnabledPref = () => Services.prefs.getBoolPref(TP_PREF); 957 958 await SpecialPowers.pushPrefEnv({ set: [[TP_PREF, TP_DEFAULT]] }); 959 960 function background() { 961 browser.privacy.websites.trackingProtectionMode.set({ value: "always" }); 962 } 963 964 function verifyState(isControlled) { 965 is(tpEnabledPref(), isControlled, "TP pref is set to the expected value."); 966 967 let controlledLabel = doc.getElementById(CONTROLLED_LABEL_ID); 968 let controlledButton = doc.getElementById(CONTROLLED_BUTTON_ID); 969 970 is( 971 controlledLabel.hidden, 972 !isControlled, 973 "The extension controlled row's visibility is as expected." 974 ); 975 is( 976 controlledButton.hidden, 977 !isControlled, 978 "The disable extension button's visibility is as expected." 979 ); 980 if (isControlled) { 981 let controlledDesc = controlledLabel.querySelector("description"); 982 Assert.deepEqual( 983 doc.l10n.getAttributes(controlledDesc), 984 { 985 id: "extension-controlling-websites-content-blocking-all-trackers", 986 args: { 987 name: "set_tp", 988 }, 989 }, 990 "The user is notified that an extension is controlling TP." 991 ); 992 } 993 994 is( 995 doc.getElementById("trackingProtectionMenu").disabled, 996 isControlled, 997 "TP control is enabled." 998 ); 999 } 1000 1001 await openPreferencesViaOpenPreferencesAPI("panePrivacy", { 1002 leaveOpen: true, 1003 }); 1004 let doc = gBrowser.contentDocument; 1005 1006 is( 1007 gBrowser.currentURI.spec, 1008 "about:preferences#privacy", 1009 "#privacy should be in the URI for about:preferences" 1010 ); 1011 1012 verifyState(false); 1013 1014 // Install an extension that sets Tracking Protection. 1015 let extension = ExtensionTestUtils.loadExtension({ 1016 useAddonManager: "permanent", 1017 manifest: { 1018 name: "set_tp", 1019 browser_specific_settings: { gecko: { id: EXTENSION_ID } }, 1020 permissions: ["privacy"], 1021 }, 1022 background, 1023 }); 1024 1025 let messageShown = waitForMessageShown(CONTROLLED_LABEL_ID); 1026 await extension.startup(); 1027 await messageShown; 1028 let addon = await AddonManager.getAddonByID(EXTENSION_ID); 1029 1030 verifyState(true); 1031 1032 await disableExtensionViaClick( 1033 CONTROLLED_LABEL_ID, 1034 CONTROLLED_BUTTON_ID, 1035 doc 1036 ); 1037 1038 verifyState(false); 1039 1040 // Enable the extension so we get the UNINSTALL event, which is needed by 1041 // ExtensionPreferencesManager to clean up properly. 1042 // TODO: BUG 1408226 1043 await reEnableExtension(addon, CONTROLLED_LABEL_ID); 1044 1045 await extension.unload(); 1046 1047 BrowserTestUtils.removeTab(gBrowser.selectedTab); 1048 }); 1049 1050 add_task(async function testExtensionControlledPasswordManager() { 1051 await SpecialPowers.pushPrefEnv({ 1052 set: [["browser.settings-redesign.enabled", false]], 1053 }); 1054 const PASSWORD_MANAGER_ENABLED_PREF = "signon.rememberSignons"; 1055 const PASSWORD_MANAGER_ENABLED_DEFAULT = true; 1056 const CONTROLLED_BUTTON_ID = "disablePasswordManagerExtension"; 1057 const CONTROLLED_LABEL_ID = "passwordManagerExtensionContent"; 1058 const EXTENSION_ID = "@remember_signons"; 1059 let manifest = { 1060 manifest_version: 2, 1061 name: "testPasswordManagerExtension", 1062 version: "1.0", 1063 description: "Testing rememberSignons", 1064 browser_specific_settings: { gecko: { id: EXTENSION_ID } }, 1065 permissions: ["privacy"], 1066 browser_action: { 1067 default_title: "Testing rememberSignons", 1068 }, 1069 }; 1070 1071 let passwordManagerEnabledPref = () => 1072 Services.prefs.getBoolPref(PASSWORD_MANAGER_ENABLED_PREF); 1073 1074 await SpecialPowers.pushPrefEnv({ 1075 set: [[PASSWORD_MANAGER_ENABLED_PREF, PASSWORD_MANAGER_ENABLED_DEFAULT]], 1076 }); 1077 is( 1078 passwordManagerEnabledPref(), 1079 true, 1080 "Password manager is enabled by default." 1081 ); 1082 1083 function verifyState(isControlled) { 1084 is( 1085 passwordManagerEnabledPref(), 1086 !isControlled, 1087 "Password manager pref is set to the expected value." 1088 ); 1089 let controlledLabel = 1090 gBrowser.contentDocument.getElementById(CONTROLLED_LABEL_ID); 1091 let controlledButton = 1092 gBrowser.contentDocument.getElementById(CONTROLLED_BUTTON_ID); 1093 is( 1094 controlledLabel.hidden, 1095 !isControlled, 1096 "The extension's controlled row visibility is as expected." 1097 ); 1098 is( 1099 controlledButton.hidden, 1100 !isControlled, 1101 "The extension's controlled button visibility is as expected." 1102 ); 1103 if (isControlled) { 1104 let controlledDesc = controlledLabel.querySelector("description"); 1105 Assert.deepEqual( 1106 gBrowser.contentDocument.l10n.getAttributes(controlledDesc), 1107 { 1108 id: "extension-controlling-password-saving", 1109 args: { 1110 name: "testPasswordManagerExtension", 1111 }, 1112 }, 1113 "The user is notified that an extension is controlling the remember signons pref." 1114 ); 1115 } 1116 } 1117 1118 await openPreferencesViaOpenPreferencesAPI("panePrivacy", { 1119 leaveOpen: true, 1120 }); 1121 1122 info("Verify that no extension is controlling the password manager pref."); 1123 verifyState(false); 1124 1125 let extension = ExtensionTestUtils.loadExtension({ 1126 manifest, 1127 useAddonManager: "permanent", 1128 background() { 1129 browser.privacy.services.passwordSavingEnabled.set({ value: false }); 1130 }, 1131 }); 1132 let messageShown = waitForMessageShown(CONTROLLED_LABEL_ID); 1133 await extension.startup(); 1134 await messageShown; 1135 1136 info( 1137 "Verify that the test extension is controlling the password manager pref." 1138 ); 1139 verifyState(true); 1140 1141 info("Verify that the extension shows as controlled when loaded again."); 1142 BrowserTestUtils.removeTab(gBrowser.selectedTab); 1143 await openPreferencesViaOpenPreferencesAPI("panePrivacy", { 1144 leaveOpen: true, 1145 }); 1146 verifyState(true); 1147 1148 await disableExtensionViaClick( 1149 CONTROLLED_LABEL_ID, 1150 CONTROLLED_BUTTON_ID, 1151 gBrowser.contentDocument 1152 ); 1153 1154 info( 1155 "Verify that disabling the test extension removes the lock on the password manager pref." 1156 ); 1157 verifyState(false); 1158 1159 await extension.unload(); 1160 1161 BrowserTestUtils.removeTab(gBrowser.selectedTab); 1162 }); 1163 1164 add_task(async function testExtensionControlledProxyConfig() { 1165 const proxySvc = Ci.nsIProtocolProxyService; 1166 const PROXY_DEFAULT = proxySvc.PROXYCONFIG_SYSTEM; 1167 const EXTENSION_ID = "@set_proxy"; 1168 const CONTROLLED_SECTION_ID = "proxyExtensionContent"; 1169 const CONTROLLED_BUTTON_ID = "disableProxyExtension"; 1170 const CONNECTION_SETTINGS_DESC_ID = "connectionSettingsDescription"; 1171 const PANEL_URL = 1172 "chrome://browser/content/preferences/dialogs/connection.xhtml"; 1173 1174 await SpecialPowers.pushPrefEnv({ set: [[PROXY_PREF, PROXY_DEFAULT]] }); 1175 1176 function background() { 1177 browser.proxy.settings.set({ value: { proxyType: "none" } }); 1178 } 1179 1180 function expectedConnectionSettingsMessage(doc, isControlled) { 1181 return isControlled 1182 ? "extension-controlling-proxy-config" 1183 : "network-proxy-connection-description"; 1184 } 1185 1186 function connectionSettingsMessagePromise(doc, isControlled) { 1187 return waitForMessageContent( 1188 CONNECTION_SETTINGS_DESC_ID, 1189 expectedConnectionSettingsMessage(doc, isControlled), 1190 doc 1191 ); 1192 } 1193 1194 function verifyProxyState(doc, isControlled) { 1195 let isPanel = doc.getElementById(CONTROLLED_BUTTON_ID); 1196 is( 1197 proxyType === proxySvc.PROXYCONFIG_DIRECT, 1198 isControlled, 1199 "Proxy pref is set to the expected value." 1200 ); 1201 1202 if (isPanel) { 1203 let controlledSection = doc.getElementById(CONTROLLED_SECTION_ID); 1204 1205 is( 1206 controlledSection.hidden, 1207 !isControlled, 1208 "The extension controlled row's visibility is as expected." 1209 ); 1210 if (isPanel) { 1211 is( 1212 doc.getElementById(CONTROLLED_BUTTON_ID).hidden, 1213 !isControlled, 1214 "The disable extension button's visibility is as expected." 1215 ); 1216 } 1217 if (isControlled) { 1218 let controlledDesc = controlledSection.querySelector("description"); 1219 Assert.deepEqual( 1220 doc.l10n.getAttributes(controlledDesc), 1221 { 1222 id: "extension-controlling-proxy-config", 1223 args: { 1224 name: "set_proxy", 1225 }, 1226 }, 1227 "The user is notified that an extension is controlling proxy settings." 1228 ); 1229 } 1230 function getProxyControls() { 1231 let controlGroup = doc.getElementById("networkProxyType"); 1232 let manualControlContainer = controlGroup.querySelector("#proxy-grid"); 1233 return { 1234 manualControls: [ 1235 ...manualControlContainer.querySelectorAll( 1236 "label[data-l10n-id]:not([control=networkProxyNone])" 1237 ), 1238 ...manualControlContainer.querySelectorAll("input"), 1239 ...manualControlContainer.querySelectorAll("checkbox"), 1240 ...doc.querySelectorAll("#networkProxySOCKSVersion > radio"), 1241 ], 1242 pacControls: [doc.getElementById("networkProxyAutoconfigURL")], 1243 otherControls: [ 1244 doc.querySelector("label[control=networkProxyNone]"), 1245 doc.getElementById("networkProxyNone"), 1246 ...controlGroup.querySelectorAll(":scope > radio"), 1247 ...doc.querySelectorAll("#ConnectionsDialogPane > checkbox"), 1248 ], 1249 }; 1250 } 1251 let controlState = isControlled ? "disabled" : "enabled"; 1252 let controls = getProxyControls(); 1253 for (let element of controls.manualControls) { 1254 let disabled = 1255 isControlled || proxyType !== proxySvc.PROXYCONFIG_MANUAL; 1256 is( 1257 element.disabled, 1258 disabled, 1259 `Manual proxy controls should be ${controlState} - control: ${element.outerHTML}.` 1260 ); 1261 } 1262 for (let element of controls.pacControls) { 1263 let disabled = isControlled || proxyType !== proxySvc.PROXYCONFIG_PAC; 1264 is( 1265 element.disabled, 1266 disabled, 1267 `PAC proxy controls should be ${controlState} - control: ${element.outerHTML}.` 1268 ); 1269 } 1270 for (let element of controls.otherControls) { 1271 is( 1272 element.disabled, 1273 isControlled, 1274 `Other proxy controls should be ${controlState} - control: ${element.outerHTML}.` 1275 ); 1276 } 1277 } else { 1278 let elem = doc.getElementById(CONNECTION_SETTINGS_DESC_ID); 1279 is( 1280 doc.l10n.getAttributes(elem).id, 1281 expectedConnectionSettingsMessage(doc, isControlled), 1282 "The connection settings description is as expected." 1283 ); 1284 } 1285 } 1286 1287 async function reEnableProxyExtension(addon) { 1288 let messageChanged = connectionSettingsMessagePromise(mainDoc, true); 1289 await addon.enable(); 1290 await messageChanged; 1291 } 1292 1293 async function openProxyPanel() { 1294 let panel = await openAndLoadSubDialog(PANEL_URL); 1295 let closingPromise = BrowserTestUtils.waitForEvent( 1296 panel.document.getElementById("ConnectionsDialog"), 1297 "dialogclosing" 1298 ); 1299 ok(panel, "Proxy panel opened."); 1300 return { panel, closingPromise }; 1301 } 1302 1303 async function closeProxyPanel(panelObj) { 1304 let dialog = panelObj.panel.document.getElementById("ConnectionsDialog"); 1305 dialog.cancelDialog(); 1306 let panelClosingEvent = await panelObj.closingPromise; 1307 ok(panelClosingEvent, "Proxy panel closed."); 1308 } 1309 1310 await openPreferencesViaOpenPreferencesAPI("paneGeneral", { 1311 leaveOpen: true, 1312 }); 1313 let mainDoc = gBrowser.contentDocument; 1314 1315 is( 1316 gBrowser.currentURI.spec, 1317 "about:preferences#general", 1318 "#general should be in the URI for about:preferences" 1319 ); 1320 1321 verifyProxyState(mainDoc, false); 1322 1323 // Open the connections panel. 1324 let panelObj = await openProxyPanel(); 1325 let panelDoc = panelObj.panel.document; 1326 1327 verifyProxyState(panelDoc, false); 1328 1329 await closeProxyPanel(panelObj); 1330 1331 verifyProxyState(mainDoc, false); 1332 1333 // Install an extension that controls proxy settings. The extension needs 1334 // incognitoOverride because controlling the proxy.settings requires private 1335 // browsing access. 1336 let extension = ExtensionTestUtils.loadExtension({ 1337 incognitoOverride: "spanning", 1338 useAddonManager: "permanent", 1339 manifest: { 1340 name: "set_proxy", 1341 browser_specific_settings: { gecko: { id: EXTENSION_ID } }, 1342 permissions: ["proxy"], 1343 }, 1344 background, 1345 }); 1346 1347 let messageChanged = connectionSettingsMessagePromise(mainDoc, true); 1348 await extension.startup(); 1349 await messageChanged; 1350 let addon = await AddonManager.getAddonByID(EXTENSION_ID); 1351 1352 verifyProxyState(mainDoc, true); 1353 messageChanged = connectionSettingsMessagePromise(mainDoc, false); 1354 1355 panelObj = await openProxyPanel(); 1356 panelDoc = panelObj.panel.document; 1357 1358 verifyProxyState(panelDoc, true); 1359 1360 await disableExtensionViaClick( 1361 CONTROLLED_SECTION_ID, 1362 CONTROLLED_BUTTON_ID, 1363 panelDoc 1364 ); 1365 1366 verifyProxyState(panelDoc, false); 1367 1368 await closeProxyPanel(panelObj); 1369 await messageChanged; 1370 1371 verifyProxyState(mainDoc, false); 1372 1373 await reEnableProxyExtension(addon); 1374 1375 verifyProxyState(mainDoc, true); 1376 messageChanged = connectionSettingsMessagePromise(mainDoc, false); 1377 1378 panelObj = await openProxyPanel(); 1379 panelDoc = panelObj.panel.document; 1380 1381 verifyProxyState(panelDoc, true); 1382 1383 await disableExtensionViaClick( 1384 CONTROLLED_SECTION_ID, 1385 CONTROLLED_BUTTON_ID, 1386 panelDoc 1387 ); 1388 1389 verifyProxyState(panelDoc, false); 1390 1391 await closeProxyPanel(panelObj); 1392 await messageChanged; 1393 1394 verifyProxyState(mainDoc, false); 1395 1396 // Enable the extension so we get the UNINSTALL event, which is needed by 1397 // ExtensionPreferencesManager to clean up properly. 1398 // TODO: BUG 1408226 1399 await reEnableProxyExtension(addon); 1400 1401 await extension.unload(); 1402 1403 BrowserTestUtils.removeTab(gBrowser.selectedTab); 1404 }); 1405 1406 // Test that the newtab menu selection is correct when loading about:preferences 1407 add_task(async function testMenuSyncFromPrefs() { 1408 const DEFAULT_NEWTAB = "about:newtab"; 1409 1410 await openPreferencesViaOpenPreferencesAPI("paneHome", { leaveOpen: true }); 1411 is( 1412 gBrowser.currentURI.spec, 1413 "about:preferences#home", 1414 "#home should be in the URI for about:preferences" 1415 ); 1416 1417 let doc = gBrowser.contentDocument; 1418 let newTabMenuList = doc.getElementById("newTabMode"); 1419 // The new tab page is set to the default. 1420 is(AboutNewTab.newTabURL, DEFAULT_NEWTAB, "new tab is set to default"); 1421 1422 is(newTabMenuList.value, "0", "New tab menulist is set to the default"); 1423 1424 newTabMenuList.value = "1"; 1425 newTabMenuList.dispatchEvent(new Event("command")); 1426 is(newTabMenuList.value, "1", "New tab menulist is set to blank"); 1427 1428 gBrowser.reloadTab(gBrowser.selectedTab); 1429 1430 await TestUtils.waitForCondition( 1431 () => gBrowser.contentDocument.getElementById("newTabMode"), 1432 "wait until element exists in new contentDoc" 1433 ); 1434 1435 is( 1436 gBrowser.contentDocument.getElementById("newTabMode").value, 1437 "1", 1438 "New tab menulist is still set to blank" 1439 ); 1440 1441 // Cleanup 1442 newTabMenuList.value = "0"; 1443 newTabMenuList.dispatchEvent(new Event("command")); 1444 is(AboutNewTab.newTabURL, DEFAULT_NEWTAB, "new tab is set to default"); 1445 BrowserTestUtils.removeTab(gBrowser.selectedTab); 1446 });