summaryrefslogtreecommitdiffstats
path: root/browser/base/content/contentTheme.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--browser/base/content/contentTheme.js171
1 files changed, 171 insertions, 0 deletions
diff --git a/browser/base/content/contentTheme.js b/browser/base/content/contentTheme.js
new file mode 100644
index 0000000000..48629ed9e4
--- /dev/null
+++ b/browser/base/content/contentTheme.js
@@ -0,0 +1,171 @@
+/* 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";
+
+{
+ function _isTextColorDark(r, g, b) {
+ return 0.2125 * r + 0.7154 * g + 0.0721 * b <= 110;
+ }
+
+ const inContentVariableMap = [
+ [
+ "--newtab-background-color",
+ {
+ lwtProperty: "ntp_background",
+ },
+ ],
+ [
+ "--newtab-text-primary-color",
+ {
+ lwtProperty: "ntp_text",
+ processColor(rgbaChannels, element) {
+ if (!rgbaChannels) {
+ element.removeAttribute("lwt-newtab");
+ element.removeAttribute("lwt-newtab-brighttext");
+ return null;
+ }
+
+ element.setAttribute("lwt-newtab", "true");
+ const { r, g, b, a } = rgbaChannels;
+ if (!_isTextColorDark(r, g, b)) {
+ element.setAttribute("lwt-newtab-brighttext", "true");
+ } else {
+ element.removeAttribute("lwt-newtab-brighttext");
+ }
+
+ return `rgba(${r}, ${g}, ${b}, ${a})`;
+ },
+ },
+ ],
+ [
+ "--lwt-sidebar-background-color",
+ {
+ lwtProperty: "sidebar",
+ processColor(rgbaChannels) {
+ if (!rgbaChannels) {
+ return null;
+ }
+ const { r, g, b } = rgbaChannels;
+ // Drop alpha channel
+ return `rgb(${r}, ${g}, ${b})`;
+ },
+ },
+ ],
+ [
+ "--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");
+ } else {
+ element.removeAttribute("lwt-sidebar-brighttext");
+ }
+
+ 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})`;
+ },
+ },
+ ],
+ ];
+
+ /**
+ * ContentThemeController handles theme updates sent by the frame script.
+ * To be able to use ContentThemeController, you must add your page to the whitelist
+ * in LightweightThemeChildListener.jsm
+ */
+ const ContentThemeController = {
+ /**
+ * Tell the frame script that the page supports theming, and watch for updates
+ * from the frame script.
+ */
+ init() {
+ addEventListener("LightweightTheme:Set", this);
+ },
+
+ /**
+ * Handle theme updates from the frame script.
+ * @param {Object} event object containing the theme update.
+ */
+ handleEvent({ type, detail }) {
+ if (type == "LightweightTheme:Set") {
+ let { data } = detail;
+ if (!data) {
+ data = {};
+ }
+ // XUL documents don't have a body
+ const element = document.body
+ ? document.body
+ : document.documentElement;
+ this._setProperties(element, data);
+ }
+ },
+
+ /**
+ * Set a CSS variable to a given value
+ * @param {Element} elem The element where the CSS variable should be added.
+ * @param {string} variableName The CSS variable to set.
+ * @param {string} value The new value of the CSS variable.
+ */
+ _setProperty(elem, variableName, value) {
+ if (value) {
+ elem.style.setProperty(variableName, value);
+ } else {
+ elem.style.removeProperty(variableName);
+ }
+ },
+
+ /**
+ * Apply theme data to an element
+ * @param {Element} root The element where the properties should be applied.
+ * @param {Object} themeData The theme data.
+ */
+ _setProperties(elem, themeData) {
+ for (let [cssVarName, definition] of inContentVariableMap) {
+ const { lwtProperty, processColor } = definition;
+ let value = themeData[lwtProperty];
+
+ if (processColor) {
+ value = processColor(value, elem);
+ } else if (value) {
+ const { r, g, b, a } = value;
+ value = `rgba(${r}, ${g}, ${b}, ${a})`;
+ }
+
+ this._setProperty(elem, cssVarName, value);
+ }
+ },
+ };
+ ContentThemeController.init();
+}