mirror of
https://github.com/zen-browser/desktop.git
synced 2026-01-17 10:27:10 +00:00
test: Fixed running tests for pinned tabs and exported machitests, b=no-bug, c=tabs, glance, tests, folders, workspaces
This commit is contained in:
@@ -20,6 +20,7 @@ import testPathsConfig from "./engine/eslint-test-paths.config.mjs";
|
||||
import repositoryGlobals from "./engine/eslint-file-globals.config.mjs";
|
||||
import rollouts from "./engine/eslint-rollouts.config.mjs";
|
||||
import subdirConfigs from "./engine/eslint-subdirs.config.mjs";
|
||||
import { globalIgnores as globalIgnoresPath } from "eslint/config";
|
||||
|
||||
const testPaths = testPathsConfig.testPaths;
|
||||
|
||||
@@ -451,6 +452,7 @@ let config = [
|
||||
},
|
||||
},
|
||||
...wrapPathsInConfig(rollouts),
|
||||
globalIgnoresPath(["src/zen/tests/"]),
|
||||
];
|
||||
|
||||
// The various places we get our globals from use true/false rather than
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"sync:raw": "surfer update",
|
||||
"sync:rc": "python3 scripts/update_ff.py --rc",
|
||||
"sync:l10n": "python3 scripts/update_ff.py --just-l10n",
|
||||
"pretty": "prettier . --write --cache && autopep8 -r --in-place scripts/ src/ --exclude */tests/*",
|
||||
"pretty": "prettier . --write --cache && autopep8 -r --in-place scripts/ src/ --exclude src/zen/tests/",
|
||||
"lint": "npx eslint src/ && prettier . --check --cache",
|
||||
"lint:fix": "npm run pretty && npx eslint src/ --fix",
|
||||
"prepare": "husky",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/themes/shared/tabbrowser/tabs.css b/browser/themes/shared/tabbrowser/tabs.css
|
||||
index 310e7866b942df5c3c34815f4612a2a2ad8c42a6..c474e1cddcecd3def3b255c5c530c0b36a38e6b0 100644
|
||||
index 310e7866b942df5c3c34815f4612a2a2ad8c42a6..d4931a0184209951ced288c894613dccdf3b11fc 100644
|
||||
--- a/browser/themes/shared/tabbrowser/tabs.css
|
||||
+++ b/browser/themes/shared/tabbrowser/tabs.css
|
||||
@@ -21,7 +21,7 @@
|
||||
@@ -152,7 +152,17 @@ index 310e7866b942df5c3c34815f4612a2a2ad8c42a6..c474e1cddcecd3def3b255c5c530c0b3
|
||||
|
||||
&:-moz-window-inactive {
|
||||
background-image:
|
||||
@@ -2382,7 +2373,6 @@ toolbar:not(#TabsToolbar) #firefox-view-button {
|
||||
@@ -2348,9 +2339,6 @@ tab-group {
|
||||
|
||||
:root:not([privatebrowsingmode]) :is(toolbarbutton, toolbarpaletteitem) ~ #tabbrowser-tabs,
|
||||
:root[privatebrowsingmode] :is(toolbarbutton:not(#firefox-view-button), toolbarpaletteitem:not(#wrapper-firefox-view-button)) ~ #tabbrowser-tabs {
|
||||
- border-inline-start: var(--tabstrip-inner-border);
|
||||
- padding-inline-start: 2px;
|
||||
- margin-inline-start: 2px;
|
||||
}
|
||||
|
||||
:root[privatebrowsingmode] :is(#firefox-view-button, #menu_openFirefoxView) {
|
||||
@@ -2382,7 +2370,6 @@ toolbar:not(#TabsToolbar) #firefox-view-button {
|
||||
list-style-image: url(chrome://global/skin/icons/plus.svg);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
diff --git a/testing/profiles/mochitest/user.js b/testing/profiles/mochitest/user.js
|
||||
index 782258420cdce901f182897b796731a1fdf69ecf..59b2827a7cd8a8580ba5061cabb36a2ba13240ba 100644
|
||||
index 782258420cdce901f182897b796731a1fdf69ecf..a762067169b1cf3cd05147f9e715eb0db56a3299 100644
|
||||
--- a/testing/profiles/mochitest/user.js
|
||||
+++ b/testing/profiles/mochitest/user.js
|
||||
@@ -36,3 +36,8 @@ user_pref("places.history.floodingPrevention.enabled", false);
|
||||
@@ -36,3 +36,9 @@ user_pref("places.history.floodingPrevention.enabled", false);
|
||||
// permission, and we can open it and wait for the user to give permission, then
|
||||
// don't do that.
|
||||
user_pref("geo.prompt.open_system_prefs", false);
|
||||
@@ -11,3 +11,4 @@ index 782258420cdce901f182897b796731a1fdf69ecf..59b2827a7cd8a8580ba5061cabb36a2b
|
||||
+user_pref("zen.watermark.enabled", false);
|
||||
+user_pref("zen.testing.enabled", true);
|
||||
+user_pref("zen.window-sync.enabled", true);
|
||||
+user_pref("widget.macos.native-context-menus", false);
|
||||
|
||||
@@ -811,7 +811,12 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#animateGlanceClosing(onTabClose, browserSidebarContainer, sidebarButtons, setNewID);
|
||||
return this.#animateGlanceClosing(
|
||||
onTabClose,
|
||||
browserSidebarContainer,
|
||||
sidebarButtons,
|
||||
setNewID
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -189,7 +189,8 @@ class nsZenWindowSync {
|
||||
for (let tab of gZenWorkspaces.allStoredTabs) {
|
||||
if (!tab.id) {
|
||||
tab.id = this.#newTabSyncId;
|
||||
lazy.TabStateFlusher.flush(tab.linkedBrowser);
|
||||
// Don't call with await here to avoid blocking the loop.
|
||||
this.#maybeFlushTabState(tab);
|
||||
}
|
||||
if (tab.pinned && !tab._zenPinnedInitialState) {
|
||||
await this.setPinnedTabState(tab);
|
||||
@@ -407,7 +408,7 @@ class nsZenWindowSync {
|
||||
this.#syncItemPosition(aOriginalItem, aTargetItem, aWindow);
|
||||
}
|
||||
if (gBrowser.isTab(aTargetItem)) {
|
||||
lazy.TabStateFlusher.flush(aTargetItem.linkedBrowser);
|
||||
this.#maybeFlushTabState(aTargetItem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -540,7 +541,7 @@ class nsZenWindowSync {
|
||||
* @param {object} aOtherTab - The tab in the other window.
|
||||
*/
|
||||
async #swapBrowserDocShellsAsync(aOurTab, aOtherTab) {
|
||||
lazy.TabStateFlusher.flush(aOtherTab.linkedBrowser);
|
||||
this.#maybeFlushTabState(aOtherTab);
|
||||
await this.#styleSwapedBrowsers(aOurTab, aOtherTab, () => {
|
||||
this.#swapBrowserDocSheellsInner(aOurTab, aOtherTab);
|
||||
});
|
||||
@@ -601,7 +602,7 @@ class nsZenWindowSync {
|
||||
// See https://github.com/zen-browser/desktop/issues/11851, swapping the browsers
|
||||
// don't seem to update the state's cache properly, leading to issues when restoring
|
||||
// the session later on.
|
||||
let tabState = this.#getTabState(aOtherTab);
|
||||
let tabStateEntries = this.#getTabEntriesFromCache(aOtherTab);
|
||||
// Running `swapBrowsersAndCloseOther` doesn't expect us to use the tab after
|
||||
// the operation, so it doesn't really care about cleaning up the other tab.
|
||||
// We need to make a new tab progress listener for the other tab after the swap.
|
||||
@@ -656,13 +657,13 @@ class nsZenWindowSync {
|
||||
// It's also important to note that if we don't flush the state here,
|
||||
// we would start receiving invalid history changes from the the incorrect
|
||||
// browser view that was just swapped out.
|
||||
lazy.TabStateFlusher.flush(aOurTab.linkedBrowser).finally(() => {
|
||||
if (!tabState.entries?.length) {
|
||||
this.#maybeFlushTabState(aOurTab).finally(() => {
|
||||
if (!tabStateEntries?.length) {
|
||||
this.log(`Error: No tab state entries found for tab ${aOtherTab.id} during swap`);
|
||||
return;
|
||||
}
|
||||
lazy.TabStateCache.update(aOurTab.linkedBrowser.permanentKey, {
|
||||
entries: tabState.entries,
|
||||
entries: tabStateEntries,
|
||||
});
|
||||
});
|
||||
return true;
|
||||
@@ -849,13 +850,30 @@ class nsZenWindowSync {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the tab state for a given tab.
|
||||
* Retrieves the tab state entries from the cache for a given tab.
|
||||
*
|
||||
* @param {object} tab - The tab to retrieve the state for.
|
||||
* @returns {object} The tab state.
|
||||
* @param {object} aTab - The tab to retrieve the state for.
|
||||
* @returns {Array} The tab state entries.
|
||||
*/
|
||||
#getTabState(tab) {
|
||||
return JSON.parse(lazy.SessionStore.getTabState(tab));
|
||||
#getTabEntriesFromCache(aTab) {
|
||||
if (!aTab.linkedBrowser) {
|
||||
return [];
|
||||
}
|
||||
let cachedState = lazy.TabStateCache.get(aTab.linkedBrowser.permanentKey) || { entries: [] };
|
||||
return cachedState.entries || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the tab state for a given tab if it has a linked browser.
|
||||
*
|
||||
* @param {object} aTab - The tab to flush the state for.
|
||||
* @returns {Promise} A promise that resolves when the operation is complete.
|
||||
*/
|
||||
#maybeFlushTabState(aTab) {
|
||||
if (!aTab.linkedBrowser) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return lazy.TabStateFlusher.flush(aTab.linkedBrowser);
|
||||
}
|
||||
|
||||
/* Mark: Public API */
|
||||
@@ -867,15 +885,15 @@ class nsZenWindowSync {
|
||||
* @returns {Promise} A promise that resolves when the operation is complete.
|
||||
*/
|
||||
setPinnedTabState(aTab) {
|
||||
return lazy.TabStateFlusher.flush(aTab.linkedBrowser).finally(() => {
|
||||
return this.#maybeFlushTabState(aTab).finally(() => {
|
||||
this.log(`Setting pinned initial state for tab ${aTab.id}`);
|
||||
const state = this.#getTabState(aTab);
|
||||
let activeIndex = "index" in state ? state.index : state.entries.length - 1;
|
||||
activeIndex = Math.min(activeIndex, state.entries.length - 1);
|
||||
const entries = this.#getTabEntriesFromCache(aTab);
|
||||
let activeIndex = "index" in entries ? entries.index : entries.entries.length - 1;
|
||||
activeIndex = Math.min(activeIndex, entries.entries.length - 1);
|
||||
activeIndex = Math.max(activeIndex, 0);
|
||||
const initialState = {
|
||||
entry: state.entries[activeIndex],
|
||||
image: state.image,
|
||||
entry: entries.entries[activeIndex],
|
||||
image: entries.image,
|
||||
};
|
||||
this.#runOnAllWindows(null, (win) => {
|
||||
const targetTab = this.getItemFromWindow(win, aTab.id);
|
||||
@@ -973,7 +991,7 @@ class nsZenWindowSync {
|
||||
SYNC_FLAG_ICON | SYNC_FLAG_LABEL | SYNC_FLAG_MOVE
|
||||
);
|
||||
});
|
||||
lazy.TabStateFlusher.flush(tab.linkedBrowser);
|
||||
this.#maybeFlushTabState(tab);
|
||||
}
|
||||
|
||||
on_ZenTabIconChanged(aEvent) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
add_task(async function test_Container_Essentials_Auto_Swithc() {
|
||||
await gZenWorkspaces.createAndSaveWorkspace("Container Profile 1", undefined, false, 1);
|
||||
const workspaces = await gZenWorkspaces._workspaces();
|
||||
const workspaces = gZenWorkspaces.getWorkspaces();
|
||||
Assert.strictEqual(workspaces.length, 2, "Two workspaces should exist.");
|
||||
|
||||
let newTab = BrowserTestUtils.addTab(gBrowser, "about:blank", {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
add_task(async function test_Check_Creation() {
|
||||
await gZenWorkspaces.createAndSaveWorkspace("Container Profile 1", undefined, false, 1);
|
||||
const workspaces = await gZenWorkspaces._workspaces();
|
||||
const workspaces = gZenWorkspaces.getWorkspaces();
|
||||
Assert.strictEqual(workspaces.length, 2, "Two workspaces should exist.");
|
||||
|
||||
await gZenWorkspaces.changeWorkspace(workspaces[1]);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
[DEFAULT]
|
||||
prefs = ["widget.macos.native-context-menus=false"]
|
||||
support-files = [
|
||||
"head.js",
|
||||
]
|
||||
|
||||
@@ -3,16 +3,6 @@
|
||||
# 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/.
|
||||
|
||||
[reportbrokensite]
|
||||
source = "browser/components/reportbrokensite/test/browser"
|
||||
is_direct_path = true
|
||||
disable = [
|
||||
"browser_addon_data_sent.js"
|
||||
]
|
||||
|
||||
[reportbrokensite.replace-manifest]
|
||||
"../../../../../" = "../../../../"
|
||||
|
||||
[safebrowsing]
|
||||
source = "browser/components/safebrowsing/content/test"
|
||||
is_direct_path = true
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
# Do not edit manually.
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
"reportbrokensite/browser.toml",
|
||||
"safebrowsing/browser.toml",
|
||||
"shell/browser.toml",
|
||||
"tooltiptext/browser.toml",
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
[DEFAULT]
|
||||
tags = "report-broken-site"
|
||||
support-files = [
|
||||
"example_report_page.html",
|
||||
"head.js",
|
||||
"sendMoreInfoTestEndpoint.html",
|
||||
]
|
||||
|
||||
["browser_addon_data_sent.js"]
|
||||
disabled="Disabled by import_external_tests.py"
|
||||
support-files = [ "send_more_info.js" ]
|
||||
skip-if = ["os == 'win' && os_version == '11.26100' && processor == 'x86_64' && opt"] # Bug 1955805
|
||||
|
||||
["browser_antitracking_data_sent.js"]
|
||||
support-files = [ "send_more_info.js" ]
|
||||
|
||||
["browser_back_buttons.js"]
|
||||
|
||||
["browser_error_messages.js"]
|
||||
|
||||
["browser_experiment_data_sent.js"]
|
||||
support-files = [ "send_more_info.js" ]
|
||||
|
||||
["browser_keyboard_navigation.js"]
|
||||
skip-if = [
|
||||
"os == 'linux' && os_version == '24.04' && processor == 'x86_64' && tsan", # Bug 1867132
|
||||
"os == 'linux' && os_version == '24.04' && processor == 'x86_64' && asan", # Bug 1867132
|
||||
"os == 'linux' && os_version == '24.04' && processor == 'x86_64' && debug", # Bug 1867132
|
||||
"os == 'win' && os_version == '11.26100' && processor == 'x86_64' && asan", # Bug 1867132
|
||||
]
|
||||
|
||||
["browser_learn_more_link.js"]
|
||||
|
||||
["browser_parent_menuitems.js"]
|
||||
|
||||
["browser_prefers_contrast.js"]
|
||||
|
||||
["browser_reason_dropdown.js"]
|
||||
|
||||
["browser_report_send.js"]
|
||||
support-files = [ "send.js" ]
|
||||
|
||||
["browser_send_more_info.js"]
|
||||
support-files = [
|
||||
"send_more_info.js",
|
||||
"../../../../toolkit/components/gfx/content/videotest.mp4",
|
||||
]
|
||||
|
||||
["browser_tab_key_order.js"]
|
||||
|
||||
["browser_tab_switch_handling.js"]
|
||||
|
||||
["browser_webcompat.com_fallback.js"]
|
||||
support-files = [
|
||||
"send_more_info.js",
|
||||
"../../../../toolkit/components/gfx/content/videotest.mp4",
|
||||
]
|
||||
@@ -1,99 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Tests to ensure that the right data is sent for
|
||||
* private windows and when ETP blocks content.
|
||||
*/
|
||||
|
||||
/* import-globals-from send.js */
|
||||
/* import-globals-from send_more_info.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { AddonTestUtils } = ChromeUtils.importESModule(
|
||||
"resource://testing-common/AddonTestUtils.sys.mjs"
|
||||
);
|
||||
AddonTestUtils.initMochitest(this);
|
||||
|
||||
Services.scriptloader.loadSubScript(
|
||||
getRootDirectory(gTestPath) + "send_more_info.js",
|
||||
this
|
||||
);
|
||||
|
||||
add_common_setup();
|
||||
|
||||
const TEMP_ID = "testtempaddon@tests.mozilla.org";
|
||||
const TEMP_NAME = "Temporary Addon";
|
||||
const TEMP_VERSION = "0.1.0";
|
||||
|
||||
const PERM_ID = "testpermaddon@tests.mozilla.org";
|
||||
const PERM_NAME = "Permanent Addon";
|
||||
const PERM_VERSION = "0.2.0";
|
||||
|
||||
const DISABLED_ID = "testdisabledaddon@tests.mozilla.org";
|
||||
const DISABLED_NAME = "Disabled Addon";
|
||||
const DISABLED_VERSION = "0.3.0";
|
||||
|
||||
const EXPECTED_ADDONS = [
|
||||
{ id: PERM_ID, name: PERM_NAME, temporary: false, version: PERM_VERSION },
|
||||
{ id: TEMP_ID, name: TEMP_NAME, temporary: true, version: TEMP_VERSION },
|
||||
];
|
||||
|
||||
function loadAddon(id, name, version, isTemp = false) {
|
||||
return ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
browser_specific_settings: { gecko: { id } },
|
||||
name,
|
||||
version,
|
||||
},
|
||||
useAddonManager: isTemp ? "temporary" : "permanent",
|
||||
});
|
||||
}
|
||||
|
||||
async function installAddons() {
|
||||
const temp = await loadAddon(TEMP_ID, TEMP_NAME, TEMP_VERSION, true);
|
||||
await temp.startup();
|
||||
|
||||
const perm = await loadAddon(PERM_ID, PERM_NAME, PERM_VERSION);
|
||||
await perm.startup();
|
||||
|
||||
const dis = await loadAddon(DISABLED_ID, DISABLED_NAME, DISABLED_VERSION);
|
||||
await dis.startup();
|
||||
await (await AddonManager.getAddonByID(DISABLED_ID)).disable();
|
||||
|
||||
return async () => {
|
||||
await temp.unload();
|
||||
await perm.unload();
|
||||
await dis.unload();
|
||||
};
|
||||
}
|
||||
|
||||
add_task(async function testSendButton() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
ensureReasonOptional();
|
||||
const addonCleanup = await installAddons();
|
||||
|
||||
const tab = await openTab(REPORTABLE_PAGE_URL);
|
||||
|
||||
await testSend(tab, AppMenu(), {
|
||||
addons: EXPECTED_ADDONS,
|
||||
});
|
||||
|
||||
closeTab(tab);
|
||||
await addonCleanup();
|
||||
});
|
||||
|
||||
add_task(async function testSendingMoreInfo() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
ensureSendMoreInfoEnabled();
|
||||
const addonCleanup = await installAddons();
|
||||
|
||||
const tab = await openTab(REPORTABLE_PAGE_URL);
|
||||
|
||||
await testSendMoreInfo(tab, HelpMenu(), {
|
||||
addons: EXPECTED_ADDONS,
|
||||
});
|
||||
|
||||
closeTab(tab);
|
||||
await addonCleanup();
|
||||
});
|
||||
@@ -1,126 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Tests to ensure that the right data is sent for
|
||||
* private windows and when ETP blocks content.
|
||||
*/
|
||||
|
||||
/* import-globals-from send.js */
|
||||
/* import-globals-from send_more_info.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
Services.scriptloader.loadSubScript(
|
||||
getRootDirectory(gTestPath) + "send_more_info.js",
|
||||
this
|
||||
);
|
||||
|
||||
add_common_setup();
|
||||
|
||||
add_task(setupStrictETP);
|
||||
|
||||
function getEtpCategory() {
|
||||
return Services.prefs.getStringPref(
|
||||
"browser.contentblocking.category",
|
||||
"standard"
|
||||
);
|
||||
}
|
||||
|
||||
add_task(async function testSendButton() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
ensureReasonOptional();
|
||||
|
||||
const win = await BrowserTestUtils.openNewBrowserWindow({ private: true });
|
||||
const blockedPromise = waitForContentBlockingEvent(3, win);
|
||||
const tab = await openTab(REPORTABLE_PAGE_URL3, win);
|
||||
await blockedPromise;
|
||||
|
||||
await testSend(tab, AppMenu(win), {
|
||||
breakageCategory: "adblocker",
|
||||
description: "another test description",
|
||||
antitracking: {
|
||||
blockList: "strict",
|
||||
blockedOrigins: null,
|
||||
isPrivateBrowsing: true,
|
||||
hasTrackingContentBlocked: true,
|
||||
hasMixedActiveContentBlocked: true,
|
||||
hasMixedDisplayContentBlocked: true,
|
||||
btpHasPurgedSite: false,
|
||||
etpCategory: getEtpCategory(),
|
||||
},
|
||||
frameworks: {
|
||||
fastclick: true,
|
||||
marfeel: true,
|
||||
mobify: true,
|
||||
},
|
||||
});
|
||||
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
});
|
||||
|
||||
add_task(async function testSendingMoreInfo() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
ensureSendMoreInfoEnabled();
|
||||
|
||||
const win = await BrowserTestUtils.openNewBrowserWindow({ private: true });
|
||||
const blockedPromise = waitForContentBlockingEvent(3, win);
|
||||
const tab = await openTab(REPORTABLE_PAGE_URL3, win);
|
||||
await blockedPromise;
|
||||
|
||||
await testSendMoreInfo(tab, HelpMenu(win), {
|
||||
antitracking: {
|
||||
blockList: "strict",
|
||||
blockedOrigins: ["https://trackertest.org"],
|
||||
isPrivateBrowsing: true,
|
||||
hasTrackingContentBlocked: true,
|
||||
hasMixedActiveContentBlocked: true,
|
||||
hasMixedDisplayContentBlocked: true,
|
||||
btpHasPurgedSite: false,
|
||||
etpCategory: getEtpCategory(),
|
||||
},
|
||||
frameworks: { fastclick: true, mobify: true, marfeel: true },
|
||||
consoleLog: [
|
||||
{
|
||||
level: "error",
|
||||
log(actual) {
|
||||
// "Blocked loading mixed display content http://example.com/tests/image/test/mochitest/blue.png"
|
||||
return (
|
||||
Array.isArray(actual) &&
|
||||
actual.length == 1 &&
|
||||
actual[0].includes("blue.png")
|
||||
);
|
||||
},
|
||||
pos: "0:1",
|
||||
uri: REPORTABLE_PAGE_URL3,
|
||||
},
|
||||
{
|
||||
level: "error",
|
||||
log(actual) {
|
||||
// "Blocked loading mixed active content http://tracking.example.org/browser/browser/base/content/test/protectionsUI/benignPage.html",
|
||||
return (
|
||||
Array.isArray(actual) &&
|
||||
actual.length == 1 &&
|
||||
actual[0].includes("benignPage.html")
|
||||
);
|
||||
},
|
||||
pos: "0:1",
|
||||
uri: REPORTABLE_PAGE_URL3,
|
||||
},
|
||||
{
|
||||
level: "warn",
|
||||
log(actual) {
|
||||
// "The resource at https://trackertest.org/ was blocked because content blocking is enabled.",
|
||||
return (
|
||||
Array.isArray(actual) &&
|
||||
actual.length == 1 &&
|
||||
actual[0].includes("trackertest.org")
|
||||
);
|
||||
},
|
||||
pos: "0:1",
|
||||
uri: REPORTABLE_PAGE_URL3,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
});
|
||||
@@ -1,34 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Tests to ensure that Report Broken Site popups will be
|
||||
* reset to whichever tab the user is on as they change
|
||||
* between windows and tabs. */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_common_setup();
|
||||
|
||||
add_task(async function testBackButtonsAreAdded() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
|
||||
await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () {
|
||||
let rbs = await AppMenu().openReportBrokenSite();
|
||||
rbs.isBackButtonEnabled();
|
||||
await rbs.clickBack();
|
||||
await rbs.close();
|
||||
|
||||
rbs = await HelpMenu().openReportBrokenSite();
|
||||
ok(!rbs.backButton, "Back button is not shown for Help Menu");
|
||||
await rbs.close();
|
||||
|
||||
rbs = await ProtectionsPanel().openReportBrokenSite();
|
||||
rbs.isBackButtonEnabled();
|
||||
await rbs.clickBack();
|
||||
await rbs.close();
|
||||
|
||||
rbs = await HelpMenu().openReportBrokenSite();
|
||||
ok(!rbs.backButton, "Back button is not shown for Help Menu");
|
||||
await rbs.close();
|
||||
});
|
||||
});
|
||||
@@ -1,64 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Test that the Report Broken Site errors messages are shown on
|
||||
* the UI if the user enters an invalid URL or clicks the send
|
||||
* button while it is disabled due to not selecting a "reason"
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
add_common_setup();
|
||||
|
||||
add_task(async function test() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
ensureReasonRequired();
|
||||
|
||||
await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () {
|
||||
for (const menu of [AppMenu(), ProtectionsPanel(), HelpMenu()]) {
|
||||
const rbs = await menu.openReportBrokenSite();
|
||||
const { sendButton, URLInput } = rbs;
|
||||
|
||||
rbs.isURLInvalidMessageHidden();
|
||||
rbs.isReasonNeededMessageHidden();
|
||||
|
||||
rbs.setURL("");
|
||||
window.document.activeElement.blur();
|
||||
rbs.isURLInvalidMessageShown();
|
||||
rbs.isReasonNeededMessageHidden();
|
||||
|
||||
rbs.setURL("https://asdf");
|
||||
window.document.activeElement.blur();
|
||||
rbs.isURLInvalidMessageHidden();
|
||||
rbs.isReasonNeededMessageHidden();
|
||||
|
||||
rbs.setURL("http:/ /asdf");
|
||||
window.document.activeElement.blur();
|
||||
rbs.isURLInvalidMessageShown();
|
||||
rbs.isReasonNeededMessageHidden();
|
||||
|
||||
rbs.setURL("https://asdf");
|
||||
const selectPromise = BrowserTestUtils.waitForSelectPopupShown(window);
|
||||
EventUtils.synthesizeMouseAtCenter(sendButton, {}, window);
|
||||
await selectPromise;
|
||||
rbs.isURLInvalidMessageHidden();
|
||||
rbs.isReasonNeededMessageShown();
|
||||
await rbs.dismissDropdownPopup();
|
||||
|
||||
rbs.chooseReason("slow");
|
||||
rbs.isURLInvalidMessageHidden();
|
||||
rbs.isReasonNeededMessageHidden();
|
||||
|
||||
rbs.setURL("");
|
||||
rbs.chooseReason("choose");
|
||||
window.ownerGlobal.document.activeElement?.blur();
|
||||
const focusPromise = BrowserTestUtils.waitForEvent(URLInput, "focus");
|
||||
EventUtils.synthesizeMouseAtCenter(sendButton, {}, window);
|
||||
await focusPromise;
|
||||
rbs.isURLInvalidMessageShown();
|
||||
rbs.isReasonNeededMessageShown();
|
||||
|
||||
rbs.clickCancel();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,88 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Tests to ensure that the right data is sent for
|
||||
* private windows and when ETP blocks content.
|
||||
*/
|
||||
|
||||
/* import-globals-from send.js */
|
||||
/* import-globals-from send_more_info.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
Services.scriptloader.loadSubScript(
|
||||
getRootDirectory(gTestPath) + "send_more_info.js",
|
||||
this
|
||||
);
|
||||
|
||||
const { ExperimentAPI } = ChromeUtils.importESModule(
|
||||
"resource://nimbus/ExperimentAPI.sys.mjs"
|
||||
);
|
||||
const { NimbusTestUtils } = ChromeUtils.importESModule(
|
||||
"resource://testing-common/NimbusTestUtils.sys.mjs"
|
||||
);
|
||||
|
||||
add_common_setup();
|
||||
|
||||
const EXPECTED_EXPERIMENTS_IN_REPORT = [
|
||||
{ slug: "test-experiment", branch: "branch", kind: "nimbusExperiment" },
|
||||
{ slug: "test-experiment-rollout", branch: "branch", kind: "nimbusRollout" },
|
||||
];
|
||||
|
||||
let EXPERIMENT_CLEANUPS;
|
||||
|
||||
add_setup(async function () {
|
||||
await ExperimentAPI.ready();
|
||||
EXPERIMENT_CLEANUPS = [
|
||||
await NimbusTestUtils.enrollWithFeatureConfig(
|
||||
{ featureId: "no-feature-firefox-desktop", value: {} },
|
||||
{ slug: "test-experiment", branchSlug: "branch" }
|
||||
),
|
||||
await NimbusTestUtils.enrollWithFeatureConfig(
|
||||
{ featureId: "no-feature-firefox-desktop", value: {} },
|
||||
{ slug: "test-experiment-rollout", isRollout: true, branchSlug: "branch" }
|
||||
),
|
||||
async () => {
|
||||
ExperimentAPI.manager.store._deleteForTests("test-experiment-disabled");
|
||||
await NimbusTestUtils.flushStore();
|
||||
},
|
||||
];
|
||||
|
||||
await NimbusTestUtils.enrollWithFeatureConfig(
|
||||
{ featureId: "no-feature-firefox-desktop", value: {} },
|
||||
{ slug: "test-experiment-disabled" }
|
||||
);
|
||||
await ExperimentAPI.manager.unenroll("test-experiment-disabled");
|
||||
});
|
||||
|
||||
add_task(async function testSendButton() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
ensureReasonOptional();
|
||||
|
||||
const tab = await openTab(REPORTABLE_PAGE_URL);
|
||||
|
||||
await testSend(tab, AppMenu(), {
|
||||
experiments: EXPECTED_EXPERIMENTS_IN_REPORT,
|
||||
});
|
||||
|
||||
closeTab(tab);
|
||||
});
|
||||
|
||||
add_task(async function testSendingMoreInfo() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
ensureSendMoreInfoEnabled();
|
||||
|
||||
const tab = await openTab(REPORTABLE_PAGE_URL);
|
||||
|
||||
await testSendMoreInfo(tab, HelpMenu(), {
|
||||
experiments: EXPECTED_EXPERIMENTS_IN_REPORT,
|
||||
});
|
||||
|
||||
closeTab(tab);
|
||||
});
|
||||
|
||||
add_task(async function teardown() {
|
||||
for (const cleanup of EXPERIMENT_CLEANUPS) {
|
||||
await cleanup();
|
||||
}
|
||||
});
|
||||
@@ -1,107 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Tests to ensure that sending or canceling reports with
|
||||
* the Send and Cancel buttons work (as well as the Okay button)
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
add_common_setup();
|
||||
|
||||
requestLongerTimeout(2);
|
||||
|
||||
async function testPressingKey(key, tabToMatch, makePromise, followUp) {
|
||||
await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () {
|
||||
for (const menu of [AppMenu(), ProtectionsPanel(), HelpMenu()]) {
|
||||
info(
|
||||
`Opening RBS to test pressing ${key} for ${tabToMatch} on ${menu.menuDescription}`
|
||||
);
|
||||
const rbs = await menu.openReportBrokenSite();
|
||||
const promise = makePromise(rbs);
|
||||
if (tabToMatch) {
|
||||
if (await tabTo(tabToMatch)) {
|
||||
await pressKeyAndAwait(promise, key);
|
||||
followUp && (await followUp(rbs));
|
||||
await rbs.close();
|
||||
ok(true, `was able to activate ${tabToMatch} with keyboard`);
|
||||
} else {
|
||||
await rbs.close();
|
||||
ok(false, `could not tab to ${tabToMatch}`);
|
||||
}
|
||||
} else {
|
||||
await pressKeyAndAwait(promise, key);
|
||||
followUp && (await followUp(rbs));
|
||||
await rbs.close();
|
||||
ok(true, `was able to use keyboard`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
add_task(async function testSendMoreInfo() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
ensureSendMoreInfoEnabled();
|
||||
await testPressingKey(
|
||||
"KEY_Enter",
|
||||
"#report-broken-site-popup-send-more-info-link",
|
||||
rbs => rbs.waitForSendMoreInfoTab(),
|
||||
() => gBrowser.removeCurrentTab()
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function testCancel() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
await testPressingKey(
|
||||
"KEY_Enter",
|
||||
"#report-broken-site-popup-cancel-button",
|
||||
rbs => BrowserTestUtils.waitForEvent(rbs.mainView, "ViewHiding")
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function testSendAndOkay() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
await testPressingKey(
|
||||
"KEY_Enter",
|
||||
"#report-broken-site-popup-send-button",
|
||||
rbs => rbs.awaitReportSentViewOpened(),
|
||||
async rbs => {
|
||||
await tabTo("#report-broken-site-popup-okay-button");
|
||||
const promise = BrowserTestUtils.waitForEvent(rbs.sentView, "ViewHiding");
|
||||
await pressKeyAndAwait(promise, "KEY_Enter");
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function testESCOnMain() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
await testPressingKey("KEY_Escape", undefined, rbs =>
|
||||
BrowserTestUtils.waitForEvent(rbs.mainView, "ViewHiding")
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function testESCOnSent() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
await testPressingKey(
|
||||
"KEY_Enter",
|
||||
"#report-broken-site-popup-send-button",
|
||||
rbs => rbs.awaitReportSentViewOpened(),
|
||||
async rbs => {
|
||||
const promise = BrowserTestUtils.waitForEvent(rbs.sentView, "ViewHiding");
|
||||
await pressKeyAndAwait(promise, "KEY_Escape");
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function testBackButtons() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () {
|
||||
for (const menu of [AppMenu(), ProtectionsPanel()]) {
|
||||
await menu.openReportBrokenSite();
|
||||
await tabTo("#report-broken-site-popup-mainView .subviewbutton-back");
|
||||
const promise = BrowserTestUtils.waitForEvent(menu.popup, "ViewShown");
|
||||
await pressKeyAndAwait(promise, "KEY_Enter");
|
||||
menu.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,36 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Tests to ensure that the reason dropdown is shown or hidden
|
||||
* based on its pref, and that its optional and required modes affect
|
||||
* the Send button and report appropriately.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
add_common_setup();
|
||||
|
||||
async function ensureLearnMoreLinkWorks(menu) {
|
||||
const rbs = await menu.openReportBrokenSite();
|
||||
const { win, mainView, learnMoreLink } = rbs;
|
||||
ok(learnMoreLink, "Found a learn more link");
|
||||
|
||||
const promises = [
|
||||
BrowserTestUtils.waitForEvent(mainView, "ViewHiding"),
|
||||
BrowserTestUtils.waitForNewTab(win.gBrowser, LEARN_MORE_TEST_URL),
|
||||
];
|
||||
EventUtils.synthesizeMouseAtCenter(learnMoreLink, {}, win);
|
||||
const results = await Promise.all(promises);
|
||||
gBrowser.removeTab(results[1]);
|
||||
}
|
||||
|
||||
add_task(async function testLearnMoreLink() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () {
|
||||
await ensureLearnMoreLinkWorks(AppMenu());
|
||||
await ensureLearnMoreLinkWorks(HelpMenu());
|
||||
await ensureLearnMoreLinkWorks(ProtectionsPanel());
|
||||
});
|
||||
const telemetry = Glean.webcompatreporting.learnMore.testGetValue();
|
||||
is(telemetry.length, 3, "Got telemetry");
|
||||
});
|
||||
@@ -1,96 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Test that the Report Broken Site menu items are disabled
|
||||
* when the active tab is not on a reportable URL, and is hidden
|
||||
* when the feature is disabled via pref. Also ensure that the
|
||||
* Report Broken Site item that is automatically generated in
|
||||
* the app menu's help sub-menu is hidden.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
add_common_setup();
|
||||
|
||||
add_task(async function testMenus() {
|
||||
ensureReportBrokenSitePreffedOff();
|
||||
|
||||
const appMenu = AppMenu();
|
||||
const menus = [appMenu, ProtectionsPanel(), HelpMenu()];
|
||||
|
||||
async function forceMenuItemStateUpdate() {
|
||||
ReportBrokenSite.enableOrDisableMenuitems(window);
|
||||
|
||||
// the hidden/disabled state of all of the menuitems may not update until one
|
||||
// is rendered; then the related <command>'s state is propagated to them all.
|
||||
await appMenu.open();
|
||||
await appMenu.close();
|
||||
}
|
||||
|
||||
await BrowserTestUtils.withNewTab("about:blank", async function () {
|
||||
await forceMenuItemStateUpdate();
|
||||
for (const { menuDescription, reportBrokenSite } of menus) {
|
||||
isMenuItemHidden(
|
||||
reportBrokenSite,
|
||||
`${menuDescription} option hidden on invalid page when preffed off`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () {
|
||||
await forceMenuItemStateUpdate();
|
||||
for (const { menuDescription, reportBrokenSite } of menus) {
|
||||
isMenuItemHidden(
|
||||
reportBrokenSite,
|
||||
`${menuDescription} option hidden on valid page when preffed off`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
|
||||
await BrowserTestUtils.withNewTab("about:blank", async function () {
|
||||
await forceMenuItemStateUpdate();
|
||||
for (const { menuDescription, reportBrokenSite } of menus) {
|
||||
isMenuItemDisabled(
|
||||
reportBrokenSite,
|
||||
`${menuDescription} option disabled on invalid page when preffed on`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () {
|
||||
await forceMenuItemStateUpdate();
|
||||
for (const { menuDescription, reportBrokenSite } of menus) {
|
||||
isMenuItemEnabled(
|
||||
reportBrokenSite,
|
||||
`${menuDescription} option enabled on valid page when preffed on`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ensureReportBrokenSitePreffedOff();
|
||||
|
||||
await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () {
|
||||
await forceMenuItemStateUpdate();
|
||||
for (const { menuDescription, reportBrokenSite } of menus) {
|
||||
isMenuItemHidden(
|
||||
reportBrokenSite,
|
||||
`${menuDescription} option hidden again when pref toggled back off`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
ensureReportBrokenSiteDisabledByPolicy();
|
||||
|
||||
await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () {
|
||||
await forceMenuItemStateUpdate();
|
||||
for (const { menuDescription, reportBrokenSite } of menus) {
|
||||
isMenuItemHidden(
|
||||
reportBrokenSite,
|
||||
`${menuDescription} option hidden when disabled by DisableFeedbackCommands enterprise policy`
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,56 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Test that the background color of the "report sent"
|
||||
* view is not green in non-default contrast modes.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
add_common_setup();
|
||||
|
||||
const HIGH_CONTRAST_MODE_OFF = [[PREFS.USE_ACCESSIBILITY_THEME, 0]];
|
||||
|
||||
const HIGH_CONTRAST_MODE_ON = [[PREFS.USE_ACCESSIBILITY_THEME, 1]];
|
||||
|
||||
add_task(async function testReportSentViewBGColor() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
ensureReasonDisabled();
|
||||
|
||||
await BrowserTestUtils.withNewTab(
|
||||
REPORTABLE_PAGE_URL,
|
||||
async function (browser) {
|
||||
const { defaultView } = browser.ownerGlobal.document;
|
||||
|
||||
const menu = AppMenu();
|
||||
|
||||
await SpecialPowers.pushPrefEnv({ set: HIGH_CONTRAST_MODE_OFF });
|
||||
const rbs = await menu.openReportBrokenSite();
|
||||
const { mainView, sentView } = rbs;
|
||||
mainView.style.backgroundColor = "var(--background-color-success)";
|
||||
const expectedReportSentBGColor =
|
||||
defaultView.getComputedStyle(mainView).backgroundColor;
|
||||
mainView.style.backgroundColor = "";
|
||||
const expectedPrefersReducedBGColor =
|
||||
defaultView.getComputedStyle(mainView).backgroundColor;
|
||||
|
||||
await rbs.clickSend();
|
||||
is(
|
||||
defaultView.getComputedStyle(sentView).backgroundColor,
|
||||
expectedReportSentBGColor,
|
||||
"Using green bgcolor when not prefers-contrast"
|
||||
);
|
||||
await rbs.clickOkay();
|
||||
|
||||
await SpecialPowers.pushPrefEnv({ set: HIGH_CONTRAST_MODE_ON });
|
||||
await menu.openReportBrokenSite();
|
||||
await rbs.clickSend();
|
||||
is(
|
||||
defaultView.getComputedStyle(sentView).backgroundColor,
|
||||
expectedPrefersReducedBGColor,
|
||||
"Using default bgcolor when prefers-contrast"
|
||||
);
|
||||
await rbs.clickOkay();
|
||||
}
|
||||
);
|
||||
});
|
||||
@@ -1,156 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Tests to ensure that the reason dropdown is shown or hidden
|
||||
* based on its pref, and that its optional and required modes affect
|
||||
* the Send button and report appropriately.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
add_common_setup();
|
||||
|
||||
requestLongerTimeout(2);
|
||||
|
||||
async function clickSendAndCheckPing(rbs, expectedReason = null) {
|
||||
await GleanPings.brokenSiteReport.testSubmission(
|
||||
() =>
|
||||
Assert.equal(
|
||||
Glean.brokenSiteReport.breakageCategory.testGetValue(),
|
||||
expectedReason
|
||||
),
|
||||
() => rbs.clickSend()
|
||||
);
|
||||
}
|
||||
|
||||
add_task(async function testReasonDropdown() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
|
||||
await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () {
|
||||
ensureReasonDisabled();
|
||||
|
||||
let rbs = await AppMenu().openReportBrokenSite();
|
||||
await rbs.isReasonHidden();
|
||||
await rbs.isSendButtonEnabled();
|
||||
await clickSendAndCheckPing(rbs);
|
||||
await rbs.clickOkay();
|
||||
|
||||
ensureReasonOptional();
|
||||
rbs = await AppMenu().openReportBrokenSite();
|
||||
await rbs.isReasonOptional();
|
||||
await rbs.isSendButtonEnabled();
|
||||
await clickSendAndCheckPing(rbs);
|
||||
await rbs.clickOkay();
|
||||
|
||||
rbs = await AppMenu().openReportBrokenSite();
|
||||
await rbs.isReasonOptional();
|
||||
rbs.chooseReason("slow");
|
||||
await rbs.isSendButtonEnabled();
|
||||
await clickSendAndCheckPing(rbs, "slow");
|
||||
await rbs.clickOkay();
|
||||
|
||||
ensureReasonRequired();
|
||||
rbs = await AppMenu().openReportBrokenSite();
|
||||
await rbs.isReasonRequired();
|
||||
await rbs.isSendButtonEnabled();
|
||||
const selectPromise = BrowserTestUtils.waitForSelectPopupShown(window);
|
||||
EventUtils.synthesizeMouseAtCenter(rbs.sendButton, {}, window);
|
||||
await selectPromise;
|
||||
rbs.chooseReason("media");
|
||||
await rbs.dismissDropdownPopup();
|
||||
await rbs.isSendButtonEnabled();
|
||||
await clickSendAndCheckPing(rbs, "media");
|
||||
await rbs.clickOkay();
|
||||
});
|
||||
});
|
||||
|
||||
async function getListItems(rbs) {
|
||||
const items = Array.from(rbs.reasonInput.querySelectorAll("option")).map(i =>
|
||||
i.id.replace("report-broken-site-popup-reason-", "")
|
||||
);
|
||||
Assert.equal(items[0], "choose", "First option is always 'choose'");
|
||||
return items.join(",");
|
||||
}
|
||||
|
||||
add_task(async function testReasonDropdownRandomized() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
ensureReasonOptional();
|
||||
|
||||
const USER_ID_PREF = "app.normandy.user_id";
|
||||
const RANDOMIZE_PREF = "ui.new-webcompat-reporter.reason-dropdown.randomized";
|
||||
|
||||
const origNormandyUserID = Services.prefs.getCharPref(
|
||||
USER_ID_PREF,
|
||||
undefined
|
||||
);
|
||||
|
||||
await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () {
|
||||
// confirm that the default order is initially used
|
||||
Services.prefs.setBoolPref(RANDOMIZE_PREF, false);
|
||||
const rbs = await AppMenu().openReportBrokenSite();
|
||||
const defaultOrder = [
|
||||
"choose",
|
||||
"checkout",
|
||||
"load",
|
||||
"slow",
|
||||
"media",
|
||||
"content",
|
||||
"account",
|
||||
"adblocker",
|
||||
"notsupported",
|
||||
"other",
|
||||
];
|
||||
Assert.deepEqual(
|
||||
await getListItems(rbs),
|
||||
defaultOrder,
|
||||
"non-random order is correct"
|
||||
);
|
||||
|
||||
// confirm that a random order happens per user
|
||||
let randomOrder;
|
||||
let isRandomized = false;
|
||||
Services.prefs.setBoolPref(RANDOMIZE_PREF, true);
|
||||
|
||||
// This becomes ClientEnvironment.randomizationId, which we can set to
|
||||
// any value which results in a different order from the default ordering.
|
||||
Services.prefs.setCharPref("app.normandy.user_id", "dummy");
|
||||
|
||||
// clicking cancel triggers a reset, which is when the randomization
|
||||
// logic is called. so we must click cancel after pref-changes here.
|
||||
rbs.clickCancel();
|
||||
await AppMenu().openReportBrokenSite();
|
||||
randomOrder = await getListItems(rbs);
|
||||
Assert.notEqual(
|
||||
randomOrder,
|
||||
defaultOrder,
|
||||
"options are randomized with pref on"
|
||||
);
|
||||
|
||||
// confirm that the order doesn't change per user
|
||||
isRandomized = false;
|
||||
for (let attempt = 0; attempt < 5; ++attempt) {
|
||||
rbs.clickCancel();
|
||||
await AppMenu().openReportBrokenSite();
|
||||
const order = await getListItems(rbs);
|
||||
|
||||
if (order != randomOrder) {
|
||||
isRandomized = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Assert.ok(!isRandomized, "options keep the same order per user");
|
||||
|
||||
// confirm that the order reverts to the default if pref flipped to false
|
||||
Services.prefs.setBoolPref(RANDOMIZE_PREF, false);
|
||||
rbs.clickCancel();
|
||||
await AppMenu().openReportBrokenSite();
|
||||
Assert.deepEqual(
|
||||
defaultOrder,
|
||||
await getListItems(rbs),
|
||||
"reverts to non-random order correctly"
|
||||
);
|
||||
rbs.clickCancel();
|
||||
});
|
||||
|
||||
Services.prefs.setCharPref(USER_ID_PREF, origNormandyUserID);
|
||||
});
|
||||
@@ -1,79 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Tests to ensure that sending or canceling reports with
|
||||
* the Send and Cancel buttons work (as well as the Okay button)
|
||||
*/
|
||||
|
||||
/* import-globals-from send.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
Services.scriptloader.loadSubScript(
|
||||
getRootDirectory(gTestPath) + "send.js",
|
||||
this
|
||||
);
|
||||
|
||||
add_common_setup();
|
||||
|
||||
requestLongerTimeout(10);
|
||||
|
||||
async function testCancel(menu, url, description) {
|
||||
let rbs = await menu.openAndPrefillReportBrokenSite(url, description);
|
||||
await rbs.clickCancel();
|
||||
ok(!rbs.opened, "clicking Cancel closes Report Broken Site");
|
||||
|
||||
// re-opening the panel, the url and description should be reset
|
||||
rbs = await menu.openReportBrokenSite();
|
||||
rbs.isMainViewResetToCurrentTab();
|
||||
rbs.close();
|
||||
}
|
||||
|
||||
add_task(async function testSendButton() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
ensureReasonOptional();
|
||||
|
||||
const tab1 = await openTab(REPORTABLE_PAGE_URL);
|
||||
|
||||
await testSend(tab1, AppMenu());
|
||||
|
||||
const tab2 = await openTab(REPORTABLE_PAGE_URL);
|
||||
|
||||
await testSend(tab2, ProtectionsPanel(), {
|
||||
url: "https://test.org/test/#fake",
|
||||
breakageCategory: "media",
|
||||
description: "test description",
|
||||
});
|
||||
|
||||
closeTab(tab1);
|
||||
closeTab(tab2);
|
||||
});
|
||||
|
||||
add_task(async function testCancelButton() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
|
||||
const tab1 = await openTab(REPORTABLE_PAGE_URL);
|
||||
|
||||
await testCancel(AppMenu());
|
||||
await testCancel(ProtectionsPanel());
|
||||
await testCancel(HelpMenu());
|
||||
|
||||
const tab2 = await openTab(REPORTABLE_PAGE_URL);
|
||||
|
||||
await testCancel(AppMenu());
|
||||
await testCancel(ProtectionsPanel());
|
||||
await testCancel(HelpMenu());
|
||||
|
||||
const win2 = await BrowserTestUtils.openNewBrowserWindow();
|
||||
const tab3 = await openTab(REPORTABLE_PAGE_URL2, win2);
|
||||
|
||||
await testCancel(AppMenu(win2));
|
||||
await testCancel(ProtectionsPanel(win2));
|
||||
await testCancel(HelpMenu(win2));
|
||||
|
||||
closeTab(tab3);
|
||||
await BrowserTestUtils.closeWindow(win2);
|
||||
|
||||
closeTab(tab1);
|
||||
closeTab(tab2);
|
||||
});
|
||||
@@ -1,65 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Tests that the send more info link appears only when its pref
|
||||
* is set to true, and that when clicked it will open a tab to
|
||||
* the webcompat.com endpoint and send the right data.
|
||||
*/
|
||||
|
||||
/* import-globals-from send_more_info.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
const VIDEO_URL = `${BASE_URL}/videotest.mp4`;
|
||||
|
||||
Services.scriptloader.loadSubScript(
|
||||
getRootDirectory(gTestPath) + "send_more_info.js",
|
||||
this
|
||||
);
|
||||
|
||||
add_common_setup();
|
||||
|
||||
requestLongerTimeout(2);
|
||||
|
||||
add_task(async function testSendMoreInfoPref() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
|
||||
await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () {
|
||||
await changeTab(gBrowser.selectedTab, REPORTABLE_PAGE_URL);
|
||||
|
||||
ensureSendMoreInfoDisabled();
|
||||
let rbs = await AppMenu().openReportBrokenSite();
|
||||
await rbs.isSendMoreInfoHidden();
|
||||
await rbs.close();
|
||||
|
||||
ensureSendMoreInfoEnabled();
|
||||
rbs = await AppMenu().openReportBrokenSite();
|
||||
await rbs.isSendMoreInfoShown();
|
||||
await rbs.close();
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function testSendingMoreInfo() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
ensureSendMoreInfoEnabled();
|
||||
|
||||
const tab = await openTab(REPORTABLE_PAGE_URL);
|
||||
|
||||
await testSendMoreInfo(tab, AppMenu());
|
||||
|
||||
await changeTab(tab, REPORTABLE_PAGE_URL2);
|
||||
|
||||
await testSendMoreInfo(tab, ProtectionsPanel(), {
|
||||
url: "https://override.com",
|
||||
description: "another",
|
||||
expectNoTabDetails: true,
|
||||
});
|
||||
|
||||
// also load a video to ensure system codec
|
||||
// information is loaded and properly sent
|
||||
const tab2 = await openTab(VIDEO_URL);
|
||||
await testSendMoreInfo(tab2, HelpMenu());
|
||||
closeTab(tab2);
|
||||
|
||||
closeTab(tab);
|
||||
});
|
||||
@@ -1,134 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Tests of the expected tab key element focus order */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_common_setup();
|
||||
|
||||
requestLongerTimeout(2);
|
||||
|
||||
async function ensureTabOrder(order, win = window) {
|
||||
const config = { window: win };
|
||||
for (let matches of order) {
|
||||
// We need to tab through all elements in each match array in any order
|
||||
if (!Array.isArray(matches)) {
|
||||
matches = [matches];
|
||||
}
|
||||
let matchesLeft = matches.length;
|
||||
while (matchesLeft--) {
|
||||
const target = await pressKeyAndGetFocus("VK_TAB", config);
|
||||
let foundMatch = false;
|
||||
for (const [i, selector] of matches.entries()) {
|
||||
foundMatch = selector && target.matches(selector);
|
||||
if (foundMatch) {
|
||||
matches[i] = "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
ok(
|
||||
foundMatch,
|
||||
`Expected [${matches}] next, got id=${target.id}, class=${target.className}, ${target}`
|
||||
);
|
||||
if (!foundMatch) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
async function ensureExpectedTabOrder(
|
||||
expectBackButton,
|
||||
expectReason,
|
||||
expectSendMoreInfo
|
||||
) {
|
||||
const { activeElement } = window.document;
|
||||
is(
|
||||
activeElement?.id,
|
||||
"report-broken-site-popup-url",
|
||||
"URL is already focused"
|
||||
);
|
||||
const order = [];
|
||||
if (expectReason) {
|
||||
order.push("#report-broken-site-popup-reason");
|
||||
}
|
||||
order.push("#report-broken-site-popup-description");
|
||||
order.push("#report-broken-site-popup-blocked-trackers-checkbox");
|
||||
if (expectSendMoreInfo) {
|
||||
order.push("#report-broken-site-popup-send-more-info-link");
|
||||
}
|
||||
// moz-button-groups swap the order of buttons to follow
|
||||
// platform conventions, so the order of send/cancel will vary.
|
||||
order.push([
|
||||
"#report-broken-site-popup-cancel-button",
|
||||
"#report-broken-site-popup-send-button",
|
||||
]);
|
||||
if (expectBackButton) {
|
||||
order.push(".subviewbutton-back");
|
||||
}
|
||||
order.push("#report-broken-site-popup-learn-more-link");
|
||||
order.push("#report-broken-site-popup-url"); // check that we've cycled back
|
||||
return ensureTabOrder(order);
|
||||
}
|
||||
|
||||
async function testTabOrder(menu) {
|
||||
ensureReasonDisabled();
|
||||
ensureSendMoreInfoDisabled();
|
||||
|
||||
const { showsBackButton } = menu;
|
||||
|
||||
let rbs = await menu.openReportBrokenSite();
|
||||
await ensureExpectedTabOrder(showsBackButton, false, false);
|
||||
await rbs.close();
|
||||
|
||||
ensureSendMoreInfoEnabled();
|
||||
rbs = await menu.openReportBrokenSite();
|
||||
await ensureExpectedTabOrder(showsBackButton, false, true);
|
||||
await rbs.close();
|
||||
|
||||
ensureReasonOptional();
|
||||
rbs = await menu.openReportBrokenSite();
|
||||
await ensureExpectedTabOrder(showsBackButton, true, true);
|
||||
await rbs.close();
|
||||
|
||||
ensureReasonRequired();
|
||||
rbs = await menu.openReportBrokenSite();
|
||||
await ensureExpectedTabOrder(showsBackButton, true, true);
|
||||
await rbs.close();
|
||||
rbs = await menu.openReportBrokenSite();
|
||||
rbs.chooseReason("slow");
|
||||
await ensureExpectedTabOrder(showsBackButton, true, true);
|
||||
await rbs.clickCancel();
|
||||
|
||||
ensureSendMoreInfoDisabled();
|
||||
rbs = await menu.openReportBrokenSite();
|
||||
await ensureExpectedTabOrder(showsBackButton, true, false);
|
||||
await rbs.close();
|
||||
rbs = await menu.openReportBrokenSite();
|
||||
rbs.chooseReason("slow");
|
||||
await ensureExpectedTabOrder(showsBackButton, true, false);
|
||||
await rbs.clickCancel();
|
||||
|
||||
ensureReasonOptional();
|
||||
rbs = await menu.openReportBrokenSite();
|
||||
await ensureExpectedTabOrder(showsBackButton, true, false);
|
||||
await rbs.close();
|
||||
|
||||
ensureReasonDisabled();
|
||||
rbs = await menu.openReportBrokenSite();
|
||||
await ensureExpectedTabOrder(showsBackButton, false, false);
|
||||
await rbs.close();
|
||||
}
|
||||
|
||||
add_task(async function testTabOrdering() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
ensureSendMoreInfoEnabled();
|
||||
|
||||
await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () {
|
||||
await testTabOrder(AppMenu());
|
||||
await testTabOrder(ProtectionsPanel());
|
||||
await testTabOrder(HelpMenu());
|
||||
});
|
||||
});
|
||||
@@ -1,81 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Tests to ensure that Report Broken Site popups will be
|
||||
* reset to whichever tab the user is on as they change
|
||||
* between windows and tabs. */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_common_setup();
|
||||
|
||||
add_task(async function testResetsProperlyOnTabSwitch() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
|
||||
const badTab = await openTab("about:blank");
|
||||
const goodTab1 = await openTab(REPORTABLE_PAGE_URL);
|
||||
const goodTab2 = await openTab(REPORTABLE_PAGE_URL2);
|
||||
|
||||
const appMenu = AppMenu();
|
||||
const protPanel = ProtectionsPanel();
|
||||
|
||||
let rbs = await appMenu.openReportBrokenSite();
|
||||
rbs.isMainViewResetToCurrentTab();
|
||||
rbs.close();
|
||||
|
||||
gBrowser.selectedTab = goodTab1;
|
||||
|
||||
rbs = await protPanel.openReportBrokenSite();
|
||||
rbs.isMainViewResetToCurrentTab();
|
||||
rbs.close();
|
||||
|
||||
gBrowser.selectedTab = badTab;
|
||||
await appMenu.open();
|
||||
appMenu.isReportBrokenSiteDisabled();
|
||||
await appMenu.close();
|
||||
|
||||
gBrowser.selectedTab = goodTab1;
|
||||
rbs = await protPanel.openReportBrokenSite();
|
||||
rbs.isMainViewResetToCurrentTab();
|
||||
rbs.close();
|
||||
|
||||
closeTab(badTab);
|
||||
closeTab(goodTab1);
|
||||
closeTab(goodTab2);
|
||||
});
|
||||
|
||||
add_task(async function testResetsProperlyOnWindowSwitch() {
|
||||
ensureReportBrokenSitePreffedOn();
|
||||
|
||||
const tab1 = await openTab(REPORTABLE_PAGE_URL);
|
||||
|
||||
const win2 = await BrowserTestUtils.openNewBrowserWindow();
|
||||
const tab2 = await openTab(REPORTABLE_PAGE_URL2, win2);
|
||||
|
||||
const appMenu1 = AppMenu();
|
||||
const appMenu2 = ProtectionsPanel(win2);
|
||||
|
||||
let rbs2 = await appMenu2.openReportBrokenSite();
|
||||
rbs2.isMainViewResetToCurrentTab();
|
||||
rbs2.close();
|
||||
|
||||
// flip back to tab1's window and ensure its URL pops up instead of tab2's URL
|
||||
await switchToWindow(window);
|
||||
isSelectedTab(window, tab1); // sanity check
|
||||
|
||||
let rbs1 = await appMenu1.openReportBrokenSite();
|
||||
rbs1.isMainViewResetToCurrentTab();
|
||||
rbs1.close();
|
||||
|
||||
// likewise flip back to tab2's window and ensure its URL pops up instead of tab1's URL
|
||||
await switchToWindow(win2);
|
||||
isSelectedTab(win2, tab2); // sanity check
|
||||
|
||||
rbs2 = await appMenu2.openReportBrokenSite();
|
||||
rbs2.isMainViewResetToCurrentTab();
|
||||
rbs2.close();
|
||||
|
||||
closeTab(tab1);
|
||||
closeTab(tab2);
|
||||
await BrowserTestUtils.closeWindow(win2);
|
||||
});
|
||||
@@ -1,45 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Tests that when Report Broken Site is disabled, it will
|
||||
* send the user to webcompat.com when clicked and it the
|
||||
* relevant tab's report data.
|
||||
*/
|
||||
|
||||
/* import-globals-from send_more_info.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
Services.scriptloader.loadSubScript(
|
||||
getRootDirectory(gTestPath) + "send_more_info.js",
|
||||
this
|
||||
);
|
||||
|
||||
add_common_setup();
|
||||
|
||||
const VIDEO_URL = `${BASE_URL}/videotest.mp4`;
|
||||
|
||||
add_setup(async function () {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["test.wait300msAfterTabSwitch", true]],
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function testWebcompatComFallbacks() {
|
||||
ensureReportBrokenSitePreffedOff();
|
||||
|
||||
const tab = await openTab(REPORTABLE_PAGE_URL);
|
||||
|
||||
await testWebcompatComFallback(tab, AppMenu());
|
||||
|
||||
await changeTab(tab, REPORTABLE_PAGE_URL2);
|
||||
await testWebcompatComFallback(tab, ProtectionsPanel());
|
||||
|
||||
// also load a video to ensure system codec
|
||||
// information is loaded and properly sent
|
||||
const tab2 = await openTab(VIDEO_URL);
|
||||
await testWebcompatComFallback(tab2, HelpMenu());
|
||||
closeTab(tab2);
|
||||
|
||||
closeTab(tab);
|
||||
});
|
||||
@@ -1,22 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!-- 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/. -->
|
||||
<html dir="ltr" xml:lang="en-US" lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<script>
|
||||
window.marfeel = 1;
|
||||
window.Mobify = { Tag: 1 };
|
||||
window.FastClick = 1;
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- blocked tracking content -->
|
||||
<iframe src="https://trackertest.org/"></iframe>
|
||||
<!-- mixed active content -->
|
||||
<iframe src="http://tracking.example.org/browser/browser/base/content/test/protectionsUI/benignPage.html"></iframe>
|
||||
<!-- mixed display content -->
|
||||
<img src="http://example.com/tests/image/test/mochitest/blue.png"></img>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,922 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const { CustomizableUITestUtils } = ChromeUtils.importESModule(
|
||||
"resource://testing-common/CustomizableUITestUtils.sys.mjs"
|
||||
);
|
||||
|
||||
const { EnterprisePolicyTesting, PoliciesPrefTracker } =
|
||||
ChromeUtils.importESModule(
|
||||
"resource://testing-common/EnterprisePolicyTesting.sys.mjs"
|
||||
);
|
||||
|
||||
const { UrlClassifierTestUtils } = ChromeUtils.importESModule(
|
||||
"resource://testing-common/UrlClassifierTestUtils.sys.mjs"
|
||||
);
|
||||
|
||||
const { ReportBrokenSite } = ChromeUtils.importESModule(
|
||||
"moz-src:///browser/components/reportbrokensite/ReportBrokenSite.sys.mjs"
|
||||
);
|
||||
|
||||
const BASE_URL =
|
||||
"https://example.com/browser/browser/components/reportbrokensite/test/browser/";
|
||||
|
||||
const REPORTABLE_PAGE_URL = "https://example.com";
|
||||
|
||||
const REPORTABLE_PAGE_URL2 = REPORTABLE_PAGE_URL.replace(".com", ".org");
|
||||
|
||||
const REPORTABLE_PAGE_URL3 = `${BASE_URL}example_report_page.html`;
|
||||
|
||||
const SUMO_BASE_URL = Services.urlFormatter.formatURLPref(
|
||||
"app.support.baseURL"
|
||||
);
|
||||
const LEARN_MORE_TEST_URL = `${SUMO_BASE_URL}report-broken-site`;
|
||||
|
||||
const NEW_REPORT_ENDPOINT_TEST_URL = `${BASE_URL}sendMoreInfoTestEndpoint.html`;
|
||||
|
||||
const PREFS = {
|
||||
DATAREPORTING_ENABLED: "datareporting.healthreport.uploadEnabled",
|
||||
REPORTER_ENABLED: "ui.new-webcompat-reporter.enabled",
|
||||
REASON: "ui.new-webcompat-reporter.reason-dropdown",
|
||||
SEND_MORE_INFO: "ui.new-webcompat-reporter.send-more-info-link",
|
||||
NEW_REPORT_ENDPOINT: "ui.new-webcompat-reporter.new-report-endpoint",
|
||||
TOUCH_EVENTS: "dom.w3c_touch_events.enabled",
|
||||
USE_ACCESSIBILITY_THEME: "ui.useAccessibilityTheme",
|
||||
};
|
||||
|
||||
function add_common_setup() {
|
||||
add_setup(async function () {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
[PREFS.NEW_REPORT_ENDPOINT, NEW_REPORT_ENDPOINT_TEST_URL],
|
||||
|
||||
// set touch events to auto-detect, as the pref gets set to 1 somewhere
|
||||
// while tests are running, making hasTouchScreen checks unreliable.
|
||||
[PREFS.TOUCH_EVENTS, 2],
|
||||
],
|
||||
});
|
||||
registerCleanupFunction(function () {
|
||||
for (const prefName of Object.values(PREFS)) {
|
||||
Services.prefs.clearUserPref(prefName);
|
||||
}
|
||||
Services.telemetry.clearEvents();
|
||||
Services.fog.testResetFOG();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function areObjectsEqual(actual, expected, path = "") {
|
||||
if (typeof expected == "function") {
|
||||
try {
|
||||
const passes = expected(actual);
|
||||
if (!passes) {
|
||||
info(`${path} not pass check function: ${actual}`);
|
||||
}
|
||||
return passes;
|
||||
} catch (e) {
|
||||
info(`${path} threw exception:
|
||||
got: ${typeof actual}, ${actual}
|
||||
expected: ${typeof expected}, ${expected}
|
||||
exception: ${e.message}
|
||||
${e.stack}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof actual != typeof expected) {
|
||||
info(`${path} types do not match:
|
||||
got: ${typeof actual}, ${actual}
|
||||
expected: ${typeof expected}, ${expected}`);
|
||||
return false;
|
||||
}
|
||||
if (typeof actual != "object" || actual === null || expected === null) {
|
||||
if (actual !== expected) {
|
||||
info(`${path} does not match
|
||||
got: ${typeof actual}, ${actual}
|
||||
expected: ${typeof expected}, ${expected}`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
const prefix = path ? `${path}.` : path;
|
||||
for (const [key, val] of Object.entries(actual)) {
|
||||
if (!(key in expected)) {
|
||||
info(`Extra ${prefix}${key}: ${val}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
let result = true;
|
||||
for (const [key, expectedVal] of Object.entries(expected)) {
|
||||
if (key in actual) {
|
||||
if (!areObjectsEqual(actual[key], expectedVal, `${prefix}${key}`)) {
|
||||
result = false;
|
||||
}
|
||||
} else {
|
||||
info(`Missing ${prefix}${key} (${expectedVal})`);
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function clickAndAwait(toClick, evt, target) {
|
||||
const menuPromise = BrowserTestUtils.waitForEvent(target, evt);
|
||||
EventUtils.synthesizeMouseAtCenter(toClick, {}, window);
|
||||
return menuPromise;
|
||||
}
|
||||
|
||||
async function openTab(url, win) {
|
||||
const options = {
|
||||
gBrowser:
|
||||
win?.gBrowser ||
|
||||
Services.wm.getMostRecentWindow("navigator:browser").gBrowser,
|
||||
url,
|
||||
};
|
||||
return BrowserTestUtils.openNewForegroundTab(options);
|
||||
}
|
||||
|
||||
async function changeTab(tab, url) {
|
||||
BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, url);
|
||||
await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
|
||||
}
|
||||
|
||||
function closeTab(tab) {
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
}
|
||||
|
||||
function switchToWindow(win) {
|
||||
const promises = [
|
||||
BrowserTestUtils.waitForEvent(win, "focus"),
|
||||
BrowserTestUtils.waitForEvent(win, "activate"),
|
||||
];
|
||||
win.focus();
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
function isSelectedTab(win, tab) {
|
||||
const selectedTab = win.document.querySelector(".tabbrowser-tab[selected]");
|
||||
is(selectedTab, tab);
|
||||
}
|
||||
|
||||
async function setupPolicyEngineWithJson(json, customSchema) {
|
||||
PoliciesPrefTracker.restoreDefaultValues();
|
||||
if (typeof json != "object") {
|
||||
let filePath = getTestFilePath(json ? json : "non-existing-file.json");
|
||||
return EnterprisePolicyTesting.setupPolicyEngineWithJson(
|
||||
filePath,
|
||||
customSchema
|
||||
);
|
||||
}
|
||||
return EnterprisePolicyTesting.setupPolicyEngineWithJson(json, customSchema);
|
||||
}
|
||||
|
||||
async function ensureReportBrokenSiteDisabledByPolicy() {
|
||||
await setupPolicyEngineWithJson({
|
||||
policies: {
|
||||
DisableFeedbackCommands: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
registerCleanupFunction(async function resetPolicies() {
|
||||
if (Services.policies.status != Ci.nsIEnterprisePolicies.INACTIVE) {
|
||||
await setupPolicyEngineWithJson("");
|
||||
}
|
||||
EnterprisePolicyTesting.resetRunOnceState();
|
||||
PoliciesPrefTracker.restoreDefaultValues();
|
||||
PoliciesPrefTracker.stop();
|
||||
});
|
||||
|
||||
function ensureReportBrokenSitePreffedOn() {
|
||||
Services.prefs.setBoolPref(PREFS.DATAREPORTING_ENABLED, true);
|
||||
Services.prefs.setBoolPref(PREFS.REPORTER_ENABLED, true);
|
||||
ensureReasonDisabled();
|
||||
}
|
||||
|
||||
function ensureReportBrokenSitePreffedOff() {
|
||||
Services.prefs.setBoolPref(PREFS.REPORTER_ENABLED, false);
|
||||
}
|
||||
|
||||
function ensureSendMoreInfoEnabled() {
|
||||
Services.prefs.setBoolPref(PREFS.SEND_MORE_INFO, true);
|
||||
}
|
||||
|
||||
function ensureSendMoreInfoDisabled() {
|
||||
Services.prefs.setBoolPref(PREFS.SEND_MORE_INFO, false);
|
||||
}
|
||||
|
||||
function ensureReasonDisabled() {
|
||||
Services.prefs.setIntPref(PREFS.REASON, 0);
|
||||
}
|
||||
|
||||
function ensureReasonOptional() {
|
||||
Services.prefs.setIntPref(PREFS.REASON, 1);
|
||||
}
|
||||
|
||||
function ensureReasonRequired() {
|
||||
Services.prefs.setIntPref(PREFS.REASON, 2);
|
||||
}
|
||||
|
||||
function isMenuItemEnabled(menuItem, itemDesc) {
|
||||
ok(!menuItem.hidden, `${itemDesc} menu item is shown`);
|
||||
ok(!menuItem.disabled, `${itemDesc} menu item is enabled`);
|
||||
}
|
||||
|
||||
function isMenuItemHidden(menuItem, itemDesc) {
|
||||
ok(
|
||||
!menuItem || menuItem.hidden || !BrowserTestUtils.isVisible(menuItem),
|
||||
`${itemDesc} menu item is hidden`
|
||||
);
|
||||
}
|
||||
|
||||
function isMenuItemDisabled(menuItem, itemDesc) {
|
||||
ok(!menuItem.hidden, `${itemDesc} menu item is shown`);
|
||||
ok(menuItem.disabled, `${itemDesc} menu item is disabled`);
|
||||
}
|
||||
|
||||
function waitForWebcompatComTab(gBrowser) {
|
||||
return BrowserTestUtils.waitForNewTab(gBrowser, NEW_REPORT_ENDPOINT_TEST_URL);
|
||||
}
|
||||
|
||||
class ReportBrokenSiteHelper {
|
||||
sourceMenu = undefined;
|
||||
win = undefined;
|
||||
|
||||
constructor(sourceMenu) {
|
||||
this.sourceMenu = sourceMenu;
|
||||
this.win = sourceMenu.win;
|
||||
}
|
||||
|
||||
getViewNode(id) {
|
||||
return PanelMultiView.getViewNode(this.win.document, id);
|
||||
}
|
||||
|
||||
get mainView() {
|
||||
return this.getViewNode("report-broken-site-popup-mainView");
|
||||
}
|
||||
|
||||
get sentView() {
|
||||
return this.getViewNode("report-broken-site-popup-reportSentView");
|
||||
}
|
||||
|
||||
get openPanel() {
|
||||
return this.mainView?.closest("panel");
|
||||
}
|
||||
|
||||
get opened() {
|
||||
return this.openPanel?.hasAttribute("panelopen");
|
||||
}
|
||||
|
||||
async click(triggerMenuItem) {
|
||||
const window = triggerMenuItem.ownerGlobal;
|
||||
await EventUtils.synthesizeMouseAtCenter(triggerMenuItem, {}, window);
|
||||
}
|
||||
|
||||
async open(triggerMenuItem) {
|
||||
const shownPromise = BrowserTestUtils.waitForEvent(
|
||||
this.mainView,
|
||||
"ViewShown"
|
||||
);
|
||||
const focusPromise = BrowserTestUtils.waitForEvent(this.URLInput, "focus");
|
||||
await this.click(triggerMenuItem);
|
||||
await shownPromise;
|
||||
await focusPromise;
|
||||
await BrowserTestUtils.waitForCondition(
|
||||
() => this.URLInput.selectionStart === 0
|
||||
);
|
||||
}
|
||||
|
||||
async #assertClickAndViewChanges(button, view, newView, newFocus) {
|
||||
ok(view.closest("panel").hasAttribute("panelopen"), "Panel is open");
|
||||
ok(BrowserTestUtils.isVisible(button), "Button is visible");
|
||||
ok(!button.disabled, "Button is enabled");
|
||||
const promises = [];
|
||||
if (newView) {
|
||||
if (newView.nodeName == "panel") {
|
||||
promises.push(BrowserTestUtils.waitForEvent(newView, "popupshown"));
|
||||
} else {
|
||||
promises.push(BrowserTestUtils.waitForEvent(newView, "ViewShown"));
|
||||
}
|
||||
} else {
|
||||
promises.push(BrowserTestUtils.waitForEvent(view, "ViewHiding"));
|
||||
}
|
||||
if (newFocus) {
|
||||
promises.push(BrowserTestUtils.waitForEvent(newFocus, "focus"));
|
||||
}
|
||||
EventUtils.synthesizeMouseAtCenter(button, {}, this.win);
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
async awaitReportSentViewOpened() {
|
||||
await Promise.all([
|
||||
BrowserTestUtils.waitForEvent(this.sentView, "ViewShown"),
|
||||
BrowserTestUtils.waitForEvent(this.okayButton, "focus"),
|
||||
]);
|
||||
}
|
||||
|
||||
async clickSend() {
|
||||
await this.#assertClickAndViewChanges(
|
||||
this.sendButton,
|
||||
this.mainView,
|
||||
this.sentView,
|
||||
this.okayButton
|
||||
);
|
||||
}
|
||||
|
||||
waitForSendMoreInfoTab() {
|
||||
return BrowserTestUtils.waitForNewTab(
|
||||
this.win.gBrowser,
|
||||
NEW_REPORT_ENDPOINT_TEST_URL
|
||||
);
|
||||
}
|
||||
|
||||
async clickSendMoreInfo() {
|
||||
const newTabPromise = waitForWebcompatComTab(this.win.gBrowser);
|
||||
EventUtils.synthesizeMouseAtCenter(this.sendMoreInfoLink, {}, this.win);
|
||||
const newTab = await newTabPromise;
|
||||
const receivedData = await SpecialPowers.spawn(
|
||||
newTab.linkedBrowser,
|
||||
[],
|
||||
async function () {
|
||||
await content.wrappedJSObject.messageArrived;
|
||||
return content.wrappedJSObject.message;
|
||||
}
|
||||
);
|
||||
this.win.gBrowser.removeCurrentTab();
|
||||
return receivedData;
|
||||
}
|
||||
|
||||
async clickCancel() {
|
||||
await this.#assertClickAndViewChanges(this.cancelButton, this.mainView);
|
||||
}
|
||||
|
||||
async clickOkay() {
|
||||
await this.#assertClickAndViewChanges(this.okayButton, this.sentView);
|
||||
}
|
||||
|
||||
async clickBack() {
|
||||
await this.#assertClickAndViewChanges(
|
||||
this.backButton,
|
||||
this.sourceMenu.popup
|
||||
);
|
||||
}
|
||||
|
||||
isBackButtonEnabled() {
|
||||
ok(BrowserTestUtils.isVisible(this.backButton), "Back button is visible");
|
||||
ok(!this.backButton.disabled, "Back button is enabled");
|
||||
}
|
||||
|
||||
close() {
|
||||
if (this.opened) {
|
||||
this.openPanel?.hidePopup(false);
|
||||
}
|
||||
this.sourceMenu?.close();
|
||||
}
|
||||
|
||||
// UI element getters
|
||||
get URLInput() {
|
||||
return this.getViewNode("report-broken-site-popup-url");
|
||||
}
|
||||
|
||||
get URLInvalidMessage() {
|
||||
return this.getViewNode("report-broken-site-popup-invalid-url-msg");
|
||||
}
|
||||
|
||||
get reasonInput() {
|
||||
return this.getViewNode("report-broken-site-popup-reason");
|
||||
}
|
||||
|
||||
get reasonDropdownPopup() {
|
||||
return this.win.document.getElementById("ContentSelectDropdown").menupopup;
|
||||
}
|
||||
|
||||
get reasonRequiredMessage() {
|
||||
return this.getViewNode("report-broken-site-popup-missing-reason-msg");
|
||||
}
|
||||
|
||||
get reasonLabelRequired() {
|
||||
return this.getViewNode("report-broken-site-popup-reason-label");
|
||||
}
|
||||
|
||||
get reasonLabelOptional() {
|
||||
return this.getViewNode("report-broken-site-popup-reason-optional-label");
|
||||
}
|
||||
|
||||
get descriptionTextarea() {
|
||||
return this.getViewNode("report-broken-site-popup-description");
|
||||
}
|
||||
|
||||
get learnMoreLink() {
|
||||
return this.getViewNode("report-broken-site-popup-learn-more-link");
|
||||
}
|
||||
|
||||
get sendMoreInfoLink() {
|
||||
return this.getViewNode("report-broken-site-popup-send-more-info-link");
|
||||
}
|
||||
|
||||
get backButton() {
|
||||
return this.mainView.querySelector(".subviewbutton-back");
|
||||
}
|
||||
|
||||
get blockedTrackersCheckbox() {
|
||||
return this.getViewNode(
|
||||
"report-broken-site-popup-blocked-trackers-checkbox"
|
||||
);
|
||||
}
|
||||
|
||||
set blockedTrackersCheckbox(checked) {
|
||||
this.blockedTrackersCheckbox.checked = checked;
|
||||
}
|
||||
|
||||
get sendButton() {
|
||||
return this.getViewNode("report-broken-site-popup-send-button");
|
||||
}
|
||||
|
||||
get cancelButton() {
|
||||
return this.getViewNode("report-broken-site-popup-cancel-button");
|
||||
}
|
||||
|
||||
get okayButton() {
|
||||
return this.getViewNode("report-broken-site-popup-okay-button");
|
||||
}
|
||||
|
||||
// Test helpers
|
||||
|
||||
#setInput(input, value) {
|
||||
input.value = value;
|
||||
input.dispatchEvent(
|
||||
new UIEvent("input", { bubbles: true, view: this.win })
|
||||
);
|
||||
}
|
||||
|
||||
setURL(value) {
|
||||
this.#setInput(this.URLInput, value);
|
||||
}
|
||||
|
||||
chooseReason(value) {
|
||||
const item = this.getViewNode(`report-broken-site-popup-reason-${value}`);
|
||||
this.reasonInput.selectedIndex = item.index;
|
||||
}
|
||||
|
||||
dismissDropdownPopup() {
|
||||
const popup = this.reasonDropdownPopup;
|
||||
const menuPromise = BrowserTestUtils.waitForPopupEvent(popup, "hidden");
|
||||
popup.hidePopup();
|
||||
return menuPromise;
|
||||
}
|
||||
|
||||
setDescription(value) {
|
||||
this.#setInput(this.descriptionTextarea, value);
|
||||
}
|
||||
|
||||
isURL(expected) {
|
||||
is(this.URLInput.value, expected);
|
||||
}
|
||||
|
||||
isURLInvalidMessageShown() {
|
||||
ok(
|
||||
BrowserTestUtils.isVisible(this.URLInvalidMessage),
|
||||
"'Please enter a valid URL' message is shown"
|
||||
);
|
||||
}
|
||||
|
||||
isURLInvalidMessageHidden() {
|
||||
ok(
|
||||
!BrowserTestUtils.isVisible(this.URLInvalidMessage),
|
||||
"'Please enter a valid URL' message is hidden"
|
||||
);
|
||||
}
|
||||
|
||||
isReasonNeededMessageShown() {
|
||||
ok(
|
||||
BrowserTestUtils.isVisible(this.reasonRequiredMessage),
|
||||
"'Please choose a reason' message is shown"
|
||||
);
|
||||
}
|
||||
|
||||
isReasonNeededMessageHidden() {
|
||||
ok(
|
||||
!BrowserTestUtils.isVisible(this.reasonRequiredMessage),
|
||||
"'Please choose a reason' message is hidden"
|
||||
);
|
||||
}
|
||||
|
||||
isSendButtonEnabled() {
|
||||
ok(BrowserTestUtils.isVisible(this.sendButton), "Send button is visible");
|
||||
ok(!this.sendButton.disabled, "Send button is enabled");
|
||||
}
|
||||
|
||||
isSendButtonDisabled() {
|
||||
ok(BrowserTestUtils.isVisible(this.sendButton), "Send button is visible");
|
||||
ok(this.sendButton.disabled, "Send button is disabled");
|
||||
}
|
||||
|
||||
isSendMoreInfoShown() {
|
||||
ok(
|
||||
BrowserTestUtils.isVisible(this.sendMoreInfoLink),
|
||||
"send more info is shown"
|
||||
);
|
||||
}
|
||||
|
||||
isSendMoreInfoHidden() {
|
||||
ok(
|
||||
!BrowserTestUtils.isVisible(this.sendMoreInfoLink),
|
||||
"send more info is hidden"
|
||||
);
|
||||
}
|
||||
|
||||
isSendMoreInfoShownOrHiddenAppropriately() {
|
||||
if (Services.prefs.getBoolPref(PREFS.SEND_MORE_INFO)) {
|
||||
this.isSendMoreInfoShown();
|
||||
} else {
|
||||
this.isSendMoreInfoHidden();
|
||||
}
|
||||
}
|
||||
|
||||
isReasonHidden() {
|
||||
ok(
|
||||
!BrowserTestUtils.isVisible(this.reasonInput),
|
||||
"reason drop-down is hidden"
|
||||
);
|
||||
ok(
|
||||
!BrowserTestUtils.isVisible(this.reasonLabelOptional),
|
||||
"optional reason label is hidden"
|
||||
);
|
||||
ok(
|
||||
!BrowserTestUtils.isVisible(this.reasonLabelRequired),
|
||||
"required reason label is hidden"
|
||||
);
|
||||
}
|
||||
|
||||
isReasonRequired() {
|
||||
ok(
|
||||
BrowserTestUtils.isVisible(this.reasonInput),
|
||||
"reason drop-down is shown"
|
||||
);
|
||||
ok(
|
||||
!BrowserTestUtils.isVisible(this.reasonLabelOptional),
|
||||
"optional reason label is hidden"
|
||||
);
|
||||
ok(
|
||||
BrowserTestUtils.isVisible(this.reasonLabelRequired),
|
||||
"required reason label is shown"
|
||||
);
|
||||
}
|
||||
|
||||
isReasonOptional() {
|
||||
ok(
|
||||
BrowserTestUtils.isVisible(this.reasonInput),
|
||||
"reason drop-down is shown"
|
||||
);
|
||||
ok(
|
||||
BrowserTestUtils.isVisible(this.reasonLabelOptional),
|
||||
"optional reason label is shown"
|
||||
);
|
||||
ok(
|
||||
!BrowserTestUtils.isVisible(this.reasonLabelRequired),
|
||||
"required reason label is hidden"
|
||||
);
|
||||
}
|
||||
|
||||
isReasonShownOrHiddenAppropriately() {
|
||||
const pref = Services.prefs.getIntPref(PREFS.REASON);
|
||||
if (pref == 2) {
|
||||
this.isReasonOptional();
|
||||
} else if (pref == 1) {
|
||||
this.isReasonOptional();
|
||||
} else {
|
||||
this.isReasonHidden();
|
||||
}
|
||||
}
|
||||
|
||||
isDescription(expected) {
|
||||
return this.descriptionTextarea.value == expected;
|
||||
}
|
||||
|
||||
isMainViewResetToCurrentTab() {
|
||||
this.isURL(this.win.gBrowser.selectedBrowser.currentURI.spec);
|
||||
this.isDescription("");
|
||||
this.isReasonShownOrHiddenAppropriately();
|
||||
this.isSendMoreInfoShownOrHiddenAppropriately();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class MenuHelper {
|
||||
menuDescription = undefined;
|
||||
|
||||
win = undefined;
|
||||
|
||||
constructor(win = window) {
|
||||
this.win = win;
|
||||
}
|
||||
|
||||
getViewNode(id) {
|
||||
return PanelMultiView.getViewNode(this.win.document, id);
|
||||
}
|
||||
|
||||
get showsBackButton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
get reportBrokenSite() {
|
||||
throw new Error("Should be defined in derived class");
|
||||
}
|
||||
|
||||
get popup() {
|
||||
throw new Error("Should be defined in derived class");
|
||||
}
|
||||
|
||||
get opened() {
|
||||
return this.popup?.hasAttribute("panelopen");
|
||||
}
|
||||
|
||||
async open() {}
|
||||
|
||||
async close() {}
|
||||
|
||||
isReportBrokenSiteDisabled() {
|
||||
return isMenuItemDisabled(this.reportBrokenSite, this.menuDescription);
|
||||
}
|
||||
|
||||
isReportBrokenSiteEnabled() {
|
||||
return isMenuItemEnabled(this.reportBrokenSite, this.menuDescription);
|
||||
}
|
||||
|
||||
isReportBrokenSiteHidden() {
|
||||
return isMenuItemHidden(this.reportBrokenSite, this.menuDescription);
|
||||
}
|
||||
|
||||
async clickReportBrokenSiteAndAwaitWebCompatTabData() {
|
||||
const newTabPromise = waitForWebcompatComTab(this.win.gBrowser);
|
||||
await this.clickReportBrokenSite();
|
||||
const newTab = await newTabPromise;
|
||||
const receivedData = await SpecialPowers.spawn(
|
||||
newTab.linkedBrowser,
|
||||
[],
|
||||
async function () {
|
||||
await content.wrappedJSObject.messageArrived;
|
||||
return content.wrappedJSObject.message;
|
||||
}
|
||||
);
|
||||
|
||||
this.win.gBrowser.removeCurrentTab();
|
||||
return receivedData;
|
||||
}
|
||||
|
||||
async clickReportBrokenSite() {
|
||||
if (!this.opened) {
|
||||
await this.open();
|
||||
}
|
||||
isMenuItemEnabled(this.reportBrokenSite, this.menuDescription);
|
||||
const rbs = new ReportBrokenSiteHelper(this);
|
||||
await rbs.click(this.reportBrokenSite);
|
||||
return rbs;
|
||||
}
|
||||
|
||||
async openReportBrokenSite() {
|
||||
if (!this.opened) {
|
||||
await this.open();
|
||||
}
|
||||
isMenuItemEnabled(this.reportBrokenSite, this.menuDescription);
|
||||
const rbs = new ReportBrokenSiteHelper(this);
|
||||
await rbs.open(this.reportBrokenSite);
|
||||
return rbs;
|
||||
}
|
||||
|
||||
async openAndPrefillReportBrokenSite(url = null, description = "") {
|
||||
let rbs = await this.openReportBrokenSite();
|
||||
rbs.isMainViewResetToCurrentTab();
|
||||
if (url) {
|
||||
rbs.setURL(url);
|
||||
}
|
||||
if (description) {
|
||||
rbs.setDescription(description);
|
||||
}
|
||||
return rbs;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class AppMenuHelper extends MenuHelper {
|
||||
menuDescription = "AppMenu";
|
||||
|
||||
get reportBrokenSite() {
|
||||
return this.getViewNode("appMenu-report-broken-site-button");
|
||||
}
|
||||
|
||||
get popup() {
|
||||
return this.win.document.getElementById("appMenu-popup");
|
||||
}
|
||||
|
||||
async open() {
|
||||
await new CustomizableUITestUtils(this.win).openMainMenu();
|
||||
}
|
||||
|
||||
async close() {
|
||||
if (this.opened) {
|
||||
await new CustomizableUITestUtils(this.win).hideMainMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class HelpMenuHelper extends MenuHelper {
|
||||
menuDescription = "Help Menu";
|
||||
|
||||
get showsBackButton() {
|
||||
return false;
|
||||
}
|
||||
|
||||
get reportBrokenSite() {
|
||||
return this.win.document.getElementById("help_reportBrokenSite");
|
||||
}
|
||||
|
||||
get popup() {
|
||||
return this.getViewNode("PanelUI-helpView");
|
||||
}
|
||||
|
||||
get helpMenu() {
|
||||
return this.win.document.getElementById("menu_HelpPopup");
|
||||
}
|
||||
|
||||
async openReportBrokenSite() {
|
||||
// We can't actually open the Help menu properly in testing, so the best
|
||||
// we can do to open its Report Broken Site panel is to force its DOM to be
|
||||
// prepared, and then soft-click the Report Broken Site menuitem to open it.
|
||||
await this.open();
|
||||
const shownPromise = BrowserTestUtils.waitForEvent(
|
||||
this.win,
|
||||
"ViewShown",
|
||||
true,
|
||||
e => e.target.classList.contains("report-broken-site-view")
|
||||
);
|
||||
this.reportBrokenSite.click();
|
||||
await shownPromise;
|
||||
return new ReportBrokenSiteHelper(this);
|
||||
}
|
||||
|
||||
async clickReportBrokenSite() {
|
||||
await this.open();
|
||||
this.reportBrokenSite.click();
|
||||
return new ReportBrokenSiteHelper(this);
|
||||
}
|
||||
|
||||
async open() {
|
||||
const { helpMenu } = this;
|
||||
const promise = BrowserTestUtils.waitForEvent(helpMenu, "popupshown");
|
||||
|
||||
// This event-faking method was copied from browser_title_case_menus.js.
|
||||
// We can't actually open the Help menu in testing, but this lets us
|
||||
// force its DOM to be properly built.
|
||||
helpMenu.dispatchEvent(new MouseEvent("popupshowing", { bubbles: true }));
|
||||
helpMenu.dispatchEvent(new MouseEvent("popupshown", { bubbles: true }));
|
||||
|
||||
await promise;
|
||||
}
|
||||
|
||||
async close() {
|
||||
const { helpMenu } = this;
|
||||
const promise = BrowserTestUtils.waitForPopupEvent(helpMenu, "hidden");
|
||||
|
||||
// (Also copied from browser_title_case_menus.js)
|
||||
// Just for good measure, we'll fire the popuphiding/popuphidden events
|
||||
// after we close the menupopups.
|
||||
helpMenu.dispatchEvent(new MouseEvent("popuphiding", { bubbles: true }));
|
||||
helpMenu.dispatchEvent(new MouseEvent("popuphidden", { bubbles: true }));
|
||||
|
||||
await promise;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ProtectionsPanelHelper extends MenuHelper {
|
||||
menuDescription = "Protections Panel";
|
||||
|
||||
get reportBrokenSite() {
|
||||
this.win.gProtectionsHandler._initializePopup();
|
||||
return this.getViewNode("protections-popup-report-broken-site-button");
|
||||
}
|
||||
|
||||
get popup() {
|
||||
this.win.gProtectionsHandler._initializePopup();
|
||||
return this.win.document.getElementById("protections-popup");
|
||||
}
|
||||
|
||||
async open() {
|
||||
const promise = BrowserTestUtils.waitForEvent(
|
||||
this.win,
|
||||
"popupshown",
|
||||
true,
|
||||
e => e.target.id == "protections-popup"
|
||||
);
|
||||
this.win.gProtectionsHandler.showProtectionsPopup();
|
||||
await promise;
|
||||
}
|
||||
|
||||
async close() {
|
||||
if (this.opened) {
|
||||
const popup = this.popup;
|
||||
const promise = BrowserTestUtils.waitForPopupEvent(popup, "hidden");
|
||||
PanelMultiView.hidePopup(popup, false);
|
||||
await promise;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function AppMenu(win = window) {
|
||||
return new AppMenuHelper(win);
|
||||
}
|
||||
|
||||
function HelpMenu(win = window) {
|
||||
return new HelpMenuHelper(win);
|
||||
}
|
||||
|
||||
function ProtectionsPanel(win = window) {
|
||||
return new ProtectionsPanelHelper(win);
|
||||
}
|
||||
|
||||
function pressKeyAndAwait(event, key, config = {}) {
|
||||
const win = config.window || window;
|
||||
if (!event.then) {
|
||||
event = BrowserTestUtils.waitForEvent(win, event, config.timeout || 200);
|
||||
}
|
||||
EventUtils.synthesizeKey(key, config, win);
|
||||
return event;
|
||||
}
|
||||
|
||||
async function pressKeyAndGetFocus(key, config = {}) {
|
||||
return (await pressKeyAndAwait("focus", key, config)).target;
|
||||
}
|
||||
|
||||
async function tabTo(match, win = window) {
|
||||
const config = { window: win };
|
||||
const { activeElement } = win.document;
|
||||
if (activeElement?.matches(match)) {
|
||||
return activeElement;
|
||||
}
|
||||
let initial = await pressKeyAndGetFocus("VK_TAB", config);
|
||||
let target = initial;
|
||||
do {
|
||||
if (target.matches(match)) {
|
||||
return target;
|
||||
}
|
||||
target = await pressKeyAndGetFocus("VK_TAB", config);
|
||||
} while (target && target !== initial);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function filterFrameworkDetectorFails(ping, expected) {
|
||||
// the framework detector's frame-script may fail to run in low memory or other
|
||||
// weird corner-cases, so we ignore the results in that case if they don't match.
|
||||
if (!areObjectsEqual(ping.frameworks, expected.frameworks)) {
|
||||
const { fastclick, mobify, marfeel } = ping.frameworks;
|
||||
if (!fastclick && !mobify && !marfeel) {
|
||||
console.info("Ignoring failure to get framework data");
|
||||
expected.frameworks = ping.frameworks;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function setupStrictETP() {
|
||||
await UrlClassifierTestUtils.addTestTrackers();
|
||||
registerCleanupFunction(() => {
|
||||
UrlClassifierTestUtils.cleanupTestTrackers();
|
||||
});
|
||||
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
["security.mixed_content.block_active_content", true],
|
||||
["security.mixed_content.block_display_content", true],
|
||||
["security.mixed_content.upgrade_display_content", false],
|
||||
[
|
||||
"urlclassifier.trackingTable",
|
||||
"content-track-digest256,mochitest2-track-simple",
|
||||
],
|
||||
["browser.contentblocking.category", "strict"],
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
// copied from browser/base/content/test/protectionsUI/head.js
|
||||
function waitForContentBlockingEvent(numChanges = 1, win = null) {
|
||||
if (!win) {
|
||||
win = window;
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
let n = 0;
|
||||
let listener = {
|
||||
onContentBlockingEvent(webProgress, request, event) {
|
||||
n = n + 1;
|
||||
info(
|
||||
`Received onContentBlockingEvent event: ${event} (${n} of ${numChanges})`
|
||||
);
|
||||
if (n >= numChanges) {
|
||||
win.gBrowser.removeProgressListener(listener);
|
||||
resolve(n);
|
||||
}
|
||||
},
|
||||
};
|
||||
win.gBrowser.addProgressListener(listener);
|
||||
});
|
||||
}
|
||||
@@ -1,355 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Helper methods for testing sending reports with
|
||||
* the Report Broken Site feature.
|
||||
*/
|
||||
|
||||
/* import-globals-from head.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { Troubleshoot } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/Troubleshoot.sys.mjs"
|
||||
);
|
||||
|
||||
function getSysinfoProperty(propertyName, defaultValue) {
|
||||
try {
|
||||
return Services.sysinfo.getProperty(propertyName);
|
||||
} catch (e) {}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
function securityStringToArray(str) {
|
||||
return str ? str.split(";") : null;
|
||||
}
|
||||
|
||||
function getExpectedGraphicsDevices(snapshot) {
|
||||
const { graphics } = snapshot;
|
||||
return [
|
||||
graphics.adapterDeviceID,
|
||||
graphics.adapterVendorID,
|
||||
graphics.adapterDeviceID2,
|
||||
graphics.adapterVendorID2,
|
||||
]
|
||||
.filter(i => i)
|
||||
.sort();
|
||||
}
|
||||
|
||||
function compareGraphicsDevices(expected, rawActual) {
|
||||
const actual = rawActual
|
||||
.map(({ deviceID, vendorID }) => [deviceID, vendorID])
|
||||
.flat()
|
||||
.filter(i => i)
|
||||
.sort();
|
||||
return areObjectsEqual(actual, expected);
|
||||
}
|
||||
|
||||
function getExpectedGraphicsDrivers(snapshot) {
|
||||
const { graphics } = snapshot;
|
||||
const expected = [];
|
||||
for (let i = 1; i < 3; ++i) {
|
||||
const version = graphics[`webgl${i}Version`];
|
||||
if (version && version != "-") {
|
||||
expected.push(graphics[`webgl${i}Renderer`]);
|
||||
expected.push(version);
|
||||
}
|
||||
}
|
||||
return expected.filter(i => i).sort();
|
||||
}
|
||||
|
||||
function compareGraphicsDrivers(expected, rawActual) {
|
||||
const actual = rawActual
|
||||
.map(({ renderer, version }) => [renderer, version])
|
||||
.flat()
|
||||
.filter(i => i)
|
||||
.sort();
|
||||
return areObjectsEqual(actual, expected);
|
||||
}
|
||||
|
||||
function getExpectedGraphicsFeatures(snapshot) {
|
||||
const expected = {};
|
||||
for (let { name, log, status } of snapshot.graphics.featureLog.features) {
|
||||
for (const item of log?.reverse() ?? []) {
|
||||
if (item.failureId && item.status == status) {
|
||||
status = `${status} (${item.message || item.failureId})`;
|
||||
}
|
||||
}
|
||||
expected[name] = status;
|
||||
}
|
||||
return expected;
|
||||
}
|
||||
|
||||
async function getExpectedWebCompatInfo(tab, snapshot, fullAppData = false) {
|
||||
const gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo);
|
||||
|
||||
const { application, graphics, intl, securitySoftware } = snapshot;
|
||||
|
||||
const { fissionAutoStart, memorySizeBytes, updateChannel, userAgent } =
|
||||
application;
|
||||
|
||||
const app = {
|
||||
defaultLocales: intl.localeService.available,
|
||||
defaultUseragentString: userAgent,
|
||||
fissionEnabled: fissionAutoStart,
|
||||
};
|
||||
if (fullAppData) {
|
||||
app.applicationName = application.name;
|
||||
app.osArchitecture = getSysinfoProperty("arch", null);
|
||||
app.osName = getSysinfoProperty("name", null);
|
||||
app.osVersion = getSysinfoProperty("version", null);
|
||||
app.updateChannel = updateChannel;
|
||||
app.version = application.version;
|
||||
}
|
||||
|
||||
const hasTouchScreen = graphics.info.ApzTouchInput == 1;
|
||||
|
||||
const { registeredAntiVirus, registeredAntiSpyware, registeredFirewall } =
|
||||
securitySoftware;
|
||||
|
||||
const browserInfo = {
|
||||
addons: [],
|
||||
app,
|
||||
experiments: [],
|
||||
graphics: {
|
||||
devicesJson(actualStr) {
|
||||
const expected = getExpectedGraphicsDevices(snapshot);
|
||||
// If undefined is saved to the Glean value here, we'll get the string "undefined" (invalid JSON).
|
||||
// We should stop using JSON like this in bug 1875185.
|
||||
if (!actualStr || actualStr == "undefined") {
|
||||
return !expected.length;
|
||||
}
|
||||
return compareGraphicsDevices(expected, JSON.parse(actualStr));
|
||||
},
|
||||
driversJson(actualStr) {
|
||||
const expected = getExpectedGraphicsDrivers(snapshot);
|
||||
// If undefined is saved to the Glean value here, we'll get the string "undefined" (invalid JSON).
|
||||
// We should stop using JSON like this in bug 1875185.
|
||||
if (!actualStr || actualStr == "undefined") {
|
||||
return !expected.length;
|
||||
}
|
||||
return compareGraphicsDrivers(expected, JSON.parse(actualStr));
|
||||
},
|
||||
featuresJson(actualStr) {
|
||||
const expected = getExpectedGraphicsFeatures(snapshot);
|
||||
// If undefined is saved to the Glean value here, we'll get the string "undefined" (invalid JSON).
|
||||
// We should stop using JSON like this in bug 1875185.
|
||||
if (!actualStr || actualStr == "undefined") {
|
||||
return !expected.length;
|
||||
}
|
||||
return areObjectsEqual(JSON.parse(actualStr), expected);
|
||||
},
|
||||
hasTouchScreen,
|
||||
monitorsJson(actualStr) {
|
||||
const expected = gfxInfo.getMonitors();
|
||||
// If undefined is saved to the Glean value here, we'll get the string "undefined" (invalid JSON).
|
||||
// We should stop using JSON like this in bug 1875185.
|
||||
if (!actualStr || actualStr == "undefined") {
|
||||
return !expected.length;
|
||||
}
|
||||
return areObjectsEqual(JSON.parse(actualStr), expected);
|
||||
},
|
||||
},
|
||||
prefs: {
|
||||
cookieBehavior: Services.prefs.getIntPref(
|
||||
"network.cookie.cookieBehavior",
|
||||
-1
|
||||
),
|
||||
forcedAcceleratedLayers: Services.prefs.getBoolPref(
|
||||
"layers.acceleration.force-enabled",
|
||||
false
|
||||
),
|
||||
globalPrivacyControlEnabled: Services.prefs.getBoolPref(
|
||||
"privacy.globalprivacycontrol.enabled",
|
||||
false
|
||||
),
|
||||
installtriggerEnabled: Services.prefs.getBoolPref(
|
||||
"extensions.InstallTrigger.enabled",
|
||||
false
|
||||
),
|
||||
opaqueResponseBlocking: Services.prefs.getBoolPref(
|
||||
"browser.opaqueResponseBlocking",
|
||||
false
|
||||
),
|
||||
resistFingerprintingEnabled: Services.prefs.getBoolPref(
|
||||
"privacy.resistFingerprinting",
|
||||
false
|
||||
),
|
||||
softwareWebrender: Services.prefs.getBoolPref(
|
||||
"gfx.webrender.software",
|
||||
false
|
||||
),
|
||||
thirdPartyCookieBlockingEnabled: Services.prefs.getBoolPref(
|
||||
"network.cookie.cookieBehavior.optInPartitioning",
|
||||
false
|
||||
),
|
||||
thirdPartyCookieBlockingEnabledInPbm: Services.prefs.getBoolPref(
|
||||
"network.cookie.cookieBehavior.optInPartitioning.pbmode",
|
||||
false
|
||||
),
|
||||
},
|
||||
security: {
|
||||
antispyware: securityStringToArray(registeredAntiSpyware),
|
||||
antivirus: securityStringToArray(registeredAntiVirus),
|
||||
firewall: securityStringToArray(registeredFirewall),
|
||||
},
|
||||
system: {
|
||||
isTablet: getSysinfoProperty("tablet", false),
|
||||
memory: Math.round(memorySizeBytes / 1024 / 1024),
|
||||
},
|
||||
};
|
||||
|
||||
const tabInfo = await tab.linkedBrowser.ownerGlobal.SpecialPowers.spawn(
|
||||
tab.linkedBrowser,
|
||||
[],
|
||||
async function () {
|
||||
return {
|
||||
devicePixelRatio: `${content.devicePixelRatio}`,
|
||||
antitracking: {
|
||||
blockList: "basic",
|
||||
blockedOrigins: null,
|
||||
isPrivateBrowsing: false,
|
||||
hasTrackingContentBlocked: false,
|
||||
hasMixedActiveContentBlocked: false,
|
||||
hasMixedDisplayContentBlocked: false,
|
||||
btpHasPurgedSite: false,
|
||||
etpCategory: "standard",
|
||||
},
|
||||
frameworks: {
|
||||
fastclick: false,
|
||||
marfeel: false,
|
||||
mobify: false,
|
||||
},
|
||||
languages: content.navigator.languages,
|
||||
useragentString: content.navigator.userAgent,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
browserInfo.graphics.devicePixelRatio = tabInfo.devicePixelRatio;
|
||||
delete tabInfo.devicePixelRatio;
|
||||
|
||||
return { browserInfo, tabInfo };
|
||||
}
|
||||
|
||||
function extractPingData(branch) {
|
||||
const data = {};
|
||||
for (const [name, value] of Object.entries(branch)) {
|
||||
data[name] = value.testGetValue();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function extractBrokenSiteReportFromGleanPing(Glean) {
|
||||
const ping = extractPingData(Glean.brokenSiteReport);
|
||||
ping.tabInfo = extractPingData(Glean.brokenSiteReportTabInfo);
|
||||
ping.tabInfo.antitracking = extractPingData(
|
||||
Glean.brokenSiteReportTabInfoAntitracking
|
||||
);
|
||||
ping.tabInfo.frameworks = extractPingData(
|
||||
Glean.brokenSiteReportTabInfoFrameworks
|
||||
);
|
||||
ping.browserInfo = {
|
||||
addons: Array.from(Glean.brokenSiteReportBrowserInfo.addons.testGetValue()),
|
||||
app: extractPingData(Glean.brokenSiteReportBrowserInfoApp),
|
||||
graphics: extractPingData(Glean.brokenSiteReportBrowserInfoGraphics),
|
||||
experiments: Array.from(
|
||||
Glean.brokenSiteReportBrowserInfo.experiments.testGetValue()
|
||||
),
|
||||
prefs: extractPingData(Glean.brokenSiteReportBrowserInfoPrefs),
|
||||
security: extractPingData(Glean.brokenSiteReportBrowserInfoSecurity),
|
||||
system: extractPingData(Glean.brokenSiteReportBrowserInfoSystem),
|
||||
};
|
||||
return ping;
|
||||
}
|
||||
|
||||
async function testSend(tab, menu, expectedOverrides = {}) {
|
||||
const url = expectedOverrides.url ?? menu.win.gBrowser.currentURI.spec;
|
||||
const description = expectedOverrides.description ?? "";
|
||||
const breakageCategory = expectedOverrides.breakageCategory ?? null;
|
||||
|
||||
let rbs = await menu.openAndPrefillReportBrokenSite(url, description);
|
||||
|
||||
const snapshot = await Troubleshoot.snapshot();
|
||||
const expected = await getExpectedWebCompatInfo(tab, snapshot);
|
||||
|
||||
expected.url = url;
|
||||
expected.description = description;
|
||||
expected.breakageCategory = breakageCategory;
|
||||
|
||||
if (expectedOverrides.addons) {
|
||||
expected.browserInfo.addons = expectedOverrides.addons;
|
||||
}
|
||||
|
||||
if (expectedOverrides.experiments) {
|
||||
expected.browserInfo.experiments = expectedOverrides.experiments;
|
||||
}
|
||||
|
||||
if (expectedOverrides.antitracking) {
|
||||
expected.tabInfo.antitracking = expectedOverrides.antitracking;
|
||||
|
||||
if (expectedOverrides.antitracking.blockedOrigins) {
|
||||
rbs.blockedTrackersCheckbox = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (expectedOverrides.frameworks) {
|
||||
expected.tabInfo.frameworks = expectedOverrides.frameworks;
|
||||
}
|
||||
|
||||
if (breakageCategory) {
|
||||
rbs.chooseReason(breakageCategory);
|
||||
}
|
||||
|
||||
Services.fog.testResetFOG();
|
||||
await GleanPings.brokenSiteReport.testSubmission(
|
||||
() => {
|
||||
const ping = extractBrokenSiteReportFromGleanPing(Glean);
|
||||
|
||||
// sanity checks
|
||||
const { browserInfo, tabInfo } = ping;
|
||||
ok(ping.url?.length, "Got a URL");
|
||||
ok(
|
||||
["basic", "strict"].includes(tabInfo.antitracking.blockList),
|
||||
"Got a blockList"
|
||||
);
|
||||
if (rbs.blockedTrackersCheckbox.checked) {
|
||||
ok(
|
||||
Array.isArray(tabInfo.antitracking.blockedOrigins),
|
||||
"Got an array for blockedOrigins"
|
||||
);
|
||||
} else {
|
||||
ok(!tabInfo.antitracking.blockedOrigins, "No blockedOrigins included");
|
||||
}
|
||||
ok(tabInfo.useragentString?.length, "Got a final UA string");
|
||||
ok(
|
||||
browserInfo.app.defaultUseragentString?.length,
|
||||
"Got a default UA string"
|
||||
);
|
||||
|
||||
filterFrameworkDetectorFails(ping.tabInfo, expected.tabInfo);
|
||||
|
||||
ok(areObjectsEqual(ping, expected), "ping matches expectations");
|
||||
},
|
||||
() => rbs.clickSend()
|
||||
);
|
||||
|
||||
await rbs.clickOkay();
|
||||
|
||||
const telemetry = Glean.webcompatreporting.send.testGetValue();
|
||||
is(telemetry?.length, 1, "Got a 'send' telemetry event");
|
||||
is(
|
||||
telemetry[0].extra.sent_with_blocked_trackers,
|
||||
String(!!expectedOverrides.antitracking?.blockedOrigins),
|
||||
"Got correct 'sent_with_blocked_trackers' flag"
|
||||
);
|
||||
|
||||
// re-opening the panel, the url and description should be reset
|
||||
rbs = await menu.openReportBrokenSite();
|
||||
rbs.isMainViewResetToCurrentTab();
|
||||
ok(
|
||||
!rbs.blockedTrackersCheckbox.checked,
|
||||
"blocked trackers checkbox is reset"
|
||||
);
|
||||
rbs.close();
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!-- 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/. -->
|
||||
<html dir="ltr" xml:lang="en-US" lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
let ready;
|
||||
window.wrtReady = new Promise(r => ready = r);
|
||||
|
||||
let arrived;
|
||||
window.messageArrived = new Promise(r => arrived = r);
|
||||
|
||||
window.addEventListener("message", e => {
|
||||
window.message = e.data;
|
||||
arrived();
|
||||
});
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
setTimeout(ready, 100);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,308 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Helper methods for testing the "send more info" link
|
||||
* of the Report Broken Site feature.
|
||||
*/
|
||||
|
||||
/* import-globals-from head.js */
|
||||
/* import-globals-from send.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
Services.scriptloader.loadSubScript(
|
||||
getRootDirectory(gTestPath) + "send.js",
|
||||
this
|
||||
);
|
||||
|
||||
// eslint-disable-next-line complexity
|
||||
async function reformatExpectedWebCompatInfo(tab, overrides) {
|
||||
const gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo);
|
||||
const snapshot = await Troubleshoot.snapshot();
|
||||
const expected = await getExpectedWebCompatInfo(tab, snapshot, true);
|
||||
const { browserInfo, tabInfo } = expected;
|
||||
const { app, graphics, prefs, security } = browserInfo;
|
||||
const {
|
||||
applicationName,
|
||||
defaultUseragentString,
|
||||
fissionEnabled,
|
||||
osArchitecture,
|
||||
osName,
|
||||
osVersion,
|
||||
updateChannel,
|
||||
version,
|
||||
} = app;
|
||||
const { devicePixelRatio, hasTouchScreen } = graphics;
|
||||
const { antitracking, languages, useragentString } = tabInfo;
|
||||
|
||||
const addons = overrides.addons || [];
|
||||
const experiments = overrides.experiments || [];
|
||||
const atOverrides = overrides.antitracking;
|
||||
const blockList = atOverrides?.blockList ?? antitracking.blockList;
|
||||
const blockedOrigins =
|
||||
atOverrides?.blockedOrigins ?? antitracking.blockedOrigins ?? [];
|
||||
const hasMixedActiveContentBlocked =
|
||||
atOverrides?.hasMixedActiveContentBlocked ??
|
||||
antitracking.hasMixedActiveContentBlocked;
|
||||
const hasMixedDisplayContentBlocked =
|
||||
atOverrides?.hasMixedDisplayContentBlocked ??
|
||||
antitracking.hasMixedDisplayContentBlocked;
|
||||
const hasTrackingContentBlocked =
|
||||
atOverrides?.hasTrackingContentBlocked ??
|
||||
antitracking.hasTrackingContentBlocked;
|
||||
const isPrivateBrowsing =
|
||||
atOverrides?.isPrivateBrowsing ?? antitracking.isPrivateBrowsing;
|
||||
const btpHasPurgedSite =
|
||||
atOverrides?.btpHasPurgedSite ?? antitracking.btpHasPurgedSite;
|
||||
const etpCategory = atOverrides?.etpCategory ?? antitracking.etpCategory;
|
||||
|
||||
const extra_labels = [];
|
||||
const frameworks = overrides.frameworks ?? {
|
||||
fastclick: false,
|
||||
mobify: false,
|
||||
marfeel: false,
|
||||
};
|
||||
|
||||
// ignore the console log unless explicily testing for it.
|
||||
const consoleLog = overrides.consoleLog ?? (() => true);
|
||||
|
||||
const finalPrefs = {};
|
||||
for (const [key, pref] of Object.entries({
|
||||
cookieBehavior: "network.cookie.cookieBehavior",
|
||||
forcedAcceleratedLayers: "layers.acceleration.force-enabled",
|
||||
globalPrivacyControlEnabled: "privacy.globalprivacycontrol.enabled",
|
||||
installtriggerEnabled: "extensions.InstallTrigger.enabled",
|
||||
opaqueResponseBlocking: "browser.opaqueResponseBlocking",
|
||||
resistFingerprintingEnabled: "privacy.resistFingerprinting",
|
||||
softwareWebrender: "gfx.webrender.software",
|
||||
thirdPartyCookieBlockingEnabled:
|
||||
"network.cookie.cookieBehavior.optInPartitioning",
|
||||
thirdPartyCookieBlockingEnabledInPbm:
|
||||
"network.cookie.cookieBehavior.optInPartitioning.pbmode",
|
||||
})) {
|
||||
if (key in prefs) {
|
||||
finalPrefs[pref] = prefs[key];
|
||||
}
|
||||
}
|
||||
|
||||
const reformatted = {
|
||||
blockList,
|
||||
details: {
|
||||
additionalData: {
|
||||
addons,
|
||||
applicationName,
|
||||
blockList,
|
||||
blockedOrigins,
|
||||
buildId: snapshot.application.buildID,
|
||||
devicePixelRatio: parseInt(devicePixelRatio),
|
||||
experiments,
|
||||
finalUserAgent: useragentString,
|
||||
fissionEnabled,
|
||||
gfxData: {
|
||||
devices(actual) {
|
||||
const devices = getExpectedGraphicsDevices(snapshot);
|
||||
return compareGraphicsDevices(devices, actual);
|
||||
},
|
||||
drivers(actual) {
|
||||
const drvs = getExpectedGraphicsDrivers(snapshot);
|
||||
return compareGraphicsDrivers(drvs, actual);
|
||||
},
|
||||
features(actual) {
|
||||
const features = getExpectedGraphicsFeatures(snapshot);
|
||||
return areObjectsEqual(actual, features);
|
||||
},
|
||||
hasTouchScreen,
|
||||
monitors(actual) {
|
||||
return areObjectsEqual(actual, gfxInfo.getMonitors());
|
||||
},
|
||||
},
|
||||
hasMixedActiveContentBlocked,
|
||||
hasMixedDisplayContentBlocked,
|
||||
hasTrackingContentBlocked,
|
||||
btpHasPurgedSite,
|
||||
isPB: isPrivateBrowsing,
|
||||
etpCategory,
|
||||
languages,
|
||||
locales: snapshot.intl.localeService.available,
|
||||
memoryMB: browserInfo.system.memory,
|
||||
osArchitecture,
|
||||
osName,
|
||||
osVersion,
|
||||
prefs: finalPrefs,
|
||||
version,
|
||||
},
|
||||
blockList,
|
||||
channel: updateChannel,
|
||||
consoleLog,
|
||||
defaultUserAgent: defaultUseragentString,
|
||||
frameworks,
|
||||
hasTouchScreen,
|
||||
"gfx.webrender.software": prefs.softwareWebrender,
|
||||
"mixed active content blocked": hasMixedActiveContentBlocked,
|
||||
"mixed passive content blocked": hasMixedDisplayContentBlocked,
|
||||
"tracking content blocked": hasTrackingContentBlocked
|
||||
? `true (${blockList})`
|
||||
: "false",
|
||||
"btp has purged site": btpHasPurgedSite,
|
||||
},
|
||||
extra_labels,
|
||||
src: "desktop-reporter",
|
||||
utm_campaign: "report-broken-site",
|
||||
utm_source: "desktop-reporter",
|
||||
};
|
||||
|
||||
const { gfxData } = reformatted.details.additionalData;
|
||||
for (const optional of [
|
||||
"directWriteEnabled",
|
||||
"directWriteVersion",
|
||||
"clearTypeParameters",
|
||||
"targetFrameRate",
|
||||
]) {
|
||||
if (optional in snapshot.graphics) {
|
||||
gfxData[optional] = snapshot.graphics[optional];
|
||||
}
|
||||
}
|
||||
|
||||
// We only care about this pref on Linux right now on webcompat.com.
|
||||
if (AppConstants.platform != "linux") {
|
||||
delete finalPrefs["layers.acceleration.force-enabled"];
|
||||
} else {
|
||||
reformatted.details["layers.acceleration.force-enabled"] =
|
||||
finalPrefs["layers.acceleration.force-enabled"];
|
||||
}
|
||||
|
||||
// Only bother adding the security key if it has any data
|
||||
if (Object.values(security).filter(e => e).length) {
|
||||
reformatted.details.additionalData.sec = security;
|
||||
}
|
||||
|
||||
const expectedCodecs = snapshot.media.codecSupportInfo
|
||||
.replaceAll(" NONE", "")
|
||||
.split("\n")
|
||||
.sort()
|
||||
.join("\n");
|
||||
if (expectedCodecs) {
|
||||
reformatted.details.additionalData.gfxData.codecSupport = rawActual => {
|
||||
const actual = Object.entries(rawActual)
|
||||
.map(
|
||||
([
|
||||
name,
|
||||
{ hardwareDecode, softwareDecode, hardwareEncode, softwareEncode },
|
||||
]) =>
|
||||
(
|
||||
`${name} ` +
|
||||
`${softwareDecode ? "SWDEC " : ""}` +
|
||||
`${hardwareDecode ? "HWDEC " : ""}` +
|
||||
`${softwareEncode ? "SWENC " : ""}` +
|
||||
`${hardwareEncode ? "HWENC " : ""}`
|
||||
).trim()
|
||||
)
|
||||
.sort()
|
||||
.join("\n");
|
||||
return areObjectsEqual(actual, expectedCodecs);
|
||||
};
|
||||
}
|
||||
|
||||
if (blockList != "basic") {
|
||||
extra_labels.push(`type-tracking-protection-${blockList}`);
|
||||
}
|
||||
|
||||
if (overrides.expectNoTabDetails) {
|
||||
delete reformatted.details.frameworks;
|
||||
delete reformatted.details.consoleLog;
|
||||
delete reformatted.details["mixed active content blocked"];
|
||||
delete reformatted.details["mixed passive content blocked"];
|
||||
delete reformatted.details["tracking content blocked"];
|
||||
delete reformatted.details["btp has purged site"];
|
||||
} else {
|
||||
const { fastclick, mobify, marfeel } = frameworks;
|
||||
if (fastclick) {
|
||||
extra_labels.push("type-fastclick");
|
||||
reformatted.details.fastclick = true;
|
||||
}
|
||||
if (mobify) {
|
||||
extra_labels.push("type-mobify");
|
||||
reformatted.details.mobify = true;
|
||||
}
|
||||
if (marfeel) {
|
||||
extra_labels.push("type-marfeel");
|
||||
reformatted.details.marfeel = true;
|
||||
}
|
||||
}
|
||||
|
||||
extra_labels.sort();
|
||||
|
||||
return reformatted;
|
||||
}
|
||||
|
||||
async function testSendMoreInfo(tab, menu, expectedOverrides = {}) {
|
||||
const url = expectedOverrides.url ?? menu.win.gBrowser.currentURI.spec;
|
||||
const description = expectedOverrides.description ?? "";
|
||||
|
||||
let rbs = await menu.openAndPrefillReportBrokenSite(url, description);
|
||||
|
||||
const receivedData = await rbs.clickSendMoreInfo();
|
||||
await checkWebcompatComPayload(
|
||||
tab,
|
||||
url,
|
||||
description,
|
||||
expectedOverrides,
|
||||
receivedData
|
||||
);
|
||||
|
||||
// re-opening the panel, the url and description should be reset
|
||||
rbs = await menu.openReportBrokenSite();
|
||||
rbs.isMainViewResetToCurrentTab();
|
||||
rbs.close();
|
||||
}
|
||||
|
||||
async function testWebcompatComFallback(tab, menu) {
|
||||
const url = menu.win.gBrowser.currentURI.spec;
|
||||
const receivedData =
|
||||
await menu.clickReportBrokenSiteAndAwaitWebCompatTabData();
|
||||
await checkWebcompatComPayload(tab, url, "", {}, receivedData);
|
||||
menu.close();
|
||||
}
|
||||
|
||||
async function checkWebcompatComPayload(
|
||||
tab,
|
||||
url,
|
||||
description,
|
||||
expectedOverrides,
|
||||
receivedData
|
||||
) {
|
||||
const expected = await reformatExpectedWebCompatInfo(tab, expectedOverrides);
|
||||
expected.url = url;
|
||||
expected.description = description;
|
||||
|
||||
// sanity checks
|
||||
const { message } = receivedData;
|
||||
const { details } = message;
|
||||
const { additionalData } = details;
|
||||
ok(message.url?.length, "Got a URL");
|
||||
ok(["basic", "strict"].includes(details.blockList), "Got a blockList");
|
||||
ok(additionalData.applicationName?.length, "Got an app name");
|
||||
ok(additionalData.osArchitecture?.length, "Got an OS arch");
|
||||
ok(additionalData.osName?.length, "Got an OS name");
|
||||
ok(additionalData.osVersion?.length, "Got an OS version");
|
||||
ok(additionalData.version?.length, "Got an app version");
|
||||
ok(details.channel?.length, "Got an app channel");
|
||||
ok(details.defaultUserAgent?.length, "Got a default UA string");
|
||||
ok(additionalData.finalUserAgent?.length, "Got a final UA string");
|
||||
|
||||
// If we're sending any tab-specific data (which includes console logs),
|
||||
// check that there is also a valid screenshot.
|
||||
if ("consoleLog" in details) {
|
||||
const isScreenshotValid = await new Promise(done => {
|
||||
var image = new Image();
|
||||
image.onload = () => done(image.width > 0);
|
||||
image.onerror = () => done(false);
|
||||
image.src = receivedData.screenshot;
|
||||
});
|
||||
ok(isScreenshotValid, "Got a valid screenshot");
|
||||
}
|
||||
|
||||
filterFrameworkDetectorFails(message.details, expected.details);
|
||||
|
||||
ok(areObjectsEqual(message, expected), "sent info matches expectations");
|
||||
}
|
||||
@@ -7,7 +7,9 @@ support-files = [
|
||||
["browser_bug400731.js"]
|
||||
|
||||
["browser_bug415846.js"]
|
||||
skip-if = ["true"] # Bug 1248632
|
||||
skip-if = [
|
||||
"true", # Bug 1248632
|
||||
]
|
||||
|
||||
["browser_mixedcontent_aboutblocked.js"]
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ add_task(async function testMalware() {
|
||||
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
|
||||
|
||||
const url = "https://www.itisatrap.org/firefox/its-an-attack.html";
|
||||
const url = "http://www.itisatrap.org/firefox/its-an-attack.html";
|
||||
BrowserTestUtils.startLoadingURIString(gBrowser.selectedBrowser, url);
|
||||
await BrowserTestUtils.browserLoaded(
|
||||
gBrowser.selectedBrowser,
|
||||
@@ -28,7 +28,7 @@ add_task(async function testUnwanted() {
|
||||
Services.prefs.setBoolPref("browser.safebrowsing.allowOverride", false);
|
||||
|
||||
// Now launch the unwanted software test
|
||||
const url = "https://www.itisatrap.org/firefox/unwanted.html";
|
||||
const url = "http://www.itisatrap.org/firefox/unwanted.html";
|
||||
BrowserTestUtils.startLoadingURIString(gBrowser.selectedBrowser, url);
|
||||
await BrowserTestUtils.browserLoaded(
|
||||
gBrowser.selectedBrowser,
|
||||
@@ -49,7 +49,7 @@ add_task(async function testPhishing() {
|
||||
Services.prefs.setBoolPref("browser.safebrowsing.allowOverride", true);
|
||||
|
||||
// Now launch the phishing test
|
||||
const url = "https://www.itisatrap.org/firefox/its-a-trap.html";
|
||||
const url = "http://www.itisatrap.org/firefox/its-a-trap.html";
|
||||
BrowserTestUtils.startLoadingURIString(gBrowser.selectedBrowser, url);
|
||||
await BrowserTestUtils.browserLoaded(
|
||||
gBrowser.selectedBrowser,
|
||||
|
||||
@@ -4,8 +4,8 @@ menu items.
|
||||
Mac makes this astonishingly painful to test since their help menu is special magic,
|
||||
but we can at least test it on the other platforms.*/
|
||||
|
||||
const NORMAL_PAGE = "https://example.com";
|
||||
const PHISH_PAGE = "https://www.itisatrap.org/firefox/its-a-trap.html";
|
||||
const NORMAL_PAGE = "http://example.com";
|
||||
const PHISH_PAGE = "http://www.itisatrap.org/firefox/its-a-trap.html";
|
||||
|
||||
/**
|
||||
* Opens a new tab and browses to some URL, tests for the existence
|
||||
@@ -13,13 +13,14 @@ const PHISH_PAGE = "https://www.itisatrap.org/firefox/its-a-trap.html";
|
||||
* the state of the menu once opened. This function will take care of
|
||||
* opening and closing the menu.
|
||||
*
|
||||
* @param {string} url The URL to browse the tab to.
|
||||
* @param {Function} testFn
|
||||
* @param url (string)
|
||||
* The URL to browse the tab to.
|
||||
* @param testFn (function)
|
||||
* The function to run once the menu has been opened. This
|
||||
* function will be passed the "reportMenu" and "errorMenu"
|
||||
* DOM nodes as arguments, in that order. This function
|
||||
* should not yield anything.
|
||||
* @returns {Promise} Promise that resolves when the test is complete
|
||||
* @returns Promise
|
||||
*/
|
||||
function check_menu_at_page(url, testFn) {
|
||||
return BrowserTestUtils.withNewTab(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* Ensure that hostnames in the whitelisted pref are not blocked. */
|
||||
|
||||
const PREF_WHITELISTED_HOSTNAMES = "urlclassifier.skipHostnames";
|
||||
const TEST_PAGE = "https://www.itisatrap.org/firefox/its-an-attack.html";
|
||||
const TEST_PAGE = "http://www.itisatrap.org/firefox/its-an-attack.html";
|
||||
var tabbrowser = null;
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
|
||||
@@ -6,10 +6,15 @@ const PHISH_URL = "https://www.itisatrap.org/firefox/its-a-trap.html";
|
||||
* Waits for a load (or custom) event to finish in a given tab. If provided
|
||||
* load an uri into the tab.
|
||||
*
|
||||
* @param {MozTabbrowserTab} tab The tab to load into.
|
||||
* @param {string} [url] The url to load, or the current url.
|
||||
* @param {string} [eventType] The load event type to wait for. Defaults to "load".
|
||||
* @returns {Promise<Event>} Promise resolved when the event is handled.
|
||||
* @param tab
|
||||
* The tab to load into.
|
||||
* @param [optional] url
|
||||
* The url to load, or the current url.
|
||||
* @param [optional] event
|
||||
* The load event type to wait for. Defaults to "load".
|
||||
* @return {Promise} resolved when the event is handled.
|
||||
* @resolves to the received event
|
||||
* @rejects if a valid load event is not received within a meaningful interval
|
||||
*/
|
||||
function promiseTabLoadEvent(tab, url, eventType = "load") {
|
||||
info(`Wait tab event: ${eventType}`);
|
||||
|
||||
@@ -3,18 +3,30 @@
|
||||
["browser_1119088.js"]
|
||||
disabled="Disabled by import_external_tests.py"
|
||||
support-files = ["mac_desktop_image.py"]
|
||||
run-if = ["os == 'mac'"]
|
||||
run-if = [
|
||||
"os == 'mac'",
|
||||
]
|
||||
tags = "os_integration"
|
||||
skip-if = ["os == 'mac' && os_version == '14.70' && processor == 'x86_64'"] # Bug 1869703
|
||||
skip-if = [
|
||||
"os == 'mac' && os_version == '14.70' && arch == 'x86_64'", # Bug 1869703
|
||||
]
|
||||
|
||||
["browser_420786.js"]
|
||||
run-if = ["os == 'linux'"]
|
||||
run-if = [
|
||||
"os == 'linux' && os_version == '22.04' && arch == 'x86_64' && display == 'wayland'",
|
||||
"os == 'linux' && os_version == '24.04' && arch == 'x86_64' && display == 'x11'",
|
||||
]
|
||||
|
||||
["browser_633221.js"]
|
||||
run-if = ["os == 'linux'"]
|
||||
run-if = [
|
||||
"os == 'linux' && os_version == '22.04' && arch == 'x86_64' && display == 'wayland'",
|
||||
"os == 'linux' && os_version == '24.04' && arch == 'x86_64' && display == 'x11'",
|
||||
]
|
||||
|
||||
["browser_createWindowsShortcut.js"]
|
||||
run-if = ["os == 'win'"]
|
||||
run-if = [
|
||||
"os == 'win'",
|
||||
]
|
||||
|
||||
["browser_doesAppNeedPin.js"]
|
||||
|
||||
@@ -24,8 +36,8 @@ support-files = [
|
||||
"headless.html",
|
||||
]
|
||||
skip-if = [
|
||||
"os == 'win'",
|
||||
"ccov",
|
||||
"os == 'win'",
|
||||
"tsan", # Bug 1429950, Bug 1583315, Bug 1696109, Bug 1701449
|
||||
]
|
||||
tags = "os_integration"
|
||||
@@ -36,8 +48,8 @@ support-files = [
|
||||
"headless.html",
|
||||
]
|
||||
skip-if = [
|
||||
"os == 'win'",
|
||||
"ccov",
|
||||
"os == 'win'",
|
||||
"tsan", # Bug 1429950, Bug 1583315, Bug 1696109, Bug 1701449
|
||||
]
|
||||
|
||||
@@ -47,8 +59,8 @@ support-files = [
|
||||
"headless.html",
|
||||
]
|
||||
skip-if = [
|
||||
"os == 'win'",
|
||||
"ccov",
|
||||
"os == 'win'",
|
||||
"tsan", # Bug 1429950, Bug 1583315, Bug 1696109, Bug 1701449
|
||||
]
|
||||
|
||||
@@ -58,8 +70,8 @@ support-files = [
|
||||
"headless.html",
|
||||
]
|
||||
skip-if = [
|
||||
"os == 'win'",
|
||||
"ccov",
|
||||
"os == 'win'",
|
||||
"tsan", # Bug 1429950, Bug 1583315, Bug 1696109, Bug 1701449
|
||||
]
|
||||
|
||||
@@ -70,8 +82,8 @@ support-files = [
|
||||
"headless_iframe.html",
|
||||
]
|
||||
skip-if = [
|
||||
"os == 'win'",
|
||||
"ccov",
|
||||
"os == 'win'",
|
||||
"tsan", # Bug 1429950, Bug 1583315, Bug 1696109, Bug 1701449
|
||||
]
|
||||
|
||||
@@ -83,19 +95,23 @@ support-files = [
|
||||
"headless_redirect.html^headers^",
|
||||
]
|
||||
skip-if = [
|
||||
"os == 'win'",
|
||||
"ccov",
|
||||
"os == 'win'",
|
||||
"tsan", # Bug 1429950, Bug 1583315, Bug 1696109, Bug 1701449
|
||||
]
|
||||
|
||||
["browser_processAUMID.js"]
|
||||
run-if = ["os == 'win'"]
|
||||
run-if = [
|
||||
"os == 'win'",
|
||||
]
|
||||
|
||||
["browser_setDefaultBrowser.js"]
|
||||
tags = "os_integration"
|
||||
|
||||
["browser_setDefaultPDFHandler.js"]
|
||||
run-if = ["os == 'win'"]
|
||||
run-if = [
|
||||
"os == 'win'",
|
||||
]
|
||||
tags = "os_integration"
|
||||
|
||||
["browser_setDesktopBackgroundPreview.js"]
|
||||
|
||||
@@ -31,138 +31,138 @@ from Cocoa import NSURL
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Utility to print, set, or "
|
||||
+ "check the path to image being used as "
|
||||
+ "the desktop background image. By "
|
||||
+ "default, prints the path to the "
|
||||
+ "current desktop background image."
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Utility to print, set, or "
|
||||
+ "check the path to image being used as "
|
||||
+ "the desktop background image. By "
|
||||
+ "default, prints the path to the "
|
||||
+ "current desktop background image."
|
||||
)
|
||||
parser.add_argument(
|
||||
"-v",
|
||||
"--verbose",
|
||||
action="store_true",
|
||||
help="print verbose debugging information",
|
||||
default=False,
|
||||
)
|
||||
group = parser.add_mutually_exclusive_group()
|
||||
group.add_argument(
|
||||
"-s",
|
||||
"--set-background-image",
|
||||
dest="newBackgroundImagePath",
|
||||
required=False,
|
||||
help="path to the new background image to set. A zero "
|
||||
+ "exit code indicates no errors occurred.",
|
||||
default=None,
|
||||
)
|
||||
group.add_argument(
|
||||
"-c",
|
||||
"--check-background-image",
|
||||
dest="checkBackgroundImagePath",
|
||||
required=False,
|
||||
help="check if the provided background image path "
|
||||
+ "matches the provided path. A zero exit code "
|
||||
+ "indicates the paths match.",
|
||||
default=None,
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
# Using logging for verbose output
|
||||
if args.verbose:
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
else:
|
||||
logging.basicConfig(level=logging.CRITICAL)
|
||||
logger = logging.getLogger("desktopImage")
|
||||
|
||||
# Print what we're going to do
|
||||
if args.checkBackgroundImagePath is not None:
|
||||
logger.debug(
|
||||
"checking provided desktop image %s matches current "
|
||||
"image" % args.checkBackgroundImagePath
|
||||
)
|
||||
parser.add_argument(
|
||||
"-v",
|
||||
"--verbose",
|
||||
action="store_true",
|
||||
help="print verbose debugging information",
|
||||
default=False,
|
||||
elif args.newBackgroundImagePath is not None:
|
||||
logger.debug("setting image to %s " % args.newBackgroundImagePath)
|
||||
else:
|
||||
logger.debug("retrieving desktop image path")
|
||||
|
||||
focussedScreen = NSScreen.mainScreen()
|
||||
if not focussedScreen:
|
||||
raise RuntimeError("mainScreen error")
|
||||
|
||||
ws = NSWorkspace.sharedWorkspace()
|
||||
if not ws:
|
||||
raise RuntimeError("sharedWorkspace error")
|
||||
|
||||
# If we're just checking the image path, check it and then return.
|
||||
# A successful exit code (0) indicates the paths match.
|
||||
if args.checkBackgroundImagePath is not None:
|
||||
# Get existing desktop image path and resolve it
|
||||
existingImageURL = getCurrentDesktopImageURL(focussedScreen, ws, logger)
|
||||
existingImagePath = existingImageURL.path()
|
||||
existingImagePathReal = os.path.realpath(existingImagePath)
|
||||
logger.debug("existing desktop image: %s" % existingImagePath)
|
||||
logger.debug("existing desktop image realpath: %s" % existingImagePath)
|
||||
|
||||
# Resolve the path we're going to check
|
||||
checkImagePathReal = os.path.realpath(args.checkBackgroundImagePath)
|
||||
logger.debug("check desktop image: %s" % args.checkBackgroundImagePath)
|
||||
logger.debug("check desktop image realpath: %s" % checkImagePathReal)
|
||||
|
||||
if existingImagePathReal == checkImagePathReal:
|
||||
print("desktop image path matches provided path")
|
||||
return True
|
||||
|
||||
print("desktop image path does NOT match provided path")
|
||||
return False
|
||||
|
||||
# Log the current desktop image
|
||||
if args.verbose:
|
||||
existingImageURL = getCurrentDesktopImageURL(focussedScreen, ws, logger)
|
||||
logger.debug("existing desktop image: %s" % existingImageURL.path())
|
||||
|
||||
# Set the desktop image
|
||||
if args.newBackgroundImagePath is not None:
|
||||
newImagePath = args.newBackgroundImagePath
|
||||
if not os.path.exists(newImagePath):
|
||||
logger.critical("%s does not exist" % newImagePath)
|
||||
return False
|
||||
if not os.access(newImagePath, os.R_OK):
|
||||
logger.critical("%s is not readable" % newImagePath)
|
||||
return False
|
||||
|
||||
logger.debug("new desktop image to set: %s" % newImagePath)
|
||||
newImageURL = NSURL.fileURLWithPath_(newImagePath)
|
||||
logger.debug("new desktop image URL to set: %s" % newImageURL)
|
||||
|
||||
status = False
|
||||
(status, error) = ws.setDesktopImageURL_forScreen_options_error_(
|
||||
newImageURL, focussedScreen, None, None
|
||||
)
|
||||
group = parser.add_mutually_exclusive_group()
|
||||
group.add_argument(
|
||||
"-s",
|
||||
"--set-background-image",
|
||||
dest="newBackgroundImagePath",
|
||||
required=False,
|
||||
help="path to the new background image to set. A zero "
|
||||
+ "exit code indicates no errors occurred.",
|
||||
default=None,
|
||||
)
|
||||
group.add_argument(
|
||||
"-c",
|
||||
"--check-background-image",
|
||||
dest="checkBackgroundImagePath",
|
||||
required=False,
|
||||
help="check if the provided background image path "
|
||||
+ "matches the provided path. A zero exit code "
|
||||
+ "indicates the paths match.",
|
||||
default=None,
|
||||
)
|
||||
args = parser.parse_args()
|
||||
if not status:
|
||||
raise RuntimeError("setDesktopImageURL error")
|
||||
|
||||
# Using logging for verbose output
|
||||
if args.verbose:
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
else:
|
||||
logging.basicConfig(level=logging.CRITICAL)
|
||||
logger = logging.getLogger("desktopImage")
|
||||
|
||||
# Print what we're going to do
|
||||
if args.checkBackgroundImagePath is not None:
|
||||
logger.debug(
|
||||
"checking provided desktop image %s matches current "
|
||||
"image" % args.checkBackgroundImagePath
|
||||
)
|
||||
elif args.newBackgroundImagePath is not None:
|
||||
logger.debug("setting image to %s " % args.newBackgroundImagePath)
|
||||
else:
|
||||
logger.debug("retrieving desktop image path")
|
||||
|
||||
focussedScreen = NSScreen.mainScreen()
|
||||
if not focussedScreen:
|
||||
raise RuntimeError("mainScreen error")
|
||||
|
||||
ws = NSWorkspace.sharedWorkspace()
|
||||
if not ws:
|
||||
raise RuntimeError("sharedWorkspace error")
|
||||
|
||||
# If we're just checking the image path, check it and then return.
|
||||
# A successful exit code (0) indicates the paths match.
|
||||
if args.checkBackgroundImagePath is not None:
|
||||
# Get existing desktop image path and resolve it
|
||||
existingImageURL = getCurrentDesktopImageURL(focussedScreen, ws, logger)
|
||||
existingImagePath = existingImageURL.path()
|
||||
existingImagePathReal = os.path.realpath(existingImagePath)
|
||||
logger.debug("existing desktop image: %s" % existingImagePath)
|
||||
logger.debug("existing desktop image realpath: %s" % existingImagePath)
|
||||
|
||||
# Resolve the path we're going to check
|
||||
checkImagePathReal = os.path.realpath(args.checkBackgroundImagePath)
|
||||
logger.debug("check desktop image: %s" % args.checkBackgroundImagePath)
|
||||
logger.debug("check desktop image realpath: %s" % checkImagePathReal)
|
||||
|
||||
if existingImagePathReal == checkImagePathReal:
|
||||
print("desktop image path matches provided path")
|
||||
return True
|
||||
|
||||
print("desktop image path does NOT match provided path")
|
||||
return False
|
||||
|
||||
# Log the current desktop image
|
||||
if args.verbose:
|
||||
existingImageURL = getCurrentDesktopImageURL(focussedScreen, ws, logger)
|
||||
logger.debug("existing desktop image: %s" % existingImageURL.path())
|
||||
|
||||
# Set the desktop image
|
||||
if args.newBackgroundImagePath is not None:
|
||||
newImagePath = args.newBackgroundImagePath
|
||||
if not os.path.exists(newImagePath):
|
||||
logger.critical("%s does not exist" % newImagePath)
|
||||
return False
|
||||
if not os.access(newImagePath, os.R_OK):
|
||||
logger.critical("%s is not readable" % newImagePath)
|
||||
return False
|
||||
|
||||
logger.debug("new desktop image to set: %s" % newImagePath)
|
||||
newImageURL = NSURL.fileURLWithPath_(newImagePath)
|
||||
logger.debug("new desktop image URL to set: %s" % newImageURL)
|
||||
|
||||
status = False
|
||||
(status, error) = ws.setDesktopImageURL_forScreen_options_error_(
|
||||
newImageURL, focussedScreen, None, None
|
||||
)
|
||||
if not status:
|
||||
raise RuntimeError("setDesktopImageURL error")
|
||||
|
||||
# Print the current desktop image
|
||||
imageURL = getCurrentDesktopImageURL(focussedScreen, ws, logger)
|
||||
imagePath = imageURL.path()
|
||||
imagePathReal = os.path.realpath(imagePath)
|
||||
logger.debug("updated desktop image URL: %s" % imageURL)
|
||||
logger.debug("updated desktop image path: %s" % imagePath)
|
||||
logger.debug("updated desktop image path (resolved): %s" % imagePathReal)
|
||||
print(imagePathReal)
|
||||
return True
|
||||
# Print the current desktop image
|
||||
imageURL = getCurrentDesktopImageURL(focussedScreen, ws, logger)
|
||||
imagePath = imageURL.path()
|
||||
imagePathReal = os.path.realpath(imagePath)
|
||||
logger.debug("updated desktop image URL: %s" % imageURL)
|
||||
logger.debug("updated desktop image path: %s" % imagePath)
|
||||
logger.debug("updated desktop image path (resolved): %s" % imagePathReal)
|
||||
print(imagePathReal)
|
||||
return True
|
||||
|
||||
|
||||
def getCurrentDesktopImageURL(focussedScreen, workspace, logger):
|
||||
imageURL = workspace.desktopImageURLForScreen_(focussedScreen)
|
||||
if not imageURL:
|
||||
raise RuntimeError("desktopImageURLForScreen returned invalid URL")
|
||||
if not imageURL.isFileURL():
|
||||
logger.warning("desktop image URL is not a file URL")
|
||||
return imageURL
|
||||
imageURL = workspace.desktopImageURLForScreen_(focussedScreen)
|
||||
if not imageURL:
|
||||
raise RuntimeError("desktopImageURLForScreen returned invalid URL")
|
||||
if not imageURL.isFileURL():
|
||||
logger.warning("desktop image URL is not a file URL")
|
||||
return imageURL
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if not main():
|
||||
sys.exit(1)
|
||||
else:
|
||||
sys.exit(0)
|
||||
if not main():
|
||||
sys.exit(1)
|
||||
else:
|
||||
sys.exit(0)
|
||||
|
||||
@@ -36,6 +36,5 @@ add_task(async function test_prefsOpen() {
|
||||
);
|
||||
shellSvc.showSecurityPreferences("Privacy_AllFiles");
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
equal(killSystemPreferences(), 0, "Ensure System Preferences was started");
|
||||
});
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
[DEFAULT]
|
||||
run-if = ["os != 'android'"]
|
||||
run-if = [
|
||||
"os != 'android'",
|
||||
]
|
||||
firefox-appdir = "browser"
|
||||
tags = "os_integration"
|
||||
|
||||
["test_macOS_showSecurityPreferences.js"]
|
||||
run-if = ["os == 'mac'"]
|
||||
run-if = [
|
||||
"os == 'mac'",
|
||||
]
|
||||
|
||||
@@ -2,7 +2,6 @@ function check(aBrowser, aElementName, aBarred, aType) {
|
||||
return SpecialPowers.spawn(
|
||||
aBrowser,
|
||||
[[aElementName, aBarred, aType]],
|
||||
// eslint-disable-next-line no-shadow
|
||||
async function ([aElementName, aBarred, aType]) {
|
||||
let e = content.document.createElement(aElementName);
|
||||
let contentElement = content.document.getElementById("content");
|
||||
@@ -56,7 +55,6 @@ function todo_check(aBrowser, aElementName, aBarred) {
|
||||
return SpecialPowers.spawn(
|
||||
aBrowser,
|
||||
[[aElementName, aBarred]],
|
||||
// eslint-disable-next-line no-shadow
|
||||
async function ([aElementName]) {
|
||||
let e = content.document.createElement(aElementName);
|
||||
let contentElement = content.document.getElementById("content");
|
||||
@@ -65,7 +63,6 @@ function todo_check(aBrowser, aElementName, aBarred) {
|
||||
let caught = false;
|
||||
try {
|
||||
e.setCustomValidity("foo");
|
||||
// eslint-disable-next-line no-shadow
|
||||
} catch (e) {
|
||||
caught = true;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,6 @@ async function do_test(test) {
|
||||
);
|
||||
|
||||
info("creating input field");
|
||||
// eslint-disable-next-line no-shadow
|
||||
await SpecialPowers.spawn(tab.linkedBrowser, [test], async function (test) {
|
||||
let doc = content.document;
|
||||
let input = doc.createElement("input");
|
||||
|
||||
@@ -15,6 +15,4 @@ prefs = ["zen.workspaces.separate-essentials=false"]
|
||||
["browser_pinned_created.js"]
|
||||
["browser_pinned_to_essential.js"]
|
||||
|
||||
["browser_private_mode_no_ctx_menu.js"]
|
||||
|
||||
["browser_issue_8726.js"]
|
||||
|
||||
@@ -15,6 +15,8 @@ add_task(async function test_Changed_Pinned() {
|
||||
|
||||
ok(tab.pinned, "The tab should be pinned after calling gBrowser.pinTab()");
|
||||
|
||||
await gBrowser.TabStateFlusher.flush(browser);
|
||||
await new Promise((r) => setTimeout(r, 500));
|
||||
BrowserTestUtils.startLoadingURIString(browser, "https://example.com/2");
|
||||
await BrowserTestUtils.browserLoaded(browser, false, "https://example.com/2");
|
||||
setTimeout(() => {
|
||||
@@ -23,7 +25,7 @@ add_task(async function test_Changed_Pinned() {
|
||||
"The tab should have a zen-pinned-changed attribute after being pinned"
|
||||
);
|
||||
resolvePromise();
|
||||
}, 0);
|
||||
}, 500);
|
||||
|
||||
await promise;
|
||||
});
|
||||
|
||||
@@ -13,9 +13,11 @@ add_task(async function test_Create_Pinned() {
|
||||
|
||||
const newTab = gBrowser.selectedTab;
|
||||
gBrowser.pinTab(newTab);
|
||||
await gBrowser.TabStateFlusher.flush(newTab.linkedBrowser);
|
||||
|
||||
ok(newTab.pinned, "The tab should be pinned after calling gBrowser.pinTab()");
|
||||
|
||||
await new Promise((r) => setTimeout(r, 500));
|
||||
const pinObject = newTab._zenPinnedInitialState;
|
||||
ok(pinObject, "The pin object should be created in the tab's _zenPinnedInitialState");
|
||||
Assert.equal(
|
||||
|
||||
@@ -19,6 +19,7 @@ add_task(async function test_NoUnload_Changed_Pinned() {
|
||||
|
||||
BrowserTestUtils.startLoadingURIString(browser, "https://example.com/2");
|
||||
await BrowserTestUtils.browserLoaded(browser, false, "https://example.com/2");
|
||||
await gBrowser.TabStateFlusher.flush(browser);
|
||||
setTimeout(() => {
|
||||
ok(
|
||||
tab.hasAttribute("zen-pinned-changed"),
|
||||
|
||||
@@ -19,6 +19,7 @@ add_task(async function test_Unload_NoReset_Pinned() {
|
||||
|
||||
BrowserTestUtils.startLoadingURIString(browser, "https://example.com/2");
|
||||
await BrowserTestUtils.browserLoaded(browser, false, "https://example.com/2");
|
||||
await gBrowser.TabStateFlusher.flush(browser);
|
||||
setTimeout(() => {
|
||||
ok(
|
||||
tab.hasAttribute("zen-pinned-changed"),
|
||||
|
||||
@@ -19,6 +19,7 @@ add_task(async function test_Unload_NoReset_Pinned() {
|
||||
|
||||
BrowserTestUtils.startLoadingURIString(browser, "https://example.com/2");
|
||||
await BrowserTestUtils.browserLoaded(browser, false, "https://example.com/2");
|
||||
await gBrowser.TabStateFlusher.flush(browser);
|
||||
setTimeout(() => {
|
||||
ok(
|
||||
tab.hasAttribute("zen-pinned-changed"),
|
||||
|
||||
@@ -19,6 +19,7 @@ add_task(async function test_Unload_Changed_Pinned() {
|
||||
|
||||
BrowserTestUtils.startLoadingURIString(browser, "https://example.com/2");
|
||||
await BrowserTestUtils.browserLoaded(browser, false, "https://example.com/2");
|
||||
await gBrowser.TabStateFlusher.flush(browser);
|
||||
setTimeout(() => {
|
||||
ok(
|
||||
tab.hasAttribute("zen-pinned-changed"),
|
||||
|
||||
@@ -19,6 +19,7 @@ add_task(async function test_Unload_NoReset_Pinned() {
|
||||
|
||||
BrowserTestUtils.startLoadingURIString(browser, "https://example.com/2");
|
||||
await BrowserTestUtils.browserLoaded(browser, false, "https://example.com/2");
|
||||
await gBrowser.TabStateFlusher.flush(browser);
|
||||
/* eslint-disable-next-line mozilla/no-arbitrary-setTimeout */
|
||||
setTimeout(() => {
|
||||
ok(
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(async function test_Private_Mode_No_Essentials() {
|
||||
let privateWindow = await BrowserTestUtils.openNewBrowserWindow({
|
||||
private: true,
|
||||
});
|
||||
await privateWindow.gZenWorkspaces.promiseInitialized;
|
||||
await BrowserTestUtils.openNewForegroundTab(privateWindow.gBrowser, "https://example.com/", true);
|
||||
|
||||
await new Promise((resolve) => {
|
||||
privateWindow.gBrowser.selectedTab.addEventListener("popupshown", function () {
|
||||
ok(
|
||||
privateWindow.document.getElementById("context_zen-add-essentials").hidden,
|
||||
"Context menu should not show Zen Essentials option in private mode"
|
||||
);
|
||||
|
||||
ok(
|
||||
privateWindow.document.getElementById("context_pinTab").hidden,
|
||||
"Context menu should not show Pin Tab option in private mode"
|
||||
);
|
||||
|
||||
resolve();
|
||||
});
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(privateWindow.gBrowser.selectedTab, {
|
||||
type: "contextmenu",
|
||||
});
|
||||
});
|
||||
|
||||
await BrowserTestUtils.closeWindow(privateWindow);
|
||||
});
|
||||
@@ -8,7 +8,7 @@ add_setup(async function () {});
|
||||
add_task(async function test_Check_Creation() {
|
||||
const currentWorkspaceUUID = gZenWorkspaces.activeWorkspace;
|
||||
await gZenWorkspaces.createAndSaveWorkspace("Test Workspace 2");
|
||||
const workspaces = await gZenWorkspaces._workspaces();
|
||||
const workspaces = gZenWorkspaces.getWorkspaces();
|
||||
Assert.strictEqual(workspaces.length, 2, "Two workspaces should exist.");
|
||||
Assert.notStrictEqual(
|
||||
currentWorkspaceUUID,
|
||||
@@ -24,7 +24,7 @@ add_task(async function test_Check_Creation() {
|
||||
BrowserTestUtils.removeTab(newTab);
|
||||
|
||||
await gZenWorkspaces.removeWorkspace(gZenWorkspaces.activeWorkspace);
|
||||
const workspacesAfterRemove = await gZenWorkspaces._workspaces();
|
||||
const workspacesAfterRemove = gZenWorkspaces.getWorkspaces();
|
||||
Assert.strictEqual(workspacesAfterRemove.workspaces.length, 1, "One workspace should exist.");
|
||||
Assert.strictEqual(
|
||||
workspacesAfterRemove[0].uuid,
|
||||
|
||||
@@ -7,7 +7,7 @@ add_task(async function test_Change_To_Empty() {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const currentWorkspaceUUID = gZenWorkspaces.activeWorkspace;
|
||||
await gZenWorkspaces.createAndSaveWorkspace("Test Workspace 2");
|
||||
const workspaces = await gZenWorkspaces._workspaces();
|
||||
const workspaces = gZenWorkspaces.getWorkspaces();
|
||||
const secondWorkspace = workspaces.workspaces[1];
|
||||
|
||||
await gZenWorkspaces.changeWorkspace(secondWorkspace.uuid);
|
||||
@@ -24,7 +24,7 @@ add_task(async function test_Change_To_Empty() {
|
||||
"The empty tab should not be selected anymore."
|
||||
);
|
||||
|
||||
const workspacesAfterRemove = await gZenWorkspaces._workspaces();
|
||||
const workspacesAfterRemove = gZenWorkspaces.getWorkspaces();
|
||||
Assert.strictEqual(workspacesAfterRemove.length, 1, "One workspace should exist.");
|
||||
Assert.strictEqual(gBrowser.tabs.length, 2, "There should be two tabs.");
|
||||
});
|
||||
|
||||
@@ -109,7 +109,7 @@ add_task(async function test_workspace_bookmark() {
|
||||
return;
|
||||
await withBookmarksShowing(async () => {
|
||||
await gZenWorkspaces.createAndSaveWorkspace("Test Workspace 2");
|
||||
const workspaces = await gZenWorkspaces._workspaces();
|
||||
const workspaces = gZenWorkspaces.getWorkspaces();
|
||||
Assert.strictEqual(workspaces.length, 2, "Two workspaces should exist.");
|
||||
const firstWorkspace = workspaces[0];
|
||||
const secondWorkspace = workspaces[1];
|
||||
@@ -156,7 +156,7 @@ add_task(async function test_workspace_bookmark() {
|
||||
|
||||
await gZenWorkspaces.removeWorkspace(secondWorkspace.uuid);
|
||||
Assert.equal(
|
||||
(await gZenWorkspaces._workspaces()).workspaces.length,
|
||||
gZenWorkspaces.getWorkspaces().workspaces.length,
|
||||
1,
|
||||
"Only one workspace should remain after removing the second one."
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user