diff --git a/browser/components/profiles/ProfilesParent.sys.mjs b/browser/components/profiles/ProfilesParent.sys.mjs index b40a9ccefabe..b3e7a14d1fef 100644 --- a/browser/components/profiles/ProfilesParent.sys.mjs +++ b/browser/components/profiles/ProfilesParent.sys.mjs @@ -390,25 +390,30 @@ export class ProfilesParent extends JSWindowActorParent { let themes = []; for (let [themeId, themeObj] of PROFILE_THEMES_MAP) { let theme = await lazy.AddonManager.getAddonByID(themeId); - if (theme) { - themes.push({ - id: themeId, - dataL10nId: themeObj.dataL10nId, - isActive: theme.isActive, - ...themeObj.colors, - isDark: themeObj.isDark, - useInAutomation: themeObj?.useInAutomation, - }); - } else { - themes.push({ - id: themeId, - dataL10nId: themeObj.dataL10nId, - isActive: false, - ...themeObj.colors, - isDark: themeObj.isDark, - useInAutomation: themeObj?.useInAutomation, - }); - } + themes.push({ + id: themeId, + dataL10nId: themeObj.dataL10nId, + isActive: theme?.isActive ?? false, + ...themeObj.colors, + isDark: themeObj.isDark, + useInAutomation: themeObj?.useInAutomation, + }); + } + + let activeAddons = await lazy.AddonManager.getActiveAddons(["theme"]); + let currentTheme = activeAddons.addons[0]; + + // Only add the current theme if it's not one of the default 10 themes. + if (!themes.find(t => t.id === currentTheme.id)) { + let safeCurrentTheme = { + id: currentTheme.id, + name: currentTheme.name, + isActive: currentTheme.isActive, + chromeColor: SelectableProfileService.currentProfile.theme.themeBg, + toolbarColor: SelectableProfileService.currentProfile.theme.themeFg, + }; + + themes.push(safeCurrentTheme); } return themes; diff --git a/browser/components/profiles/SelectableProfileService.sys.mjs b/browser/components/profiles/SelectableProfileService.sys.mjs index 4938586f338c..f910c73c2647 100644 --- a/browser/components/profiles/SelectableProfileService.sys.mjs +++ b/browser/components/profiles/SelectableProfileService.sys.mjs @@ -723,8 +723,8 @@ class SelectableProfileServiceClass extends EventEmitter { let theme = isDark && !!data.darkTheme ? data.darkTheme : data.theme; - let themeFg = theme.toolbar_text; - let themeBg = theme.toolbarColor; + let themeFg = theme.toolbar_text || theme.textcolor; + let themeBg = theme.toolbarColor || theme.accentcolor; if (theme.id === DEFAULT_THEME_ID || !themeFg || !themeBg) { window.addEventListener( diff --git a/browser/components/profiles/content/edit-profile-card.mjs b/browser/components/profiles/content/edit-profile-card.mjs index 871f6530574b..0967829859b2 100644 --- a/browser/components/profiles/content/edit-profile-card.mjs +++ b/browser/components/profiles/content/edit-profile-card.mjs @@ -5,7 +5,7 @@ /* eslint-env mozilla/remote-page */ import { MozLitElement } from "chrome://global/content/lit-utils.mjs"; -import { html } from "chrome://global/content/vendor/lit.all.mjs"; +import { html, ifDefined } from "chrome://global/content/vendor/lit.all.mjs"; /** * Like DeferredTask but usable from content. @@ -345,12 +345,15 @@ export class EditProfileCard extends MozLitElement { value=${this.profile.themeId} data-l10n-id="edit-profile-page-theme-header-2" name="theme" - id="themes" @click=${this.handleThemeClick} > ${this.themes.map( t => - html` + html` ${this.name}${super.inputTemplate()} diff --git a/browser/components/profiles/content/profiles-theme-card.css b/browser/components/profiles/content/profiles-theme-card.css index 5ef7a0c6b2ab..47c45b5c1f08 100644 --- a/browser/components/profiles/content/profiles-theme-card.css +++ b/browser/components/profiles/content/profiles-theme-card.css @@ -58,6 +58,13 @@ moz-card { border-top-left-radius: var(--preview-image-border-radius); border-top-right-radius: var(--preview-image-border-radius); + /* + * We set the background color here in case the + * ProfilesThemeCard.theme.contentColor doesn't exist. For example, when the + * theme card is a theme from AMO and not one of the default themes. + */ + background-color: var(--newtab-background-color, var(--in-content-page-background)); + > img { -moz-context-properties: fill, stroke, fill-opacity; width: 100%; diff --git a/browser/components/profiles/content/profiles-theme-card.mjs b/browser/components/profiles/content/profiles-theme-card.mjs index 673361de3ff6..cad8610a5e1d 100644 --- a/browser/components/profiles/content/profiles-theme-card.mjs +++ b/browser/components/profiles/content/profiles-theme-card.mjs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { MozLitElement } from "chrome://global/content/lit-utils.mjs"; -import { html } from "chrome://global/content/vendor/lit.all.mjs"; +import { html, ifDefined } from "chrome://global/content/vendor/lit.all.mjs"; /** * Element used for displaying a theme on the about:editprofile and about:newprofile pages. @@ -20,11 +20,6 @@ export class ProfilesThemeCard extends MozLitElement { imgHolder: ".img-holder", }; - firstUpdated() { - super.firstUpdated(); - this.updateThemeImage(); - } - updateThemeImage() { if (!this.theme) { return; @@ -34,17 +29,20 @@ export class ProfilesThemeCard extends MozLitElement { // For system theme, we use a special SVG that shows the light/dark wave design this.backgroundImg.src = "chrome://browser/content/profiles/assets/system-theme-background.svg"; - // Reset any inline styles since the SVG has its own colors - this.backgroundImg.style.fill = ""; - this.backgroundImg.style.stroke = ""; - this.imgHolder.style.backgroundColor = ""; } else { + let contentColor; + if (!this.theme.contentColor) { + let styles = window.getComputedStyle(document.body); + contentColor = styles.getPropertyValue("background-color"); + } + // For other themes, use the standard SVG with dynamic colors this.backgroundImg.src = "chrome://browser/content/profiles/assets/theme-selector-background.svg"; this.backgroundImg.style.fill = this.theme.chromeColor; this.backgroundImg.style.stroke = this.theme.toolbarColor; - this.imgHolder.style.backgroundColor = this.theme.contentColor; + this.imgHolder.style.backgroundColor = + this.theme.contentColor ?? contentColor; } } @@ -71,9 +69,11 @@ export class ProfilesThemeCard extends MozLitElement {
+ id=${this.theme.name} + data-l10n-id=${ifDefined(this.theme.dataL10nId)} + > + ${this.theme.name} + `; } diff --git a/browser/components/profiles/tests/browser/browser.toml b/browser/components/profiles/tests/browser/browser.toml index ea17ca3346c6..5ff0361a37e6 100644 --- a/browser/components/profiles/tests/browser/browser.toml +++ b/browser/components/profiles/tests/browser/browser.toml @@ -39,6 +39,8 @@ skip-if = ["os == 'mac' && os_version == '15.30' && arch == 'aarch64' && opt && ["browser_preferences.js"] fail-if = ["a11y_checks"] # Bug 1955503 +["browser_test_current_theme_from_amo.js"] + ["browser_test_last_tab.js"] ["browser_test_nimbus_feature.js"] diff --git a/browser/components/profiles/tests/browser/browser_test_current_theme_from_amo.js b/browser/components/profiles/tests/browser/browser_test_current_theme_from_amo.js new file mode 100644 index 000000000000..58e0302619a9 --- /dev/null +++ b/browser/components/profiles/tests/browser/browser_test_current_theme_from_amo.js @@ -0,0 +1,81 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const lazy = {}; +ChromeUtils.defineESModuleGetters(lazy, { + AddonManager: "resource://gre/modules/AddonManager.sys.mjs", +}); + +const { AddonTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/AddonTestUtils.sys.mjs" +); + +add_task(async function test_currentThemeFromAMOExistsOnEditPage() { + await initGroupDatabase(); + let profile = SelectableProfileService.currentProfile; + Assert.ok(profile, "Should have a profile now"); + + const BLUE_THEME_ID = "blue@test.mozilla.org"; + let blueTheme = await AddonTestUtils.createTempWebExtensionFile({ + manifest: { + name: "blue theme", + version: "1.0", + browser_specific_settings: { gecko: { id: BLUE_THEME_ID } }, + theme: { + colors: { + frame: "blue", + }, + }, + }, + }); + + let install = await lazy.AddonManager.getInstallForFile( + blueTheme, + "application/x-xpinstall" + ); + const themeEnabled = AddonTestUtils.promiseAddonEvent( + "onEnabled", + addon => addon.id === BLUE_THEME_ID + ); + + install.install().then(themeAddon => themeAddon.enable()); + + await themeEnabled; + + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "about:editprofile", + }, + async browser => { + await SpecialPowers.spawn(browser, [], async () => { + let editProfileCard = + content.document.querySelector("edit-profile-card").wrappedJSObject; + + await ContentTaskUtils.waitForCondition( + () => editProfileCard.initialized, + "Waiting for edit-profile-card to be initialized" + ); + + await editProfileCard.updateComplete; + + Assert.equal( + editProfileCard.themes.length, + 11, + "Should have 11 themes with the currennt theme from AMO" + ); + + Assert.equal( + editProfileCard.themes.at(-1).id, + "blue@test.mozilla.org", + "The last theme should be the blue test theme" + ); + }); + } + ); + + const blueThemeAddon = await AddonManager.getAddonByID(BLUE_THEME_ID); + await blueThemeAddon.uninstall(); +});