summaryrefslogtreecommitdiffstats
path: root/toolkit/components/reader
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:35:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:35:49 +0000
commitd8bbc7858622b6d9c278469aab701ca0b609cddf (patch)
treeeff41dc61d9f714852212739e6b3738b82a2af87 /toolkit/components/reader
parentReleasing progress-linux version 125.0.3-1~progress7.99u1. (diff)
downloadfirefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.tar.xz
firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.zip
Merging upstream version 126.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/reader')
-rw-r--r--toolkit/components/reader/.eslintrc.js2
-rw-r--r--toolkit/components/reader/AboutReader.sys.mjs241
-rw-r--r--toolkit/components/reader/ReaderMode.sys.mjs4
-rw-r--r--toolkit/components/reader/color-input.css47
-rw-r--r--toolkit/components/reader/color-input.mjs69
-rw-r--r--toolkit/components/reader/color-input.stories.mjs32
-rw-r--r--toolkit/components/reader/content/aboutReader.html71
-rw-r--r--toolkit/components/reader/jar.mn2
-rw-r--r--toolkit/components/reader/moz.build4
-rw-r--r--toolkit/components/reader/tests/browser/browser.toml (renamed from toolkit/components/reader/test/browser.toml)0
-rw-r--r--toolkit/components/reader/tests/browser/browser_bug1124271_readerModePinnedTab.js (renamed from toolkit/components/reader/test/browser_bug1124271_readerModePinnedTab.js)0
-rw-r--r--toolkit/components/reader/tests/browser/browser_bug1453818_samesite_cookie.js (renamed from toolkit/components/reader/test/browser_bug1453818_samesite_cookie.js)0
-rw-r--r--toolkit/components/reader/tests/browser/browser_bug1780350_readerModeSaveScroll.js (renamed from toolkit/components/reader/test/browser_bug1780350_readerModeSaveScroll.js)0
-rw-r--r--toolkit/components/reader/tests/browser/browser_drag_url_readerMode.js (renamed from toolkit/components/reader/test/browser_drag_url_readerMode.js)0
-rw-r--r--toolkit/components/reader/tests/browser/browser_localfile_readerMode.js (renamed from toolkit/components/reader/test/browser_localfile_readerMode.js)0
-rw-r--r--toolkit/components/reader/tests/browser/browser_readerMode.js (renamed from toolkit/components/reader/test/browser_readerMode.js)2
-rw-r--r--toolkit/components/reader/tests/browser/browser_readerMode_bc_reuse.js (renamed from toolkit/components/reader/test/browser_readerMode_bc_reuse.js)0
-rw-r--r--toolkit/components/reader/tests/browser/browser_readerMode_cached.js (renamed from toolkit/components/reader/test/browser_readerMode_cached.js)2
-rw-r--r--toolkit/components/reader/tests/browser/browser_readerMode_colorSchemePref.js (renamed from toolkit/components/reader/test/browser_readerMode_colorSchemePref.js)54
-rw-r--r--toolkit/components/reader/tests/browser/browser_readerMode_hidden_nodes.js (renamed from toolkit/components/reader/test/browser_readerMode_hidden_nodes.js)2
-rw-r--r--toolkit/components/reader/tests/browser/browser_readerMode_menu.js (renamed from toolkit/components/reader/test/browser_readerMode_menu.js)40
-rw-r--r--toolkit/components/reader/tests/browser/browser_readerMode_pocket.js (renamed from toolkit/components/reader/test/browser_readerMode_pocket.js)0
-rw-r--r--toolkit/components/reader/tests/browser/browser_readerMode_readingTime.js (renamed from toolkit/components/reader/test/browser_readerMode_readingTime.js)0
-rw-r--r--toolkit/components/reader/tests/browser/browser_readerMode_refresh.js (renamed from toolkit/components/reader/test/browser_readerMode_refresh.js)0
-rw-r--r--toolkit/components/reader/tests/browser/browser_readerMode_remoteType.js (renamed from toolkit/components/reader/test/browser_readerMode_remoteType.js)0
-rw-r--r--toolkit/components/reader/tests/browser/browser_readerMode_samesite_cookie_redirect.js (renamed from toolkit/components/reader/test/browser_readerMode_samesite_cookie_redirect.js)0
-rw-r--r--toolkit/components/reader/tests/browser/browser_readerMode_with_anchor.js (renamed from toolkit/components/reader/test/browser_readerMode_with_anchor.js)0
-rw-r--r--toolkit/components/reader/tests/browser/getCookies.sjs (renamed from toolkit/components/reader/test/getCookies.sjs)0
-rw-r--r--toolkit/components/reader/tests/browser/head.js (renamed from toolkit/components/reader/test/head.js)0
-rw-r--r--toolkit/components/reader/tests/browser/linkToGetCookies.html (renamed from toolkit/components/reader/test/linkToGetCookies.html)2
-rw-r--r--toolkit/components/reader/tests/browser/readerModeArticle.html (renamed from toolkit/components/reader/test/readerModeArticle.html)0
-rw-r--r--toolkit/components/reader/tests/browser/readerModeArticleContainsLink.html (renamed from toolkit/components/reader/test/readerModeArticleContainsLink.html)2
-rw-r--r--toolkit/components/reader/tests/browser/readerModeArticleHiddenNodes.html (renamed from toolkit/components/reader/test/readerModeArticleHiddenNodes.html)0
-rw-r--r--toolkit/components/reader/tests/browser/readerModeArticleMedium.html (renamed from toolkit/components/reader/test/readerModeArticleMedium.html)0
-rw-r--r--toolkit/components/reader/tests/browser/readerModeArticleShort.html (renamed from toolkit/components/reader/test/readerModeArticleShort.html)0
-rw-r--r--toolkit/components/reader/tests/browser/readerModeArticleTextPlain.txt (renamed from toolkit/components/reader/test/readerModeArticleTextPlain.txt)0
-rw-r--r--toolkit/components/reader/tests/browser/readerModeNonArticle.html (renamed from toolkit/components/reader/test/readerModeNonArticle.html)0
-rw-r--r--toolkit/components/reader/tests/browser/readerModeRandom.sjs (renamed from toolkit/components/reader/test/readerModeRandom.sjs)0
-rw-r--r--toolkit/components/reader/tests/browser/setSameSiteCookie.html (renamed from toolkit/components/reader/test/setSameSiteCookie.html)0
-rw-r--r--toolkit/components/reader/tests/browser/setSameSiteCookie.html^headers^ (renamed from toolkit/components/reader/test/setSameSiteCookie.html^headers^)0
-rw-r--r--toolkit/components/reader/tests/chrome/chrome.toml3
-rw-r--r--toolkit/components/reader/tests/chrome/test_color_input.html39
42 files changed, 572 insertions, 46 deletions
diff --git a/toolkit/components/reader/.eslintrc.js b/toolkit/components/reader/.eslintrc.js
index 4df95dd5f8..bf83f31ab1 100644
--- a/toolkit/components/reader/.eslintrc.js
+++ b/toolkit/components/reader/.eslintrc.js
@@ -8,6 +8,6 @@ module.exports = {
rules: {
"no-inner-declarations": "error",
"no-shadow": "error",
- "no-unused-vars": ["error", { vars: "all", args: "none" }],
+ "no-unused-vars": ["error", { vars: "all", argsIgnorePattern: "^_" }],
},
};
diff --git a/toolkit/components/reader/AboutReader.sys.mjs b/toolkit/components/reader/AboutReader.sys.mjs
index 6b1c28c228..75776b619f 100644
--- a/toolkit/components/reader/AboutReader.sys.mjs
+++ b/toolkit/components/reader/AboutReader.sys.mjs
@@ -8,6 +8,7 @@ import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
const lazy = {};
let gScrollPositions = new Map();
+let lastSelectedTheme = "auto";
ChromeUtils.defineESModuleGetters(lazy, {
AsyncPrefs: "resource://gre/modules/AsyncPrefs.sys.mjs",
@@ -26,10 +27,31 @@ ChromeUtils.defineLazyGetter(
);
const COLORSCHEME_L10N_IDS = {
- light: "about-reader-color-scheme-light",
- dark: "about-reader-color-scheme-dark",
- sepia: "about-reader-color-scheme-sepia",
- auto: "about-reader-color-scheme-auto",
+ auto: "about-reader-color-theme-auto",
+ light: "about-reader-color-theme-light",
+ dark: "about-reader-color-theme-dark",
+ sepia: "about-reader-color-theme-sepia",
+ contrast: "about-reader-color-theme-contrast",
+ gray: "about-reader-color-theme-gray",
+ custom: "about-reader-color-theme-custom",
+};
+
+const CUSTOM_THEME_COLOR_INPUTS = [
+ "foreground",
+ "background",
+ "unvisited-links",
+ "visited-links",
+ "selection-highlight",
+];
+
+const COLORS_MENU_TABS = ["fxtheme", "customtheme"];
+
+const DEFAULT_COLORS = {
+ background: "#FFFFFF",
+ foreground: "#14151A",
+ "unvisited-links": "#0060DF",
+ "visited-links": "#321C64",
+ "selection-highlight": "#FFFFCC",
};
Services.telemetry.setEventRecordingEnabled("readermode", true);
@@ -147,9 +169,27 @@ export var AboutReader = function (
// we're ready for any external setup, send a signal for that.
this._actor.sendAsyncMessage("Reader:OnSetup");
- let colorSchemeValues = JSON.parse(
+ // set up segmented tab controls for colors menu.
+ this._setupColorsTabs(
+ COLORS_MENU_TABS,
+ this._handleColorsTabClick.bind(this)
+ );
+
+ // fetch color scheme values from prefs.
+ let colorsMenuColorSchemeValues = JSON.parse(
Services.prefs.getCharPref("reader.color_scheme.values")
);
+ // remove contrast and gray options from regular menu.
+ let colorSchemeValues = [...colorsMenuColorSchemeValues];
+ colorSchemeValues.splice(colorSchemeValues.length - 2, 2);
+
+ let colorsMenuColorSchemeOptions = colorsMenuColorSchemeValues.map(value => ({
+ l10nId: COLORSCHEME_L10N_IDS[value],
+ groupName: "color-scheme",
+ value,
+ itemClass: value + "-button",
+ }));
+
let colorSchemeOptions = colorSchemeValues.map(value => ({
l10nId: COLORSCHEME_L10N_IDS[value],
groupName: "color-scheme",
@@ -158,12 +198,33 @@ export var AboutReader = function (
}));
let colorScheme = Services.prefs.getCharPref("reader.color_scheme");
- this._setupSegmentedButton(
- "color-scheme-buttons",
- colorSchemeOptions,
- colorScheme,
- this._setColorSchemePref.bind(this)
- );
+ if (Services.prefs.getBoolPref("reader.colors_menu.enabled", false)) {
+ doc.getElementById("regular-color-scheme").hidden = true;
+ doc.getElementById("custom-colors-color-scheme").hidden = false;
+ this._setupSegmentedButton(
+ "colors-menu-color-scheme-buttons",
+ colorsMenuColorSchemeOptions,
+ colorScheme,
+ this._setColorSchemePref.bind(this)
+ );
+ this._setupCustomColors(
+ CUSTOM_THEME_COLOR_INPUTS,
+ "custom-colors-selection",
+ "about-reader-custom-colors"
+ );
+ this._setupButton(
+ "custom-colors-reset-button",
+ this._resetCustomColors.bind(this)
+ );
+ } else {
+ this._setupSegmentedButton(
+ "color-scheme-buttons",
+ colorSchemeOptions,
+ colorScheme,
+ this._setColorSchemePref.bind(this)
+ );
+ }
+
this._setColorSchemePref(colorScheme);
let fontTypeOptions = [
@@ -738,19 +799,43 @@ AboutReader.prototype = {
this._colorScheme = "hcm";
}
+ if (this._colorScheme == "custom") {
+ const colorInputs = this._doc.querySelectorAll("color-input");
+ colorInputs.forEach(input => {
+ // Set document body styles to pref values.
+ let property = input.getAttribute("prop-name");
+ let pref = `reader.custom_colors.${property}`;
+ let customColor = Services.prefs.getStringPref(pref, "");
+ // If customColor is truthy, set the value from pref.
+ if (customColor) {
+ let cssProp = `--custom-theme-${property}`;
+ this._doc.body.style.setProperty(cssProp, customColor);
+ }
+ });
+ }
+
bodyClasses.add(this._colorScheme);
},
- // Pref values include "dark", "light", "sepia", and "auto"
- _setColorSchemePref(colorSchemePref) {
+ // Pref values include "auto", "dark", "light", "sepia",
+ // "gray", "contrast", and "custom"
+ _setColorSchemePref(colorSchemePref, fromInputEvent = false) {
+ // The input event for the last selected segmented button is fired
+ // upon loading a reader article in the same session. To prevent it
+ // from overwriting custom colors, we return false.
+ if (this._colorScheme == "custom" && fromInputEvent) {
+ lastSelectedTheme = colorSchemePref;
+ return false;
+ }
this._setColorScheme(colorSchemePref);
lazy.AsyncPrefs.set("reader.color_scheme", colorSchemePref);
+ return true;
},
_setFontType(newFontType) {
if (this._fontType === newFontType) {
- return;
+ return false;
}
let bodyClasses = this._doc.body.classList;
@@ -763,6 +848,8 @@ AboutReader.prototype = {
bodyClasses.add(this._fontType);
lazy.AsyncPrefs.set("reader.font_type", this._fontType);
+
+ return true;
},
async _loadArticle(docContentType = "document") {
@@ -1094,14 +1181,17 @@ AboutReader.prototype = {
label.removeAttribute("checked");
}
- aEvent.target.nextElementSibling.setAttribute("checked", "true");
- callback(option.value);
+ let setOption = callback(option.value, true);
+ if (setOption) {
+ aEvent.target.setAttribute("checked", "true");
+ aEvent.target.nextElementSibling.setAttribute("checked", "true");
+ }
},
true
);
if (option.value === initialValue) {
- radioButton.checked = true;
+ radioButton.setAttribute("checked", "true");
item.setAttribute("checked", "true");
}
}
@@ -1124,6 +1214,121 @@ AboutReader.prototype = {
);
},
+ _handleColorsTabClick(option) {
+ let doc = this._doc;
+ if (option == "customtheme") {
+ this._setColorSchemePref("custom");
+ lazy.AsyncPrefs.set("reader.color_scheme", "custom");
+
+ // Store the last selected preset theme button.
+ const colorSchemePresets = doc.querySelector(
+ ".colors-menu-color-scheme-buttons"
+ );
+ const labels = colorSchemePresets.querySelectorAll("label");
+ labels.forEach(label => {
+ if (label.hasAttribute("checked")) {
+ lastSelectedTheme = label.className.split("-")[0];
+ }
+ });
+ }
+ if (option == "fxtheme") {
+ this._setColorSchemePref(lastSelectedTheme);
+ lazy.AsyncPrefs.set("reader.color_scheme", lastSelectedTheme);
+ // set the last selected button to checked.
+ const colorSchemePresets = doc.querySelector(
+ ".colors-menu-color-scheme-buttons"
+ );
+ const labels = colorSchemePresets.querySelectorAll("label");
+ labels.forEach(label => {
+ if (label.className == `${lastSelectedTheme}-button`) {
+ label.setAttribute("checked", "true");
+ label.previousElementSibling.setAttribute("checked", "true");
+ }
+ });
+ }
+ },
+
+ _setupColorsTabs(options, callback) {
+ let doc = this._doc;
+ let colorScheme = Services.prefs.getCharPref("reader.color_scheme");
+ for (let option of options) {
+ let tabButton = doc.getElementById(`tabs-deck-button-${option}`);
+ // Open custom theme tab if color scheme is set to custom.
+ if (option == "customtheme" && colorScheme == "custom") {
+ tabButton.click();
+ }
+ tabButton.addEventListener(
+ "click",
+ function (aEvent) {
+ if (!aEvent.isTrusted) {
+ return;
+ }
+
+ callback(option);
+ },
+ true
+ );
+ }
+ },
+
+ _setupColorInput(prop) {
+ let doc = this._doc;
+ let input = doc.createElement("color-input");
+ input.setAttribute("prop-name", prop);
+ let labelL10nId = `about-reader-custom-colors-${prop}`;
+ input.setAttribute("data-l10n-id", labelL10nId);
+
+ let pref = `reader.custom_colors.${prop}`;
+ let customColor = Services.prefs.getStringPref(pref, "");
+ // Set the swatch color from prefs if one has been set.
+ if (customColor) {
+ input.setAttribute("color", customColor);
+ } else {
+ let defaultColor = DEFAULT_COLORS[prop];
+ input.setAttribute("color", defaultColor);
+ }
+
+ // Attach event listener to update the pref and page colors on input.
+ input.addEventListener("color-picked", e => {
+ const cssPropToUpdate = `--custom-theme-${prop}`;
+ this._doc.body.style.setProperty(cssPropToUpdate, e.detail);
+
+ const prefToUpdate = `reader.custom_colors.${prop}`;
+ lazy.AsyncPrefs.set(prefToUpdate, e.detail);
+ });
+
+ return input;
+ },
+
+ _setupCustomColors(options, id) {
+ let doc = this._doc;
+ const list = doc.getElementsByClassName(id)[0];
+
+ for (let option of options) {
+ let listItem = doc.createElement("li");
+ let colorInput = this._setupColorInput(option);
+ listItem.appendChild(colorInput);
+ list.appendChild(listItem);
+ }
+ },
+
+ _resetCustomColors() {
+ // Need to reset prefs, page colors, and color inputs.
+ const colorInputs = this._doc.querySelectorAll("color-input");
+ colorInputs.forEach(input => {
+ let property = input.getAttribute("prop-name");
+ let pref = `reader.custom_colors.${property}`;
+ lazy.AsyncPrefs.set(pref, "");
+
+ // Set css props to empty strings so they use fallback value.
+ let cssProp = `--custom-theme-${property}`;
+ this._doc.body.style.setProperty(cssProp, "");
+
+ let defaultColor = DEFAULT_COLORS[property];
+ input.setAttribute("color", defaultColor);
+ });
+ },
+
_toggleDropdownClicked(event) {
let dropdown = event.target.closest(".dropdown");
@@ -1143,7 +1348,7 @@ AboutReader.prototype = {
/*
* If the ReaderView banner font-dropdown is closed, open it.
*/
- _openDropdown(dropdown, window) {
+ _openDropdown(dropdown) {
if (dropdown.classList.contains("open")) {
return;
}
diff --git a/toolkit/components/reader/ReaderMode.sys.mjs b/toolkit/components/reader/ReaderMode.sys.mjs
index 4b754d88b0..c2561bfb23 100644
--- a/toolkit/components/reader/ReaderMode.sys.mjs
+++ b/toolkit/components/reader/ReaderMode.sys.mjs
@@ -273,11 +273,11 @@ export var ReaderMode = {
"READER_MODE_DOWNLOAD_RESULT"
);
return new Promise((resolve, reject) => {
- let xhr = new XMLHttpRequest();
+ let xhr = new XMLHttpRequest({ mozAnon: false });
xhr.open("GET", url, true);
xhr.onerror = evt => reject(evt.error);
xhr.responseType = docContentType === "text/plain" ? "text" : "document";
- xhr.onload = evt => {
+ xhr.onload = () => {
if (xhr.status !== 200) {
reject("Reader mode XHR failed with status: " + xhr.status);
histogram.add(DOWNLOAD_ERROR_XHR);
diff --git a/toolkit/components/reader/color-input.css b/toolkit/components/reader/color-input.css
new file mode 100644
index 0000000000..93e269dd16
--- /dev/null
+++ b/toolkit/components/reader/color-input.css
@@ -0,0 +1,47 @@
+/* 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/. */
+
+.color-input-container {
+ display: flex;
+ position: relative;
+ justify-content: flex-start;
+ align-items: center;
+ gap: var(--space-small);
+ min-height: 46px;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ padding: 0 var(--space-small);
+ border-radius: var(--border-radius-small);
+}
+
+.color-input-container:hover {
+ background-color: var(--toolbar-button-background-hover);
+}
+
+#color-swatch:focus-visible {
+ outline: none;
+}
+
+.color-input-container:focus-within {
+ outline: 2px solid var(--primary-color);
+ outline-offset: var(--focus-outline-offset);
+}
+
+.icon-container {
+ display: flex;
+ margin-inline: auto var(--space-xsmall);
+}
+
+#color-swatch {
+ appearance: none;
+ width: 34px;
+ height: 34px;
+ background-color: transparent;
+ border: none;
+ cursor: pointer;
+}
+
+#color-swatch::-moz-color-swatch {
+ border-radius: var(--border-radius-circle);
+ border: 1px solid rgba(0, 0, 0, 0.25);
+}
diff --git a/toolkit/components/reader/color-input.mjs b/toolkit/components/reader/color-input.mjs
new file mode 100644
index 0000000000..1c460dac3e
--- /dev/null
+++ b/toolkit/components/reader/color-input.mjs
@@ -0,0 +1,69 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import { html } from "chrome://global/content/vendor/lit.all.mjs";
+import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
+
+/**
+ * @tagname color-input
+ * @property {string} color - The initial color value as a hex code.
+ * @property {string} propName - The property that the color input sets.
+ * @property {string} l10nId - l10nId for label text.
+ */
+export default class ColorInput extends MozLitElement {
+ static properties = {
+ color: { type: String },
+ propName: { type: String, attribute: "prop-name" },
+ l10nId: { type: String, attribute: "data-l10n-id" },
+ };
+
+ static queries = {
+ inputEl: "#color-swatch",
+ };
+
+ handleColorInput(event) {
+ this.color = event.target.value;
+ this.dispatchEvent(
+ new CustomEvent("color-picked", {
+ detail: this.color,
+ })
+ );
+ }
+
+ /* Function to launch color picker when the user clicks anywhere in the container. */
+ handleClick(event) {
+ // If the user directly clicks the color swatch, no need to propagate click.
+ if (event.target.matches("input")) {
+ return;
+ }
+ this.inputEl.click();
+ }
+
+ render() {
+ return html`
+ <link
+ rel="stylesheet"
+ href="chrome://global/content/reader/color-input.css"
+ />
+ <div class="color-input-container" @click="${this.handleClick}">
+ <input
+ type="color"
+ name="${this.propName}"
+ .value="${this.color}"
+ id="color-swatch"
+ @input="${this.handleColorInput}"
+ />
+ <label for="color-swatch" data-l10n-id=${this.l10nId}></label>
+ <div class="icon-container">
+ <img
+ class="icon"
+ role="presentation"
+ src="chrome://global/skin/icons/edit-outline.svg"
+ />
+ </div>
+ </div>
+ `;
+ }
+}
+customElements.define("color-input", ColorInput);
diff --git a/toolkit/components/reader/color-input.stories.mjs b/toolkit/components/reader/color-input.stories.mjs
new file mode 100644
index 0000000000..cec85a8d98
--- /dev/null
+++ b/toolkit/components/reader/color-input.stories.mjs
@@ -0,0 +1,32 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import { html } from "../../content/widgets/vendor/lit.all.mjs";
+// eslint-disable-next-line import/no-unassigned-import
+import "chrome://global/content/reader/color-input.mjs";
+
+export default {
+ title: "Domain-specific UI Widgets/Reader View/Color Input",
+ component: "color-input",
+ argTypes: {},
+ parameters: {
+ status: "stable",
+ fluent: `moz-color-input-label = Background`,
+ },
+};
+
+const Template = ({ color, propName, labelL10nId }) => html`
+ <color-input
+ color=${color}
+ data-l10n-id=${labelL10nId}
+ prop-name=${propName}
+ ></color-input>
+`;
+
+export const Default = Template.bind({});
+Default.args = {
+ propName: "background",
+ color: "#7293C9",
+ labelL10nId: "moz-color-input-label",
+};
diff --git a/toolkit/components/reader/content/aboutReader.html b/toolkit/components/reader/content/aboutReader.html
index db93e9f80b..d1c9164d42 100644
--- a/toolkit/components/reader/content/aboutReader.html
+++ b/toolkit/components/reader/content/aboutReader.html
@@ -14,11 +14,23 @@
<meta name="viewport" content="width=device-width; user-scalable=0" />
<link
rel="stylesheet"
+ href="chrome://global/skin/design-system/tokens-brand.css"
+ />
+ <link
+ rel="stylesheet"
href="chrome://global/skin/aboutReader.css"
type="text/css"
/>
<link rel="localization" href="toolkit/about/aboutReader.ftl" />
<link rel="localization" href="toolkit/branding/brandings.ftl" />
+ <script
+ type="module"
+ src="chrome://global/content/reader/color-input.mjs"
+ ></script>
+ <script
+ type="module"
+ src="chrome://global/content/elements/named-deck.js"
+ ></script>
</head>
<body>
@@ -53,7 +65,6 @@
</button>
</li>
<li class="dropdown-popup">
- <div class="dropdown-arrow"></div>
<div class="font-type-buttons radiorow"></div>
<div class="font-size-buttons buttonrow">
<button
@@ -88,7 +99,63 @@
data-l10n-id="about-reader-toolbar-lineheightplus"
></button>
</div>
- <div class="color-scheme-buttons radiorow"></div>
+ <div
+ class="color-scheme-buttons radiorow"
+ id="regular-color-scheme"
+ hidden="false"
+ ></div>
+ </li>
+ </ul>
+ <ul
+ class="dropdown colors-dropdown"
+ id="custom-colors-color-scheme"
+ hidden="true"
+ >
+ <li>
+ <button
+ class="dropdown-toggle toolbar-button colors-button"
+ aria-labelledby="toolbar-color-controls"
+ data-telemetry-id="reader-color-controls"
+ >
+ <span
+ class="hover-label"
+ id="toolbar-color-controls"
+ data-l10n-id="about-reader-toolbar-color-controls"
+ ></span>
+ </button>
+ </li>
+ <li class="dropdown-popup" id="color-controls">
+ <h2
+ data-l10n-id="about-reader-colors-menu-header"
+ id="about-reader-colors-menu-header"
+ ></h2>
+ <button-group aria-labelledby="about-reader-colors-menu-header">
+ <button
+ is="named-deck-button"
+ deck="tabs-deck"
+ name="fxtheme"
+ data-l10n-id="about-reader-fxtheme-tab"
+ ></button>
+ <button
+ is="named-deck-button"
+ deck="tabs-deck"
+ name="customtheme"
+ data-l10n-id="about-reader-customtheme-tab"
+ ></button>
+ </button-group>
+ <named-deck id="tabs-deck" is-tabbed>
+ <div
+ name="fxtheme"
+ class="colors-menu-color-scheme-buttons radiorow"
+ ></div>
+ <div name="customtheme">
+ <ul class="custom-colors-selection"></ul>
+ <button
+ class="custom-colors-reset-button"
+ data-l10n-id="about-reader-custom-colors-reset-button"
+ ></button>
+ </div>
+ </named-deck>
</li>
</ul>
</div>
diff --git a/toolkit/components/reader/jar.mn b/toolkit/components/reader/jar.mn
index 4b72136192..587dd45cf8 100644
--- a/toolkit/components/reader/jar.mn
+++ b/toolkit/components/reader/jar.mn
@@ -4,3 +4,5 @@
toolkit.jar:
content/global/reader/aboutReader.html (content/aboutReader.html)
+ content/global/reader/color-input.css (color-input.css)
+ content/global/reader/color-input.mjs (color-input.mjs)
diff --git a/toolkit/components/reader/moz.build b/toolkit/components/reader/moz.build
index e57a0fe705..dba7a5a2ef 100644
--- a/toolkit/components/reader/moz.build
+++ b/toolkit/components/reader/moz.build
@@ -22,7 +22,9 @@ EXTRA_JS_MODULES.reader = [
"ReaderWorker.sys.mjs",
]
-BROWSER_CHROME_MANIFESTS += ["test/browser.toml"]
+BROWSER_CHROME_MANIFESTS += ["tests/browser/browser.toml"]
+
+MOCHITEST_CHROME_MANIFESTS += ["tests/chrome/chrome.toml"]
with Files("**"):
BUG_COMPONENT = ("Toolkit", "Reader Mode")
diff --git a/toolkit/components/reader/test/browser.toml b/toolkit/components/reader/tests/browser/browser.toml
index 9382e6d60f..9382e6d60f 100644
--- a/toolkit/components/reader/test/browser.toml
+++ b/toolkit/components/reader/tests/browser/browser.toml
diff --git a/toolkit/components/reader/test/browser_bug1124271_readerModePinnedTab.js b/toolkit/components/reader/tests/browser/browser_bug1124271_readerModePinnedTab.js
index 346d503675..346d503675 100644
--- a/toolkit/components/reader/test/browser_bug1124271_readerModePinnedTab.js
+++ b/toolkit/components/reader/tests/browser/browser_bug1124271_readerModePinnedTab.js
diff --git a/toolkit/components/reader/test/browser_bug1453818_samesite_cookie.js b/toolkit/components/reader/tests/browser/browser_bug1453818_samesite_cookie.js
index 1fbfdeabfb..1fbfdeabfb 100644
--- a/toolkit/components/reader/test/browser_bug1453818_samesite_cookie.js
+++ b/toolkit/components/reader/tests/browser/browser_bug1453818_samesite_cookie.js
diff --git a/toolkit/components/reader/test/browser_bug1780350_readerModeSaveScroll.js b/toolkit/components/reader/tests/browser/browser_bug1780350_readerModeSaveScroll.js
index 76add5511e..76add5511e 100644
--- a/toolkit/components/reader/test/browser_bug1780350_readerModeSaveScroll.js
+++ b/toolkit/components/reader/tests/browser/browser_bug1780350_readerModeSaveScroll.js
diff --git a/toolkit/components/reader/test/browser_drag_url_readerMode.js b/toolkit/components/reader/tests/browser/browser_drag_url_readerMode.js
index 2dae1872c3..2dae1872c3 100644
--- a/toolkit/components/reader/test/browser_drag_url_readerMode.js
+++ b/toolkit/components/reader/tests/browser/browser_drag_url_readerMode.js
diff --git a/toolkit/components/reader/test/browser_localfile_readerMode.js b/toolkit/components/reader/tests/browser/browser_localfile_readerMode.js
index 118e4bb23f..118e4bb23f 100644
--- a/toolkit/components/reader/test/browser_localfile_readerMode.js
+++ b/toolkit/components/reader/tests/browser/browser_localfile_readerMode.js
diff --git a/toolkit/components/reader/test/browser_readerMode.js b/toolkit/components/reader/tests/browser/browser_readerMode.js
index a38e0a6de6..9093aa7fc1 100644
--- a/toolkit/components/reader/test/browser_readerMode.js
+++ b/toolkit/components/reader/tests/browser/browser_readerMode.js
@@ -23,7 +23,7 @@ ChromeUtils.defineESModuleGetters(this, {
add_task(async function test_reader_button() {
registerCleanupFunction(function () {
// Reset test prefs.
- TEST_PREFS.forEach(([name, value]) => {
+ TEST_PREFS.forEach(([name]) => {
Services.prefs.clearUserPref(name);
});
while (gBrowser.tabs.length > 1) {
diff --git a/toolkit/components/reader/test/browser_readerMode_bc_reuse.js b/toolkit/components/reader/tests/browser/browser_readerMode_bc_reuse.js
index 9ac0e367ca..9ac0e367ca 100644
--- a/toolkit/components/reader/test/browser_readerMode_bc_reuse.js
+++ b/toolkit/components/reader/tests/browser/browser_readerMode_bc_reuse.js
diff --git a/toolkit/components/reader/test/browser_readerMode_cached.js b/toolkit/components/reader/tests/browser/browser_readerMode_cached.js
index 7f36a15dbb..ca9dd4a447 100644
--- a/toolkit/components/reader/test/browser_readerMode_cached.js
+++ b/toolkit/components/reader/tests/browser/browser_readerMode_cached.js
@@ -7,7 +7,7 @@
// contained within it, so if the article gets reloaded instead of using
// the cached version, it would have a different value in it.
const URL =
- "http://mochi.test:8888/browser/toolkit/components/reader/test/readerModeRandom.sjs";
+ "http://mochi.test:8888/browser/toolkit/components/reader/tests/browser/readerModeRandom.sjs";
add_task(async function () {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URL);
diff --git a/toolkit/components/reader/test/browser_readerMode_colorSchemePref.js b/toolkit/components/reader/tests/browser/browser_readerMode_colorSchemePref.js
index 0bee6eaf05..73d3f160b8 100644
--- a/toolkit/components/reader/test/browser_readerMode_colorSchemePref.js
+++ b/toolkit/components/reader/tests/browser/browser_readerMode_colorSchemePref.js
@@ -65,3 +65,57 @@ add_task(async function () {
await testColorScheme(0, "sepia");
await testColorScheme(1, "sepia");
});
+
+async function testCustomColors(aPref, color) {
+ // Set the theme selection to custom.
+ Services.prefs.setBoolPref("reader.colors_menu.enabled", true);
+ Services.prefs.setCharPref("reader.color_scheme", "custom");
+
+ // Set the custom pref to the color value.
+ Services.prefs.setCharPref(`reader.custom_colors.${aPref}`, color);
+
+ // Open a browser tab, enter reader mode, and test if the page colors
+ // reflect the pref selection.
+ await BrowserTestUtils.withNewTab(
+ TEST_PATH + "readerModeArticle.html",
+ async function (browser) {
+ let pageShownPromise = BrowserTestUtils.waitForContentEvent(
+ browser,
+ "AboutReaderContentReady"
+ );
+
+ let readerButton = document.getElementById("reader-mode-button");
+ readerButton.click();
+ await pageShownPromise;
+
+ let colorScheme = Services.prefs.getCharPref("reader.color_scheme");
+ Assert.equal(colorScheme, "custom");
+ let prefValue = Services.prefs.getStringPref(
+ `reader.custom_colors.${aPref}`
+ );
+ let cssProp = `--custom-theme-${aPref}`;
+
+ await SpecialPowers.spawn(
+ browser,
+ [prefValue, cssProp],
+ (customColor, prop) => {
+ let style = content.window.getComputedStyle(content.document.body);
+ let actualColor = style.getPropertyValue(prop);
+ Assert.equal(customColor, actualColor);
+ }
+ );
+ }
+ );
+}
+
+/**
+ * Test that the custom color scheme selection updates the document colors correctly.
+ */
+add_task(async function () {
+ await testCustomColors("foreground", "#ffffff");
+ await testCustomColors("background", "#000000");
+ await testCustomColors("unvisited-links", "#ffffff");
+ await testCustomColors("visited-links", "#ffffff");
+ await testCustomColors("visited-links", "#ffffff");
+ await testCustomColors("selection-highlight", "#ffffff");
+});
diff --git a/toolkit/components/reader/test/browser_readerMode_hidden_nodes.js b/toolkit/components/reader/tests/browser/browser_readerMode_hidden_nodes.js
index d8e432a164..a6d058dfb1 100644
--- a/toolkit/components/reader/test/browser_readerMode_hidden_nodes.js
+++ b/toolkit/components/reader/tests/browser/browser_readerMode_hidden_nodes.js
@@ -18,7 +18,7 @@ var readerButton = document.getElementById("reader-mode-button");
add_task(async function test_reader_button() {
registerCleanupFunction(function () {
// Reset test prefs.
- TEST_PREFS.forEach(([name, value]) => {
+ TEST_PREFS.forEach(([name]) => {
Services.prefs.clearUserPref(name);
});
while (gBrowser.tabs.length > 1) {
diff --git a/toolkit/components/reader/test/browser_readerMode_menu.js b/toolkit/components/reader/tests/browser/browser_readerMode_menu.js
index 304fefa5d0..2c08faf4f9 100644
--- a/toolkit/components/reader/test/browser_readerMode_menu.js
+++ b/toolkit/components/reader/tests/browser/browser_readerMode_menu.js
@@ -41,28 +41,34 @@ add_task(async function () {
dispatchMouseEvent(win, target, "click");
}
- let doc = content.document;
- let win = content.window;
- let styleButton = doc.querySelector(".style-button");
+ async function testOpenCloseDropdown(target) {
+ let button = doc.querySelector(`.${target}-button`);
- let styleDropdown = doc.querySelector(".style-dropdown");
- ok(!styleDropdown.classList.contains("open"), "dropdown is closed");
+ let dropdown = doc.querySelector(`.${target}-dropdown`);
+ ok(!dropdown.classList.contains("open"), "dropdown is closed");
- simulateClick(styleButton);
- ok(styleDropdown.classList.contains("open"), "dropdown is open");
+ simulateClick(button);
+ ok(dropdown.classList.contains("open"), "dropdown is open");
- // simulate clicking on the article title to close the dropdown
- let title = doc.querySelector("h1");
- simulateClick(title);
- ok(!styleDropdown.classList.contains("open"), "dropdown is closed");
+ // simulate clicking on the article title to close the dropdown
+ let title = doc.querySelector(".reader-title");
+ simulateClick(title);
+ ok(!dropdown.classList.contains("open"), "dropdown is closed");
- // reopen the dropdown
- simulateClick(styleButton);
- ok(styleDropdown.classList.contains("open"), "dropdown is open");
+ // reopen the dropdown
+ simulateClick(button);
+ ok(dropdown.classList.contains("open"), "dropdown is open");
+
+ // now click on the button again to close it
+ simulateClick(button);
+ ok(!dropdown.classList.contains("open"), "dropdown is closed");
+ }
+
+ let doc = content.document;
+ let win = content.window;
- // now click on the button again to close it
- simulateClick(styleButton);
- ok(!styleDropdown.classList.contains("open"), "dropdown is closed");
+ testOpenCloseDropdown("style");
+ testOpenCloseDropdown("colors");
});
}
);
diff --git a/toolkit/components/reader/test/browser_readerMode_pocket.js b/toolkit/components/reader/tests/browser/browser_readerMode_pocket.js
index 43426383ff..43426383ff 100644
--- a/toolkit/components/reader/test/browser_readerMode_pocket.js
+++ b/toolkit/components/reader/tests/browser/browser_readerMode_pocket.js
diff --git a/toolkit/components/reader/test/browser_readerMode_readingTime.js b/toolkit/components/reader/tests/browser/browser_readerMode_readingTime.js
index 91631b6234..91631b6234 100644
--- a/toolkit/components/reader/test/browser_readerMode_readingTime.js
+++ b/toolkit/components/reader/tests/browser/browser_readerMode_readingTime.js
diff --git a/toolkit/components/reader/test/browser_readerMode_refresh.js b/toolkit/components/reader/tests/browser/browser_readerMode_refresh.js
index 00b4557f70..00b4557f70 100644
--- a/toolkit/components/reader/test/browser_readerMode_refresh.js
+++ b/toolkit/components/reader/tests/browser/browser_readerMode_refresh.js
diff --git a/toolkit/components/reader/test/browser_readerMode_remoteType.js b/toolkit/components/reader/tests/browser/browser_readerMode_remoteType.js
index c2510667c8..c2510667c8 100644
--- a/toolkit/components/reader/test/browser_readerMode_remoteType.js
+++ b/toolkit/components/reader/tests/browser/browser_readerMode_remoteType.js
diff --git a/toolkit/components/reader/test/browser_readerMode_samesite_cookie_redirect.js b/toolkit/components/reader/tests/browser/browser_readerMode_samesite_cookie_redirect.js
index 22703b9a81..22703b9a81 100644
--- a/toolkit/components/reader/test/browser_readerMode_samesite_cookie_redirect.js
+++ b/toolkit/components/reader/tests/browser/browser_readerMode_samesite_cookie_redirect.js
diff --git a/toolkit/components/reader/test/browser_readerMode_with_anchor.js b/toolkit/components/reader/tests/browser/browser_readerMode_with_anchor.js
index 229daaed9d..229daaed9d 100644
--- a/toolkit/components/reader/test/browser_readerMode_with_anchor.js
+++ b/toolkit/components/reader/tests/browser/browser_readerMode_with_anchor.js
diff --git a/toolkit/components/reader/test/getCookies.sjs b/toolkit/components/reader/tests/browser/getCookies.sjs
index 02e29fd877..02e29fd877 100644
--- a/toolkit/components/reader/test/getCookies.sjs
+++ b/toolkit/components/reader/tests/browser/getCookies.sjs
diff --git a/toolkit/components/reader/test/head.js b/toolkit/components/reader/tests/browser/head.js
index 5f9baf8fcd..5f9baf8fcd 100644
--- a/toolkit/components/reader/test/head.js
+++ b/toolkit/components/reader/tests/browser/head.js
diff --git a/toolkit/components/reader/test/linkToGetCookies.html b/toolkit/components/reader/tests/browser/linkToGetCookies.html
index 341046a21d..a05d32af4e 100644
--- a/toolkit/components/reader/test/linkToGetCookies.html
+++ b/toolkit/components/reader/tests/browser/linkToGetCookies.html
@@ -7,7 +7,7 @@
<article>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.</p>
- <p><a href="http://example.com/browser/toolkit/components/reader/test/getCookies.sjs" id="link">Cross-origin link to getCookies.html</a></p>
+ <p><a href="http://example.com/browser/toolkit/components/reader/tests/browser/getCookies.sjs" id="link">Cross-origin link to getCookies.html</a></p>
</article>
</body>
</html>
diff --git a/toolkit/components/reader/test/readerModeArticle.html b/toolkit/components/reader/tests/browser/readerModeArticle.html
index a0f1c64da0..a0f1c64da0 100644
--- a/toolkit/components/reader/test/readerModeArticle.html
+++ b/toolkit/components/reader/tests/browser/readerModeArticle.html
diff --git a/toolkit/components/reader/test/readerModeArticleContainsLink.html b/toolkit/components/reader/tests/browser/readerModeArticleContainsLink.html
index 871349adcd..be2d7d6469 100644
--- a/toolkit/components/reader/test/readerModeArticleContainsLink.html
+++ b/toolkit/components/reader/tests/browser/readerModeArticleContainsLink.html
@@ -12,7 +12,7 @@
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.</p>
<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
-<p><a href="http://example.com/browser/toolkit/components/reader/test/readerModeArticle.html" id="link">Link to another page.</a></p>
+<p><a href="http://example.com/browser/toolkit/components/reader/tests/browser/readerModeArticle.html" id="link">Link to another page.</a></p>
<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
</div>
diff --git a/toolkit/components/reader/test/readerModeArticleHiddenNodes.html b/toolkit/components/reader/tests/browser/readerModeArticleHiddenNodes.html
index 92441b7978..92441b7978 100644
--- a/toolkit/components/reader/test/readerModeArticleHiddenNodes.html
+++ b/toolkit/components/reader/tests/browser/readerModeArticleHiddenNodes.html
diff --git a/toolkit/components/reader/test/readerModeArticleMedium.html b/toolkit/components/reader/tests/browser/readerModeArticleMedium.html
index 70b172cf63..70b172cf63 100644
--- a/toolkit/components/reader/test/readerModeArticleMedium.html
+++ b/toolkit/components/reader/tests/browser/readerModeArticleMedium.html
diff --git a/toolkit/components/reader/test/readerModeArticleShort.html b/toolkit/components/reader/tests/browser/readerModeArticleShort.html
index 692471f27f..692471f27f 100644
--- a/toolkit/components/reader/test/readerModeArticleShort.html
+++ b/toolkit/components/reader/tests/browser/readerModeArticleShort.html
diff --git a/toolkit/components/reader/test/readerModeArticleTextPlain.txt b/toolkit/components/reader/tests/browser/readerModeArticleTextPlain.txt
index c5b7861b73..c5b7861b73 100644
--- a/toolkit/components/reader/test/readerModeArticleTextPlain.txt
+++ b/toolkit/components/reader/tests/browser/readerModeArticleTextPlain.txt
diff --git a/toolkit/components/reader/test/readerModeNonArticle.html b/toolkit/components/reader/tests/browser/readerModeNonArticle.html
index e216af3c1f..e216af3c1f 100644
--- a/toolkit/components/reader/test/readerModeNonArticle.html
+++ b/toolkit/components/reader/tests/browser/readerModeNonArticle.html
diff --git a/toolkit/components/reader/test/readerModeRandom.sjs b/toolkit/components/reader/tests/browser/readerModeRandom.sjs
index f6bb15c06a..f6bb15c06a 100644
--- a/toolkit/components/reader/test/readerModeRandom.sjs
+++ b/toolkit/components/reader/tests/browser/readerModeRandom.sjs
diff --git a/toolkit/components/reader/test/setSameSiteCookie.html b/toolkit/components/reader/tests/browser/setSameSiteCookie.html
index 67bb714922..67bb714922 100644
--- a/toolkit/components/reader/test/setSameSiteCookie.html
+++ b/toolkit/components/reader/tests/browser/setSameSiteCookie.html
diff --git a/toolkit/components/reader/test/setSameSiteCookie.html^headers^ b/toolkit/components/reader/tests/browser/setSameSiteCookie.html^headers^
index c0229c93b6..c0229c93b6 100644
--- a/toolkit/components/reader/test/setSameSiteCookie.html^headers^
+++ b/toolkit/components/reader/tests/browser/setSameSiteCookie.html^headers^
diff --git a/toolkit/components/reader/tests/chrome/chrome.toml b/toolkit/components/reader/tests/chrome/chrome.toml
new file mode 100644
index 0000000000..e416c49181
--- /dev/null
+++ b/toolkit/components/reader/tests/chrome/chrome.toml
@@ -0,0 +1,3 @@
+[DEFAULT]
+
+["test_color_input.html"]
diff --git a/toolkit/components/reader/tests/chrome/test_color_input.html b/toolkit/components/reader/tests/chrome/test_color_input.html
new file mode 100644
index 0000000000..4cd8cde77b
--- /dev/null
+++ b/toolkit/components/reader/tests/chrome/test_color_input.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>ColorInput Tests</title>
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+ <script type="module" src="chrome://global/content/reader/color-input.mjs"></script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: block">
+ <color-input color="#ffffff" prop-name="test-prop" data-l10n-id="color-input-test-label"></color-input>
+</div>
+<pre id="test">
+ <script class="testbody" type="application/javascript">
+ add_task(async function testColorInput() {
+ const colorInput = document.querySelector("color-input");
+ ok(colorInput, "color input element is rendered");
+
+ let input = colorInput.shadowRoot.querySelector("input");
+ is(input.value, "#ffffff", "color input has the correct initial value");
+ });
+ add_task(async function testColorInputEvents() {
+ const colorInput = document.querySelector("color-input");
+ let input = colorInput.shadowRoot.querySelector("input");
+
+ const pickedColor = new Promise((resolve) => {
+ colorInput.addEventListener("color-picked", (event) => resolve(event.detail), { once: true });
+ });
+ input.value = "#0000ff";
+ input.dispatchEvent(new Event("input"));
+ let color = await pickedColor;
+ is(color, "#0000ff", "color-picked event dispatches on input");
+ });
+ </script>
+</pre>
+</body>
+</html>