diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /browser/tools/mozscreenshots/mozscreenshots/extension/configurations | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'browser/tools/mozscreenshots/mozscreenshots/extension/configurations')
13 files changed, 1453 insertions, 0 deletions
diff --git a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/AppMenu.sys.mjs b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/AppMenu.sys.mjs new file mode 100644 index 0000000000..8309eab623 --- /dev/null +++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/AppMenu.sys.mjs @@ -0,0 +1,77 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { BrowserTestUtils } from "resource://testing-common/BrowserTestUtils.sys.mjs"; + +export var AppMenu = { + init(libDir) {}, + + configurations: { + appMenuMainView: { + selectors: ["#appMenu-popup"], + async applyConfig() { + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + await reopenAppMenu(browserWindow); + }, + }, + + appMenuHistorySubview: { + selectors: ["#appMenu-popup"], + async applyConfig() { + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + await reopenAppMenu(browserWindow); + + browserWindow.document.getElementById("appMenu-library-button").click(); + let view = browserWindow.document.getElementById("appMenu-libraryView"); + let promiseViewShown = BrowserTestUtils.waitForEvent(view, "ViewShown"); + await promiseViewShown; + }, + + verifyConfig: verifyConfigHelper, + }, + + appMenuHelpSubview: { + selectors: ["#appMenu-popup"], + async applyConfig() { + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + await reopenAppMenu(browserWindow); + + browserWindow.document.getElementById("appMenu-help-button2").click(); + let view = browserWindow.document.getElementById("PanelUI-helpView"); + let promiseViewShown = BrowserTestUtils.waitForEvent(view, "ViewShown"); + await promiseViewShown; + }, + + verifyConfig: verifyConfigHelper, + }, + }, +}; + +async function reopenAppMenu(browserWindow) { + browserWindow.PanelUI.hide(); + let promiseViewShown = BrowserTestUtils.waitForEvent( + browserWindow.PanelUI.panel, + "ViewShown" + ); + browserWindow.PanelUI.show(); + await promiseViewShown; +} + +function verifyConfigHelper() { + if (isCustomizing()) { + return "navigator:browser has the customizing attribute"; + } + return undefined; +} + +function isCustomizing() { + let browserWindow = Services.wm.getMostRecentWindow("navigator:browser"); + if (browserWindow.document.documentElement.hasAttribute("customizing")) { + return true; + } + return false; +} diff --git a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Buttons.sys.mjs b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Buttons.sys.mjs new file mode 100644 index 0000000000..2bc12d9012 --- /dev/null +++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Buttons.sys.mjs @@ -0,0 +1,97 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { CustomizableUI } from "resource:///modules/CustomizableUI.sys.mjs"; + +export var Buttons = { + init(libDir) { + createWidget(); + }, + + configurations: { + navBarButtons: { + selectors: ["#nav-bar"], + applyConfig: async () => { + CustomizableUI.addWidgetToArea( + "screenshot-widget", + CustomizableUI.AREA_NAVBAR + ); + }, + }, + + tabsToolbarButtons: { + selectors: ["#TabsToolbar"], + applyConfig: async () => { + CustomizableUI.addWidgetToArea( + "screenshot-widget", + CustomizableUI.AREA_TABSTRIP + ); + }, + }, + + menuPanelButtons: { + selectors: ["#widget-overflow"], + applyConfig: async () => { + CustomizableUI.addWidgetToArea( + "screenshot-widget", + CustomizableUI.AREA_FIXED_OVERFLOW_PANEL + ); + }, + + async verifyConfig() { + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + if (browserWindow.PanelUI.panel.state == "closed") { + return "The button isn't shown when the panel isn't open."; + } + return undefined; + }, + }, + + custPaletteButtons: { + selectors: ["#customization-palette"], + applyConfig: async () => { + CustomizableUI.removeWidgetFromArea("screenshot-widget"); + }, + + async verifyConfig() { + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + if ( + browserWindow.document.documentElement.getAttribute("customizing") != + "true" + ) { + return "The button isn't shown when we're not in customize mode."; + } + return undefined; + }, + }, + }, +}; + +function createWidget() { + let id = "screenshot-widget"; + let spec = { + id, + label: "My Button", + removable: true, + tooltiptext: "", + type: "button", + }; + CustomizableUI.createWidget(spec); + + // Append a <style> for the image + let browserWindow = Services.wm.getMostRecentWindow("navigator:browser"); + let st = browserWindow.document.createElementNS( + "http://www.w3.org/1999/xhtml", + "style" + ); + let styles = + "" + + "#screenshot-widget > .toolbarbutton-icon {" + + " list-style-image: url(chrome://browser/skin/thumb-down.svg);" + + "}"; + st.appendChild(browserWindow.document.createTextNode(styles)); + browserWindow.document.documentElement.appendChild(st); +} diff --git a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/ControlCenter.sys.mjs b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/ControlCenter.sys.mjs new file mode 100644 index 0000000000..2ada0e831c --- /dev/null +++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/ControlCenter.sys.mjs @@ -0,0 +1,320 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs"; +import { BrowserTestUtils } from "resource://testing-common/BrowserTestUtils.sys.mjs"; +import { setTimeout } from "resource://gre/modules/Timer.sys.mjs"; +import { UrlClassifierTestUtils } from "resource://testing-common/UrlClassifierTestUtils.sys.mjs"; + +import { SitePermissions } from "resource:///modules/SitePermissions.sys.mjs"; + +const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm"); + +const CC_SELECTORS = ["#identity-popup", "#urlbar-input-container"]; +const PP_SELECTORS = ["#protections-popup", "#urlbar-input-container"]; + +const RESOURCE_PATH = + "browser/browser/tools/mozscreenshots/mozscreenshots/extension/mozscreenshots/browser/resources/lib/controlCenter"; +const HTTP_PAGE = "http://example.com/"; +const HTTPS_PAGE = "https://example.com/"; +const PERMISSIONS_PAGE = "https://test1.example.com/"; +const HTTP_PASSWORD_PAGE = `http://test2.example.org/${RESOURCE_PATH}/password.html`; +const MIXED_CONTENT_URL = `https://example.com/${RESOURCE_PATH}/mixed.html`; +const MIXED_ACTIVE_CONTENT_URL = `https://example.com/${RESOURCE_PATH}/mixed_active.html`; +const MIXED_PASSIVE_CONTENT_URL = `https://example.com/${RESOURCE_PATH}/mixed_passive.html`; +const TRACKING_PAGE = `http://tracking.example.org/${RESOURCE_PATH}/tracking.html`; + +export var ControlCenter = { + init(libDir) {}, + + configurations: { + about: { + selectors: CC_SELECTORS, + async applyConfig() { + await loadPage("about:rights"); + await openIdentityPopup(); + }, + }, + + localFile: { + // This selector is different so we can exclude the changing file: path + selectors: ["#identity-popup-security-button"], + async applyConfig() { + let channel = NetUtil.newChannel({ + uri: "resource://mozscreenshots/lib/mozscreenshots.html", + loadUsingSystemPrincipal: true, + }); + channel = channel.QueryInterface(Ci.nsIFileChannel); + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + let gBrowser = browserWindow.gBrowser; + BrowserTestUtils.loadURIString( + gBrowser.selectedBrowser, + channel.file.path + ); + await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); + await openIdentityPopup(); + }, + }, + + http: { + selectors: CC_SELECTORS, + async applyConfig() { + await loadPage(HTTP_PAGE); + await openIdentityPopup(); + }, + }, + + httpSubView: { + selectors: CC_SELECTORS, + async applyConfig() { + await loadPage(HTTP_PAGE); + await openIdentityPopup(true); + }, + }, + + https: { + selectors: CC_SELECTORS, + async applyConfig() { + await loadPage(HTTPS_PAGE); + await openIdentityPopup(); + }, + }, + + httpsSubView: { + selectors: CC_SELECTORS, + async applyConfig() { + await loadPage(HTTPS_PAGE); + await openIdentityPopup(true); + }, + }, + + singlePermission: { + selectors: CC_SELECTORS, + async applyConfig() { + let principal = + Services.scriptSecurityManager.createContentPrincipalFromOrigin( + PERMISSIONS_PAGE + ); + SitePermissions.setForPrincipal( + principal, + "camera", + SitePermissions.ALLOW + ); + + await loadPage(PERMISSIONS_PAGE); + await openIdentityPopup(); + }, + }, + + allPermissions: { + selectors: CC_SELECTORS, + async applyConfig() { + // TODO: (Bug 1330601) Rewrite this to consider temporary (TAB) permission states. + // There are 2 possible non-default permission states, so we alternate between them. + let states = [SitePermissions.ALLOW, SitePermissions.BLOCK]; + let principal = + Services.scriptSecurityManager.createContentPrincipalFromOrigin( + PERMISSIONS_PAGE + ); + SitePermissions.listPermissions().forEach(function (permission, index) { + SitePermissions.setForPrincipal( + principal, + permission, + states[index % 2] + ); + }); + + await loadPage(PERMISSIONS_PAGE); + await openIdentityPopup(); + }, + }, + + mixed: { + selectors: CC_SELECTORS, + async applyConfig() { + await loadPage(MIXED_CONTENT_URL); + await openIdentityPopup(); + }, + }, + + mixedSubView: { + selectors: CC_SELECTORS, + async applyConfig() { + await loadPage(MIXED_CONTENT_URL); + await openIdentityPopup(true); + }, + }, + + mixedPassive: { + selectors: CC_SELECTORS, + async applyConfig() { + await loadPage(MIXED_PASSIVE_CONTENT_URL); + await openIdentityPopup(); + }, + }, + + mixedPassiveSubView: { + selectors: CC_SELECTORS, + async applyConfig() { + await loadPage(MIXED_PASSIVE_CONTENT_URL); + await openIdentityPopup(true); + }, + }, + + mixedActive: { + selectors: CC_SELECTORS, + async applyConfig() { + await loadPage(MIXED_ACTIVE_CONTENT_URL); + await openIdentityPopup(); + }, + }, + + mixedActiveSubView: { + selectors: CC_SELECTORS, + async applyConfig() { + await loadPage(MIXED_ACTIVE_CONTENT_URL); + await openIdentityPopup(true); + }, + }, + + mixedActiveUnblocked: { + selectors: CC_SELECTORS, + async applyConfig() { + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + let gBrowser = browserWindow.gBrowser; + await loadPage(MIXED_ACTIVE_CONTENT_URL); + gBrowser.ownerGlobal.gIdentityHandler.disableMixedContentProtection(); + await BrowserTestUtils.browserLoaded( + gBrowser.selectedBrowser, + false, + MIXED_ACTIVE_CONTENT_URL + ); + await openIdentityPopup(); + }, + }, + + mixedActiveUnblockedSubView: { + selectors: CC_SELECTORS, + async applyConfig() { + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + let gBrowser = browserWindow.gBrowser; + await loadPage(MIXED_ACTIVE_CONTENT_URL); + gBrowser.ownerGlobal.gIdentityHandler.disableMixedContentProtection(); + await BrowserTestUtils.browserLoaded( + gBrowser.selectedBrowser, + false, + MIXED_ACTIVE_CONTENT_URL + ); + await openIdentityPopup(true); + }, + }, + + httpPassword: { + selectors: CC_SELECTORS, + async applyConfig() { + await loadPage(HTTP_PASSWORD_PAGE); + await openIdentityPopup(); + }, + }, + + httpPasswordSubView: { + selectors: CC_SELECTORS, + async applyConfig() { + await loadPage(HTTP_PASSWORD_PAGE); + await openIdentityPopup(true); + }, + }, + + trackingProtectionNoElements: { + selectors: PP_SELECTORS, + async applyConfig() { + Services.prefs.setBoolPref("privacy.trackingprotection.enabled", true); + + await loadPage(HTTP_PAGE); + await openProtectionsPopup(); + }, + }, + + trackingProtectionEnabled: { + selectors: PP_SELECTORS, + async applyConfig() { + Services.prefs.setBoolPref("privacy.trackingprotection.enabled", true); + await UrlClassifierTestUtils.addTestTrackers(); + + await loadPage(TRACKING_PAGE); + await openProtectionsPopup(); + }, + }, + + trackingProtectionDisabled: { + selectors: PP_SELECTORS, + async applyConfig() { + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + let gBrowser = browserWindow.gBrowser; + Services.prefs.setBoolPref("privacy.trackingprotection.enabled", true); + await UrlClassifierTestUtils.addTestTrackers(); + + await loadPage(TRACKING_PAGE); + + // unblock the page + let loaded = BrowserTestUtils.browserLoaded( + gBrowser.selectedBrowser, + false, + TRACKING_PAGE + ); + gBrowser.ownerGlobal.gProtectionsHandler.disableForCurrentPage(); + await loaded; + await openProtectionsPopup(); + }, + }, + }, +}; + +async function loadPage(url) { + let browserWindow = Services.wm.getMostRecentWindow("navigator:browser"); + let gBrowser = browserWindow.gBrowser; + BrowserTestUtils.loadURIString(gBrowser.selectedBrowser, url); + await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, url); +} + +async function openIdentityPopup(expand) { + let browserWindow = Services.wm.getMostRecentWindow("navigator:browser"); + let gBrowser = browserWindow.gBrowser; + let { gIdentityHandler } = gBrowser.ownerGlobal; + // Ensure the popup is available, if it's never been opened. + gIdentityHandler._initializePopup(); + gIdentityHandler._identityPopup.hidePopup(); + // Disable the popup shadow on OSX until we have figured out bug 1425253. + if (AppConstants.platform == "macosx") { + gIdentityHandler._identityPopup.classList.add("no-shadow"); + } + gIdentityHandler._identityIconBox.click(); + if (expand) { + // give some time for opening to avoid weird style issues + await new Promise(c => setTimeout(c, 500)); + gIdentityHandler._identityPopup + .querySelector("#identity-popup-security-button") + .click(); + } +} + +async function openProtectionsPopup() { + let browserWindow = Services.wm.getMostRecentWindow("navigator:browser"); + let gBrowser = browserWindow.gBrowser; + let { gProtectionsHandler } = gBrowser.ownerGlobal; + // Force initializing the popup; we can't add classes otherwise. + gProtectionsHandler._initializePopup(); + gProtectionsHandler._protectionsPopup.hidePopup(); + // Disable the popup shadow on OSX until we have figured out bug 1425253. + if (AppConstants.platform == "macosx") { + gProtectionsHandler._protectionsPopup.classList.add("no-shadow"); + } + gProtectionsHandler.showProtectionsPopup(); + // Wait for any animation. + await new Promise(_ => setTimeout(_, 500)); +} diff --git a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/CustomizeMode.sys.mjs b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/CustomizeMode.sys.mjs new file mode 100644 index 0000000000..a5a1b65b69 --- /dev/null +++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/CustomizeMode.sys.mjs @@ -0,0 +1,72 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { setTimeout } from "resource://gre/modules/Timer.sys.mjs"; + +export var CustomizeMode = { + init(libDir) {}, + + configurations: { + notCustomizing: { + selectors: ["#navigator-toolbox"], + applyConfig() { + return new Promise(resolve => { + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + if ( + !browserWindow.document.documentElement.hasAttribute("customizing") + ) { + resolve("notCustomizing: already not customizing"); + return; + } + function onCustomizationEnds() { + browserWindow.gNavToolbox.removeEventListener( + "aftercustomization", + onCustomizationEnds + ); + // Wait for final changes + setTimeout( + () => resolve("notCustomizing: onCustomizationEnds"), + 500 + ); + } + browserWindow.gNavToolbox.addEventListener( + "aftercustomization", + onCustomizationEnds + ); + browserWindow.gCustomizeMode.exit(); + }); + }, + }, + + customizing: { + selectors: ["#navigator-toolbox", "#customization-container"], + applyConfig() { + return new Promise(resolve => { + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + if ( + browserWindow.document.documentElement.hasAttribute("customizing") + ) { + resolve("customizing: already customizing"); + return; + } + function onCustomizing() { + browserWindow.gNavToolbox.removeEventListener( + "customizationready", + onCustomizing + ); + // Wait for final changes + setTimeout(() => resolve("customizing: onCustomizing"), 500); + } + browserWindow.gNavToolbox.addEventListener( + "customizationready", + onCustomizing + ); + browserWindow.gCustomizeMode.enter(); + }); + }, + }, + }, +}; diff --git a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/DevTools.sys.mjs b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/DevTools.sys.mjs new file mode 100644 index 0000000000..addef011c0 --- /dev/null +++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/DevTools.sys.mjs @@ -0,0 +1,74 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { require } from "resource://devtools/shared/loader/Loader.sys.mjs"; + +const { gDevTools } = require("devtools/client/framework/devtools"); + +import { setTimeout } from "resource://gre/modules/Timer.sys.mjs"; + +async function showToolboxForSelectedTab(toolId, hostType) { + const browserWindow = Services.wm.getMostRecentWindow("navigator:browser"); + const tab = browserWindow.gBrowser.selectedTab; + return gDevTools.showToolboxForTab(tab, { toolId, hostType }); +} + +function selectToolbox(toolbox) { + return toolbox.win.document.querySelector("#toolbox-container"); +} + +export var DevTools = { + init(libDir) { + let panels = [ + "options", + "webconsole", + "jsdebugger", + "styleeditor", + "performance", + "netmonitor", + ]; + + panels.forEach(panel => { + this.configurations[panel] = {}; + this.configurations[panel].applyConfig = async function () { + Services.prefs.setIntPref("devtools.toolbox.footer.height", 800); + let toolbox = await showToolboxForSelectedTab(panel, "bottom"); + this.selectors = [selectToolbox.bind(null, toolbox)]; + await new Promise(resolve => setTimeout(resolve, 500)); + }; + }); + }, + + configurations: { + bottomToolbox: { + async applyConfig() { + Services.prefs.clearUserPref("devtools.toolbox.footer.height"); + let toolbox = await showToolboxForSelectedTab("inspector", "bottom"); + this.selectors = [selectToolbox.bind(null, toolbox)]; + await new Promise(resolve => setTimeout(resolve, 1000)); + }, + }, + sideToolbox: { + async applyConfig() { + let toolbox = await showToolboxForSelectedTab("inspector", "right"); + this.selectors = [selectToolbox.bind(null, toolbox)]; + await new Promise(resolve => setTimeout(resolve, 1000)); + }, + async verifyConfig() { + return "Panel sizes are regularly inconsistent"; + }, + }, + undockedToolbox: { + windowType: "devtools:toolbox", + async applyConfig() { + let toolbox = await showToolboxForSelectedTab("inspector", "window"); + this.selectors = [selectToolbox.bind(null, toolbox)]; + await new Promise(resolve => setTimeout(resolve, 1000)); + }, + async verifyConfig() { + return "Panel sizes are regularly inconsistent"; + }, + }, + }, +}; diff --git a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/LightweightThemes.sys.mjs b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/LightweightThemes.sys.mjs new file mode 100644 index 0000000000..91c3349ec7 --- /dev/null +++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/LightweightThemes.sys.mjs @@ -0,0 +1,51 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { AddonManager } from "resource://gre/modules/AddonManager.sys.mjs"; + +export var LightweightThemes = { + init(libDir) {}, + + configurations: { + noLWT: { + selectors: [], + async applyConfig() { + let addon = await AddonManager.getAddonByID( + "default-theme@mozilla.org" + ); + await addon.enable(); + }, + }, + + compactLight: { + selectors: [], + async applyConfig() { + let addon = await AddonManager.getAddonByID( + "firefox-compact-light@mozilla.org" + ); + await addon.enable(); + }, + }, + + compactDark: { + selectors: [], + async applyConfig() { + let addon = await AddonManager.getAddonByID( + "firefox-compact-dark@mozilla.org" + ); + await addon.enable(); + }, + }, + + alpenGlow: { + selectors: [], + async applyConfig() { + let addon = await AddonManager.getAddonByID( + "firefox-alpenglow@mozilla.org" + ); + await addon.enable(); + }, + }, + }, +}; diff --git a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/PermissionPrompts.sys.mjs b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/PermissionPrompts.sys.mjs new file mode 100644 index 0000000000..de12c69e81 --- /dev/null +++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/PermissionPrompts.sys.mjs @@ -0,0 +1,168 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Various parts here are run in the content process. +/* global content */ + +import { BrowserTestUtils } from "resource://testing-common/BrowserTestUtils.sys.mjs"; + +const URL = + "https://test1.example.com/browser/browser/tools/mozscreenshots/mozscreenshots/extension/mozscreenshots/browser/resources/lib/permissionPrompts.html"; +let lastTab = null; + +export var PermissionPrompts = { + init(libDir) { + Services.prefs.setBoolPref("media.navigator.permission.fake", true); + Services.prefs.setBoolPref("extensions.install.requireBuiltInCerts", false); + Services.prefs.setBoolPref("signon.rememberSignons", true); + }, + + configurations: { + shareDevices: { + selectors: ["#notification-popup", "#identity-box"], + async applyConfig() { + await closeLastTab(); + await clickOn("#webRTC-shareDevices"); + }, + }, + + shareMicrophone: { + selectors: ["#notification-popup", "#identity-box"], + async applyConfig() { + await closeLastTab(); + await clickOn("#webRTC-shareMicrophone"); + }, + }, + + shareVideoAndMicrophone: { + selectors: ["#notification-popup", "#identity-box"], + async applyConfig() { + await closeLastTab(); + await clickOn("#webRTC-shareDevices2"); + }, + }, + + shareScreen: { + selectors: ["#notification-popup", "#identity-box"], + async applyConfig() { + await closeLastTab(); + await clickOn("#webRTC-shareScreen"); + }, + }, + + geo: { + selectors: ["#notification-popup", "#identity-box"], + async applyConfig() { + await closeLastTab(); + await clickOn("#geo"); + }, + }, + + persistentStorage: { + selectors: ["#notification-popup", "#identity-box"], + async applyConfig() { + await closeLastTab(); + await clickOn("#persistent-storage"); + }, + }, + + loginCapture: { + selectors: ["#notification-popup", "#identity-box"], + async applyConfig() { + await closeLastTab(); + // we need to emulate user input in the form for the save-password prompt to be shown + await clickOn("#login-capture", function beforeContentFn() { + const { E10SUtils } = ChromeUtils.importESModule( + "resource://gre/modules/E10SUtils.sys.mjs" + ); + E10SUtils.wrapHandlingUserInput(content, true, function () { + let element = content.document.querySelector( + "input[type=password]" + ); + element.setUserInput("123456"); + }); + }); + }, + }, + + notifications: { + selectors: ["#notification-popup", "#identity-box"], + async applyConfig() { + await closeLastTab(); + await clickOn("#web-notifications"); + }, + }, + + addons: { + selectors: ["#notification-popup", "#identity-box"], + async applyConfig() { + Services.prefs.setBoolPref("xpinstall.whitelist.required", true); + + await closeLastTab(); + await clickOn("#addons"); + }, + }, + + addonsNoWhitelist: { + selectors: ["#notification-popup", "#identity-box"], + async applyConfig() { + Services.prefs.setBoolPref("xpinstall.whitelist.required", false); + + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + let notification = browserWindow.document.getElementById( + "addon-webext-permissions-notification" + ); + + await closeLastTab(); + await clickOn("#addons"); + + // We want to skip the progress-notification, so we wait for + // the install-confirmation screen to be "not hidden" = shown. + return BrowserTestUtils.waitForCondition( + () => !notification.hidden, + "addon install confirmation did not show", + 200 + ).catch(msg => { + return Promise.resolve({ todo: msg }); + }); + }, + }, + }, +}; + +async function closeLastTab() { + if (!lastTab) { + return; + } + BrowserTestUtils.removeTab(lastTab); + lastTab = null; +} + +async function clickOn(selector, beforeContentFn) { + let browserWindow = Services.wm.getMostRecentWindow("navigator:browser"); + + // Save the tab so we can close it later. + lastTab = await BrowserTestUtils.openNewForegroundTab( + browserWindow.gBrowser, + URL + ); + + let { SpecialPowers } = lastTab.ownerGlobal; + if (beforeContentFn) { + await SpecialPowers.spawn(lastTab.linkedBrowser, [], beforeContentFn); + } + + await SpecialPowers.spawn(lastTab.linkedBrowser, [selector], arg => { + /* eslint-env mozilla/chrome-script */ + let element = content.document.querySelector(arg); + return EventUtils.synthesizeClick(element); + }); + + // Wait for the popup to actually be shown before making the screenshot + await BrowserTestUtils.waitForEvent( + browserWindow.PopupNotifications.panel, + "popupshown" + ); +} diff --git a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Preferences.sys.mjs b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Preferences.sys.mjs new file mode 100644 index 0000000000..77026523ba --- /dev/null +++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Preferences.sys.mjs @@ -0,0 +1,183 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Various parts here are run in the content process. +/* global content */ + +import { TestUtils } from "resource://testing-common/TestUtils.sys.mjs"; + +export var Preferences = { + init(libDir) { + let panes = [ + ["paneGeneral"], + ["paneGeneral", browsingGroup], + ["paneGeneral", connectionDialog], + ["paneSearch"], + ["panePrivacy"], + ["panePrivacy", cacheGroup], + ["panePrivacy", clearRecentHistoryDialog], + ["panePrivacy", certManager], + ["panePrivacy", deviceManager], + ["panePrivacy", DNTDialog], + ["paneSync"], + ]; + + for (let [primary, customFn] of panes) { + let configName = primary.replace(/^pane/, "prefs"); + if (customFn) { + configName += "-" + customFn.name; + } + this.configurations[configName] = {}; + this.configurations[configName].selectors = ["#browser"]; + if (primary == "panePrivacy" && customFn) { + this.configurations[configName].applyConfig = async () => { + return { todo: `${configName} times out on the try server` }; + }; + } else { + this.configurations[configName].applyConfig = prefHelper.bind( + null, + primary, + customFn + ); + } + } + }, + + configurations: {}, +}; + +let prefHelper = async function (primary, customFn = null) { + let browserWindow = Services.wm.getMostRecentWindow("navigator:browser"); + let selectedBrowser = browserWindow.gBrowser.selectedBrowser; + + // close any dialog that might still be open + await selectedBrowser.ownerGlobal.SpecialPowers.spawn( + selectedBrowser, + [], + async function () { + // Check that gSubDialog is defined on the content window + // and that there is an open dialog to close + if (!content.window.gSubDialog || !content.window.gSubDialog._topDialog) { + return; + } + content.window.gSubDialog.close(); + } + ); + + let readyPromise = null; + if (selectedBrowser.currentURI.specIgnoringRef == "about:preferences") { + if ( + selectedBrowser.currentURI.spec == + "about:preferences#" + primary.replace(/^pane/, "") + ) { + // We're already on the correct pane. + readyPromise = Promise.resolve(); + } else { + readyPromise = paintPromise(browserWindow); + } + } else { + readyPromise = TestUtils.topicObserved("sync-pane-loaded"); + } + + browserWindow.openPreferences(primary); + + await readyPromise; + + if (customFn) { + let customPaintPromise = paintPromise(browserWindow); + let result = await customFn(selectedBrowser); + await customPaintPromise; + return result; + } + return undefined; +}; + +function paintPromise(browserWindow) { + return new Promise(resolve => { + browserWindow.addEventListener( + "MozAfterPaint", + function () { + resolve(); + }, + { once: true } + ); + }); +} + +async function browsingGroup(aBrowser) { + await aBrowser.ownerGlobal.SpecialPowers.spawn( + aBrowser, + [], + async function () { + content.document.getElementById("browsingGroup").scrollIntoView(); + } + ); +} + +async function cacheGroup(aBrowser) { + await aBrowser.ownerGlobal.SpecialPowers.spawn( + aBrowser, + [], + async function () { + content.document.getElementById("cacheGroup").scrollIntoView(); + } + ); +} + +async function DNTDialog(aBrowser) { + return aBrowser.ownerGlobal.SpecialPowers.spawn( + aBrowser, + [], + async function () { + const button = content.document.getElementById("doNotTrackSettings"); + if (!button) { + return { + todo: "The dialog may have exited before we could click the button", + }; + } + button.click(); + return undefined; + } + ); +} + +async function connectionDialog(aBrowser) { + await aBrowser.ownerGlobal.SpecialPowers.spawn( + aBrowser, + [], + async function () { + content.document.getElementById("connectionSettings").click(); + } + ); +} + +async function clearRecentHistoryDialog(aBrowser) { + await aBrowser.ownerGlobal.SpecialPowers.spawn( + aBrowser, + [], + async function () { + content.document.getElementById("clearHistoryButton").click(); + } + ); +} + +async function certManager(aBrowser) { + await aBrowser.ownerGlobal.SpecialPowers.spawn( + aBrowser, + [], + async function () { + content.document.getElementById("viewCertificatesButton").click(); + } + ); +} + +async function deviceManager(aBrowser) { + await aBrowser.ownerGlobal.SpecialPowers.spawn( + aBrowser, + [], + async function () { + content.document.getElementById("viewSecurityDevicesButton").click(); + } + ); +} diff --git a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Tabs.sys.mjs b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Tabs.sys.mjs new file mode 100644 index 0000000000..85b134b8bc --- /dev/null +++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Tabs.sys.mjs @@ -0,0 +1,219 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const CUST_TAB = "chrome://browser/skin/customize.svg"; +const PREFS_TAB = "chrome://global/skin/icons/settings.svg"; +const DEFAULT_FAVICON_TAB = `data:text/html,<meta%20charset="utf-8"><title>No%20favicon</title>`; + +import { setTimeout } from "resource://gre/modules/Timer.sys.mjs"; +import { TestUtils } from "resource://testing-common/TestUtils.sys.mjs"; + +export var Tabs = { + init(libDir) {}, + + configurations: { + fiveTabs: { + selectors: ["#tabbrowser-tabs"], + async applyConfig() { + fiveTabsHelper(); + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + hoverTab(browserWindow.gBrowser.tabs[3]); + await new Promise((resolve, reject) => { + setTimeout(resolve, 3000); + }); + await allTabTitlesDisplayed(browserWindow); + }, + }, + + fourPinned: { + selectors: ["#tabbrowser-tabs"], + async applyConfig() { + fiveTabsHelper(); + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + let tab = browserWindow.gBrowser.addTab(PREFS_TAB, { + triggeringPrincipal: + Services.scriptSecurityManager.getSystemPrincipal(), + }); + browserWindow.gBrowser.pinTab(tab); + tab = browserWindow.gBrowser.addTab(CUST_TAB, { + triggeringPrincipal: + Services.scriptSecurityManager.getSystemPrincipal(), + }); + browserWindow.gBrowser.pinTab(tab); + tab = browserWindow.gBrowser.addTab("about:privatebrowsing", { + triggeringPrincipal: + Services.scriptSecurityManager.getSystemPrincipal(), + }); + browserWindow.gBrowser.pinTab(tab); + tab = browserWindow.gBrowser.addTab("about:home", { + triggeringPrincipal: + Services.scriptSecurityManager.getSystemPrincipal(), + }); + browserWindow.gBrowser.pinTab(tab); + browserWindow.gBrowser.selectTabAtIndex(5); + hoverTab(browserWindow.gBrowser.tabs[2]); + // also hover the new tab button + let newTabButton = browserWindow.gBrowser.tabContainer.newTabButton; + hoverTab(newTabButton); + + await new Promise((resolve, reject) => { + setTimeout(resolve, 3000); + }); + await allTabTitlesDisplayed(browserWindow); + }, + }, + + twoPinnedWithOverflow: { + selectors: ["#tabbrowser-tabs"], + async applyConfig() { + fiveTabsHelper(); + + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + browserWindow.gBrowser.loadTabs( + [ + PREFS_TAB, + CUST_TAB, + "about:home", + DEFAULT_FAVICON_TAB, + "about:newtab", + "about:addons", + "about:home", + DEFAULT_FAVICON_TAB, + "about:newtab", + "about:addons", + "about:home", + DEFAULT_FAVICON_TAB, + "about:newtab", + "about:addons", + "about:home", + DEFAULT_FAVICON_TAB, + "about:newtab", + "about:addons", + "about:home", + DEFAULT_FAVICON_TAB, + "about:newtab", + "about:addons", + "about:home", + DEFAULT_FAVICON_TAB, + "about:newtab", + "about:addons", + "about:home", + DEFAULT_FAVICON_TAB, + "about:newtab", + ], + { + inBackground: true, + replace: true, + triggeringPrincipal: + Services.scriptSecurityManager.getSystemPrincipal(), + } + ); + browserWindow.gBrowser.pinTab(browserWindow.gBrowser.tabs[1]); + browserWindow.gBrowser.pinTab(browserWindow.gBrowser.tabs[2]); + browserWindow.gBrowser.selectTabAtIndex(3); + hoverTab(browserWindow.gBrowser.tabs[5]); + + await new Promise((resolve, reject) => { + setTimeout(resolve, 3000); + }); + + // Make sure the tabstrip is scrolled all the way to the left. + browserWindow.gBrowser.tabContainer.arrowScrollbox.scrollByIndex( + -100, + true + ); + + await allTabTitlesDisplayed(browserWindow); + }, + }, + }, +}; + +/* helpers */ + +async function allTabTitlesDisplayed(browserWindow) { + let specToTitleMap = { + "about:home": "New Tab", + "about:newtab": "New Tab", + "about:addons": "Add-ons Manager", + "about:privatebrowsing": "about:privatebrowsing", + }; + specToTitleMap[PREFS_TAB] = "global/skin/icons/settings.svg"; + specToTitleMap[CUST_TAB] = "browser/skin/customize.svg"; + specToTitleMap[DEFAULT_FAVICON_TAB] = "No favicon"; + + let tabTitlePromises = []; + for (let tab of browserWindow.gBrowser.tabs) { + function getSpec() { + return ( + tab.linkedBrowser && + tab.linkedBrowser.documentURI && + tab.linkedBrowser.documentURI.spec + ); + } + function tabTitleLoaded() { + let spec = getSpec(); + return spec ? tab.label == specToTitleMap[spec] : false; + } + let promise = TestUtils.waitForCondition( + tabTitleLoaded, + `Tab (${getSpec()}) should be showing "${ + specToTitleMap[getSpec()] + }". Got "${tab.label}"` + ); + tabTitlePromises.push(promise); + } + + return Promise.all(tabTitlePromises); +} + +function fiveTabsHelper() { + // some with no favicon and some with. Selected tab in middle. + closeAllButOneTab("about:addons"); + + let browserWindow = Services.wm.getMostRecentWindow("navigator:browser"); + browserWindow.gBrowser.loadTabs( + [ + "about:addons", + "about:home", + DEFAULT_FAVICON_TAB, + "about:newtab", + CUST_TAB, + ], + { + inBackground: true, + replace: true, + triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(), + } + ); + browserWindow.gBrowser.selectTabAtIndex(1); +} + +function closeAllButOneTab(url = "about:blank") { + let browserWindow = Services.wm.getMostRecentWindow("navigator:browser"); + let gBrowser = browserWindow.gBrowser; + // Close all tabs except the last so we don't quit the browser. + while (gBrowser.tabs.length > 1) { + gBrowser.removeTab(gBrowser.selectedTab, { animate: false }); + } + gBrowser.selectedBrowser.loadURI(Services.io.newURI(url), { + triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(), + }); + if (gBrowser.selectedTab.pinned) { + gBrowser.unpinTab(gBrowser.selectedTab); + } + let newTabButton = gBrowser.tabContainer.newTabButton; + hoverTab(newTabButton, false); +} + +function hoverTab(tab, hover = true) { + if (hover) { + InspectorUtils.addPseudoClassLock(tab, ":hover"); + } else { + InspectorUtils.clearPseudoClassLocks(tab); + } +} diff --git a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/TabsInTitlebar.sys.mjs b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/TabsInTitlebar.sys.mjs new file mode 100644 index 0000000000..bc5b12c219 --- /dev/null +++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/TabsInTitlebar.sys.mjs @@ -0,0 +1,28 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const PREF_TABS_IN_TITLEBAR = "browser.tabs.inTitlebar"; + +export var TabsInTitlebar = { + init(libDir) {}, + + configurations: { + tabsInTitlebar: { + selectors: ["#navigator-toolbox"], + async applyConfig() { + Services.prefs.setIntPref(PREF_TABS_IN_TITLEBAR, 1); + return undefined; + }, + }, + + tabsOutsideTitlebar: { + selectors: ["#navigator-toolbox"].concat( + Services.appinfo.OS == "Linux" ? [] : ["#titlebar"] + ), + async applyConfig() { + Services.prefs.setIntPref(PREF_TABS_IN_TITLEBAR, 0); + }, + }, + }, +}; diff --git a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Toolbars.sys.mjs b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Toolbars.sys.mjs new file mode 100644 index 0000000000..06b1159a5e --- /dev/null +++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Toolbars.sys.mjs @@ -0,0 +1,54 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +export var Toolbars = { + init(libDir) {}, + + configurations: { + onlyNavBar: { + selectors: ["#navigator-toolbox"], + async applyConfig() { + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + let personalToolbar = + browserWindow.document.getElementById("PersonalToolbar"); + browserWindow.setToolbarVisibility(personalToolbar, false); + toggleMenubarIfNecessary(false); + }, + }, + + allToolbars: { + selectors: ["#navigator-toolbox"], + async applyConfig() { + // Boookmarks and menubar + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + let personalToolbar = + browserWindow.document.getElementById("PersonalToolbar"); + browserWindow.setToolbarVisibility(personalToolbar, true); + toggleMenubarIfNecessary(true); + }, + + async verifyConfig() { + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + if (browserWindow.fullScreen) { + return "The bookmark toolbar and menubar are not shown in fullscreen."; + } + return undefined; + }, + }, + }, +}; + +// helpers + +function toggleMenubarIfNecessary(visible) { + let browserWindow = Services.wm.getMostRecentWindow("navigator:browser"); + // The menubar is not shown on OS X or while in fullScreen + if (Services.appinfo.OS != "Darwin" /* && !browserWindow.fullScreen*/) { + let menubar = browserWindow.document.getElementById("toolbar-menubar"); + browserWindow.setToolbarVisibility(menubar, visible); + } +} diff --git a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/UIDensities.sys.mjs b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/UIDensities.sys.mjs new file mode 100644 index 0000000000..37cc123727 --- /dev/null +++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/UIDensities.sys.mjs @@ -0,0 +1,42 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +export var UIDensities = { + init(libDir) {}, + + configurations: { + compactDensity: { + selectors: ["#navigator-toolbox", "#appMenu-popup", "#widget-overflow"], + async applyConfig() { + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + browserWindow.gCustomizeMode.setUIDensity( + browserWindow.gUIDensity.MODE_COMPACT + ); + }, + }, + + normalDensity: { + selectors: ["#navigator-toolbox", "#appMenu-popup", "#widget-overflow"], + async applyConfig() { + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + browserWindow.gCustomizeMode.setUIDensity( + browserWindow.gUIDensity.MODE_NORMAL + ); + }, + }, + + touchDensity: { + selectors: ["#navigator-toolbox", "#appMenu-popup", "#widget-overflow"], + async applyConfig() { + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + browserWindow.gCustomizeMode.setUIDensity( + browserWindow.gUIDensity.MODE_TOUCH + ); + }, + }, + }, +}; diff --git a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/WindowSize.sys.mjs b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/WindowSize.sys.mjs new file mode 100644 index 0000000000..98a4e3ec00 --- /dev/null +++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/WindowSize.sys.mjs @@ -0,0 +1,68 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { setTimeout } from "resource://gre/modules/Timer.sys.mjs"; +import { BrowserTestUtils } from "resource://testing-common/BrowserTestUtils.sys.mjs"; + +export var WindowSize = { + init(libDir) { + Services.prefs.setBoolPref("browser.fullscreen.autohide", false); + }, + + configurations: { + maximized: { + selectors: [":root"], + async applyConfig() { + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + await toggleFullScreen(browserWindow, false); + + // Wait for the Lion fullscreen transition to end as there doesn't seem to be an event + // and trying to maximize while still leaving fullscreen doesn't work. + await new Promise((resolve, reject) => { + setTimeout(function waitToLeaveFS() { + browserWindow.maximize(); + resolve(); + }, 5000); + }); + }, + }, + + normal: { + selectors: [":root"], + async applyConfig() { + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + await toggleFullScreen(browserWindow, false); + browserWindow.restore(); + await new Promise((resolve, reject) => { + setTimeout(resolve, 5000); + }); + }, + }, + + fullScreen: { + selectors: [":root"], + async applyConfig() { + let browserWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + await toggleFullScreen(browserWindow, true); + // OS X Lion fullscreen transition takes a while + await new Promise((resolve, reject) => { + setTimeout(resolve, 5000); + }); + }, + }, + }, +}; + +function toggleFullScreen(browserWindow, wantsFS) { + browserWindow.fullScreen = wantsFS; + return BrowserTestUtils.waitForCondition(() => { + return ( + wantsFS == + browserWindow.document.documentElement.hasAttribute("inFullscreen") + ); + }, "waiting for @inFullscreen change"); +} |