--- a/browser/components/places/content/bookmarksSidebar.js
+++ b/browser/components/places/content/bookmarksSidebar.js
@@ -1,15 +1,18 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* 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-globals-from ../../../../toolkit/components/places/PlacesUtils.jsm */
+const { LightweightThemeConsumer } = ChromeUtils.import("resource://gre/modules/LightweightThemeConsumer.jsm", {});
+new LightweightThemeConsumer(document, window.top);
+
function init() {
let uidensity = window.top.document.documentElement.getAttribute("uidensity");
if (uidensity) {
document.documentElement.setAttribute("uidensity", uidensity);
}
document.getElementById("bookmarks-view").place =
"place:type=" + Ci.nsINavHistoryQueryOptions.RESULTS_AS_ROOTS_QUERY;
--- a/browser/components/places/content/historySidebar.js
+++ b/browser/components/places/content/historySidebar.js
@@ -2,16 +2,19 @@
/* 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-globals-from ../../../../toolkit/components/places/PlacesUtils.jsm */
ChromeUtils.import("resource://gre/modules/TelemetryStopwatch.jsm");
+const { LightweightThemeConsumer } = ChromeUtils.import("resource://gre/modules/LightweightThemeConsumer.jsm", {});
+new LightweightThemeConsumer(document, window.top);
+
var gHistoryTree;
var gSearchBox;
var gHistoryGrouping = "";
var gSearching = false;
function HistorySidebarInit() {
let uidensity = window.top.document.documentElement.getAttribute("uidensity");
if (uidensity) {
--- a/browser/components/syncedtabs/sidebar.js
+++ b/browser/components/syncedtabs/sidebar.js
@@ -6,16 +6,19 @@
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.import("resource://services-sync/SyncedTabs.jsm");
ChromeUtils.import("resource:///modules/syncedtabs/SyncedTabsDeckComponent.js");
ChromeUtils.defineModuleGetter(this, "fxAccounts",
"resource://gre/modules/FxAccounts.jsm");
+const { LightweightThemeConsumer } = ChromeUtils.import("resource://gre/modules/LightweightThemeConsumer.jsm", {});
+new LightweightThemeConsumer(document, window.top);
+
var syncedTabsDeckComponent = new SyncedTabsDeckComponent({window, SyncedTabs, fxAccounts});
let onLoaded = () => {
syncedTabsDeckComponent.init();
document.getElementById("template-container").appendChild(syncedTabsDeckComponent.container);
};
let onUnloaded = () => {
--- a/browser/modules/ThemeVariableMap.jsm
+++ b/browser/modules/ThemeVariableMap.jsm
@@ -18,16 +18,31 @@ const ThemeVariableMap = [
}],
["--tab-loading-fill", {
lwtProperty: "tab_loading",
optionalElementID: "tabbrowser-tabs"
}],
["--lwt-tab-text", {
lwtProperty: "tab_text"
}],
+ ["--lwt-sidebar-background", {
+ lwtProperty: "sidebar"
+ }],
+ ["--lwt-sidebar-text", {
+ lwtProperty: "sidebar_text"
+ }],
+ ["--lwt-sidebar-border", {
+ lwtProperty: "sidebar_border"
+ }],
+ ["--lwt-sidebar-highlight", {
+ lwtProperty: "sidebar_highlight"
+ }],
+ ["--lwt-sidebar-highlight-text", {
+ lwtProperty: "sidebar_highlight_text"
+ }],
["--tab-line-color", {
lwtProperty: "tab_line",
optionalElementID: "tabbrowser-tabs"
}],
["--lwt-background-tab-separator-color", {
lwtProperty: "tab_background_separator",
}],
["--toolbar-bgcolor", {
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -600,22 +600,22 @@ html|input.urlbar-input {
#sidebar-box {
-moz-appearance: -moz-mac-source-list;
-moz-font-smoothing-background-color: -moz-mac-source-list;
/* Default font size is 11px on mac, so this is 12px */
font-size: 1.0909rem;
}
#sidebar-header {
- border-bottom: 1px solid hsla(240, 5%, 5%, .1);
- background-color: transparent;
+ border-bottom: 1px solid var(--lwt-sidebar-border, hsla(240, 5%, 5%, .1));
+ background-color: var(--lwt-sidebar-background, transparent);
}
.sidebar-splitter {
- border-color: hsla(240, 5%, 5%, .1);
+ border-color: var(--lwt-sidebar-border, hsla(240, 5%, 5%, .1));
}
/* ----- CONTENT ----- */
.browserContainer > findbar {
background: @scopeBarBackground@;
border-top: @scopeBarSeparatorBorder@;
color: -moz-DialogText;
@@ -728,16 +728,18 @@ html|input.urlbar-input {
@media (min-resolution: 2dppx) {
.tab-drop-indicator {
list-style-image: url(chrome://browser/skin/tabbrowser/tabDragIndicator@2x.png);
width: 12px;
}
}
+%include ../shared/places/places.inc.css
+
/* Bookmarks toolbar */
#PlacesToolbarDropIndicator {
list-style-image: url(chrome://browser/skin/places/toolbarDropMarker.png);
}
/* Bookmark drag and drop styles */
.bookmark-item[dragover-into="true"] {
--- a/browser/themes/osx/places/places.css
+++ b/browser/themes/osx/places/places.css
@@ -21,16 +21,18 @@
:root[uidensity=touch] .sidebar-placesTreechildren::-moz-tree-row {
min-height: 32px;
}
.sidebar-placesTree {
-moz-appearance: -moz-mac-source-list;
-moz-font-smoothing-background-color: -moz-mac-source-list;
+ color: var(--lwt-sidebar-text, inherit);
+ background-color: transparent;
}
.sidebar-placesTreechildren::-moz-tree-separator {
border-top: 1px solid #505d6d;
margin: 0 10px;
}
.sidebar-placesTreechildren::-moz-tree-row {
@@ -88,23 +90,27 @@
list-style-image: url("chrome://global/skin/tree/arrow-disclosure.svg#arrow-disclosure-collapsed-rtl");
}
.sidebar-placesTreechildren:-moz-locale-dir(rtl)::-moz-tree-twisty(closed, selected) {
list-style-image: url("chrome://global/skin/tree/arrow-disclosure.svg#arrow-disclosure-collapsed-inverted-rtl");
}
@media (-moz-mac-yosemite-theme) {
+ .sidebar-placesTreechildren {
+ background-color: var(--lwt-sidebar-background, transparent);
+ }
+
.sidebar-placesTreechildren::-moz-tree-cell-text(selected) {
color: -moz-dialogtext;
font-weight: 500;
}
.sidebar-placesTreechildren::-moz-tree-cell-text(selected, focus) {
- color: #fff;
+ color: var(--lwt-sidebar-highlight-text, #fff);
}
.sidebar-placesTreechildren::-moz-tree-twisty(closed, selected) {
list-style-image: url("chrome://global/skin/tree/arrow-disclosure.svg#arrow-disclosure-collapsed");
}
.sidebar-placesTreechildren::-moz-tree-twisty(closed, selected, focus) {
list-style-image: url("chrome://global/skin/tree/arrow-disclosure.svg#arrow-disclosure-collapsed-inverted");
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/places/places.inc.css
@@ -0,0 +1,22 @@
+/* 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/. */
+
+.sidebar,
+#sidebar {
+ background-color: var(--lwt-sidebar-background, transparent);
+ color: color: var(--lwt-sidebar-text, black);
+ border-color: var(--lwt-sidebar-border, transparent);
+}
+
+.sidebar-header,
+#sidebar-header {
+ background-color: var(--lwt-sidebar-background, transparent);
+ color: var(--lwt-sidebar-text, black);
+ border-color: var(--lwt-sidebar-border, transparent);
+}
+
+:root[style*="--lwt-sidebar-highlight"] treechildren::-moz-tree-row(hover) {
+ color: var(--lwt-sidebar-highlight-text);
+ background-color: var(--lwt-sidebar-highlight);
+}
\ No newline at end of file
--- a/browser/themes/shared/places/tree-icons.inc.css
+++ b/browser/themes/shared/places/tree-icons.inc.css
@@ -1,15 +1,15 @@
/* 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/. */
treechildren:-moz-tree-image {
-moz-context-properties: fill, fill-opacity;
- fill: -moz-FieldText;
+ fill: currentColor;
fill-opacity: 0.7;
}
treechildren::-moz-tree-image(title) {
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
padding-inline-end: 2px;
margin: 0 2px;
width: 16px;
--- a/browser/themes/shared/sidebar.inc.css
+++ b/browser/themes/shared/sidebar.inc.css
@@ -1,14 +1,16 @@
%if 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/. */
%endif
+%include ../shared/places/places.inc.css
+
.sidebar-header,
#sidebar-header {
font-size: 1.333em;
font-weight: lighter;
padding: 8px;
}
%ifndef MOZ_WIDGET_GTK
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -657,21 +657,21 @@ html|*.urlbar-input:-moz-lwtheme::placeh
%include ../shared/sidebar.inc.css
#sidebar-box {
background-color: -moz-Field;
color: -moz-FieldText;
}
#sidebar-header {
- border-bottom: 1px solid ThreeDLightShadow;
+ border-bottom: 1px solid var(--lwt-sidebar-border, ThreeDLightShadow);
}
.sidebar-splitter {
- border-color: ThreeDLightShadow;
+ border-color: var(--lwt-sidebar-border, ThreeDLightShadow);;
}
.browserContainer > findbar {
background-color: -moz-dialog;
color: -moz-DialogText;
text-shadow: none;
}
@@ -711,16 +711,18 @@ html|*.urlbar-input:-moz-lwtheme::placeh
}
/* All tabs menupopup */
.alltabs-item[selected="true"] {
font-weight: bold;
}
+%include ../shared/places/places.inc.css
+
/* Bookmarks toolbar */
#PlacesToolbarDropIndicator {
list-style-image: url(chrome://browser/skin/places/toolbarDropMarker.png);
}
toolbarbutton.bookmark-item[dragover="true"][open="true"] {
-moz-appearance: none;
background: Highlight !important;
--- a/browser/themes/windows/places/places.css
+++ b/browser/themes/windows/places/places.css
@@ -7,17 +7,17 @@
#history-panel,
#bookmarksPanel {
background-color: transparent;
}
.sidebar-placesTree {
-moz-appearance: none;
background-color: transparent;
- color: inherit;
+ color: var(--lwt-sidebar-text, inherit);
border: 0;
margin: 0;
}
:root[uidensity=touch] #search-box,
:root[uidensity=touch] .sidebar-placesTreechildren::-moz-tree-row {
min-height: 32px;
}
--- a/toolkit/components/extensions/parent/ext-theme.js
+++ b/toolkit/components/extensions/parent/ext-theme.js
@@ -165,16 +165,21 @@ class Theme {
case "toolbar_vertical_separator":
case "button_background_hover":
case "button_background_active":
case "popup":
case "popup_text":
case "popup_border":
case "popup_highlight":
case "popup_highlight_text":
+ case "sidebar":
+ case "sidebar_text":
+ case "sidebar_border":
+ case "sidebar_highlight":
+ case "sidebar_highlight_text":
this.lwtStyles[color] = cssColor;
break;
}
}
}
/**
* Helper method for loading images found in the extension's manifest.
--- a/toolkit/components/extensions/schemas/theme.json
+++ b/toolkit/components/extensions/schemas/theme.json
@@ -191,16 +191,36 @@
},
"popup_highlight": {
"$ref": "ThemeColor",
"optional": true
},
"popup_highlight_text": {
"$ref": "ThemeColor",
"optional": true
+ },
+ "sidebar": {
+ "$ref": "ThemeColor",
+ "optional": true
+ },
+ "sidebar_text": {
+ "$ref": "ThemeColor",
+ "optional": true
+ },
+ "sidebar_border": {
+ "$ref": "ThemeColor",
+ "optional": true
+ },
+ "sidebar_highlight": {
+ "$ref": "ThemeColor",
+ "optional": true
+ },
+ "sidebar_highlight_text": {
+ "$ref": "ThemeColor",
+ "optional": true
}
},
"additionalProperties": { "$ref": "UnrecognizedProperty" }
},
"icons": {
"type": "object",
"optional": true,
"properties": {
--- a/toolkit/components/extensions/test/browser/browser.ini
+++ b/toolkit/components/extensions/test/browser/browser.ini
@@ -21,11 +21,12 @@ support-files =
[browser_ext_themes_toolbar_fields_focus.js]
[browser_ext_themes_toolbar_fields.js]
[browser_ext_themes_toolbars.js]
[browser_ext_themes_toolbarbutton_icons.js]
[browser_ext_themes_toolbarbutton_colors.js]
[browser_ext_themes_theme_transition.js]
[browser_ext_themes_arrowpanels.js]
[browser_ext_themes_tab_selected.js]
+[browser_ext_themes_sidebars.js]
[browser_ext_themes_autocomplete_popup.js]
[browser_ext_themes_sanitization.js]
[browser_ext_themes_findbar.js]
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/browser/browser_ext_themes_sidebars.js
@@ -0,0 +1,62 @@
+"use strict";
+
+// This test checks applied WebExtension themes that attempt to change
+// popup properties
+
+add_task(async function test_popup_styling(browser, accDoc) {
+ const BACKGROUND_COLOR = "#FF0000";
+ const TEXT_COLOR = "#008000";
+ const BORDER_COLOR = "#0000FF";
+ const HIGHLIGHT_COLOR = "#FF00FF";
+ const HIGHLIGHT_TEXT_COLOR = "#00FF00";
+
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ "theme": {
+ "images": {
+ "headerURL": "image1.png",
+ },
+ "colors": {
+ "accentcolor": ACCENT_COLOR,
+ "textcolor": TEXT_COLOR,
+ "sidebar": BACKGROUND_COLOR,
+ "sidebar_text": TEXT_COLOR,
+ "sidebar_border": BORDER_COLOR,
+ "sidebar_highlight": HIGHLIGHT_COLOR,
+ "sidebar_highlight_text": HIGHLIGHT_TEXT_COLOR,
+ },
+ },
+ },
+ files: {
+ "image1.png": BACKGROUND,
+ },
+ });
+
+
+ await BrowserTestUtils.withNewTab({gBrowser, url: "https://example.com"}, async function(browser) {
+ await extension.startup();
+ let sidebar = document.getElementById("sidebar");
+ BrowserTestUtils.waitForEvent(sidebar, "load", true);
+ SidebarUI.toggle("viewBookmarksSidebar");
+
+ let sidebarContent = document.getElementById("sidebar");
+ let sidebarComputedStyle = window.getComputedStyle(sidebarContent);
+
+ // Ensure sidebar background color was set properly
+ Assert.equal(
+ sidebarComputedStyle.getPropertyValue("background-color"),
+ `rgb(${hexToRGB(BACKGROUND_COLOR).join(", ")})`,
+ "Popup background color should have been themed"
+ );
+
+ // Ensure sidebar text color was set properly
+ Assert.equal(
+ sidebarComputedStyle.getPropertyValue("color"),
+ `rgb(${hexToRGB(TEXT_COLOR).join(", ")})`,
+ "Popup text color should have been themed"
+ );
+
+ SidebarUI.toggle("viewBookmarksSidebar");
+ await extension.unload();
+ });
+});
--- a/toolkit/modules/LightweightThemeConsumer.jsm
+++ b/toolkit/modules/LightweightThemeConsumer.jsm
@@ -87,25 +87,38 @@ const toolkitVariableMap = [
// Get the theme variables from the app resource directory.
// This allows per-app variables.
ChromeUtils.import("resource:///modules/ThemeVariableMap.jsm");
ChromeUtils.defineModuleGetter(this, "LightweightThemeImageOptimizer",
"resource://gre/modules/addons/LightweightThemeImageOptimizer.jsm");
-function LightweightThemeConsumer(aDocument) {
+/**
+ * Class that allows to watch theme changes to a certain window
+ * @param aDocument The document where the theme should applied
+ * @param aWindow The window that is targeted by the theme update
+ */
+function LightweightThemeConsumer(aDocument, aWindow = aDocument.defaultView) {
this._doc = aDocument;
- this._win = aDocument.defaultView;
+ this._win = aWindow;
+ this._doc.defaultView.gThemeConsumer = this;
Services.obs.addObserver(this, "lightweight-theme-styling-update");
var temp = {};
ChromeUtils.import("resource://gre/modules/LightweightThemeManager.jsm", temp);
- this._update(temp.LightweightThemeManager.currentThemeForDisplay);
+
+ if (aWindow == aDocument.defaultView) {
+ // If this is the root window, sync with LWTManager
+ this._update(temp.LightweightThemeManager.currentThemeForDisplay);
+ } else {
+ // Otherwise, sync with root window
+ this._update(aWindow.gThemeConsumer._lastData);
+ }
this._win.addEventListener("resolutionchange", this);
this._win.addEventListener("unload", this, { once: true });
}
LightweightThemeConsumer.prototype = {
_lastData: null,
// Whether the active lightweight theme should be shown on the window.
@@ -236,16 +249,19 @@ function _setProperties(root, active, th
const {
lwtProperty,
optionalElementID,
processColor,
isColor = true
} = definition;
let elem = optionalElementID ? root.ownerDocument.getElementById(optionalElementID)
: root;
+ if (!elem) {
+ continue;
+ }
let val = themeData[lwtProperty];
if (isColor) {
val = _sanitizeCSSColor(root.ownerDocument, val);
if (processColor) {
val = processColor(_parseRGBA(val), elem);
}
}
--- a/toolkit/themes/windows/global/tree.css
+++ b/toolkit/themes/windows/global/tree.css
@@ -332,35 +332,35 @@ treechildren::-moz-tree-cell-text(active
%ifdef XP_WIN
@media (-moz-windows-default-theme) {
treechildren {
--treechildren-outline: none;
--treechildren-focusColor: rgb(123,195,255);
--treechildren-selectedFocusColor: rgb(205,232,255);
--treechildren-currentColor: rgb(125,162,206);
- --treechildren-hoverColor: rgb(229,243,255);
+ --treechildren-hoverColor: var(--lwt-sidebar-highlight-text, rgb(229,243,255));
--treechildren-selectedBorder: rgb(217,217,217);
--treechildren-selectedBackground: rgb(217,217,217);
--treechildren-currentFocusBorder: var(--treechildren-focusColor);
--treechildren-selectedFocusBorder: var(--treechildren-selectedFocusColor) var(--treechildren-selectedFocusColor) rgb(165,214,255);
--treechildren-selectedFocusBackground: var(--treechildren-selectedFocusColor);
--treechildren-selectedFocusCurrentBorder: var(--treechildren-focusColor);
--treechildren-selectedFocusCurrentBackground: rgb(205,232,255);
--treechildren-hoverBorder: var(--treechildren-hoverColor);
- --treechildren-hoverBackground: rgb(229,243,255);
+ --treechildren-hoverBackground: var(--lwt-sidebar-highlight, rgb(229,243,255));
--treechildren-hoverCurrentBorder: var(--treechildren-currentColor);
--treechildren-hoverCurrentBackground: rgba(131,183,249,.16);
--treechildren-hoverSelectedBorder: var(--treechildren-focusColor);
--treechildren-hoverSelectedBackground: rgb(205,232,255);
}
treechildren::-moz-tree-row {
height: 1.8em;
- color: -moz-FieldText;
+ color: currentColor;
margin-inline-start: 1px;
margin-inline-end: 1px;
border-width: 1px;
border-color: transparent;
background-repeat: no-repeat;
background-size: 100% 100%;
}
@@ -411,27 +411,27 @@ treechildren::-moz-tree-cell-text(active
treechildren::-moz-tree-cell(dropOn) {
background-image: none;
background-color: transparent;
border-radius: 0;
}
treechildren::-moz-tree-cell-text(primary, dropOn) {
- color: -moz-FieldText;
+ color: currentColor;
}
treechildren::-moz-tree-cell-text {
padding-bottom: initial;
border-color: transparent;
background-color: transparent;
}
treechildren::-moz-tree-cell-text(selected, focus) {
- color: -moz-DialogText;
+ color: currentColor;
}
@media (-moz-os-version: windows-win7),
(-moz-os-version: windows-win8) {
treechildren {
--treechildren-2ndBorderColor: rgba(255,255,255,.4);
--treechildren-outline: 1px solid var(--treechildren-2ndBorderColor);
--treechildren-selectedBackground: rgba(190,190,190,.4);