Bug 1418602 - Allow theming sidebars. r=mconley

MozReview-Commit-ID: 97zkU7raehV

--HG--
extra : rebase_source : ae7fb55a913abd1d59b0dfbbca6e24a7e7b9ff15
This commit is contained in:
Tim Nguyen 2018-08-06 17:46:43 +01:00
parent 309a23afc3
commit aaded6fa49
16 changed files with 278 additions and 17 deletions

View File

@ -13,6 +13,11 @@ ChromeUtils.import("resource://gre/modules/Services.jsm");
* LightweightThemeChild forwards theme data to in-content pages.
*/
class LightweightThemeChild extends ActorChild {
/**
* Initiate a new instance of this class from a message manager.
* It is possible to use a stub message manager for browsers that
* do not have one, like the non-remote browser sidebars.
*/
constructor(mm) {
super(mm);

View File

@ -32,6 +32,43 @@ const inContentVariableMap = [
return `rgba(${r}, ${g}, ${b}, ${a})`;
},
}],
["--lwt-sidebar-background-color", {
lwtProperty: "sidebar",
}],
["--lwt-sidebar-text-color", {
lwtProperty: "sidebar_text",
processColor(rgbaChannels, element) {
if (!rgbaChannels) {
element.removeAttribute("lwt-sidebar");
element.removeAttribute("lwt-sidebar-brighttext");
return null;
}
element.setAttribute("lwt-sidebar", "true");
const {r, g, b, a} = rgbaChannels;
if (!_isTextColorDark(r, g, b)) {
element.setAttribute("lwt-sidebar-brighttext", "true");
}
return `rgba(${r}, ${g}, ${b}, ${a})`;
},
}],
["--lwt-sidebar-highlight-background-color", {
lwtProperty: "sidebar_highlight",
}],
["--lwt-sidebar-highlight-text-color", {
lwtProperty: "sidebar_highlight_text",
processColor(rgbaChannels, element) {
if (!rgbaChannels) {
element.removeAttribute("lwt-sidebar-highlight");
return null;
}
element.setAttribute("lwt-sidebar-highlight", "true");
const {r, g, b, a} = rgbaChannels;
return `rgba(${r}, ${g}, ${b}, ${a})`;
},
}],
];
/**
@ -58,7 +95,9 @@ const ContentThemeController = {
if (!data) {
data = {};
}
this._setProperties(document.body, data);
// XUL documents don't have a body
const element = document.body ? document.body : document.documentElement;
this._setProperties(element, data);
}
},
@ -90,7 +129,7 @@ const ContentThemeController = {
let value = themeData[lwtProperty];
if (processColor) {
value = processColor(value, document.body);
value = processColor(value, elem);
} else if (value) {
const {r, g, b, a} = value;
value = `rgba(${r}, ${g}, ${b}, ${a})`;

View File

@ -7,6 +7,7 @@
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetters(this, {
LightweightThemeChild: "resource:///actors/LightweightThemeChild.jsm",
PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
PlacesUIUtils: "resource:///modules/PlacesUIUtils.jsm",
PlacesTransactions: "resource://gre/modules/PlacesTransactions.jsm",
@ -25,6 +26,13 @@ function init() {
document.documentElement.setAttribute("uidensity", uidensity);
}
/* Listen for sidebar theme changes */
new LightweightThemeChild({
content: window,
chromeOuterWindowID: window.top.windowUtils.outerWindowID,
docShell: window.docShell,
});
document.getElementById("bookmarks-view").place =
"place:type=" + Ci.nsINavHistoryQueryOptions.RESULTS_AS_ROOTS_QUERY;
}

View File

@ -30,6 +30,8 @@
src="chrome://global/content/globalOverlay.js"/>
<script type="application/javascript"
src="chrome://browser/content/utilityOverlay.js"/>
<script type="application/javascript"
src="chrome://browser/content/contentTheme.js"/>
#include placesCommands.inc.xul
#include ../../../../toolkit/content/editMenuCommands.inc.xul

View File

@ -7,6 +7,7 @@
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetters(this, {
LightweightThemeChild: "resource:///actors/LightweightThemeChild.jsm",
PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
PlacesUIUtils: "resource:///modules/PlacesUIUtils.jsm",
PlacesTransactions: "resource://gre/modules/PlacesTransactions.jsm",
@ -32,6 +33,13 @@ function HistorySidebarInit() {
document.documentElement.setAttribute("uidensity", uidensity);
}
/* Listen for sidebar theme changes */
new LightweightThemeChild({
content: window,
chromeOuterWindowID: window.top.windowUtils.outerWindowID,
docShell: window.docShell,
});
gHistoryTree = document.getElementById("historyTree");
gSearchBox = document.getElementById("search-box");

View File

@ -30,6 +30,8 @@
src="chrome://global/content/globalOverlay.js"/>
<script type="application/javascript"
src="chrome://browser/content/utilityOverlay.js"/>
<script type="application/javascript"
src="chrome://browser/content/contentTheme.js"/>
#include ../../../../toolkit/content/editMenuCommands.inc.xul

View File

@ -84,4 +84,8 @@ const ThemeVariableMap = [
const ThemeContentPropertyList = [
"ntp_background",
"ntp_text",
"sidebar",
"sidebar_highlight",
"sidebar_highlight_text",
"sidebar_text",
];

View File

@ -23,13 +23,6 @@
outline: 1px dotted -moz-DialogText;
}
.sidebar-placesTree {
margin: 0;
color: inherit;
-moz-appearance: none;
background: transparent;
}
:root[uidensity=touch] #search-box,
:root[uidensity=touch] .sidebar-placesTreechildren::-moz-tree-row {
min-height: 32px;

View File

@ -10,6 +10,9 @@
margin: 0;
/* Default font size is 11px on mac, so this is 12px */
font-size: 1.0909rem;
}
.sidebar-panel:not([lwt-sidebar]) .sidebar-placesTree {
-moz-appearance: -moz-mac-source-list;
-moz-font-smoothing-background-color: -moz-mac-source-list;
}

View File

@ -7,6 +7,51 @@
background-color: transparent;
}
/* Themed sidebars */
.sidebar-panel[lwt-sidebar] {
background-color: var(--lwt-sidebar-background-color);
color: var(--lwt-sidebar-text-color);
}
.sidebar-panel[lwt-sidebar] .sidebar-placesTreechildren::-moz-tree-row(selected) {
background-color: hsla(0,0%,80%,.3);
}
.sidebar-panel[lwt-sidebar-brighttext] .sidebar-placesTreechildren::-moz-tree-row(selected) {
-moz-appearance: none;
background-color: rgba(249,249,250,.1);
}
.sidebar-panel[lwt-sidebar-brighttext] .sidebar-placesTreechildren::-moz-tree-image(selected),
.sidebar-panel[lwt-sidebar-brighttext] .sidebar-placesTreechildren::-moz-tree-twisty(selected),
.sidebar-panel[lwt-sidebar-brighttext] .sidebar-placesTreechildren::-moz-tree-cell-text(selected) {
color: var(--lwt-sidebar-text-color);
}
.sidebar-panel[lwt-sidebar-highlight] .sidebar-placesTreechildren::-moz-tree-row(selected,focus) {
-moz-appearance: none;
background-color: var(--lwt-sidebar-highlight-background-color);
}
.sidebar-panel[lwt-sidebar-highlight] .sidebar-placesTreechildren::-moz-tree-image(selected, focus),
.sidebar-panel[lwt-sidebar-highlight] .sidebar-placesTreechildren::-moz-tree-twisty(selected, focus),
.sidebar-panel[lwt-sidebar-highlight] .sidebar-placesTreechildren::-moz-tree-cell-text(selected, focus) {
color: var(--lwt-sidebar-highlight-text-color);
}
/* Sidebar tree */
.sidebar-placesTree {
-moz-appearance: none;
background-color: transparent;
color: inherit;
border: 0;
margin: 0;
}
/* View button */
#viewButton {
-moz-appearance: none;
border-radius: 4px;

View File

@ -6,14 +6,6 @@
%include ../../shared/places/places.inc.css
.sidebar-placesTree {
-moz-appearance: none;
background-color: transparent;
color: inherit;
border: 0;
margin: 0;
}
:root[uidensity=touch] #search-box,
:root[uidensity=touch] .sidebar-placesTreechildren::-moz-tree-row {
min-height: 32px;

View File

@ -184,6 +184,10 @@ class Theme {
case "popup_highlight_text":
case "ntp_background":
case "ntp_text":
case "sidebar":
case "sidebar_text":
case "sidebar_highlight":
case "sidebar_highlight_text":
this.lwtStyles[color] = cssColor;
break;
default:

View File

@ -236,6 +236,22 @@
"ntp_text": {
"$ref": "ThemeColor",
"optional": true
},
"sidebar": {
"$ref": "ThemeColor",
"optional": true
},
"sidebar_text": {
"$ref": "ThemeColor",
"optional": true
},
"sidebar_highlight": {
"$ref": "ThemeColor",
"optional": true
},
"sidebar_highlight_text": {
"$ref": "ThemeColor",
"optional": true
}
},
"additionalProperties": { "$ref": "ThemeColor" }

View File

@ -32,5 +32,6 @@ skip-if = verify
[browser_ext_themes_tab_selected.js]
[browser_ext_themes_autocomplete_popup.js]
[browser_ext_themes_sanitization.js]
[browser_ext_themes_sidebars.js]
[browser_ext_themes_findbar.js]
[browser_ext_themes_warnings.js]

View File

@ -0,0 +1,133 @@
"use strict";
// This test checks whether the sidebar color properties work.
/**
* Test whether the selected browser has the sidebar theme applied
* @param {Object} theme that is applied
* @param {boolean} isBrightText whether the brighttext attribute should be set
*/
async function test_sidebar_theme(theme, isBrightText) {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
theme,
},
});
const content = SidebarUI.browser.contentWindow;
const root = content.document.documentElement;
ok(!root.hasAttribute("lwt-sidebar"),
"Sidebar should not have lwt-sidebar attribute");
ok(!root.hasAttribute("lwt-sidebar-brighttext"),
"Sidebar should not have lwt-sidebar-brighttext attribute");
ok(!root.hasAttribute("lwt-sidebar-highlight"),
"Sidebar should not have lwt-sidebar-highlight attribute");
const rootCS = content.getComputedStyle(root);
const originalBackground = rootCS.backgroundColor;
const originalColor = rootCS.color;
const treeChildren = content.document.querySelector(".sidebar-placesTreechildren");
// ::-moz-tree-row(selected, focus) computed style can't be accessed, so we create a fake one.
const highlightCS = {
get backgroundColor() {
// Standardize to rgb like other computed style.
let color = rootCS.getPropertyValue("--lwt-sidebar-highlight-background-color");
let [r, g, b, a] = color.replace("rgba(", "").split(",").map(channel => parseInt(channel));
return `rgb(${r}, ${g}, ${b})`;
},
get color() {
let color = rootCS.getPropertyValue("--lwt-sidebar-highlight-text-color");
let [r, g, b, a] = color.replace("rgba(", "").split(",").map(channel => parseInt(channel));
return `rgb(${r}, ${g}, ${b})`;
}
};
const originalHighlightBackground = highlightCS.backgroundColor;
const originalHighlightColor = highlightCS.color;
await extension.startup();
Services.ppmm.sharedData.flush();
const actualBackground = hexToCSS(theme.colors.sidebar) || originalBackground;
const actualColor = hexToCSS(theme.colors.sidebar_text) || originalColor;
const actualHighlightBackground = hexToCSS(theme.colors.sidebar_highlight) || originalHighlightBackground;
const actualHighlightColor = hexToCSS(theme.colors.sidebar_highlight_text) || originalHighlightColor;
const isCustomHighlight = !!theme.colors.sidebar_highlight_text;
const isCustomSidebar = !!theme.colors.sidebar_text;
is(root.hasAttribute("lwt-sidebar"), isCustomSidebar,
`Sidebar should${!isCustomSidebar ? " not" : ""} have lwt-sidebar attribute`);
is(root.hasAttribute("lwt-sidebar-brighttext"), isBrightText,
`Sidebar should${!isBrightText ? " not" : ""} have lwt-sidebar-brighttext attribute`);
is(root.hasAttribute("lwt-sidebar-highlight"), isCustomHighlight,
`Sidebar should${!isCustomHighlight ? " not" : ""} have lwt-sidebar-highlight attribute`);
is(rootCS.backgroundColor, actualBackground, "Sidebar background should be set.");
is(rootCS.color, actualColor, "Sidebar text color should be set.");
is(highlightCS.backgroundColor, actualHighlightBackground,
"Sidebar highlight background color should be set.");
is(highlightCS.color, actualHighlightColor,
"Sidebar highlight text color should be set.");
await extension.unload();
Services.ppmm.sharedData.flush();
ok(!root.hasAttribute("lwt-sidebar"),
"Sidebar should not have lwt-sidebar attribute");
ok(!root.hasAttribute("lwt-sidebar-brighttext"),
"Sidebar should not have lwt-sidebar-brighttext attribute");
ok(!root.hasAttribute("lwt-sidebar-highlight"),
"Sidebar should not have lwt-sidebar-highlight attribute");
is(rootCS.backgroundColor, originalBackground,
"Sidebar background should be reset.");
is(rootCS.color, originalColor,
"Sidebar text color should be reset.");
is(highlightCS.backgroundColor, originalHighlightBackground,
"Sidebar highlight background color should be reset.");
is(highlightCS.color, originalHighlightColor,
"Sidebar highlight text color should be reset.");
}
add_task(async function test_support_sidebar_colors() {
for (let command of ["viewBookmarksSidebar", "viewHistorySidebar"]) {
info("Executing command: " + command);
await SidebarUI.show(command);
await test_sidebar_theme({
colors: {
sidebar: "#fafad2", // lightgoldenrodyellow
sidebar_text: "#2f4f4f", // darkslategrey
},
}, false);
await test_sidebar_theme({
colors: {
sidebar: "#8b4513", // saddlebrown
sidebar_text: "#ffa07a" // lightsalmon
},
}, true);
await test_sidebar_theme({
colors: {
sidebar: "#fffafa", // snow
sidebar_text: "#663399", // rebeccapurple
sidebar_highlight: "#7cfc00", // lawngreen
sidebar_highlight_text: "#ffefd5", // papayawhip
},
}, false);
await test_sidebar_theme({
colors: {
sidebar_highlight: "#a0522d", // sienna
sidebar_highlight_text: "#fff5ee", // seashell
},
}, false);
}
});

View File

@ -38,6 +38,9 @@ const FRAME_COLOR = [71, 105, 91];
const TAB_BACKGROUND_TEXT_COLOR = [207, 221, 192, .9];
function hexToRGB(hex) {
if (!hex) {
return null;
}
hex = parseInt((hex.indexOf("#") > -1 ? hex.substring(1) : hex), 16);
return [hex >> 16, (hex & 0x00FF00) >> 8, (hex & 0x0000FF)];
}
@ -47,6 +50,9 @@ function rgbToCSS(rgb) {
}
function hexToCSS(hex) {
if (!hex) {
return null;
}
return rgbToCSS(hexToRGB(hex));
}