зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1820477 - Remove Colorway Closet modal code. r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D174861
This commit is contained in:
Родитель
b8a4804d09
Коммит
2595ca85bd
|
@ -239,7 +239,6 @@ module.exports = {
|
|||
"browser/components/Browser*",
|
||||
"browser/components/aboutlogins/**",
|
||||
"browser/components/attribution/**",
|
||||
"browser/components/colorways/**",
|
||||
"browser/components/customizableui/**",
|
||||
"browser/components/downloads/**",
|
||||
"browser/components/enterprisepolicies/**",
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["ColorwayClosetOpener"];
|
||||
|
||||
const { BrowserWindowTracker } = ChromeUtils.import(
|
||||
"resource:///modules/BrowserWindowTracker.jsm"
|
||||
);
|
||||
|
||||
let ColorwayClosetOpener = {
|
||||
/**
|
||||
* Opens the colorway closet modal.
|
||||
* @param {String} source
|
||||
* Indicates from where the modal was opened, and it is used for existing telemetry probes.
|
||||
* Valid "source" types include: "aboutaddons", "firefoxview" and "unknown" (default).
|
||||
* @param {Function} onClosed
|
||||
* Function that is called after the modal is closed.
|
||||
* @See Events.yaml for existing colorway closet probes
|
||||
*/
|
||||
openModal: ({ source = "unknown", onClosed = null } = {}) => {
|
||||
let { gBrowser } = BrowserWindowTracker.getTopWindow();
|
||||
let dialogBox = gBrowser.getTabDialogBox(gBrowser.selectedBrowser);
|
||||
return dialogBox.open(
|
||||
"chrome://browser/content/colorways/colorwaycloset.html",
|
||||
{
|
||||
features: "resizable=no",
|
||||
sizeTo: "available",
|
||||
},
|
||||
{ source, onClosed }
|
||||
);
|
||||
},
|
||||
};
|
|
@ -1,268 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
:root {
|
||||
height: 100%;
|
||||
|
||||
/* This will give us a larger base font size on macOS: */
|
||||
font: menu;
|
||||
|
||||
--body-columns: 1fr;
|
||||
--body-rows: auto auto 1fr auto;
|
||||
|
||||
--figure-width: min(37.5vw, 300px);
|
||||
|
||||
--card-border-zap-gradient: linear-gradient(90deg, #9059FF 0%, #FF4AA2 52.08%, #FFBD4F 100%);
|
||||
|
||||
--colorway-selector-align: center;
|
||||
--colorway-name-font-size: 1.5em;
|
||||
|
||||
--homepage-reset-column: 1;
|
||||
--homepage-reset-align: start;
|
||||
}
|
||||
|
||||
@media (max-width: 560px) {
|
||||
:root {
|
||||
--font-scale: 0.9em;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
:root {
|
||||
--body-columns: 1em auto 1fr;
|
||||
--body-rows: auto 1fr auto;
|
||||
|
||||
--header-column: 2/4;
|
||||
|
||||
--figure-column: 2;
|
||||
--figure-row: 2;
|
||||
|
||||
--customization-panel-column: 3;
|
||||
--customization-panel-padding-inline-start: 2.5em;
|
||||
|
||||
--colorway-selector-align: start;
|
||||
--colorway-name-font-size: 2em;
|
||||
|
||||
--homepage-reset-column: 1/4;
|
||||
--homepage-reset-align: end;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: var(--body-columns);
|
||||
grid-template-rows: var(--body-rows);
|
||||
padding: 0 2em 1em;
|
||||
box-sizing: border-box;
|
||||
font-size: var(--font-scale);
|
||||
}
|
||||
|
||||
fieldset {
|
||||
border: unset;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
|
||||
body > header {
|
||||
grid-row: 1;
|
||||
margin-top: 1em;
|
||||
grid-column: var(--header-column);
|
||||
}
|
||||
|
||||
#collection-title {
|
||||
display: inline-block;
|
||||
margin-inline: 0 .7em;
|
||||
margin-block: 0 .2em;
|
||||
padding: 0;
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#collection-expiry-date {
|
||||
display: inline-block;
|
||||
background: var(--card-border-zap-gradient);
|
||||
background-origin: border-box;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 1.5em;
|
||||
}
|
||||
|
||||
#collection-expiry-date > span {
|
||||
display: inline-block;
|
||||
color: var(--in-content-page-color);
|
||||
background: var(--in-content-page-background);
|
||||
border-radius: 1.5em;
|
||||
padding: .3em 1em;
|
||||
}
|
||||
|
||||
/* Illustration */
|
||||
|
||||
figure {
|
||||
grid-column: var(--figure-column);
|
||||
grid-row: var(--figure-row);
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
margin: 1em 0 0;
|
||||
min-width: var(--figure-width);
|
||||
min-height: var(--figure-width);
|
||||
}
|
||||
|
||||
figure > img {
|
||||
max-width: var(--figure-width);
|
||||
max-height: var(--figure-width);
|
||||
object-fit: scale-down;
|
||||
}
|
||||
|
||||
/* Selector and colorway details */
|
||||
|
||||
#colorway-customization-panel {
|
||||
align-self: stretch;
|
||||
padding-inline-start: var(--customization-panel-padding-inline-start);
|
||||
grid-column: var(--customization-panel-column);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#colorway-customization-panel > * {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
#colorway-selector,
|
||||
#modal-buttons {
|
||||
flex: 3;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#colorway-selector {
|
||||
justify-content: var(--colorway-selector-align);
|
||||
}
|
||||
|
||||
#colorway-selector > input[type="radio"],
|
||||
#colorway-selector > input[type="radio"]:checked {
|
||||
box-sizing: content-box;
|
||||
padding: 2px;
|
||||
border: 2px solid transparent;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
--colorway-icon: none;
|
||||
appearance: none;
|
||||
background-color: unset;
|
||||
background-image: var(--colorway-icon);
|
||||
background-origin: content-box;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
/* The icon may not be a perfect circle, so we render it bigger and clipped using background-clip and border-radius: */
|
||||
background-clip: content-box;
|
||||
background-size: 105%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
#colorway-selector > input[type="radio"]:enabled:checked,
|
||||
#colorway-selector > input[type="radio"]:enabled:checked:hover {
|
||||
border-color: var(--in-content-accent-color);
|
||||
}
|
||||
|
||||
/* override common-shared.css */
|
||||
#colorway-selector > input[type="radio"]:is(:enabled:hover, :enabled:hover:active, :checked, :enabled:checked:hover, :enabled:checked:hover:active) {
|
||||
background-color: unset;
|
||||
}
|
||||
|
||||
#colorway-name {
|
||||
font-size: var(--colorway-name-font-size);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#colorway-description {
|
||||
line-height: 1.5;
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
/* Intensity Picker */
|
||||
|
||||
#colorway-intensities > legend {
|
||||
padding-inline-start: 0;
|
||||
margin-bottom: .5em;
|
||||
color: var(--in-content-deemphasized-text);
|
||||
}
|
||||
|
||||
#colorway-intensity-radios {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: .5em;
|
||||
}
|
||||
|
||||
#colorway-intensity-radios > label {
|
||||
background-color: var(--in-content-box-background-color);
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--in-content-border-color);
|
||||
color: var(--in-content-text-color);
|
||||
|
||||
flex: 1;
|
||||
overflow: clip;
|
||||
padding: .5em;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.colorway-intensity-radio {
|
||||
margin-block: 0 !important;
|
||||
}
|
||||
|
||||
#set-colorway {
|
||||
margin-inline-start: 0;
|
||||
}
|
||||
|
||||
/* Homepage reset footer */
|
||||
|
||||
#homepage-reset-container:not([hidden]) {
|
||||
display: flex;
|
||||
grid-column: var(--homepage-reset-column);
|
||||
}
|
||||
|
||||
#homepage-reset-prompt,
|
||||
#homepage-reset-success {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
align-items: center;
|
||||
justify-content: var(--homepage-reset-align);
|
||||
}
|
||||
|
||||
#homepage-reset-prompt > span,
|
||||
#homepage-reset-success > span {
|
||||
padding-inline-end: 1em;
|
||||
}
|
||||
|
||||
#homepage-reset-container:not(.success) > #homepage-reset-success,
|
||||
#homepage-reset-container.success > #homepage-reset-prompt {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#homepage-reset-success > span {
|
||||
position: relative;
|
||||
padding-inline-start: calc(22px + .5em);
|
||||
}
|
||||
|
||||
#homepage-reset-success > span::before {
|
||||
content: "";
|
||||
|
||||
background: var(--green-70) url('chrome://global/skin/icons/check.svg') center center no-repeat;
|
||||
-moz-context-properties: fill;
|
||||
fill: white;
|
||||
border-radius: 100%;
|
||||
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
|
||||
position: absolute;
|
||||
inset-inline-start: 0;
|
||||
inset-block-start: calc((1em - 22px) / 2);
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
<!-- 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/. -->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html style="max-width: 67em; max-height: 40em;">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Security-Policy"
|
||||
content="default-src chrome:; object-src 'none'">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title data-l10n-id="colorways-modal-title"></title>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://global/skin/in-content/common.css">
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://browser/content/colorways/colorwaycloset.css">
|
||||
<link rel="localization" href="branding/brand.ftl">
|
||||
<link rel="localization" href="toolkit/branding/brandings.ftl">
|
||||
<link rel="localization" href="browser/colorwaycloset.ftl">
|
||||
<link rel="localization" href="browser/colorways.ftl">
|
||||
<script src="chrome://browser/content/colorways/colorwaycloset.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1 id="collection-title"></h1>
|
||||
<span id="collection-expiry-date"><span></span></span>
|
||||
</header>
|
||||
<figure role="presentation">
|
||||
<img id="colorway-figure" role="presentation">
|
||||
</figure>
|
||||
<main id="colorway-customization-panel">
|
||||
<fieldset id="colorway-selector"></fieldset>
|
||||
<h2 id="colorway-name"></h2>
|
||||
<p id="colorway-description"></p>
|
||||
<fieldset id="colorway-intensities">
|
||||
<legend data-l10n-id="colorway-intensity-selector-label"></legend>
|
||||
<div id="colorway-intensity-radios">
|
||||
<label>
|
||||
<input type="radio" name="intensity" class="colorway-intensity-radio" data-intensity="soft">
|
||||
<span data-l10n-id="colorway-intensity-soft"></span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="intensity" class="colorway-intensity-radio" data-intensity="balanced">
|
||||
<span data-l10n-id="colorway-intensity-balanced"></span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="intensity" class="colorway-intensity-radio" data-intensity="bold">
|
||||
<span data-l10n-id="colorway-intensity-bold"></span>
|
||||
</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset id="modal-buttons">
|
||||
<button id="set-colorway" data-l10n-id="colorway-closet-set-colorway-button" class="primary"></button>
|
||||
<button id="cancel" data-l10n-id="colorway-closet-cancel-button"></button>
|
||||
</fieldset>
|
||||
</main>
|
||||
<footer id="homepage-reset-container" hidden>
|
||||
<div id="homepage-reset-prompt">
|
||||
<span data-l10n-id="colorway-homepage-reset-prompt"></span>
|
||||
<button data-l10n-id="colorway-homepage-reset-apply-button"></button>
|
||||
</div>
|
||||
<div id="homepage-reset-success">
|
||||
<span data-l10n-id="colorway-homepage-reset-success-message"></span>
|
||||
<button data-l10n-id="colorway-homepage-reset-undo-button"></button>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
|
@ -1,332 +0,0 @@
|
|||
/* 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/. */
|
||||
"use strict";
|
||||
|
||||
const { BuiltInThemes } = ChromeUtils.importESModule(
|
||||
"resource:///modules/BuiltInThemes.sys.mjs"
|
||||
);
|
||||
|
||||
const { AddonManager } = ChromeUtils.import(
|
||||
"resource://gre/modules/AddonManager.jsm"
|
||||
);
|
||||
|
||||
const INTENSITY_SOFT = "soft";
|
||||
const INTENSITY_BALANCED = "balanced";
|
||||
const INTENSITY_BOLD = "bold";
|
||||
const ID_SUFFIX_COLORWAY = "-colorway@mozilla.org";
|
||||
const ID_SUFFIX_PRIMARY_INTENSITY = `-${INTENSITY_BALANCED}${ID_SUFFIX_COLORWAY}`;
|
||||
const ID_SUFFIX_DARK_COLORWAY = `-${INTENSITY_BOLD}${ID_SUFFIX_COLORWAY}`;
|
||||
const ID_SUFFIXES_FOR_SECONDARY_INTENSITIES = new RegExp(
|
||||
`-(${INTENSITY_SOFT}|${INTENSITY_BOLD})-colorway@mozilla\\.org$`
|
||||
);
|
||||
const MATCH_INTENSITY_FROM_ID = new RegExp(
|
||||
`-(${INTENSITY_SOFT}|${INTENSITY_BALANCED}|${INTENSITY_BOLD})-colorway@mozilla\\.org$`
|
||||
);
|
||||
|
||||
/**
|
||||
* Helper for colorway closet related telemetry probes.
|
||||
*/
|
||||
const ColorwaysTelemetry = {
|
||||
init() {
|
||||
Services.telemetry.setEventRecordingEnabled("colorways_modal", true);
|
||||
},
|
||||
|
||||
recordEvent(telemetryEventData) {
|
||||
if (!telemetryEventData || !Object.entries(telemetryEventData).length) {
|
||||
console.error("Unable to record event due to missing telemetry data");
|
||||
return;
|
||||
}
|
||||
|
||||
if (telemetryEventData.source && ColorwayCloset.previousTheme?.id) {
|
||||
telemetryEventData.method = BuiltInThemes.isColorwayFromCurrentCollection(
|
||||
ColorwayCloset.previousTheme.id
|
||||
)
|
||||
? "change_colorway"
|
||||
: "try_colorways";
|
||||
telemetryEventData.object = telemetryEventData.source;
|
||||
}
|
||||
Services.telemetry.recordEvent(
|
||||
"colorways_modal",
|
||||
telemetryEventData.method,
|
||||
telemetryEventData.object,
|
||||
telemetryEventData.value || null,
|
||||
telemetryEventData.extraKeys || null
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
const ColorwayCloset = {
|
||||
// This is essentially an instant-apply dialog, but we make an effort to only
|
||||
// keep the theme change if the user hits the "Set colorway" button, and
|
||||
// otherwise revert to the previous theme upon closing the modal. However,
|
||||
// this doesn't cover the application quitting while the modal is open, in
|
||||
// which case the theme change will be kept.
|
||||
revertToPreviousTheme: true,
|
||||
|
||||
el: {
|
||||
colorwayRadios: document.getElementById("colorway-selector"),
|
||||
intensityContainer: document.getElementById("colorway-intensities"),
|
||||
colorwayFigure: document.getElementById("colorway-figure"),
|
||||
colorwayName: document.getElementById("colorway-name"),
|
||||
collectionTitle: document.getElementById("collection-title"),
|
||||
colorwayDescription: document.getElementById("colorway-description"),
|
||||
expiryDateSpan: document.querySelector("#collection-expiry-date > span"),
|
||||
setColorwayButton: document.getElementById("set-colorway"),
|
||||
cancelButton: document.getElementById("cancel"),
|
||||
homepageResetContainer: document.getElementById("homepage-reset-container"),
|
||||
},
|
||||
|
||||
init() {
|
||||
window.addEventListener("unload", this);
|
||||
|
||||
ColorwaysTelemetry.init();
|
||||
|
||||
this._displayCollectionData();
|
||||
|
||||
AddonManager.addAddonListener(this);
|
||||
this._initColorwayRadios().then(() => {
|
||||
this.el.colorwayRadios.addEventListener("change", this);
|
||||
this.el.intensityContainer.addEventListener("change", this);
|
||||
|
||||
let args = window?.arguments?.[0];
|
||||
// Record telemetry probes that are called upon opening the modal.
|
||||
ColorwaysTelemetry.recordEvent(args);
|
||||
|
||||
this.el.setColorwayButton.onclick = () => {
|
||||
this.revertToPreviousTheme = false;
|
||||
window.close();
|
||||
};
|
||||
});
|
||||
|
||||
this.el.cancelButton.onclick = () => {
|
||||
window.close();
|
||||
};
|
||||
|
||||
this._displayHomepageResetOption();
|
||||
},
|
||||
|
||||
async _initColorwayRadios() {
|
||||
BuiltInThemes.ensureBuiltInThemes();
|
||||
let themes = await AddonManager.getAddonsByTypes(["theme"]);
|
||||
this.previousTheme = themes.find(theme => theme.isActive);
|
||||
this.colorways = themes.filter(theme =>
|
||||
BuiltInThemes.isColorwayFromCurrentCollection(theme.id)
|
||||
);
|
||||
|
||||
// The radio buttons represent colorway "groups". A group is a colorway
|
||||
// from the current collection to represent related colorways with another
|
||||
// intensity. If the current collection doesn't have intensities, each
|
||||
// colorway is their own group.
|
||||
this.colorwayGroups = this.colorways.filter(
|
||||
colorway => !ID_SUFFIXES_FOR_SECONDARY_INTENSITIES.test(colorway.id)
|
||||
);
|
||||
|
||||
for (const addon of this.colorwayGroups) {
|
||||
let input = document.createElement("input");
|
||||
input.type = "radio";
|
||||
input.name = "colorway";
|
||||
input.value = addon.id;
|
||||
input.setAttribute("title", this._getColorwayGroupName(addon));
|
||||
if (addon.iconURL) {
|
||||
input.style.setProperty("--colorway-icon", `url(${addon.iconURL})`);
|
||||
}
|
||||
this.el.colorwayRadios.appendChild(input);
|
||||
}
|
||||
|
||||
// If the current active theme is part of our collection, make the UI reflect
|
||||
// that. Otherwise go ahead and enable the first colorway in our list.
|
||||
this.selectedColorway = this.colorways.find(colorway => colorway.isActive);
|
||||
if (this.selectedColorway) {
|
||||
this.refresh();
|
||||
} else {
|
||||
let colorwayToEnable = this.colorwayGroups[0];
|
||||
// If the user has been using a theme with a dark color scheme, make an
|
||||
// effort to default to a colorway with a dark color scheme as well.
|
||||
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
||||
let firstDarkColorway = this.colorways.find(colorway =>
|
||||
colorway.id.endsWith(ID_SUFFIX_DARK_COLORWAY)
|
||||
);
|
||||
colorwayToEnable = firstDarkColorway || colorwayToEnable;
|
||||
}
|
||||
colorwayToEnable.enable();
|
||||
}
|
||||
},
|
||||
|
||||
_displayHomepageResetOption() {
|
||||
const { HomePage } = ChromeUtils.import("resource:///modules/HomePage.jsm");
|
||||
this.el.homepageResetContainer.hidden = HomePage.isDefault;
|
||||
if (!HomePage.isDefault) {
|
||||
let homeState;
|
||||
this.el.homepageResetContainer
|
||||
.querySelector("#homepage-reset-prompt > button")
|
||||
.addEventListener("click", () => {
|
||||
ColorwaysTelemetry.recordEvent({
|
||||
method: "homepage_reset",
|
||||
object: "modal",
|
||||
});
|
||||
homeState = HomePage.get();
|
||||
HomePage.reset();
|
||||
this.el.homepageResetContainer.classList.add("success");
|
||||
});
|
||||
this.el.homepageResetContainer
|
||||
.querySelector("#homepage-reset-success > button")
|
||||
.addEventListener("click", () => {
|
||||
ColorwaysTelemetry.recordEvent({
|
||||
method: "homepage_reset_undo",
|
||||
object: "modal",
|
||||
});
|
||||
HomePage.set(homeState);
|
||||
this.el.homepageResetContainer.classList.remove("success");
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_displayCollectionData() {
|
||||
const collection = BuiltInThemes.findActiveColorwayCollection();
|
||||
if (!collection) {
|
||||
// Whoops. There should be no entry point to this UI without an active
|
||||
// collection.
|
||||
window.close();
|
||||
}
|
||||
document.l10n.setAttributes(
|
||||
this.el.collectionTitle,
|
||||
collection.l10nId.title
|
||||
);
|
||||
document.l10n.setAttributes(
|
||||
this.el.expiryDateSpan,
|
||||
"colorway-collection-expiry-label",
|
||||
{
|
||||
expiryDate: collection.expiry.getTime(),
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
_getFigureUrl() {
|
||||
return BuiltInThemes.builtInThemeMap.get(this.selectedColorway.id)
|
||||
.figureUrl;
|
||||
},
|
||||
|
||||
_displayColorwayData() {
|
||||
this.el.colorwayName.innerText = this._getColorwayGroupName(
|
||||
this.selectedColorway
|
||||
);
|
||||
this.el.colorwayDescription.innerText = this.selectedColorway.description;
|
||||
this.el.colorwayFigure.src = this._getFigureUrl();
|
||||
|
||||
this.el.intensityContainer.hidden = !this.hasIntensities;
|
||||
if (this.hasIntensities) {
|
||||
let selectedIntensity = this.selectedColorway.id.match(
|
||||
MATCH_INTENSITY_FROM_ID
|
||||
)[1];
|
||||
for (let radio of document.querySelectorAll(
|
||||
".colorway-intensity-radio"
|
||||
)) {
|
||||
let intensity = radio.getAttribute("data-intensity");
|
||||
radio.value = this._changeIntensity(
|
||||
this.selectedColorway.id,
|
||||
intensity
|
||||
);
|
||||
if (intensity == selectedIntensity) {
|
||||
radio.checked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_getColorwayGroupId(colorwayId) {
|
||||
let groupId = colorwayId.replace(
|
||||
ID_SUFFIXES_FOR_SECONDARY_INTENSITIES,
|
||||
ID_SUFFIX_PRIMARY_INTENSITY
|
||||
);
|
||||
return this.colorwayGroups.map(addon => addon.id).includes(groupId)
|
||||
? groupId
|
||||
: null;
|
||||
},
|
||||
|
||||
_changeIntensity(colorwayId, intensity) {
|
||||
return colorwayId.replace(
|
||||
MATCH_INTENSITY_FROM_ID,
|
||||
`-${intensity}${ID_SUFFIX_COLORWAY}`
|
||||
);
|
||||
},
|
||||
|
||||
_getColorwayGroupName(addon) {
|
||||
return BuiltInThemes.getLocalizedColorwayGroupName(addon.id) || addon.name;
|
||||
},
|
||||
|
||||
handleEvent(e) {
|
||||
switch (e.type) {
|
||||
case "change":
|
||||
let newId = e.target.value;
|
||||
// Persist the selected intensity when toggling between colorway radios.
|
||||
if (e.currentTarget == this.el.colorwayRadios && this.hasIntensities) {
|
||||
let selectedIntensity = document
|
||||
.querySelector(".colorway-intensity-radio:checked")
|
||||
.getAttribute("data-intensity");
|
||||
newId = this._changeIntensity(newId, selectedIntensity);
|
||||
}
|
||||
this.colorways.find(colorway => colorway.id == newId).enable();
|
||||
break;
|
||||
case "unload":
|
||||
AddonManager.removeAddonListener(this);
|
||||
if (this.revertToPreviousTheme) {
|
||||
this.previousTheme.enable();
|
||||
ColorwaysTelemetry.recordEvent({
|
||||
method: "cancel",
|
||||
object: "modal",
|
||||
});
|
||||
} else {
|
||||
ColorwaysTelemetry.recordEvent({
|
||||
method: "set_colorway",
|
||||
object: "modal",
|
||||
value: null,
|
||||
extraKeys: { colorway_id: this.selectedColorway.id },
|
||||
});
|
||||
}
|
||||
|
||||
// `onClosed` is an additional callback passed upon opening the modal.
|
||||
// Here, `onClosed` is passed by about:addons and is called after the
|
||||
// the modal closes. This is to defer re-rendering the about:addons page
|
||||
// until the user has closed the dialog by setting a new colorways theme
|
||||
// or pressing cancel to revert to the previous theme.
|
||||
const { onClosed } = window?.arguments?.[0] || {};
|
||||
onClosed?.({ colorwayChanged: !this.revertToPreviousTheme });
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
onEnabled(addon) {
|
||||
if (addon.type == "theme") {
|
||||
if (!this.colorways.find(colorway => colorway.id == addon.id)) {
|
||||
// The selected theme changed to a non-colorway from outside the modal.
|
||||
// This UI can't represent that state, so bail out.
|
||||
this.revertToPreviousTheme = false;
|
||||
window.close();
|
||||
return;
|
||||
}
|
||||
this.selectedColorway = addon;
|
||||
this.refresh();
|
||||
}
|
||||
},
|
||||
|
||||
refresh() {
|
||||
this.groupIdForSelectedColorway = this._getColorwayGroupId(
|
||||
this.selectedColorway.id
|
||||
);
|
||||
this.hasIntensities = this.groupIdForSelectedColorway.endsWith(
|
||||
ID_SUFFIX_PRIMARY_INTENSITY
|
||||
);
|
||||
for (let input of this.el.colorwayRadios.children) {
|
||||
if (input.value == this.groupIdForSelectedColorway) {
|
||||
input.checked = true;
|
||||
this._displayColorwayData();
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.el.setColorwayButton.disabled =
|
||||
this.previousTheme.id == this.selectedColorway.id;
|
||||
},
|
||||
};
|
||||
|
||||
ColorwayCloset.init();
|
|
@ -1,8 +0,0 @@
|
|||
# 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/.
|
||||
|
||||
browser.jar:
|
||||
content/browser/colorways/colorwaycloset.html
|
||||
content/browser/colorways/colorwaycloset.css
|
||||
content/browser/colorways/colorwaycloset.js
|
|
@ -1,14 +0,0 @@
|
|||
# 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/.
|
||||
|
||||
with Files("**"):
|
||||
BUG_COMPONENT = ("Firefox", "Theme")
|
||||
|
||||
JAR_MANIFESTS += ["jar.mn"]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
"ColorwayClosetOpener.jsm",
|
||||
]
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ["tests/browser/browser.ini"]
|
|
@ -1,8 +0,0 @@
|
|||
[DEFAULT]
|
||||
run-if = nightly_build
|
||||
support-files =
|
||||
head.js
|
||||
|
||||
[browser_colorwayCloset_modalButtons.js]
|
||||
[browser_colorwayCloset_modalUI.js]
|
||||
[browser_colorwayCloset_telemetry.js]
|
|
@ -1,158 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Tests that the selected colorway is still enabled after pressing the Set Colorway button
|
||||
* in the modal.
|
||||
*/
|
||||
add_task(async function colorwaycloset_modal_set_colorway() {
|
||||
await testInColorwayClosetModal(async (document, contentWindow) => {
|
||||
// Select colorway on modal
|
||||
info("Selecting colorway radio button");
|
||||
const {
|
||||
colorwayIntensities,
|
||||
setColorwayButton,
|
||||
} = getColorwayClosetTestElements(document);
|
||||
|
||||
// Select new intensity
|
||||
// Wait for intensity button to be initialized
|
||||
await BrowserTestUtils.waitForMutationCondition(
|
||||
colorwayIntensities,
|
||||
{ subtree: true, attributeFilter: ["value"] },
|
||||
() =>
|
||||
colorwayIntensities.querySelector(
|
||||
`input[value="${SOFT_COLORWAY_THEME_ID}"]`
|
||||
),
|
||||
"Waiting for intensity button to be available"
|
||||
);
|
||||
let intensitiesChangedPromise = BrowserTestUtils.waitForEvent(
|
||||
colorwayIntensities,
|
||||
"change",
|
||||
"Waiting for intensities change event"
|
||||
);
|
||||
let themeChangedPromise = waitForAddonEnabled(SOFT_COLORWAY_THEME_ID);
|
||||
|
||||
info("Selecting new intensity");
|
||||
colorwayIntensities
|
||||
.querySelector(`input[value="${SOFT_COLORWAY_THEME_ID}"]`)
|
||||
.click();
|
||||
await intensitiesChangedPromise;
|
||||
await themeChangedPromise;
|
||||
|
||||
// Set colorway
|
||||
await BrowserTestUtils.waitForMutationCondition(
|
||||
setColorwayButton,
|
||||
{ childList: true, attributeFilter: ["disabled"] },
|
||||
() => !setColorwayButton.disabled,
|
||||
"Waiting for set-colorway button to be available for selection"
|
||||
);
|
||||
let modalClosedPromise = BrowserTestUtils.waitForEvent(
|
||||
contentWindow,
|
||||
"unload",
|
||||
"Waiting for modal to close"
|
||||
);
|
||||
|
||||
info("Selecting set colorway button");
|
||||
setColorwayButton.click();
|
||||
info("Closing modal");
|
||||
await modalClosedPromise;
|
||||
|
||||
// Verify theme selection is saved
|
||||
const activeTheme = Services.prefs.getStringPref(
|
||||
"extensions.activeThemeID"
|
||||
);
|
||||
is(
|
||||
activeTheme,
|
||||
SOFT_COLORWAY_THEME_ID,
|
||||
"Current theme is still selected colorway"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that the selected colorway is not enabled after pressing the Cancel Button.
|
||||
* Theme should be reverted to previous option.
|
||||
*/
|
||||
add_task(async function colorwaycloset_modal_cancel() {
|
||||
const previousTheme = Services.prefs.getStringPref(
|
||||
"extensions.activeThemeID"
|
||||
);
|
||||
info(`Previous theme is ${previousTheme}`);
|
||||
|
||||
await testInColorwayClosetModal(
|
||||
async (document, contentWindow) => {
|
||||
// Wait for colorway to load before checking modal UI
|
||||
await waitForAddonEnabled(NO_INTENSITY_COLORWAY_THEME_ID);
|
||||
|
||||
// Cancel colorway selection
|
||||
const { cancelButton } = getColorwayClosetTestElements(document);
|
||||
let themeRevertedPromise = waitForAddonEnabled(previousTheme);
|
||||
let modalClosedPromise = BrowserTestUtils.waitForEvent(
|
||||
contentWindow,
|
||||
"unload",
|
||||
"Waiting for modal to close"
|
||||
);
|
||||
info("Selecting cancel button");
|
||||
cancelButton.click();
|
||||
|
||||
info("Verifying that previous theme is restored");
|
||||
await themeRevertedPromise;
|
||||
info("Closing modal");
|
||||
await modalClosedPromise;
|
||||
},
|
||||
[NO_INTENSITY_COLORWAY_THEME_ID]
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that the Firefox homepage apply and undo options are visible
|
||||
* on the modal if a non-default setting for homepage is enabled.
|
||||
*/
|
||||
add_task(async function colorwaycloset_custom_home_page() {
|
||||
await HomePage.set("https://www.example.com");
|
||||
await testInColorwayClosetModal(document => {
|
||||
const { homepageResetApplyButton } = getColorwayClosetTestElements(
|
||||
document
|
||||
);
|
||||
let v = getColorwayClosetElementVisibility(document);
|
||||
ok(
|
||||
v.homepageResetContainer.isVisible,
|
||||
"Homepage reset prompt should be shown"
|
||||
);
|
||||
ok(
|
||||
v.homepageResetSuccessMessage.isHidden,
|
||||
"Success message should not be shown"
|
||||
);
|
||||
ok(v.homepageResetUndoButton.isHidden, "Undo button should not be shown");
|
||||
ok(v.homepageResetMessage.isVisible, "Reset message should be shown");
|
||||
ok(v.homepageResetApplyButton.isVisible, "Apply button should be shown");
|
||||
|
||||
homepageResetApplyButton.click();
|
||||
v = getColorwayClosetElementVisibility(document);
|
||||
|
||||
ok(
|
||||
v.homepageResetSuccessMessage.isVisible,
|
||||
"Success message should be shown"
|
||||
);
|
||||
ok(v.homepageResetUndoButton.isVisible, "Undo button should be shown");
|
||||
ok(v.homepageResetMessage.isHidden, "Reset message should not be shown");
|
||||
ok(v.homepageResetApplyButton.isHidden, "Apply button should not be shown");
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that the Firefox homepage apply and undo options are not visible
|
||||
* on the modal if the default setting for homepage is enabled.
|
||||
*/
|
||||
add_task(async function colorwaycloset_default_home_page() {
|
||||
await HomePage.set(HomePage.getOriginalDefault());
|
||||
await testInColorwayClosetModal(document => {
|
||||
const { homepageResetContainer } = getColorwayClosetTestElements(document);
|
||||
ok(
|
||||
BrowserTestUtils.is_hidden(homepageResetContainer),
|
||||
"Homepage reset prompt should be hidden"
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,379 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Tests that all colorway details such as the collection title, collection expiry date,
|
||||
* and colorway figure are displayed on the modal.
|
||||
*/
|
||||
add_task(async function colorwaycloset_show_colorway() {
|
||||
await testInColorwayClosetModal(async document => {
|
||||
is(
|
||||
document.documentElement.style.width,
|
||||
"",
|
||||
"In order for the modal layout to be responsive, the modal document " +
|
||||
"should not have a width set after the dialog frame has been set up"
|
||||
);
|
||||
const el = getColorwayClosetTestElements(document);
|
||||
const expiryL10nAttributes = document.l10n.getAttributes(el.expiryDateSpan);
|
||||
is(
|
||||
document.l10n.getAttributes(el.collectionTitle).id,
|
||||
TEST_COLORWAY_COLLECTION.l10nId.title,
|
||||
"Correct collection title should be shown"
|
||||
);
|
||||
is(
|
||||
expiryL10nAttributes.args.expiryDate,
|
||||
TEST_COLORWAY_COLLECTION.expiry.getTime(),
|
||||
"Correct expiry date should be shown"
|
||||
);
|
||||
is(
|
||||
expiryL10nAttributes.id,
|
||||
EXPIRY_DATE_L10N_ID,
|
||||
"Correct expiry date format should be shown"
|
||||
);
|
||||
|
||||
info("Verifying figure src");
|
||||
await BrowserTestUtils.waitForMutationCondition(
|
||||
el.colorwayFigure,
|
||||
{ childList: true, attributeFilter: ["src"] },
|
||||
() => el.colorwayFigure.src === MOCK_THEME_FIGURE_URL,
|
||||
"Waiting for figure image to have expected URL"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that modal details and theme are updated when a new colorway radio button is selected.
|
||||
*/
|
||||
add_task(async function colorwaycloset_modal_select_colorway() {
|
||||
await testInColorwayClosetModal(
|
||||
async document => {
|
||||
const {
|
||||
colorwaySelector,
|
||||
colorwayName,
|
||||
colorwayDescription,
|
||||
colorwayIntensities,
|
||||
} = getColorwayClosetTestElements(document);
|
||||
|
||||
is(
|
||||
colorwaySelector.children.length,
|
||||
2,
|
||||
"There should be two colorway radio buttons"
|
||||
);
|
||||
|
||||
// Select colorway on modal
|
||||
const colorwayGroupButton1 = colorwaySelector.querySelector(
|
||||
`input[value="${BALANCED_COLORWAY_THEME_ID}"]`
|
||||
);
|
||||
let selectorChangedPromise = BrowserTestUtils.waitForEvent(
|
||||
colorwaySelector,
|
||||
"change",
|
||||
"Waiting for radio button change event"
|
||||
);
|
||||
let themeChangedPromise = waitForAddonEnabled(BALANCED_COLORWAY_THEME_ID);
|
||||
|
||||
info("Selecting colorway radio button");
|
||||
colorwayGroupButton1.click();
|
||||
info("Waiting for radio button change event to resolve");
|
||||
await selectorChangedPromise;
|
||||
info("Waiting for theme to change");
|
||||
await themeChangedPromise;
|
||||
|
||||
// Verify values of first colorway
|
||||
is(colorwayName.textContent, MOCK_THEME_NAME, "Theme name is correct");
|
||||
is(
|
||||
colorwayDescription.textContent,
|
||||
MOCK_THEME_DESCRIPTION,
|
||||
"Theme description is correct"
|
||||
);
|
||||
ok(
|
||||
colorwayIntensities.querySelector(
|
||||
`input[value="${SOFT_COLORWAY_THEME_ID}"]`
|
||||
),
|
||||
"Soft intensity should be correct"
|
||||
);
|
||||
ok(
|
||||
colorwayIntensities.querySelector(
|
||||
`input[value="${BALANCED_COLORWAY_THEME_ID}"]`
|
||||
),
|
||||
"Balanced intensity should be correct"
|
||||
);
|
||||
ok(
|
||||
colorwayIntensities.querySelector(
|
||||
`input[value="${BOLD_COLORWAY_THEME_ID}"]`
|
||||
),
|
||||
"Bold intensity should be correct"
|
||||
);
|
||||
|
||||
// Select a new colorway
|
||||
const colorwayGroupButton2 = colorwaySelector.querySelector(
|
||||
`input[value="${BALANCED_COLORWAY_THEME_ID_2}"]`
|
||||
);
|
||||
selectorChangedPromise = BrowserTestUtils.waitForEvent(
|
||||
colorwaySelector,
|
||||
"change",
|
||||
"Waiting for radio button change event"
|
||||
);
|
||||
themeChangedPromise = waitForAddonEnabled(BALANCED_COLORWAY_THEME_ID_2);
|
||||
|
||||
info("Selecting another colorway radio button");
|
||||
colorwayGroupButton2.click();
|
||||
info("Waiting for radio button change event to resolve");
|
||||
await selectorChangedPromise;
|
||||
info("Waiting for theme to change");
|
||||
await themeChangedPromise;
|
||||
|
||||
// Verify values of new colorway
|
||||
is(colorwayName.textContent, MOCK_THEME_NAME_2, "Theme name is updated");
|
||||
is(
|
||||
colorwayDescription.textContent,
|
||||
MOCK_THEME_DESCRIPTION_2,
|
||||
"Theme description is updated"
|
||||
);
|
||||
ok(
|
||||
colorwayIntensities.querySelector(
|
||||
`input[value="${SOFT_COLORWAY_THEME_ID_2}"]`
|
||||
),
|
||||
"Soft intensity should be updated"
|
||||
);
|
||||
ok(
|
||||
colorwayIntensities.querySelector(
|
||||
`input[value="${BALANCED_COLORWAY_THEME_ID_2}"]`
|
||||
),
|
||||
"Balanced intensity should be updated"
|
||||
);
|
||||
ok(
|
||||
colorwayIntensities.querySelector(
|
||||
`input[value="${BOLD_COLORWAY_THEME_ID_2}"]`
|
||||
),
|
||||
"Bold intensity should be updated"
|
||||
);
|
||||
},
|
||||
[
|
||||
SOFT_COLORWAY_THEME_ID,
|
||||
BALANCED_COLORWAY_THEME_ID,
|
||||
BOLD_COLORWAY_THEME_ID,
|
||||
SOFT_COLORWAY_THEME_ID_2,
|
||||
BALANCED_COLORWAY_THEME_ID_2,
|
||||
BOLD_COLORWAY_THEME_ID_2,
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that modal details and theme are updated when a new colorway radio button is selected,
|
||||
* but when the colorway has no intensity options.
|
||||
*/
|
||||
add_task(async function colorwaycloset_modal_select_colorway_no_intensity() {
|
||||
await testInColorwayClosetModal(
|
||||
async document => {
|
||||
// Select colorway on modal
|
||||
const {
|
||||
colorwaySelector,
|
||||
colorwayName,
|
||||
colorwayDescription,
|
||||
colorwayIntensities,
|
||||
} = getColorwayClosetTestElements(document);
|
||||
|
||||
is(
|
||||
colorwaySelector.children.length,
|
||||
2,
|
||||
"There should be two colorway radio buttons"
|
||||
);
|
||||
|
||||
const colorwayGroupButton1 = colorwaySelector.querySelector(
|
||||
`input[value="${BALANCED_COLORWAY_THEME_ID}"]`
|
||||
);
|
||||
let selectorChangedPromise = BrowserTestUtils.waitForEvent(
|
||||
colorwaySelector,
|
||||
"change",
|
||||
"Waiting for radio button change event"
|
||||
);
|
||||
let themeChangedPromise = waitForAddonEnabled(BALANCED_COLORWAY_THEME_ID);
|
||||
|
||||
info("Selecting colorway radio button");
|
||||
colorwayGroupButton1.click();
|
||||
info("Waiting for radio button change event to resolve");
|
||||
await selectorChangedPromise;
|
||||
info("Waiting for theme to change");
|
||||
await themeChangedPromise;
|
||||
|
||||
// Verify values of first colorway
|
||||
is(colorwayName.textContent, MOCK_THEME_NAME, "Theme name is correct");
|
||||
is(
|
||||
colorwayDescription.textContent,
|
||||
MOCK_THEME_DESCRIPTION,
|
||||
"Theme description is correct"
|
||||
);
|
||||
ok(
|
||||
colorwayIntensities.querySelector(
|
||||
`input[value="${SOFT_COLORWAY_THEME_ID}"]`
|
||||
),
|
||||
"Soft intensity should be correct"
|
||||
);
|
||||
ok(
|
||||
colorwayIntensities.querySelector(
|
||||
`input[value="${BALANCED_COLORWAY_THEME_ID}"]`
|
||||
),
|
||||
"Balanced intensity should be correct"
|
||||
);
|
||||
ok(
|
||||
colorwayIntensities.querySelector(
|
||||
`input[value="${BOLD_COLORWAY_THEME_ID}"]`
|
||||
),
|
||||
"Bold intensity should be correct"
|
||||
);
|
||||
|
||||
// Select a new colorway
|
||||
const colorwayGroupButton2 = colorwaySelector.querySelector(
|
||||
`input[value="${NO_INTENSITY_COLORWAY_THEME_ID}"]`
|
||||
);
|
||||
selectorChangedPromise = BrowserTestUtils.waitForEvent(
|
||||
colorwaySelector,
|
||||
"change",
|
||||
"Waiting for radio button change event"
|
||||
);
|
||||
themeChangedPromise = waitForAddonEnabled(NO_INTENSITY_COLORWAY_THEME_ID);
|
||||
|
||||
info("Selecting another colorway radio button but with no intensity");
|
||||
colorwayGroupButton2.click();
|
||||
info("Waiting for radio button change event to resolve");
|
||||
await selectorChangedPromise;
|
||||
info("Waiting for theme to change");
|
||||
await themeChangedPromise;
|
||||
|
||||
// Verify there are no intensities
|
||||
info("Verifying intensity button is not visible");
|
||||
let v = getColorwayClosetElementVisibility(document);
|
||||
ok(
|
||||
!v.colorwayIntensities.isVisible,
|
||||
"Colorway intensities should not be shown"
|
||||
);
|
||||
},
|
||||
[
|
||||
SOFT_COLORWAY_THEME_ID,
|
||||
BALANCED_COLORWAY_THEME_ID,
|
||||
BOLD_COLORWAY_THEME_ID,
|
||||
NO_INTENSITY_COLORWAY_THEME_ID,
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that an active colorway in the current collection is selected and displayed when
|
||||
* opening the modal.
|
||||
*/
|
||||
add_task(async function colorwaycloset_modal_show_active_colorway() {
|
||||
await testInColorwayClosetModal(
|
||||
async document => {
|
||||
const {
|
||||
colorwaySelector,
|
||||
colorwayIntensities,
|
||||
} = getColorwayClosetTestElements(document);
|
||||
info(
|
||||
"Verify that the correct colorway family button is checked by default"
|
||||
);
|
||||
ok(
|
||||
colorwaySelector.querySelector(
|
||||
`input[value="${BALANCED_COLORWAY_THEME_ID}"]`
|
||||
).checked,
|
||||
"Colorway group button should be checked by default"
|
||||
);
|
||||
ok(
|
||||
colorwayIntensities.querySelector(
|
||||
`input[value="${SOFT_COLORWAY_THEME_ID}"]`
|
||||
).checked,
|
||||
"Soft intensity should be checked by default"
|
||||
);
|
||||
},
|
||||
undefined,
|
||||
SOFT_COLORWAY_THEME_ID
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that a colorway available in the active collection is displayed in the
|
||||
* colorway closet modal if the current theme is an expired colorway.
|
||||
*/
|
||||
add_task(async function colorwaycloset_modal_expired_colorway() {
|
||||
const previousTheme = Services.prefs.getStringPref(
|
||||
"extensions.activeThemeID"
|
||||
);
|
||||
info(`Previous theme is ${previousTheme}`);
|
||||
|
||||
await testInColorwayClosetModal(
|
||||
async document => {
|
||||
const {
|
||||
colorwaySelector,
|
||||
colorwayIntensities,
|
||||
} = getColorwayClosetTestElements(document);
|
||||
|
||||
// Wait for colorway to load before checking modal UI
|
||||
await waitForAddonEnabled(BALANCED_COLORWAY_THEME_ID);
|
||||
|
||||
ok(
|
||||
colorwaySelector.querySelector(
|
||||
`input[value="${BALANCED_COLORWAY_THEME_ID}"]`
|
||||
).checked,
|
||||
"Colorway group button should be checked by default"
|
||||
);
|
||||
ok(
|
||||
colorwayIntensities.querySelector(
|
||||
`input[value="${BALANCED_COLORWAY_THEME_ID}"]`
|
||||
).checked,
|
||||
"Correct intensity should be checked by default"
|
||||
);
|
||||
},
|
||||
[
|
||||
SOFT_COLORWAY_THEME_ID,
|
||||
BALANCED_COLORWAY_THEME_ID,
|
||||
BOLD_COLORWAY_THEME_ID,
|
||||
NO_INTENSITY_EXPIRED_COLORWAY_THEME_ID,
|
||||
],
|
||||
NO_INTENSITY_EXPIRED_COLORWAY_THEME_ID
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that bold intensity is checked by default upon the opening the modal
|
||||
* if the current theme has a dark scheme.
|
||||
*/
|
||||
add_task(async function colorwaycloset_modal_dark_scheme() {
|
||||
await testInColorwayClosetModal(
|
||||
async document => {
|
||||
const {
|
||||
colorwaySelector,
|
||||
colorwayIntensities,
|
||||
} = getColorwayClosetTestElements(document);
|
||||
|
||||
const previousTheme = Services.prefs.getStringPref(
|
||||
"extensions.activeThemeID"
|
||||
);
|
||||
info(`Previous theme is ${previousTheme}`);
|
||||
|
||||
// Wait for theme to load before checking modal UI
|
||||
await waitForAddonEnabled(BOLD_COLORWAY_THEME_ID);
|
||||
|
||||
ok(
|
||||
colorwaySelector.querySelector(
|
||||
`input[value="${BALANCED_COLORWAY_THEME_ID}"]`
|
||||
).checked,
|
||||
"Colorway group button should be checked by default"
|
||||
);
|
||||
ok(
|
||||
colorwayIntensities.querySelector(
|
||||
`input[value="${BOLD_COLORWAY_THEME_ID}"]`
|
||||
).checked,
|
||||
"Bold intensity should be checked by default"
|
||||
);
|
||||
},
|
||||
[
|
||||
SOFT_COLORWAY_THEME_ID,
|
||||
BALANCED_COLORWAY_THEME_ID,
|
||||
BOLD_COLORWAY_THEME_ID,
|
||||
MOCK_DARK_THEME_ID,
|
||||
],
|
||||
MOCK_DARK_THEME_ID
|
||||
);
|
||||
});
|
|
@ -1,290 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { TelemetryTestUtils } = ChromeUtils.importESModule(
|
||||
"resource://testing-common/TelemetryTestUtils.sys.mjs"
|
||||
);
|
||||
|
||||
AddonTestUtils.initMochitest(this);
|
||||
|
||||
add_setup(async function setup_tests() {
|
||||
Services.telemetry.clearEvents();
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that telemetry is registered when the Cancel button is selected on the Colorway Closet modal.
|
||||
*/
|
||||
add_task(async function colorwaycloset_modal_cancel() {
|
||||
await testInColorwayClosetModal(async (document, contentWindow) => {
|
||||
Services.telemetry.clearEvents();
|
||||
registerCleanupFunction(() => {
|
||||
Services.telemetry.clearEvents();
|
||||
});
|
||||
|
||||
const { cancelButton } = getColorwayClosetTestElements(document);
|
||||
let modalClosedPromise = BrowserTestUtils.waitForEvent(
|
||||
contentWindow,
|
||||
"unload",
|
||||
"Waiting for modal to close"
|
||||
);
|
||||
|
||||
cancelButton.click();
|
||||
info("Closing modal");
|
||||
await modalClosedPromise;
|
||||
await waitForColorwaysTelemetryPromise();
|
||||
|
||||
TelemetryTestUtils.assertEvents(
|
||||
[
|
||||
{
|
||||
category: "colorways_modal",
|
||||
method: "cancel",
|
||||
object: "modal",
|
||||
},
|
||||
],
|
||||
{ category: "colorways_modal", object: "modal" }
|
||||
);
|
||||
Services.telemetry.clearEvents();
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that telemetry is registered when the Set Colorway button is selected on the Colorway Closet modal.
|
||||
*/
|
||||
add_task(async function colorwaycloset_modal_set_colorway() {
|
||||
await testInColorwayClosetModal(async (document, contentWindow) => {
|
||||
Services.telemetry.clearEvents();
|
||||
registerCleanupFunction(() => {
|
||||
Services.telemetry.clearEvents();
|
||||
});
|
||||
|
||||
// Select colorway on modal
|
||||
info("Selecting colorway radio button");
|
||||
const {
|
||||
colorwaySelector,
|
||||
colorwayIntensities,
|
||||
setColorwayButton,
|
||||
} = getColorwayClosetTestElements(document);
|
||||
const colorwayFamilyButton = colorwaySelector.querySelector(
|
||||
`input[value="${BALANCED_COLORWAY_THEME_ID}"]`
|
||||
);
|
||||
colorwayFamilyButton.click();
|
||||
|
||||
// Select new intensity
|
||||
info("Selecting new intensity button");
|
||||
await BrowserTestUtils.waitForMutationCondition(
|
||||
colorwayIntensities,
|
||||
{ subtree: true, attributeFilter: ["value"] },
|
||||
() =>
|
||||
colorwayIntensities.querySelector(
|
||||
`input[value="${SOFT_COLORWAY_THEME_ID}"]`
|
||||
),
|
||||
"Waiting for intensity button to be available"
|
||||
);
|
||||
let intensitiesChangedPromise = BrowserTestUtils.waitForEvent(
|
||||
colorwayIntensities,
|
||||
"change",
|
||||
"Waiting for intensities change event"
|
||||
);
|
||||
let themeChangedPromise = BrowserTestUtils.waitForCondition(() => {
|
||||
const activeTheme = Services.prefs.getStringPref(
|
||||
"extensions.activeThemeID"
|
||||
);
|
||||
return activeTheme === SOFT_COLORWAY_THEME_ID;
|
||||
}, "Waiting for the current theme to change after new intensity");
|
||||
|
||||
colorwayIntensities
|
||||
.querySelector(`input[value="${SOFT_COLORWAY_THEME_ID}"]`)
|
||||
.click();
|
||||
await intensitiesChangedPromise;
|
||||
await themeChangedPromise;
|
||||
|
||||
// Set colorway
|
||||
info("Selecting set colorway button");
|
||||
await BrowserTestUtils.waitForMutationCondition(
|
||||
setColorwayButton,
|
||||
{ childList: true, attributeFilter: ["disabled"] },
|
||||
() => !setColorwayButton.disabled,
|
||||
"Waiting for set-colorway button to be available for selection"
|
||||
);
|
||||
let modalClosedPromise = BrowserTestUtils.waitForEvent(
|
||||
contentWindow,
|
||||
"unload",
|
||||
"Waiting for modal to close"
|
||||
);
|
||||
|
||||
setColorwayButton.click();
|
||||
await waitForColorwaysTelemetryPromise();
|
||||
info("Closing modal");
|
||||
await modalClosedPromise;
|
||||
|
||||
TelemetryTestUtils.assertEvents(
|
||||
[
|
||||
{
|
||||
category: "colorways_modal",
|
||||
method: "set_colorway",
|
||||
object: "modal",
|
||||
value: null,
|
||||
extra: {
|
||||
colorway_id: SOFT_COLORWAY_THEME_ID,
|
||||
},
|
||||
},
|
||||
],
|
||||
{ category: "colorways_modal", object: "modal" }
|
||||
);
|
||||
|
||||
Services.telemetry.clearEvents();
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that telemetry is registered when the Set Colorway button is selected on the Colorway Closet modal,
|
||||
* but for a selected colorway theme that does not have an intensity.
|
||||
*/
|
||||
add_task(async function colorwaycloset_modal_set_colorway_no_intensity() {
|
||||
await testInColorwayClosetModal(
|
||||
async (document, contentWindow) => {
|
||||
Services.telemetry.clearEvents();
|
||||
registerCleanupFunction(() => {
|
||||
Services.telemetry.clearEvents();
|
||||
});
|
||||
const {
|
||||
colorwaySelector,
|
||||
setColorwayButton,
|
||||
} = getColorwayClosetTestElements(document);
|
||||
|
||||
// Select colorway on modal
|
||||
info("Selecting colorway radio button");
|
||||
const colorwayFamilyButton = colorwaySelector.querySelector(
|
||||
`input[value="${NO_INTENSITY_COLORWAY_THEME_ID}"]`
|
||||
);
|
||||
let themeChangedPromise = BrowserTestUtils.waitForCondition(() => {
|
||||
const activeTheme = Services.prefs.getStringPref(
|
||||
"extensions.activeThemeID"
|
||||
);
|
||||
return activeTheme === NO_INTENSITY_COLORWAY_THEME_ID;
|
||||
}, "Waiting for the current theme to change after new intensity");
|
||||
colorwayFamilyButton.click();
|
||||
await themeChangedPromise;
|
||||
|
||||
// Set colorway
|
||||
info("Selecting set colorway button");
|
||||
await BrowserTestUtils.waitForMutationCondition(
|
||||
setColorwayButton,
|
||||
{ childList: true, attributeFilter: ["disabled"] },
|
||||
() => !setColorwayButton.disabled,
|
||||
"Waiting for set-colorway button to be available for selection"
|
||||
);
|
||||
let modalClosedPromise = BrowserTestUtils.waitForEvent(
|
||||
contentWindow,
|
||||
"unload",
|
||||
"Waiting for modal to close"
|
||||
);
|
||||
|
||||
setColorwayButton.click();
|
||||
await waitForColorwaysTelemetryPromise();
|
||||
info("Closing modal");
|
||||
await modalClosedPromise;
|
||||
|
||||
TelemetryTestUtils.assertEvents(
|
||||
[
|
||||
{
|
||||
category: "colorways_modal",
|
||||
method: "set_colorway",
|
||||
object: "modal",
|
||||
value: null,
|
||||
extra: {
|
||||
colorway_id: NO_INTENSITY_COLORWAY_THEME_ID,
|
||||
},
|
||||
},
|
||||
],
|
||||
{ category: "colorways_modal", object: "modal" }
|
||||
);
|
||||
|
||||
Services.telemetry.clearEvents();
|
||||
},
|
||||
[NO_INTENSITY_COLORWAY_THEME_ID]
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that telemetry is registered when the Firefox Home apply and undo buttons are selected on the Colorway Closet modal.
|
||||
*/
|
||||
add_task(async function colorwaycloset_modal_firefox_home() {
|
||||
// Set homepage to NOT Firefox Home so that banner appears on the modal
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.startup.homepage", "about:blank"]],
|
||||
});
|
||||
await testInColorwayClosetModal(async document => {
|
||||
Services.telemetry.clearEvents();
|
||||
registerCleanupFunction(() => {
|
||||
Services.telemetry.clearEvents();
|
||||
});
|
||||
|
||||
// Ensure Firefox Home banner is visible first on the modal
|
||||
const {
|
||||
homepageResetContainer,
|
||||
homepageResetApplyButton,
|
||||
homepageResetUndoButton,
|
||||
} = getColorwayClosetTestElements(document);
|
||||
|
||||
ok(homepageResetContainer, "Firefox Home banner is visible on the modal");
|
||||
ok(homepageResetApplyButton, "Firefox Home Apply button should be visible");
|
||||
|
||||
homepageResetApplyButton.click();
|
||||
await waitForColorwaysTelemetryPromise();
|
||||
|
||||
TelemetryTestUtils.assertEvents(
|
||||
[
|
||||
{
|
||||
category: "colorways_modal",
|
||||
method: "homepage_reset",
|
||||
object: "modal",
|
||||
},
|
||||
],
|
||||
{ category: "colorways_modal", object: "modal" }
|
||||
);
|
||||
|
||||
ok(homepageResetUndoButton, "Firefox Home Undo button should be visible");
|
||||
|
||||
homepageResetUndoButton.click();
|
||||
await waitForColorwaysTelemetryPromise();
|
||||
|
||||
TelemetryTestUtils.assertEvents(
|
||||
[
|
||||
{
|
||||
category: "colorways_modal",
|
||||
method: "homepage_reset_undo",
|
||||
object: "modal",
|
||||
},
|
||||
],
|
||||
{ category: "colorways_modal", object: "modal" }
|
||||
);
|
||||
|
||||
Services.telemetry.clearEvents();
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that there is an event telemetry object "unknown" when no source is defined upon
|
||||
* opening the modal.
|
||||
*/
|
||||
add_task(async function colorwaycloset_modal_unknown_source() {
|
||||
await testInColorwayClosetModal(async document => {
|
||||
// Since we already open the modal in testInColorwayClosetModal,
|
||||
// do not clear telemetry events until after we verify
|
||||
// the event with "unknown" source.
|
||||
registerCleanupFunction(() => {
|
||||
Services.telemetry.clearEvents();
|
||||
});
|
||||
|
||||
await waitForColorwaysTelemetryPromise();
|
||||
TelemetryTestUtils.assertNumberOfEvents(1, {
|
||||
category: "colorways_modal",
|
||||
object: "unknown",
|
||||
});
|
||||
|
||||
Services.telemetry.clearEvents();
|
||||
});
|
||||
});
|
|
@ -1,366 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { AddonTestUtils } = ChromeUtils.import(
|
||||
"resource://testing-common/AddonTestUtils.jsm"
|
||||
);
|
||||
const { BuiltInThemes } = ChromeUtils.importESModule(
|
||||
"resource:///modules/BuiltInThemes.sys.mjs"
|
||||
);
|
||||
const { ColorwayClosetOpener } = ChromeUtils.import(
|
||||
"resource:///modules/ColorwayClosetOpener.jsm"
|
||||
);
|
||||
const { sinon } = ChromeUtils.importESModule(
|
||||
"resource://testing-common/Sinon.sys.mjs"
|
||||
);
|
||||
|
||||
const MOCK_COLLECTION_TEST_CARD_IMAGE_PATH = "mockCollectionPreview.avif";
|
||||
const MOCK_THEME_NAME = "Mock Theme";
|
||||
const MOCK_THEME_NAME_2 = "Mock Theme 2";
|
||||
const MOCK_THEME_DESCRIPTION = "Mock Theme Description";
|
||||
const MOCK_THEME_DESCRIPTION_2 = "Mock Theme 2 Description";
|
||||
const MOCK_THEME_FIGURE_URL = "https://www.example.com/figure.avif";
|
||||
|
||||
// fluent string ids
|
||||
const EXPIRY_DATE_L10N_ID = "colorway-collection-expiry-label";
|
||||
const MOCK_COLLECTION_L10N_TITLE = "mock-collection-l10n";
|
||||
const MOCK_COLLECTION_L10N_DESCRIPTION = "mock-collection-l10n-description";
|
||||
const MOCK_COLLECTION_L10N_SHORT_DESCRIPTION =
|
||||
"mock-collection-l10n-short-description";
|
||||
|
||||
// colorway theme ids
|
||||
const SOFT_COLORWAY_THEME_ID = "mocktheme-soft-colorway@mozilla.org";
|
||||
const BALANCED_COLORWAY_THEME_ID = "mocktheme-balanced-colorway@mozilla.org";
|
||||
const BOLD_COLORWAY_THEME_ID = "mocktheme-bold-colorway@mozilla.org";
|
||||
const SOFT_COLORWAY_THEME_ID_2 = "mocktheme2-soft-colorway@mozilla.org";
|
||||
const BALANCED_COLORWAY_THEME_ID_2 = "mocktheme2-balanced-colorway@mozilla.org";
|
||||
const BOLD_COLORWAY_THEME_ID_2 = "mocktheme2-bold-colorway@mozilla.org";
|
||||
const NO_INTENSITY_COLORWAY_THEME_ID = "mocktheme-colorway@mozilla.org";
|
||||
const NO_INTENSITY_EXPIRED_COLORWAY_THEME_ID =
|
||||
"expiredmocktheme-colorway@mozilla.org";
|
||||
|
||||
// non-colorway theme ids
|
||||
const MOCK_DARK_THEME_ID = "mocktheme-dark@mozilla.org";
|
||||
|
||||
// collections
|
||||
const MOCK_COLLECTION_ID = "mock-collection";
|
||||
const TEST_COLORWAY_COLLECTION = {
|
||||
id: MOCK_COLLECTION_ID,
|
||||
expiry: new Date("3000-01-01"),
|
||||
l10nId: {
|
||||
title: MOCK_COLLECTION_L10N_TITLE,
|
||||
description: MOCK_COLLECTION_L10N_DESCRIPTION,
|
||||
},
|
||||
cardImagePath: MOCK_COLLECTION_TEST_CARD_IMAGE_PATH,
|
||||
};
|
||||
|
||||
function installTestTheme(id) {
|
||||
let name, description;
|
||||
if (
|
||||
[
|
||||
SOFT_COLORWAY_THEME_ID_2,
|
||||
BALANCED_COLORWAY_THEME_ID_2,
|
||||
BOLD_COLORWAY_THEME_ID_2,
|
||||
].includes(id)
|
||||
) {
|
||||
name = MOCK_THEME_NAME_2;
|
||||
description = MOCK_THEME_DESCRIPTION_2;
|
||||
} else {
|
||||
name = MOCK_THEME_NAME;
|
||||
description = MOCK_THEME_DESCRIPTION;
|
||||
}
|
||||
let xpi = AddonTestUtils.createTempWebExtensionFile({
|
||||
manifest: {
|
||||
name,
|
||||
description,
|
||||
browser_specific_settings: { gecko: { id } },
|
||||
theme:
|
||||
id === MOCK_DARK_THEME_ID
|
||||
? { properties: { color_scheme: "dark" } }
|
||||
: {},
|
||||
},
|
||||
});
|
||||
return AddonTestUtils.promiseInstallFile(xpi);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates stubs for BuiltInThemes
|
||||
* @param {Boolean} hasActiveCollection false to create an expired collection; has default value of true to create an active collection
|
||||
* @returns {Object} sinon sandbox containing all stubs for BuiltInThemes
|
||||
* @see BuiltInThemes
|
||||
*/
|
||||
function initBuiltInThemesStubs(hasActiveCollection = true) {
|
||||
info("Creating BuiltInThemes stubs");
|
||||
const sandbox = sinon.createSandbox();
|
||||
registerCleanupFunction(() => {
|
||||
info("Restoring BuiltInThemes sandbox for cleanup");
|
||||
sandbox.restore();
|
||||
});
|
||||
sandbox.stub(BuiltInThemes, "getLocalizedColorwayGroupName").callsFake(id => {
|
||||
if (
|
||||
[
|
||||
SOFT_COLORWAY_THEME_ID_2,
|
||||
BALANCED_COLORWAY_THEME_ID_2,
|
||||
BOLD_COLORWAY_THEME_ID_2,
|
||||
].includes(id)
|
||||
) {
|
||||
return MOCK_THEME_NAME_2;
|
||||
}
|
||||
|
||||
return MOCK_THEME_NAME;
|
||||
});
|
||||
sandbox
|
||||
.stub(BuiltInThemes, "getLocalizedColorwayDescription")
|
||||
.callsFake(id => {
|
||||
if (
|
||||
[
|
||||
SOFT_COLORWAY_THEME_ID_2,
|
||||
BALANCED_COLORWAY_THEME_ID_2,
|
||||
BOLD_COLORWAY_THEME_ID_2,
|
||||
].includes(id)
|
||||
) {
|
||||
return MOCK_THEME_DESCRIPTION_2;
|
||||
}
|
||||
|
||||
return MOCK_THEME_DESCRIPTION;
|
||||
});
|
||||
sandbox.stub(BuiltInThemes.builtInThemeMap, "get").callsFake(id => {
|
||||
let mockThemeProperties = {
|
||||
collection: MOCK_COLLECTION_ID,
|
||||
figureUrl: MOCK_THEME_FIGURE_URL,
|
||||
};
|
||||
if (id === NO_INTENSITY_EXPIRED_COLORWAY_THEME_ID) {
|
||||
mockThemeProperties.expiry = new Date("1970-01-01");
|
||||
}
|
||||
return mockThemeProperties;
|
||||
});
|
||||
|
||||
if (hasActiveCollection) {
|
||||
sandbox
|
||||
.stub(BuiltInThemes, "findActiveColorwayCollection")
|
||||
.returns(TEST_COLORWAY_COLLECTION);
|
||||
} else {
|
||||
sandbox.stub(BuiltInThemes, "findActiveColorwayCollection").returns(null);
|
||||
}
|
||||
|
||||
sandbox
|
||||
.stub(BuiltInThemes, "isColorwayFromCurrentCollection")
|
||||
.callsFake(id =>
|
||||
[
|
||||
SOFT_COLORWAY_THEME_ID,
|
||||
BALANCED_COLORWAY_THEME_ID,
|
||||
BOLD_COLORWAY_THEME_ID,
|
||||
NO_INTENSITY_COLORWAY_THEME_ID,
|
||||
SOFT_COLORWAY_THEME_ID_2,
|
||||
BALANCED_COLORWAY_THEME_ID_2,
|
||||
BOLD_COLORWAY_THEME_ID_2,
|
||||
].includes(id)
|
||||
);
|
||||
return sandbox.restore.bind(sandbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates stubs for ColorwayClosetOpener
|
||||
* @returns {Object} sinon sandbox containing all stubs for ColorwayClosetOpener
|
||||
* @see ColorwayClosetOpener
|
||||
*/
|
||||
function initColorwayClosetOpenerStubs() {
|
||||
info("Creating ColorwayClosetOpener stubs");
|
||||
const sandbox = sinon.createSandbox();
|
||||
registerCleanupFunction(() => {
|
||||
info("Restoring ColorwayClosetOpener sandbox for cleanup");
|
||||
sandbox.restore();
|
||||
});
|
||||
sandbox.stub(ColorwayClosetOpener, "openModal").resolves({});
|
||||
return sandbox.restore.bind(sandbox);
|
||||
}
|
||||
|
||||
function getColorwayClosetTestElements(document) {
|
||||
return {
|
||||
colorwayFigure: document.getElementById("colorway-figure"),
|
||||
collectionTitle: document.getElementById("collection-title"),
|
||||
expiryDateSpan: document.querySelector("#collection-expiry-date > span"),
|
||||
colorwaySelector: document.querySelector("#colorway-selector"),
|
||||
colorwayIntensities: document.querySelector("#colorway-intensity-radios"),
|
||||
setColorwayButton: document.getElementById("set-colorway"),
|
||||
cancelButton: document.getElementById("cancel"),
|
||||
colorwayName: document.querySelector("#colorway-name"),
|
||||
colorwayDescription: document.querySelector("#colorway-description"),
|
||||
homepageResetContainer: document.getElementById("homepage-reset-container"),
|
||||
homepageResetSuccessMessage: document.querySelector(
|
||||
"#homepage-reset-success > span"
|
||||
),
|
||||
homepageResetUndoButton: document.querySelector(
|
||||
"#homepage-reset-success > button"
|
||||
),
|
||||
homepageResetMessage: document.querySelector(
|
||||
"#homepage-reset-prompt > span"
|
||||
),
|
||||
homepageResetApplyButton: document.querySelector(
|
||||
"#homepage-reset-prompt > button"
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
function getColorwayClosetElementVisibility(document) {
|
||||
const elements = getColorwayClosetTestElements(document);
|
||||
let v = {};
|
||||
for (const k in elements) {
|
||||
const isVisible = BrowserTestUtils.is_visible(elements[k]);
|
||||
v[k] = {
|
||||
isVisible,
|
||||
isHidden: !isVisible,
|
||||
};
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
async function testInColorwayClosetModal(
|
||||
testMethod,
|
||||
themesToInstall = [
|
||||
SOFT_COLORWAY_THEME_ID,
|
||||
BALANCED_COLORWAY_THEME_ID,
|
||||
BOLD_COLORWAY_THEME_ID,
|
||||
],
|
||||
themeToEnable = undefined
|
||||
) {
|
||||
const clearBuiltInThemesStubs = initBuiltInThemesStubs();
|
||||
let themesToUninstall = [];
|
||||
for (let theme of themesToInstall) {
|
||||
info(`Installing ${theme}`);
|
||||
const { addon } = await installTestTheme(theme);
|
||||
// For some tests, we might want a colorway theme already enabled
|
||||
// before opening the modal. If there is such a theme, be sure
|
||||
// to enable it after installing all mock themes.
|
||||
if (themeToEnable && themeToEnable === theme) {
|
||||
info(`Enabling ${addon.id}`);
|
||||
await addon.enable();
|
||||
} else {
|
||||
info(`Disabling ${addon.id}`);
|
||||
await addon.disable();
|
||||
}
|
||||
themesToUninstall.push(addon);
|
||||
}
|
||||
|
||||
const { closedPromise, dialog } = ColorwayClosetOpener.openModal();
|
||||
await dialog._dialogReady;
|
||||
const document = dialog._frame.contentDocument;
|
||||
let contentWindow = dialog._frame.contentWindow;
|
||||
try {
|
||||
await testMethod(document, contentWindow);
|
||||
} finally {
|
||||
// If the window is still open after the test, close it.
|
||||
contentWindow = dialog._frame.contentWindow;
|
||||
if (contentWindow && !contentWindow.closed) {
|
||||
info("Modal is still open. Closing modal before ending test.");
|
||||
document.getElementById("cancel").click();
|
||||
} else {
|
||||
info("Modal is already closed");
|
||||
}
|
||||
await closedPromise;
|
||||
for (let addon of themesToUninstall) {
|
||||
info(`Uninstalling theme ${addon.id}`);
|
||||
await addon.disable();
|
||||
await addon.uninstall();
|
||||
}
|
||||
clearBuiltInThemesStubs();
|
||||
// Clear any telemetry events recorded after closing the modal
|
||||
Services.telemetry.clearEvents();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers mock Fluent locale strings for colorway collections.
|
||||
*/
|
||||
async function registerMockCollectionL10nIds() {
|
||||
info("Register mock fluent locale strings");
|
||||
|
||||
let tmpDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
|
||||
tmpDir.append("l10n-colorwaycloset-mocks");
|
||||
|
||||
await IOUtils.makeDirectory(tmpDir.path, { ignoreExisting: true });
|
||||
await IOUtils.writeUTF8(
|
||||
PathUtils.join(tmpDir.path, "mock-colorways.ftl"),
|
||||
[
|
||||
`${MOCK_COLLECTION_L10N_TITLE} = Mock collection title`,
|
||||
`${MOCK_COLLECTION_L10N_SHORT_DESCRIPTION} = Mock collection subheading`,
|
||||
].join("\n")
|
||||
);
|
||||
|
||||
let resProto = Services.io
|
||||
.getProtocolHandler("resource")
|
||||
.QueryInterface(Ci.nsIResProtocolHandler);
|
||||
|
||||
resProto.setSubstitution(
|
||||
"l10n-colorwaycloset-mocks",
|
||||
Services.io.newFileURI(tmpDir)
|
||||
);
|
||||
|
||||
let mockSource = new L10nFileSource(
|
||||
"colorwayscloset-mocks",
|
||||
"app",
|
||||
["en-US"],
|
||||
"resource://l10n-colorwaycloset-mocks/"
|
||||
);
|
||||
|
||||
let l10nReg = L10nRegistry.getInstance();
|
||||
l10nReg.registerSources([mockSource]);
|
||||
|
||||
registerCleanupFunction(async () => {
|
||||
l10nReg.removeSources([mockSource]);
|
||||
resProto.setSubstitution("l10n-colorwaycloset-mocks", null);
|
||||
info(`Clearing temporary directory ${tmpDir.path}`);
|
||||
await IOUtils.remove(tmpDir.path, { recursive: true, ignoreAbsent: true });
|
||||
});
|
||||
|
||||
// Confirm that the mock fluent resources are available as expected.
|
||||
let bundles = l10nReg.generateBundles(["en-US"], ["mock-colorways.ftl"]);
|
||||
let bundle0 = (await bundles.next()).value;
|
||||
is(
|
||||
bundle0.locales[0],
|
||||
"en-US",
|
||||
"Got the expected locale in the mock L10nFileSource"
|
||||
);
|
||||
ok(
|
||||
bundle0.hasMessage(MOCK_COLLECTION_L10N_TITLE),
|
||||
"Got the expected l10n id in the mock L10nFileSource"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for an addon to be enabled.
|
||||
* @param {String} addonId the string id of an addon
|
||||
* @returns {Promise} resolved promise when the the specified addon is enabled
|
||||
*/
|
||||
function waitForAddonEnabled(addonId) {
|
||||
return new Promise(resolve => {
|
||||
let listener = {
|
||||
onEnabled(enabledAddon) {
|
||||
if (enabledAddon.id == addonId) {
|
||||
AddonManager.removeAddonListener(listener);
|
||||
info(`Addon ${addonId} enabled. Removing listener and resolving.`);
|
||||
resolve();
|
||||
}
|
||||
},
|
||||
};
|
||||
info(`Adding onEnabled listener for "${addonId}`);
|
||||
AddonManager.addAddonListener(listener);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a Colorways telemetry event to trigger.
|
||||
* @returns {Promise} promise from BrowserTestUtils.waitForCondition
|
||||
*/
|
||||
async function waitForColorwaysTelemetryPromise() {
|
||||
return BrowserTestUtils.waitForCondition(() => {
|
||||
let events = Services.telemetry.snapshotEvents(
|
||||
Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
|
||||
false
|
||||
).parent;
|
||||
let colorwayEvents = events.filter(e => e[1] === "colorways_modal");
|
||||
return colorwayEvents && colorwayEvents.length;
|
||||
}, "Waiting for Colorways events ping");
|
||||
}
|
|
@ -30,7 +30,6 @@ DIRS += [
|
|||
"about",
|
||||
"aboutlogins",
|
||||
"attribution",
|
||||
"colorways",
|
||||
"contextualidentity",
|
||||
"customizableui",
|
||||
"doh",
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
# 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/.
|
||||
|
||||
# Variables:
|
||||
# $expiryDate (string) - date on which the colorway collection expires. When formatting this, you may omit the year, only exposing the month and day, as colorway collections will always expire within a year.
|
||||
colorway-collection-expiry-label = Expires { DATETIME($expiryDate, month: "long", day: "numeric") }
|
||||
|
||||
# Document title, not shown in the UI but exposed through accessibility APIs
|
||||
colorways-modal-title = Choose Your Colorway
|
||||
|
||||
colorway-intensity-selector-label = Intensity
|
||||
colorway-intensity-soft = Soft
|
||||
colorway-intensity-balanced = Balanced
|
||||
# "Bold" is used in the sense of bravery or courage, not in the sense of
|
||||
# emphasized text.
|
||||
colorway-intensity-bold = Bold
|
||||
|
||||
# Label for the button to keep using the selected colorway in the browser
|
||||
colorway-closet-set-colorway-button = Set colorway
|
||||
colorway-closet-cancel-button = Cancel
|
||||
|
||||
colorway-homepage-reset-prompt = Make { -firefox-home-brand-name } your colorful homepage
|
||||
colorway-homepage-reset-success-message = { -firefox-home-brand-name } is now your homepage
|
||||
colorway-homepage-reset-apply-button = Apply
|
||||
colorway-homepage-reset-undo-button = Undo
|
|
@ -18,7 +18,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
|||
XPCOMUtils.defineLazyModuleGetters(lazy, {
|
||||
AddonManager: "resource://gre/modules/AddonManager.jsm",
|
||||
Spotlight: "resource://activity-stream/lib/Spotlight.jsm",
|
||||
ColorwayClosetOpener: "resource:///modules/ColorwayClosetOpener.jsm",
|
||||
});
|
||||
|
||||
export const SpecialMessageActions = {
|
||||
|
@ -407,9 +406,6 @@ export const SpecialMessageActions = {
|
|||
break;
|
||||
case "OPEN_FIREFOX_VIEW_AND_COLORWAYS_MODAL":
|
||||
window.FirefoxViewHandler.openTab();
|
||||
lazy.ColorwayClosetOpener.openModal({
|
||||
source: "firefoxview",
|
||||
});
|
||||
break;
|
||||
case "RELOAD_BROWSER":
|
||||
browser.reload();
|
||||
|
|
|
@ -31,4 +31,4 @@ skip-if = os != "win"
|
|||
[browser_sma_set_prefs.js]
|
||||
[browser_sma_click_element.js]
|
||||
[browser_sma_handle_multiaction.js]
|
||||
[browser_sma_open_firefoxview_colorways_modal.js]
|
||||
[browser_sma_open_firefoxview.js]
|
||||
|
|
|
@ -3,14 +3,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { ColorwayClosetOpener } = ChromeUtils.import(
|
||||
"resource:///modules/ColorwayClosetOpener.jsm"
|
||||
);
|
||||
|
||||
add_task(async function test_open_firefoxview_and_colorways_modal() {
|
||||
const sandbox = sinon.createSandbox();
|
||||
const spy = sandbox.spy(ColorwayClosetOpener, "openModal");
|
||||
|
||||
add_task(async function test_open_firefoxview() {
|
||||
const tabPromise = BrowserTestUtils.waitForNewTab(
|
||||
gBrowser,
|
||||
"about:firefoxview"
|
||||
|
@ -22,8 +15,6 @@ add_task(async function test_open_firefoxview_and_colorways_modal() {
|
|||
const tab = await tabPromise;
|
||||
|
||||
ok(tab, "should open about:firefoxview in a new tab");
|
||||
ok(spy.calledOnce, "ColorwayClosetOpener's openModal was called once");
|
||||
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
sandbox.restore();
|
||||
});
|
|
@ -3735,88 +3735,6 @@ synced_tabs:
|
|||
tab_pos: position of the tab clicked
|
||||
filter: was there a filter enabled
|
||||
|
||||
colorways_modal:
|
||||
try_colorways:
|
||||
objects: ["firefoxview", "aboutaddons", "unknown"]
|
||||
description: >
|
||||
Recorded when the Colorway Closet modal opens when no colorway from the current collection was selected. The object is the source from where the user opened the modal.
|
||||
notification_emails:
|
||||
- firefoxview@mozilla.com
|
||||
products:
|
||||
- "firefox"
|
||||
record_in_processes:
|
||||
- main
|
||||
bug_numbers:
|
||||
- 1779642
|
||||
- 1747229
|
||||
expiry_version: "never"
|
||||
release_channel_collection: opt-out
|
||||
change_colorway:
|
||||
objects: ["firefoxview", "aboutaddons", "unknown"]
|
||||
description: >
|
||||
Recorded when the Colorway Closet modal opens when a colorway from the current collection was already selected. The object is the source from where the user opened the modal.
|
||||
notification_emails:
|
||||
- firefoxview@mozilla.com
|
||||
products:
|
||||
- "firefox"
|
||||
record_in_processes:
|
||||
- main
|
||||
bug_numbers:
|
||||
- 1779642
|
||||
- 1747229
|
||||
expiry_version: "never"
|
||||
release_channel_collection: opt-out
|
||||
cancel:
|
||||
description: >
|
||||
Recorded when colorway selection is canceled and the colorway closet modal is closed. This may be done by pressing the Cancel button or ESC key, or by closing the browser tab or window.
|
||||
objects: ["modal"]
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- "main"
|
||||
bug_numbers: [1747229]
|
||||
notification_emails:
|
||||
- firefoxview@mozilla.com
|
||||
expiry_version: "never"
|
||||
products: ["firefox"]
|
||||
set_colorway:
|
||||
description: >
|
||||
Recorded when a colorway and intensity are set in the colorway closet modal
|
||||
objects: ["modal"]
|
||||
extra_keys:
|
||||
colorway_id: The id of the selected colorway
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- "main"
|
||||
bug_numbers: [1747229]
|
||||
notification_emails:
|
||||
- firefoxview@mozilla.com
|
||||
expiry_version: "never"
|
||||
products: ["firefox"]
|
||||
homepage_reset:
|
||||
description: >
|
||||
Recorded when the apply button is selected in the colorway modal. This will set the user’s home page default to Firefox Home
|
||||
objects: ["modal"]
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- "main"
|
||||
bug_numbers: [1747229]
|
||||
notification_emails:
|
||||
- firefoxview@mozilla.com
|
||||
expiry_version: "never"
|
||||
products: ["firefox"]
|
||||
homepage_reset_undo:
|
||||
description: >
|
||||
Recorded when the undo button is selected in the colorway modal. This will undo the apply button selection for setting Firefox Home to default
|
||||
objects: ["modal"]
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- "main"
|
||||
bug_numbers: [1747229]
|
||||
notification_emails:
|
||||
- firefoxview@mozilla.com
|
||||
expiry_version: "never"
|
||||
products: ["firefox"]
|
||||
|
||||
firefoxview:
|
||||
entered:
|
||||
objects: ["firefoxview"]
|
||||
|
|
|
@ -241,8 +241,6 @@
|
|||
"browser/components/migration/ChromeProfileMigrator.jsm",
|
||||
"resource:///modules/ChromeWindowsLoginCrypto.jsm":
|
||||
"browser/components/migration/ChromeWindowsLoginCrypto.jsm",
|
||||
"resource:///modules/ColorwayClosetOpener.jsm":
|
||||
"browser/components/colorways/ColorwayClosetOpener.jsm",
|
||||
"resource:///modules/CommonNames.jsm":
|
||||
"browser/components/places/CommonNames.jsm",
|
||||
"resource:///modules/ContentCrashHandlers.jsm":
|
||||
|
|
Загрузка…
Ссылка в новой задаче