├── .gitattributes
├── JS
├── animateContextMenus.uc.js
├── clearDownloadsButton.uc.js
├── hideScrollbar.uc.js
├── macosTheme.uc.js
└── navbarToolbarButtonSlider.uc.js
├── LICENSE
├── README.md
├── assets
├── adaptive-tab-bar-extension-support.gif
├── adaptive.gif
├── context.png
├── hide_scroll_bar.gif
├── library.png
├── mac_os_theme.gif
├── navbar.gif
└── preview.png
├── img
└── new_tab_wallpaper.jpg
├── includes
├── realfire-addons-page.css
├── realfire-button.css
├── realfire-checkbox.css
├── realfire-colours.css
├── realfire-config.css
├── realfire-findbar.css
├── realfire-icons.css
├── realfire-inputs.css
├── realfire-layout.css
├── realfire-library.css
├── realfire-nav-bar.css
├── realfire-popups.css
├── realfire-responsive.css
├── realfire-settings-page.css
├── realfire-side-bar.css
└── realfire-tabs.css
├── programs
├── install-curl.bat
├── install-curl.sh
├── install.bat
├── install.sh
├── local-settings.js
├── mozilla.cfg
├── uninstall.bat
├── uninstall.sh
└── user.js
├── resources
└── material
│ ├── actual-zoom.svg
│ ├── all-history.svg
│ ├── bookmark-manage.svg
│ ├── checked copy.svg
│ ├── checked.svg
│ ├── close-hover.svg
│ ├── close-tab-option.svg
│ ├── close.svg
│ ├── command-pick.svg
│ ├── desktop-bg.svg
│ ├── duplicate-tab.svg
│ ├── experiments.svg
│ ├── ideas.svg
│ ├── inactive.svg
│ ├── maximize-hover.svg
│ ├── maximize-restore.svg
│ ├── maximize-svg.svg
│ ├── maximize.svg
│ ├── minimize-hover.svg
│ ├── minimize.svg
│ ├── move-container.svg
│ ├── move-end.svg
│ ├── move-start.svg
│ ├── move-tab.svg
│ ├── new-container.svg
│ ├── open_new_tabs.svg
│ ├── page-source.svg
│ ├── pause.svg
│ ├── playButton.svg
│ ├── quit.svg
│ ├── radio-checked.svg
│ ├── radio-unchecked.svg
│ ├── redo.svg
│ ├── reload.svg
│ ├── remote-debug.svg
│ ├── restore-session.svg
│ ├── select-all.svg
│ ├── send-tab.svg
│ ├── share-tab.svg
│ ├── signout.svg
│ ├── terminal.svg
│ ├── toolbox.svg
│ ├── translate.svg
│ ├── unchecked.svg
│ ├── userScriptsMenu.svg
│ ├── web-page-source-code.svg
│ ├── zoom-in.svg
│ └── zoom-out.svg
├── userChrome.css
├── userContent.css
└── utils
├── boot.sys.mjs
├── chrome.manifest
├── fs.sys.mjs
├── uc_api.sys.mjs
└── utils.sys.mjs
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/JS/animateContextMenus.uc.js:
--------------------------------------------------------------------------------
1 | // ==UserScript==
2 | // @name Animate Context Menus
3 | // @version 1.0.4
4 | // @author aminomancer
5 | // @homepage https://github.com/aminomancer/uc.css.js
6 | // @description Give all context menus the same opening animation that panel popups like the app menu have — the menu slides down 70px and fades in opacity at the same time. It's a cool effect that doesn't trigger a reflow since it uses transform, but it does repaint the menu, so I wouldn't recommend using this on weak hardware.
7 | // @downloadURL https://cdn.jsdelivr.net/gh/aminomancer/uc.css.js@master/JS/animateContextMenus.uc.js
8 | // @updateURL https://cdn.jsdelivr.net/gh/aminomancer/uc.css.js@master/JS/animateContextMenus.uc.js
9 | // @license This Source Code Form is subject to the terms of the Creative Commons Attribution-NonCommercial-ShareAlike International License, v. 4.0. If a copy of the CC BY-NC-SA 4.0 was not distributed with this file, You can obtain one at http://creativecommons.org/licenses/by-nc-sa/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
10 | // @include *
11 | // ==/UserScript==
12 |
13 | class AnimateContextMenus {
14 | constructor() {
15 | document.documentElement.setAttribute("animate-menupopups", true);
16 | addEventListener("popupshowing", this);
17 | addEventListener("popupshown", this);
18 | addEventListener("popuphidden", this);
19 | let css = `:root[animate-menupopups]
20 | :not(menulist)
21 | > menupopup:not([position], [type="arrow"], [animate="false"]) {
22 | opacity: 0;
23 | transform: translateY(-70px) scaleX(0.95) scaleY(0.5);
24 | transform-origin: top;
25 | transition-property: transform, opacity;
26 | transition-duration: 0.18s, 0.18s;
27 | transition-timing-function: var(--animation-easing-function, cubic-bezier(0.07, 0.95, 0, 1)),
28 | ease-out;
29 | transform-style: flat;
30 | backface-visibility: hidden;
31 | }
32 | :root[animate-menupopups]
33 | :not(menulist)
34 | > menupopup:not([position], [type="arrow"])[animate][animate="open"] {
35 | opacity: 1;
36 | transition-duration: 0.18s, 0.18s;
37 | transform: none !important;
38 | transition-timing-function: var(--animation-easing-function, cubic-bezier(0.07, 0.95, 0, 1)),
39 | ease-in-out;
40 | }
41 | :root[animate-menupopups]
42 | :not(menulist)
43 | > menupopup:not([position], [type="arrow"])[animate][animate="cancel"] {
44 | transform: none;
45 | }
46 | :root[animate-menupopups] :not(menulist) > menupopup:not([position], [type="arrow"])[animating] {
47 | pointer-events: none;
48 | }`;
49 | let sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(
50 | Ci.nsIStyleSheetService
51 | );
52 | let uri = Services.io.newURI(
53 | `data:text/css;charset=UTF=8,${encodeURIComponent(css)}`
54 | );
55 | if (!sss.sheetRegistered(uri, sss.AUTHOR_SHEET)) {
56 | sss.loadAndRegisterSheet(uri, sss.AUTHOR_SHEET);
57 | }
58 | }
59 | handleEvent(e) {
60 | if (e.target.tagName !== "menupopup") return;
61 | if (e.target.hasAttribute("position")) return;
62 | if (e.target.getAttribute("type") == "arrow") return;
63 | if (e.target.parentElement) {
64 | if (e.target.parentElement.tagName == "menulist") return;
65 | }
66 | if (
67 | e.target.shadowRoot &&
68 | e.target.shadowRoot.firstElementChild.classList.contains(
69 | "panel-arrowcontainer"
70 | )
71 | ) {
72 | return;
73 | }
74 | this[`on_${e.type}`](e);
75 | }
76 | on_popupshowing(e) {
77 | if (e.target.getAttribute("animate") != "false") {
78 | e.target.setAttribute("animate", "open");
79 | e.target.setAttribute("animating", "true");
80 | }
81 | }
82 | on_popupshown(e) {
83 | e.target.removeAttribute("animating");
84 | }
85 | on_popuphidden(e) {
86 | if (e.target.getAttribute("animate") != "false") {
87 | e.target.removeAttribute("animate");
88 | }
89 | }
90 | }
91 |
92 | new AnimateContextMenus();
93 |
--------------------------------------------------------------------------------
/JS/clearDownloadsButton.uc.js:
--------------------------------------------------------------------------------
1 | // ==UserScript==
2 | // @name Clear Downloads Panel Button
3 | // @version 1.4.2
4 | // @author aminomancer
5 | // @homepageURL https://github.com/aminomancer/uc.css.js
6 | // @description Place a "Clear Downloads" button in the downloads panel, right next to the "Show all downloads" button.
7 | // @downloadURL https://cdn.jsdelivr.net/gh/aminomancer/uc.css.js@master/JS/clearDownloadsButton.uc.js
8 | // @updateURL https://cdn.jsdelivr.net/gh/aminomancer/uc.css.js@master/JS/clearDownloadsButton.uc.js
9 | // @license This Source Code Form is subject to the terms of the Creative Commons Attribution-NonCommercial-ShareAlike International License, v. 4.0. If a copy of the CC BY-NC-SA 4.0 was not distributed with this file, You can obtain one at http://creativecommons.org/licenses/by-nc-sa/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
10 | // ==/UserScript==
11 |
12 | class ClearDLPanel {
13 | constructor() {
14 | this.makeButton();
15 | this.setCountHandler();
16 | Services.obs.addObserver(this, "downloads-panel-count-changed");
17 | }
18 | async genStrings() {
19 | this.strings = await new Localization(["browser/downloads.ftl"], true);
20 | const messages = await this.strings.formatMessages([
21 | "downloads-cmd-clear-downloads",
22 | ]);
23 | this.label = messages[0].attributes[0].value;
24 | this.accessKey = messages[0].attributes[1].value;
25 | return [this.label, this.accessKey];
26 | }
27 | async makeButton() {
28 | this.clearPanelButton = document.createXULElement("button");
29 | let strings = await this.genStrings();
30 | let labelString = this.sentenceCase(strings[0]);
31 | for (const [key, val] of Object.entries({
32 | id: "clearDownloadsPanel",
33 | class:
34 | DownloadsView.downloadsHistory.className ||
35 | "downloadsPanelFooterButton subviewbutton panel-subview-footer-button toolbarbutton-1",
36 | oncommand: `goDoCommand('downloadsCmd_clearList'); DownloadsPanel.hidePanel();`,
37 | label: labelString,
38 | accesskey: strings[1],
39 | flex: "1",
40 | pack: "start",
41 | })) {
42 | this.clearPanelButton.setAttribute(key, val);
43 | }
44 | DownloadsView.downloadsHistory.after(this.clearPanelButton);
45 | this.clearPanelButton.hidden = !DownloadsView._visibleViewItems?.size > 0;
46 | this.clearPanelButton
47 | ?.closest("#downloadsFooter")
48 | .prepend(document.createXULElement("toolbarseparator"));
49 | this.clearPanelButton?.parentElement.setAttribute("uc-hbox", "true");
50 | }
51 | sentenceCase(str) {
52 | return str
53 | .toLocaleLowerCase()
54 | .replace(RTL_UI ? /.$/i : /^./i, function (letter) {
55 | return letter.toLocaleUpperCase();
56 | })
57 | .trim();
58 | }
59 | setCountHandler() {
60 | eval(
61 | `DownloadsView._itemCountChanged = function ${DownloadsView._itemCountChanged
62 | .toSource()
63 | .replace(
64 | /hiddenCount \> 0\;\n/,
65 | `hiddenCount > 0;\n Services.obs.notifyObservers(null, "downloads-panel-count-changed", String(count));\n`
66 | )}`
67 | );
68 | }
69 | observe(_sub, _top, data) {
70 | this.clearPanelButton.hidden = parseInt(data) < 1;
71 | }
72 | }
73 |
74 | if (gBrowserInit.delayedStartupFinished) {
75 | new ClearDLPanel();
76 | } else {
77 | let delayedListener = (subject, topic) => {
78 | if (topic == "browser-delayed-startup-finished" && subject == window) {
79 | Services.obs.removeObserver(delayedListener, topic);
80 | new ClearDLPanel();
81 | }
82 | };
83 | Services.obs.addObserver(delayedListener, "browser-delayed-startup-finished");
84 | }
85 |
--------------------------------------------------------------------------------
/JS/hideScrollbar.uc.js:
--------------------------------------------------------------------------------
1 | // ==UserScript==
2 | // @name Floating Scrollbar
3 | // @version 1.0.0
4 | // @author Hakanbaban53
5 | // @homepage https://github.com/Hakanbaban53/RealFire
6 | // @description Auto hide scrollbar.
7 | // @downloadURL https://cdn.jsdelivr.net/gh/Hakanbaban53/RealFire@main/JS/hideScrollbar.uc.js
8 | // @updateURL https://cdn.jsdelivr.net/gh/Hakanbaban53/RealFire@main/JS/hideScrollbar.uc.js
9 | // @license This Source Code Form is subject to the terms of the Creative Commons Attribution-NonCommercial-ShareAlike International License, v. 4.0. If a copy of the CC BY-NC-SA 4.0 was not distributed with this file, You can obtain one at http://creativecommons.org/licenses/by-nc-sa/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
10 | // ==/UserScript==
11 |
12 | (function () {
13 | // var prefs = Services.prefs,
14 | // enabled;
15 | // if (prefs.prefHasUserValue('userChromeJS.floatingScrollbar.enabled')) {
16 | // enabled = prefs.getBoolPref('userChromeJS.floatingScrollbar.enabled')
17 | // } else {
18 | // prefs.setBoolPref('userChromeJS.floatingScrollbar.enabled', true);
19 | // enabled = true;
20 | // }
21 |
22 | var css = `
23 | link[href$="global.css"] ~ scrollbox {
24 | overflow-y: auto !important;
25 | }
26 | link[href$="global.css"] ~ .menupopup-scrollbutton {
27 | display: none !important;
28 | }
29 | link[href$="global.css"] ~ hbox > arrowscrollbox.in-bookmarks-menu {
30 | padding-bottom: 0px !important;
31 | }
32 | link[href$="global.css"] ~ scrollbox {
33 | padding-top: 0px !important;
34 | }
35 | link[href$="global.css"] ~ .scrollbutton-up,
36 | link[href$="global.css"] ~ .scrollbutton-down,
37 | link[href$="global.css"] ~ spacer[part=arrowscrollbox-overflow-start-indicator],
38 | link[href$="global.css"] ~ spacer[part=arrowscrollbox-overflow-end-indicator] {
39 | display: none !important;
40 | }
41 | .hidevscroll-scrollbar {
42 | -moz-appearance: none!important;
43 | margin-left: 7px!important;
44 | border: none!important;
45 | position: relative!important;
46 | background-color: transparent!important;
47 | padding: 0px!important;
48 | z-index: 2147483647!important;
49 | }
50 | .hidevscroll-scrollbar[orient = "vertical"] {
51 | -moz-margin-start: -7px!important;
52 | min-width: 7px!important;
53 | }
54 | .hidevscroll-scrollbar[orient = "vertical"] thumb {
55 | min-height: 20px!important;
56 | }
57 | .hidevscroll-scrollbar thumb {
58 | -moz-appearance: none!important;
59 | border-width: 0px!important;
60 | border-radius: 7px!important;
61 | background-color: rgb(136, 137, 141, 1)!important;
62 | opacity: 0!important;
63 | transition: opacity 0.4s ease-in-out!important;
64 | -webkit-transform-style: preserve-3d!important;
65 | -webkit-backface-visibility: hidden!important;
66 | }
67 | .hidevscroll-scrollbar:hover thumb {
68 | background-color: rgb(136, 137, 141, 1)!important;
69 | opacity: 0.7!important;
70 | transition: opacity 0.1s ease-in-out!important;
71 | -webkit-transform-style: preserve-3d!important;
72 | -webkit-backface-visibility: hidden!important;
73 | }
74 | .hidevscroll-scrollbar[orient = "vertical"] thumb:active {
75 | background: linear-gradient(to top, #c50ed2, #8500f7) !important;
76 | }
77 | .hidevscroll-scrollbar[orient = "horizontal"] thumb:active {
78 | background: linear-gradient(to left, #c50ed2, #8500f7) !important;
79 | }
80 | .hidevscroll-scrollbar thumb:active {
81 | opacity: 0.9!important;
82 | transition: opacity 0.06s ease-in-out!important;
83 | -webkit-transform-style: preserve-3d!important;
84 | -webkit-backface-visibility: hidden!important;
85 | }
86 | .hidevscroll-scrollbar scrollbarbutton, .hidevscroll-scrollbar gripper {
87 | display: none!important;
88 | }
89 | :not(select):not(hbox) > scrollbar {
90 | position: relative;
91 | background-color: transparent;
92 | background-image: none;
93 | z-index: 2147483647;
94 | padding: 0px;
95 | }
96 | :not(select):not(hbox) > scrollbar[orient = "vertical"] {
97 | -moz-margin-start: -7px;
98 | min-width: 7px;
99 | max-width: 7px;
100 | }
101 | :not(select):not(hbox) > scrollbar[orient = "vertical"] thumb {
102 | min-height: 20px;
103 | }
104 | :not(select):not(hbox) > scrollbar[orient = "horizontal"] {
105 | margin-top: -7px;
106 | min-height: 7px;
107 | max-height: 7px;
108 | }
109 | :not(select):not(hbox) > scrollbar[orient = "horizontal"] thumb {
110 | max-width: 20px;
111 | }
112 | :not(select):not(hbox) > scrollbar thumb {
113 | -moz-appearance: none!important;
114 | border-width: 0px!important;
115 | border-radius: 7px!important;
116 | background-color: rgb(136, 137, 141, 1)!important;
117 | opacity: 0!important;
118 | transition: opacity 0.4s ease-in-out;
119 | -webkit-transform-style: preserve-3d;
120 | -webkit-backface-visibility: hidden;
121 | }
122 | :not(select):not(hbox) > scrollbar:hover thumb {
123 | background-color: rgb(136, 137, 141, 1)!important;
124 | opacity: 0.7!important;
125 | transition: opacity 0.1s ease-in-out;
126 | -webkit-transform-style: preserve-3d;
127 | -webkit-backface-visibility: hidden;
128 | }
129 | :not(select):not(hbox) > scrollbar[orient = "vertical"] thumb:active {
130 | background: linear-gradient(to top, #c50ed2, #8500f7) !important;
131 | }
132 | :not(select):not(hbox) > scrollbar[orient = "horizontal"] thumb:active {
133 | background: linear-gradient(to left, #c50ed2, #8500f7) !important;
134 | }
135 | :not(select):not(hbox) > scrollbar thumb:active {
136 | opacity: 0.9!important;
137 | transition: opacity 0.06s ease-in-out;
138 | -webkit-transform-style: preserve-3d;
139 | -webkit-backface-visibility: hidden;
140 | }
141 | :not(select):not(hbox) > scrollbar scrollbarbutton, :not(select):not(hbox) > scrollbar gripper {
142 | display: none;
143 | }
144 | `;
145 |
146 | var sss = Cc['@mozilla.org/content/style-sheet-service;1'].getService(Ci.nsIStyleSheetService);
147 | var uri = makeURI('data:text/css;charset=UTF=8,' + encodeURIComponent(css));
148 |
149 | // if (enabled) {
150 | sss.loadAndRegisterSheet(uri, sss.AGENT_SHEET);
151 | // }
152 | })();
153 |
--------------------------------------------------------------------------------
/JS/macosTheme.uc.js:
--------------------------------------------------------------------------------
1 | // ==UserScript==
2 | // @name MacOS Window Control & Font Theme
3 | // @version 1.1.2
4 | // @author Hakanbaban53
5 | // @homepage https://github.com/Hakanbaban53/RealFire
6 | // @description Move the window control to the left and recolor it and change the font.
7 | // @downloadURL https://cdn.jsdelivr.net/gh/Hakanbaban53/RealFire@main/JS/macosTheme.uc.js
8 | // @updateURL https://cdn.jsdelivr.net/gh/Hakanbaban53/RealFire@main/JS/macosTheme.uc.js
9 | // @license This Source Code Form is subject to the terms of the Creative Commons Attribution-NonCommercial-ShareAlike International License, v. 4.0. If a copy of the CC BY-NC-SA 4.0 was not distributed with this file, You can obtain one at http://creativecommons.org/licenses/by-nc-sa/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
10 | // ==/UserScript==
11 |
12 | (function () {
13 | // CSS rules to apply
14 | var css = `
15 | /* Default font family for most elements, with fallbacks */
16 | *:not([class*="FokDXb"]):not([class*="upload"]):not([class*="icon"]):not([class*="mui-amount"]):not([class*="chaoshi"]):not([class*="top-nav"]):not([href*="ju.taobao.com"]):not([class*="Icon"]):not(b):not(ins):not(i):not(s) {
17 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Ubuntu", "Cantarell", sans-serif !important;
18 | }
19 |
20 | #toolbar-menubar .titlebar-buttonbox-container {
21 | display: flex !important;
22 | }
23 | #toolbar-menubar {
24 | display: flex;
25 | flex-direction: row-reverse;
26 | }
27 |
28 | /* Toolbar adjustments for when width is 1000px or more */
29 | @media (min-width: 1000px) {
30 | #navigator-toolbox:not([inFullscreen]) #TabsToolbar .titlebar-buttonbox-container {
31 | visibility: visible !important;
32 | display: block !important;
33 | position: absolute !important;
34 | top: 12px;
35 | left: -8px;
36 | }
37 | /* Hide titlebar buttonbox container in toolbar menubar by default */
38 | #toolbar-menubar .titlebar-buttonbox-container {
39 | display: none !important;
40 | }
41 | }
42 |
43 |
44 | /* Reorder toolbar items */
45 | #TabsToolbar .toolbar-items {
46 | order: 1 !important;
47 | }
48 |
49 | #TabsToolbar .titlebar-buttonbox-container {
50 | order: 0 !important;
51 | }
52 |
53 | /* Styling for titlebar buttons */
54 | :root[sizemode="maximized"] .titlebar-buttonbox-container {
55 | padding-top: 0 !important;
56 | }
57 |
58 | :root:-moz-window-inactive:not([customizing]) .titlebar-buttonbox > toolbarbutton:not(:hover) {
59 | opacity: 0.65 !important;
60 | list-style-image: url(chrome://userchrome/content/material/inactive.svg) !important;
61 | }
62 |
63 | .titlebar-buttonbox {
64 | gap: 10px;
65 | margin-right: 12px !important;
66 | margin-left: 12px !important;
67 | }
68 |
69 | .titlebar-button > .toolbarbutton-icon,
70 | .toolbarbutton-icon {
71 | opacity: 1 !important;
72 | appearance: none !important;
73 | background-image: none !important;
74 | }
75 |
76 | .titlebar-button > .toolbarbutton-icon {
77 | height: 15px !important;
78 | min-height: 25px !important;
79 | width: 15px !important;
80 | min-width: 25px !important;
81 | padding-left: 6px !important;
82 | padding-right: 6px !important;
83 | }
84 |
85 | /* Order and appearance of titlebar buttons */
86 | .titlebar-close {
87 | order: 0 !important;
88 | padding: 0 !important;
89 | list-style-image: url(chrome://userchrome/content/material/close.svg) !important;
90 | }
91 |
92 | .titlebar-min {
93 | order: 1 !important;
94 | padding: 0 !important;
95 | list-style-image: url(chrome://userchrome/content/material/minimize.svg) !important;
96 | }
97 |
98 | .titlebar-max, .titlebar-restore {
99 | order: 2 !important;
100 | padding: 0 !important;
101 | list-style-image: url(chrome://userchrome/content/material/maximize.svg) !important;
102 | }
103 |
104 | /* Hover states for titlebar buttons */
105 | .titlebar-min:hover {
106 | list-style-image: url(chrome://userchrome/content/material/minimize-hover.svg) !important;
107 | }
108 |
109 | .titlebar-max:hover {
110 | list-style-image: url(chrome://userchrome/content/material/maximize-hover.svg) !important;
111 | }
112 |
113 | .titlebar-restore:hover {
114 | list-style-image: url(chrome://userchrome/content/material/maximize-restore.svg) !important;
115 | }
116 |
117 | .titlebar-close:hover {
118 | list-style-image: url(chrome://userchrome/content/material/close-hover.svg) !important;
119 | }
120 | `;
121 |
122 | // Function to initialize the script
123 | function init() {
124 | var root = document.documentElement;
125 | var urlbarPosition = getComputedStyle(root).getPropertyValue('--uc-urlbar-position').trim();
126 | // console.log('URL Bar Position:', urlbarPosition);
127 |
128 | // Function to apply styles based on the media query status
129 | function applyStyles(matches) {
130 | var navBar = document.getElementById('nav-bar');
131 | var titleBar = document.getElementById('titlebar');
132 |
133 | if (urlbarPosition === '1') {
134 | navBar.style.paddingLeft = matches ? '106px' : '0';
135 | } else if (urlbarPosition === '3') {
136 | titleBar.style.paddingLeft = matches ? '106px' : '0';
137 | }
138 | }
139 |
140 | // Initial application of styles
141 | applyStyles(window.matchMedia('(min-width: 1000px)').matches);
142 |
143 | // Listen for changes in the media query status
144 | window.matchMedia('(min-width: 1000px)').addEventListener('change', function (event) {
145 | applyStyles(event.matches);
146 | });
147 | }
148 |
149 | // Check if the browser initialization is complete
150 | if (gBrowserInit.delayedStartupFinished) {
151 | init();
152 | } else {
153 | let delayedListener = (subject, topic) => {
154 | if (topic == "browser-delayed-startup-finished" && subject == window) {
155 | Services.obs.removeObserver(delayedListener, topic);
156 | init();
157 | }
158 | };
159 | Services.obs.addObserver(delayedListener, "browser-delayed-startup-finished");
160 | }
161 |
162 | // Create a style element and append the CSS rules
163 | var style = document.getElementById("macos-theme-style");
164 | if (!style) {
165 | style = document.createElement("style");
166 | style.id = "macos-theme-style";
167 | style.type = "text/css";
168 | style.textContent = css;
169 | document.head.appendChild(style);
170 | }
171 | })();
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Hakan İSMAİL
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # [RealFire 🔥](https://github.com/Hakanbaban53/RealFire)
4 |
5 | **A minimalist animated oneliner theme for Firefox perfectly matching real Dark**
6 |
7 |
8 | 
9 |
10 | ## 🏞 Screenshots
11 |
12 | Click me 🐈
13 |
14 | Adaptive Tab Bar Extension Support
15 | 
16 |
17 | MacOs Window Control & Fonts
18 | 
19 |
20 | Animated Background
21 | 
22 |
23 | Context Menu
24 | 
25 |
26 | Auto-hide Scrollbars
27 | 
28 |
29 | Library
30 | 
31 |
32 | Adaptive Window Color With Windows & GNU/Linux
33 | 
34 |
35 |
36 |
37 | ## 📃 Browser JS Files
38 |
39 | ### [`userChrome.css`](./userChrome.css)
40 |
41 | This helps to customize Firefox User Interface.
42 |
43 | ### [`userContent.css`](./userContent.css)
44 |
45 | This helps to customize web content like a specific site.
46 |
47 | ### [`hideScrollbar.uc.js`](./JS/hideScrollbar.uc.js)
48 |
49 | It's now possible to autohide scrollbars.
50 |
51 | ### [`macosTheme.uc.js`](./JS/macosTheme.uc.js)
52 |
53 | This script to convert font and window controls to macos style.
54 |
55 | ## ❓ **But how does it work?**
56 |
57 | Custom startup-script (aka [`mozilla.cfg`](./programs/mozilla.cfg) here) is loaded using [`local-settings.js`](./programs/local-settings.js). This startup-script adds "loader" scripts from `utils` folder that loads arbitrary javascript files from the `script` folder into Firefox
58 | `mozilla.cfg` also helps in setting local webpage as your homepage. Details in [Installation](#Installation) (Currently Not Working!).
59 |
60 | ## 💡 Installation
61 |
62 | GUI Installation
63 | Firefox Theme Installer
64 |
65 | ### [Check This Repo](https://github.com/Hakanbaban53/Firefox-Theme-Installer?tab=readme-ov-file#--------firefox-theme-installer--)
66 |
67 | Explore the Firefox Theme Installer repository for an easy and efficient way to install and manage your Firefox themes.
68 |
69 |
70 |
71 | Curl based Installation (You can install this theme with one line command)
72 |
73 | GNU/Linux & MacOS
74 |
75 | ```console
76 | $ curl -s -o- https://raw.githubusercontent.com/Hakanbaban53/RealFire/main/programs/install-curl.sh | bash # Standard
77 | $ curl -s -o- https://raw.githubusercontent.com/Hakanbaban53/RealFire/main/programs/install-curl.sh | bash -s -- -f ~/.var/app/org.mozilla.firefox/.mozilla/firefox # Flatpak
78 | $ curl -s -o- https://raw.githubusercontent.com/Hakanbaban53/RealFire/main/programs/install-curl.sh | bash -s -- -f ~/snap/firefox/common/.mozilla/firefox/ # Snap
79 | ```
80 |
81 |
82 |
83 | Windows
84 |
85 | ```powershell
86 | > curl -sL "https://raw.githubusercontent.com/Hakanbaban53/RealFire/main/programs/install-curl.bat" > %TEMP%\install-curl.bat && %TEMP%\install-curl.bat REM Standard
87 | > curl -sL "https://raw.githubusercontent.com/Hakanbaban53/RealFire/main/programs/install-curl.bat" > %TEMP%\install-curl.bat && %TEMP%\install-curl.bat -b "C:\Program Files (x86)\Mozilla Firefox" REM Custom binary folder
88 | ```
89 |
90 |
91 | This will download the master branch and run the installation script.
92 | `mozilla.cfg` can be configured after complete installation
93 |
94 |
95 |
96 | Script Installation
97 |
98 | 1. Clone the repository and enter folder:
99 |
100 | ```console
101 | $ git clone https://github.com/Hakanbaban53/RealFire.git && cd RealFire
102 | ```
103 |
104 | 2. Run installation script
105 |
106 | This script will lookup default Firefox profile location and install the theme with default configurations.
107 |
108 | GNU/Linux & MacOS
109 |
110 | ```console
111 | $ ./programs/install.sh # Standard
112 | $ ./programs/install.sh -f ~/.var/app/org.mozilla.firefox/.mozilla/firefox # Flatpak
113 | $ ./programs/install.sh -f ~/snap/firefox/common/.mozilla/firefox/ # Snap
114 | ```
115 |
116 |
117 |
118 | Windows
119 |
120 | ```powershell
121 | > programs\install.bat REM Standard
122 | > programs\install.bat -e -b "C:\Program Files (x86)\Mozilla Firefox" REM Disable fx-autoconfig and Custom binary folder
123 | ```
124 |
125 |
126 |
127 | #### Script options
128 |
129 | - `-b ` _optional_
130 |
131 | - Set custom Firefox binary folder path, for example `/usr/lib32/firefox`
132 | - Default: Auto detects in linux. `C:\Program Files\Mozilla Firefox` in windows
133 |
134 | - `-f ` _optional_
135 |
136 | - Set custom Firefox folder path, for example `~/.mozilla/icecat/`
137 | - Default: `~/.mozilla/firefox/` in linux. `%APPDATA%\Mozilla\Firefox` in windows
138 |
139 | - `-p ` _optional_
140 |
141 | - Set custom profile name, for example `4htgy4pu.app`
142 | - Default: Profile folder name found in `profiles.ini` at ->
143 |
144 | ```
145 | [Install4F96D1932A9F858E]
146 | Default=1yrah0xg.default-release
147 | Locked=1
148 | ```
149 |
150 | - `-e` _optional_
151 |
152 | - Install [`fx-autoconfig`](https://github.com/MrOtherGuy/fx-autoconfig)
153 | - Runs sudo to copy `mozilla.cfg` and `local-settings.js` to Application Binary folder
154 | - Default: True
155 |
156 | - `-h` _optional_
157 | - Shows help message with flags info
158 |
159 |
160 | Manual Installation
161 |
162 | 1. Open `about:support` in new tab and click `Open Directory` near `Profile Directory`.
163 |
164 | 2. Open this directory in terminal and clone the repository
165 |
166 | Note: If you already have a `chrome` folder under `Profile Directory`, rename it to `chrome_bak` or anything else to preserve your old theme.
167 |
168 | ```console
169 | $ cd {Your profile directory}
170 |
171 | $ git clone https://github.com/Hakanbaban53/RealFire.git chrome
172 |
173 | $ cd chrome
174 | ```
175 |
176 | MacOS
177 |
178 | - `about:support` > `Application Binary` > `{Installation folder}firefox`
179 | Generally `Installation folder` is `/Applications/Firefox.app/Contents/MacOS/` (`Firefox Nightly` for Nightly version)
180 |
181 | For `MacOS`, our destination folder is `/Applications/Firefox.app/Contents/Resources/`
182 |
183 | ```console
184 | $ ln -s "`pwd`/programs/user.js" ../user.js
185 |
186 | $ cp ./programs/mozilla.cfg /Applications/Firefox.app/Contents/Resources/
187 |
188 | $ cp ./programs/local-settings.js /Applications/Firefox.app/Contents/Resources/defaults/pref/
189 | ```
190 |
191 |
192 |
193 | Windows
194 |
195 | - `about:support` > `Application Binary` > `{Installation folder}firefox.exe`
196 | Generally `Installation folder` is `C:\Program Files\Mozilla Firefox\`
197 |
198 | ```powershell
199 | > mklink ..\user.js "%cd%\programs\user.js"
200 |
201 | > copy .\programs\mozilla.cfg "C:\Program Files\Mozilla Firefox\"
202 |
203 | > copy .\programs\local-settings.js "C:\Program Files\Mozilla Firefox\defaults\pref\"
204 | ```
205 |
206 | ```
207 |
208 |
209 |
210 | - 🗑️ If you want to remove the Theme:
211 |
212 | #### GNU/Linux & MacOS
213 | ./programs/uninstall.sh
214 |
215 | #### Windows
216 | ./programs/uninstall.bat
217 |
218 |
219 | #### 🔧 Follow-up changes
220 |
221 | 1. In Firefox
222 |
223 | - Right click hamburger button > `customize toolbar` disable `Title Bar`, `Drag Space`.
224 | - Remove `Flexible Space` from urlbar.
225 | - Set Density to `Compact/Normal/Touch` and Themes to `Dark` or `Light`.
226 |
227 | 2. Open `about:support` > `Clear startup cache...` > `Restart` **_twice_**
228 |
229 | 3. ### **Voilà**
230 |
231 | ## ⚙️ Configuration
232 |
233 | 1. You can use the [ realfire-config.css ](/includes/realfire-config.css) change the a lot of variables.
234 |
235 | 2. If you run the automatic installation script, it will install all the files in the folders where they need to be installed.
236 |
237 | 3. If something breaks on your system then please raise a issue
238 |
239 | 4. If you want to use `vertical tabs`, you may need to edit this line in the [realfire-config.css](/includes/realfire-config.css#L59) file.
240 |
241 | ## 📌 Known issues
242 |
243 | - Adaptive window color with windows not working on preferences page and start page (Windows only). If you want the change it use the [ realfire-config.css ](/includes/realfire-config.css) file.
244 |
245 | ## 📂 Folder structure
246 |
247 | ```css
248 | 🗃 .
249 | ├── 🖿 assets
250 | │ └── 🖻 preview images
251 | ├── 🖿 img
252 | │ └── 🖻 new tab background image
253 | ├── 🖿 includes
254 | │ ├── 🗎 realfire-checkbox.css
255 | │ ├── 🗎 realfire-icons.css
256 | │ ├── 🗎 realfire-config.css
257 | │ └── 🗐 other .css files
258 | ├── 🖿 JS
259 | │ ├── 🗎 aboutUserChrome.sys.mjs
260 | │ ├── 🗎 navbarToolbarButtonSlider.uc.js
261 | │ ├── 🗎 macosTheme.us.js
262 | │ └── 🗐 many script in .uc.js format
263 | ├── 🖿 programs
264 | │ ├── 🗎 install-cfg.sh
265 | │ ├── 🗎 install.sh
266 | │ ├── 🗎 install-curl.sh
267 | │ ├── 🗎 install.bat
268 | │ ├── 🗎 install-curl.bat
269 | │ ├── 🗎 local-settings.js
270 | │ ├── 🗎 mozilla.cfg
271 | │ ├── 🗎 uninstall.bat
272 | │ ├── 🗎 uninstall.sh
273 | │ └── 🗎 user.js
274 | ├── 🖿 resources
275 | │ └── 🖿 icons
276 | │ └── 🗐 many icons in .svg format
277 | ├── 🖿 utils
278 | │ ├── 🗎 .editorconfig
279 | │ ├── 🗎 boot.sys.mjs
280 | │ ├── 🗎 chrome.manifest
281 | │ ├── 🗎 fs.sys.mjs
282 | │ └── 🗎 utils.sys.mjs
283 | ├── 🗎 README.md
284 | ├── 🗎 userChrome.css
285 | └── 🗎 userContent.css
286 |
287 | ```
288 |
289 | ## Credits
290 |
291 | - I started with this amazing material theme : [Sweet_Pop!](https://github.com/PROxZIMA/Sweet-Pop) by [PROxZIMA](https://github.com/PROxZIMA)
292 |
293 | - One of the best dark theme for Firefox : [ShadowFox](https://overdodactyl.github.io/ShadowFox) by [overdodactyl](https://github.com/overdodactyl)
294 |
295 | - [Theme inspiration](https://www.reddit.com/r/FirefoxCSS/comments/ci7i69/another_oneline_theme/) by [u/SENDMEJUDES](https://www.reddit.com/user/SENDMEJUDES/)
296 |
297 | - [Installation script](https://github.com/rafaelmardojai/firefox-gnome-theme) details.
298 |
299 | ---
300 |
301 | ## Stargazers over time
302 |
303 | [](https://starchart.cc/Hakanbaban53/RealFire)
304 |
305 | [Back to top](#RealFire_🔥)
306 |
307 | ---
308 |
309 | Hakan İSMAİL ❤
310 |
--------------------------------------------------------------------------------
/assets/adaptive-tab-bar-extension-support.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hakanbaban53/RealFire/61a2d4d6325d13bbc729a40445bda27acd1c2f59/assets/adaptive-tab-bar-extension-support.gif
--------------------------------------------------------------------------------
/assets/adaptive.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hakanbaban53/RealFire/61a2d4d6325d13bbc729a40445bda27acd1c2f59/assets/adaptive.gif
--------------------------------------------------------------------------------
/assets/context.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hakanbaban53/RealFire/61a2d4d6325d13bbc729a40445bda27acd1c2f59/assets/context.png
--------------------------------------------------------------------------------
/assets/hide_scroll_bar.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hakanbaban53/RealFire/61a2d4d6325d13bbc729a40445bda27acd1c2f59/assets/hide_scroll_bar.gif
--------------------------------------------------------------------------------
/assets/library.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hakanbaban53/RealFire/61a2d4d6325d13bbc729a40445bda27acd1c2f59/assets/library.png
--------------------------------------------------------------------------------
/assets/mac_os_theme.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hakanbaban53/RealFire/61a2d4d6325d13bbc729a40445bda27acd1c2f59/assets/mac_os_theme.gif
--------------------------------------------------------------------------------
/assets/navbar.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hakanbaban53/RealFire/61a2d4d6325d13bbc729a40445bda27acd1c2f59/assets/navbar.gif
--------------------------------------------------------------------------------
/assets/preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hakanbaban53/RealFire/61a2d4d6325d13bbc729a40445bda27acd1c2f59/assets/preview.png
--------------------------------------------------------------------------------
/img/new_tab_wallpaper.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hakanbaban53/RealFire/61a2d4d6325d13bbc729a40445bda27acd1c2f59/img/new_tab_wallpaper.jpg
--------------------------------------------------------------------------------
/includes/realfire-addons-page.css:
--------------------------------------------------------------------------------
1 | @-moz-document url(about:addons) {
2 |
3 | /* Navigation menu */
4 | #sidebar {
5 | align-items: center !important;
6 | background-color: var(--uc-base-colour) !important;
7 | border-right: 2px solid var(--settings-color) !important;
8 | -moz-appearance: none !important;
9 | }
10 |
11 | .sticky-container {
12 | border-bottom: 2px solid var(--accent-color) !important;
13 | -moz-appearance: none !important;
14 | }
15 |
16 | .main-heading {
17 | padding: 16px !important;
18 | background-color: var(--uc-base-colour) !important;
19 | border-top: 2px solid var(--accent-color) !important;
20 | border-inline: 2px solid var(--accent-color) !important;
21 | border-radius: var(--uc-border-radius) var(--uc-border-radius) 0 0 !important;
22 | }
23 |
24 | #content {
25 | background: var(--uc-base-colour) !important;
26 | }
27 |
28 | #categories {
29 | width: auto !important;
30 | }
31 |
32 | #categories richlistitem {
33 | color: var(--uc-inverted-colour) !important;
34 | border-radius: var(--uc-border-radius) !important;
35 | margin-inline: 20px !important;
36 | justify-content: center !important;
37 | }
38 |
39 | /* Sidebar footer */
40 | .sidebar-footer-list {
41 | margin-inline: 0 !important;
42 | margin-inline-start: 0 !important;
43 | }
44 |
45 | /* Selected category color */
46 | @media not (prefers-contrast) {
47 | #categories > .category[selected],
48 | #categories > .category.selected {
49 | color: var(--settings-color) !important;
50 | }
51 | }
52 |
53 | /* Selected privacy option background */
54 | .privacy-detailedoption.selected {
55 | border-color: var(--settings-color) !important;
56 | background-color: color-mix(var(--settings-color) 20%, transparent) !important;
57 | }
58 |
59 | /* Links */
60 | a,
61 | .text-link {
62 | color: var(--settings-color) !important;
63 | }
64 |
65 | a:hover,
66 | .text-link:hover,
67 | .text-link:is(:not([disabled="true"]), :enabled):hover {
68 | color: color-mix(var(--uc-inverted-colour), var(--settings-color)) !important;
69 | }
70 |
71 | /* Addon card hover effect */
72 | addon-card:not([expanded]) > .addon.card:hover {
73 | box-shadow: 0 0 0 5px var(--accent-field-color) !important;
74 | }
75 |
76 | /* Focus styles */
77 | tree:focus-visible,
78 | textarea:focus-visible,
79 | search-textbox[focused],
80 | richlistbox:focus-visible,
81 | input:is([type="email"], [type="tel"], [type="text"], [type="password"], [type="url"], [type="number"]):focus,
82 | #searchInput[focused="true"] {
83 | outline: 2px solid var(--settings-color) !important;
84 | }
85 |
86 | /* Search input */
87 | #searchInput {
88 | border-radius: var(--uc-border-radius) !important;
89 | }
90 |
91 | /* Buttons */
92 | button,
93 | #row-selector.selector {
94 | color: var(--uc-inverted-colour) !important;
95 | border-radius: var(--uc-border-radius) !important;
96 | }
97 |
98 | button.primary,
99 | button[default],
100 | button[autofocus],
101 | button[type="submit"],
102 | button:not([disabled])[default="true"] {
103 | background-color: var(--accent-color) !important;
104 | border-color: var(--accent-color) !important;
105 | color: var(--button-text-white) !important;
106 | }
107 |
108 | /* Focus styles for controls */
109 | button:focus-visible,
110 | select:focus-visible,
111 | menulist:focus-visible,
112 | radio[focused="true"] > .radio-check,
113 | tab:focus-visible > .tab-middle > .tab-text,
114 | checkbox:not([native]):focus-visible > .checkbox-check,
115 | input:is([type="checkbox"], [type="color"], [type="radio"]):focus-visible {
116 | outline: 2px solid var(--uc-inverted-colour) !important;
117 | outline-offset: 0 !important;
118 | }
119 |
120 | }
121 |
--------------------------------------------------------------------------------
/includes/realfire-button.css:
--------------------------------------------------------------------------------
1 | button,
2 | #row-selector.selector {
3 | color: var(--uc-inverted-colour) !important;
4 | border-radius: var(--uc-border-radius) !important;
5 | }
6 |
7 | button:focus-visible,
8 | select:focus-visible,
9 | menulist:focus-visible,
10 | radio[focused="true"]>.radio-check,
11 | tab:focus-visible>.tab-middle>.tab-text,
12 | checkbox:not([native]):focus-visible>.checkbox-check,
13 | input:is([type="checkbox"], [type="color"], [type="radio"]):focus-visible {
14 | outline-offset: 0px !important;
15 | outline: var(--uc-inverted-colour) solid 2px !important;
16 | }
17 |
18 | button:not([disabled])[default],
19 | button[data-l10n-id="permission-dialog-btn-open-link"] {
20 | color: var(--button-text-white) !important;
21 | background-color: var(--accent-color) !important;
22 | }
--------------------------------------------------------------------------------
/includes/realfire-checkbox.css:
--------------------------------------------------------------------------------
1 | .checkbox-check[checked],
2 | input[type="checkbox"]:checked {
3 | background-size: 14px !important;
4 | fill: var(--uc-inverted-colour) !important;
5 | background-color: var(--accent-color) !important;
6 | }
7 | .checkbox-check {
8 | border-radius: 4px !important;
9 | }
10 |
11 | .radio-check[selected],
12 | input[type="radio"]:checked {
13 | fill: var(--uc-inverted-colour) !important;
14 | background-color: var(--accent-color) !important;
15 | }
--------------------------------------------------------------------------------
/includes/realfire-colours.css:
--------------------------------------------------------------------------------
1 | /* ---+---+---+---+---+---+---+
2 | | C | O | L | O | U | R | S |
3 | +---+---+---+---+---+---+---+ */
4 |
5 | /* Dark Mode Color Scheme */
6 | @media (prefers-color-scheme: dark) {
7 | :root {
8 | /* Container Tabs Plugin Colors */
9 | --uc-identity-colour-red: #fc5c65;
10 | --uc-identity-colour-pink: #f78fb3;
11 | --uc-identity-colour-blue: #0078d7;
12 | --uc-identity-colour-green: #b8e994;
13 | --uc-identity-colour-purple: #786fa6;
14 | --uc-identity-colour-yellow: #f7d794;
15 | --uc-identity-colour-orange: #f19066;
16 | --uc-identity-colour-turquoise: #55e6c1;
17 |
18 | /* RealFire Main Color Scheme */
19 | --uc-base-colour: #000000;
20 | --uc-muted-colour: #c3c3c3;
21 | --uc-inverted-colour: #fafafc;
22 | --uc-highlight-colour: #191b1c;
23 | --uc-accent-colour: AccentColor;
24 | }
25 | }
26 |
27 | /* Light Mode Color Scheme */
28 | @media (prefers-color-scheme: light) {
29 | :root {
30 | /* Container Tabs Plugin Colors */
31 | --uc-identity-colour-red: #fc5c65;
32 | --uc-identity-colour-blue: #1d65f5;
33 | --uc-identity-colour-pink: #ec83d0;
34 | --uc-identity-colour-green: #40a02b;
35 | --uc-identity-colour-purple: #822fee;
36 | --uc-identity-colour-yellow: #e49320;
37 | --uc-identity-colour-orange: #fe640b;
38 | --uc-identity-colour-turquoise: #209fb5;
39 |
40 | /* RealFire Main Color Scheme */
41 | --uc-base-colour: #fafafc;
42 | --uc-muted-colour: #292929;
43 | --uc-inverted-colour: #1e2021;
44 | --uc-highlight-colour: #dadadc;
45 | --uc-accent-colour: AccentColor;
46 | }
47 | }
48 |
49 | /* Variables for UI Density */
50 | :root[uidensity="compact"] {
51 | --sidebar-menupopup-height: 29px;
52 | }
53 |
54 | :root[uidensity="touch"] {
55 | --sidebar-menupopup-height: 41px;
56 | }
57 |
58 | /* General UI Variables */
59 | :root {
60 | --tab-radius: 8px;
61 | --navbar-percent: 32vw;
62 | --tab-border-width: 2px;
63 | --toolbar-percent: 68vw;
64 | --sidebar-menupopup-height: 36px;
65 | --subview-height: var(--tab-min-height);
66 | --bookmark-block-padding: 1px;
67 | --menupopup-height: var(--tab-min-height);
68 | --navbar-margin-top: calc(0px - var(--tab-min-height));
69 | --toolbarbutton-inner-padding: 6px;
70 | --toolbarbutton-outer-padding: 3px;
71 | --urlbar-icon-padding: 3px;
72 | --urlbar-min-height: calc(var(--tab-min-height) - 3px);
73 |
74 | /* Colors */
75 | --accent-color: var(--uc-accent-colour);
76 | --settings-color: var(--uc-accent-colour);
77 | --button-text-white: #ffffff;
78 | --accent-field-color: color-mix(in srgb, field 70%, var(--accent-color));
79 | --accent-hover-color: color-mix(in srgb, var(--accent-color) 90%, var(--uc-inverted-colour) 20%);
80 |
81 | /* Light-weight Themes (LWT) */
82 | --lwt-frame: var(--uc-base-colour);
83 | --lwt-text-color: var(--uc-inverted-colour);
84 | --toolbar-field-color: var(--uc-inverted-colour);
85 | --toolbar-field-focus-border-color: transparent;
86 | --toolbar-field-focus-color: var(--uc-inverted-colour);
87 | --urlbar-popup-url-color: var(--uc-accent-colour);
88 | --lwt-toolbar-field-highlight: var(--uc-inverted-colour);
89 | --lwt-tab-text: var(--lwt-text-colour);
90 | --toolbar-color: var(--lwt-text-color);
91 | --toolbarseparator-color: var(--uc-accent-colour);
92 | --toolbarbutton-active-background: var(--toolbarbutton-hover-background);
93 | --sidebar-background-color: var(--lwt-sidebar-background-color);
94 | --urlbar-box-text-color: var(--uc-muted-colour);
95 | --urlbar-box-hover-text-color: var(--uc-inverted-colour);
96 | }
97 |
--------------------------------------------------------------------------------
/includes/realfire-config.css:
--------------------------------------------------------------------------------
1 | /*---+---+---+---+---+---+---+
2 | | G | L | O | B | A | L |
3 | +---+---+---+---+---+---+---*/
4 |
5 | :root {
6 | /* Global Border Radius */
7 | --uc-border-radius: 8px;
8 |
9 | /* Distance the Statuspanel floats away from the window border */
10 | --uc-status-panel-spacing: 12px;
11 |
12 | /* Animation Duration */
13 | --uc-animation-duration: 0.3s;
14 | }
15 |
16 | /* Remove window control buttons */
17 | /* .titlebar-buttonbox-container { display: none !important; } */
18 |
19 | #pageActionButton {
20 | display: none !important;
21 | }
22 |
23 | #PanelUI-menu-button {
24 | padding: 8px !important;
25 | }
26 |
27 | #PanelUI-menu-button .toolbarbutton-badge-stack {
28 | padding: 8px !important;
29 | }
30 |
31 | /*---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
32 | | B | O | O | K | M | A | R | S | | T | O | O | L | B | A | R |
33 | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---*/
34 |
35 | :root {
36 | /* Position of the Personal Toolbar (0 - top, 4 - bottom) */
37 | --uc-toolbar-position: 4;
38 |
39 | /* Darken the Personal Toolbar (0-1) */
40 | --uc-darken-toolbar: 0.2;
41 | /* Darken by 20% in dark mode */
42 | }
43 |
44 | @media (prefers-color-scheme: light) {
45 | :root {
46 | --uc-darken-toolbar: 0;
47 | /* No darkening in light mode */
48 | }
49 | }
50 |
51 | /*---+---+---+---+---+---+---+
52 | | U | R | L | B | A | R |
53 | +---+---+---+---+---+---+---*/
54 |
55 | :root {
56 | /* Width of the URL Bar (min-width and max-width) */
57 | /* If you want to use vertical tabs, you can set the max-width to 100vh */
58 | --uc-urlbar-min-width: 20vw;
59 | --uc-urlbar-max-width: 40vw;
60 |
61 | /* Position of the URL Bar (1 - tabs on right, 3 - tabs on left) */
62 | --uc-urlbar-position: 1;
63 |
64 | /* Firefox can be wonky with vertical URL Bar placement */
65 | --uc-urlbar-top-spacing: 0px;
66 | }
67 |
68 | /* Disable Navigation Buttons */
69 | /* #back-button, #forward-button { display: none !important; } */
70 |
71 | /* Disable Tracking Protection Shield */
72 | #tracking-protection-icon-container {
73 | display: none !important;
74 | }
75 |
76 | /* Hide Encryption and Permissions icons */
77 | /* #identity-permission-box { display: none !important; } */
78 | /* #identity-box { display: none !important; } */
79 |
80 | /* Hide everything BUT the zoom indicator within the URL Bar */
81 | /* #page-action-buttons > :not(#urlbar-zoom-button) { display: none !important; } */
82 |
83 | /* Hide the Go-arrow in the URL Bar */
84 | #urlbar-go-button {
85 | display: none !important;
86 | }
87 |
88 | /* Hide the Extensions Menu Icon */
89 | /* #unified-extensions-button { display: none !important; } */
90 |
91 | /*---+---+---+---+---+---+---+
92 | | T | A | B | B | A | R |
93 | +---+---+---+---+---+---+---*/
94 |
95 | :root {
96 | /* Active and Inactive Tab Widths */
97 | --uc-active-tab-width: clamp(100px, 30vw, 300px);
98 | --uc-inactive-tab-width: clamp(100px, 20vw, 200px);
99 |
100 | /* Show Tab Close Button (none - hide, -moz-inline-block - show) */
101 | --show-tab-close-button: -moz-inline-block;
102 |
103 | /* Show Tab Close Button on Tab Hover (none - hide, -moz-inline-block - show) */
104 | --show-tab-close-button-hover: -moz-inline-block;
105 |
106 | /*Set the tab position 0px is stuck the bottom */
107 | --uc-tab-block-margin: 6px;
108 |
109 | /* Hide the all Tabs button from the Tab Bar (show: -moz-box, hide: none) */
110 | --uc-show-all-tabs-button: -moz-box;
111 |
112 | /* Margin of the Container Tabs Indicator */
113 | --container-tabs-indicator-margin: 10px;
114 |
115 | /* Glow added to the container indicator */
116 | --uc-identity-glow: 0 1px 10px 1px;
117 | /* No glow by default */
118 | }
119 |
120 | /* Hide the secondary Tab Label (e.g., playing indicator) */
121 | .tab-secondary-label {
122 | display: none !important;
123 | }
--------------------------------------------------------------------------------
/includes/realfire-findbar.css:
--------------------------------------------------------------------------------
1 | findbar {
2 | border: none !important;
3 | padding: 6px !important;
4 | background: var(--uc-base-colour) !important;
5 | }
6 |
7 | .findbar-button:hover {
8 | background: var(--uc-highlight-colour) !important;
9 | }
10 |
11 | .textbox-search-sign,
12 | .textbox-search-icon,
13 | .findbar-textbox {
14 | fill: var(--uc-inverted-colour);
15 | padding-inline-start: 28px !important;
16 | background-repeat: no-repeat !important;
17 | background-color: transparent !important;
18 | background-position: 5px center !important;
19 | -moz-context-properties: fill, fill-opacity;
20 | }
21 |
22 |
23 |
24 | .findbar-find-status:not([status="notfound"]) {
25 | display: none !important;
26 | }
27 |
28 | hbox[anonid="findbar-textbox-wrapper"] {
29 | height: 28px !important;
30 | border-radius: var(--uc-border-radius) !important;
31 | background-color: var(--uc-base-colour) !important;
32 | border: 2px solid rgba(217, 217, 217, 0.5) !important;
33 | transition: background-color var(--uc-animation-duration) cubic-bezier(0, -0.74, 0.25, 1) !important;
34 | }
35 |
36 | hbox[anonid="findbar-textbox-wrapper"]:hover {
37 | background-color: var(--uc-highlight-colour) !important;
38 | }
39 |
40 | hbox[anonid="findbar-textbox-wrapper"]:focus-within {
41 | border: 2px solid var(--accent-color) !important;
42 | }
43 |
44 | hbox[anonid="findbar-textbox-wrapper"] toolbarbutton {
45 | border: 0 !important;
46 | margin: 0 !important;
47 | padding: 0 !important;
48 | width: 24px !important;
49 | opacity: 0.5 !important;
50 | height: 24px !important;
51 | display: flex !important;
52 | background: 0 !important;
53 | box-shadow: none !important;
54 | border-radius: 99px !important;
55 | transition: background-color var(--uc-animation-duration) ease !important;
56 | }
57 |
58 | hbox[anonid="findbar-textbox-wrapper"] toolbarbutton[disabled] {
59 | display: none !important;
60 | }
61 |
62 | hbox[anonid="findbar-textbox-wrapper"] toolbarbutton .toolbarbutton-text {
63 | visibility: collapse !important;
64 | }
65 |
66 | hbox[anonid="findbar-textbox-wrapper"] toolbarbutton:not([disabled]):hover {
67 | opacity: 1 !important;
68 | background-color: transparent !important;
69 | }
70 |
71 | hbox[anonid="findbar-textbox-wrapper"]
72 | toolbarbutton:not([disabled]):hover:active {
73 | opacity: 1 !important;
74 | transition-duration: var(--uc-animation-duration) !important;
75 | background-color: transparent !important;
76 | }
77 |
78 |
79 |
--------------------------------------------------------------------------------
/includes/realfire-icons.css:
--------------------------------------------------------------------------------
1 | /* menupopup:not(.in-menulist) > menu:not(.menu-iconic),
2 | menupopup:not(.in-menulist, [aria-label])
3 | > menuitem:not(.menuitem-iconic, [type="checkbox"], [type="radio"]) {
4 | padding-inline-start: calc(2em + 16 px) !important;
5 | } */
6 |
7 | .subviewbutton .toolbarbutton-icon {
8 | display: -moz-inline-box !important;
9 | }
10 |
11 | input[type="radio"]:checked,
12 | .radio-check[selected],
13 | menuitem[type="radio"][checked="true"] {
14 | background-image: url("chrome://userchrome/content/material/radio-checked.svg");
15 | }
16 |
17 | input[type="radio"]:not([checked]),
18 | .radio-check,
19 | menuitem[type="radio"]:not([checked="true"]) {
20 | background-image: url("chrome://userchrome/content/material/radio-unchecked.svg") !important;
21 | }
22 |
23 | menuitem[type="checkbox"][checked="true"] {
24 | background-image: url("chrome://userchrome/content/material/checked.svg") !important;
25 | }
26 |
27 | menuitem[type="checkbox"]:not([checked="true"]) {
28 | background-image: url("chrome://userchrome/content/material/unchecked.svg") !important;
29 | }
30 |
31 | .bookmark-item {
32 | list-style-image: url("chrome://userchrome/content/material/bookmark-manage.svg") !important;
33 | }
34 |
35 | #appMenu-translate-button {
36 | list-style-image: url("chrome://userchrome/content/material/translate.svg");
37 | }
38 |
39 | menuitem[data-l10n-id$="-sync-now"],
40 | #PanelUI-fxa-menu-setup-sync-button {
41 | background-image: url("chrome://browser/skin/sync.svg");
42 | list-style-image: url("chrome://browser/skin/sync.svg");
43 | }
44 |
45 | menu.sync-ui-item,
46 | #PanelUI-fxa-menu-sendtab-button {
47 | background-image: url("chrome://userchrome/content/material/send-tab.svg");
48 | list-style-image: url("chrome://userchrome/content/material/send-tab.svg");
49 | }
50 |
51 | #menu_browserContentToolbox,
52 | .subviewbutton[label="Browser Content Toolbox"],
53 | .subviewbutton[data-l10n-id$="appmenuitem-more-tools"] {
54 | background-image: url("chrome://userchrome/content/material/toolbox.svg");
55 | list-style-image: url("chrome://userchrome/content/material/toolbox.svg");
56 | }
57 |
58 | #menu_preferences,
59 | #openSettingsMenuItem,
60 | .subviewbutton[data-l10n-id$="-settings"] {
61 | background-image: url("chrome://global/skin/icons/settings.svg");
62 | list-style-image: url("chrome://global/skin/icons/settings.svg");
63 | }
64 |
65 | #menu_preferences,
66 | #openSettingsMenuItem,
67 | .subviewbutton[id="appMenu-advanced-settings-button"]{
68 | list-style-image: url("chrome://userchrome/content/material/experiments.svg");
69 | }
70 |
71 |
72 | #PanelUI-fxa-menu-account-signout-button {
73 | background-image: url("chrome://userchrome/content/material/signout.svg");
74 | list-style-image: url("chrome://userchrome/content/material/signout.svg");
75 | }
76 |
77 | #menu_newNavigatorTab,
78 | menuitem[id$="openANewTab"],
79 | #appMenu-new-tab-button2 {
80 | background-image: url("chrome://browser/skin/new-tab.svg");
81 | list-style-image: url("chrome://browser/skin/new-tab.svg");
82 | }
83 |
84 | #menu_newNavigator,
85 | #historyUndoWindowMenu,
86 | menuitem[data-l10n-id*="-open-"][data-l10n-id$="-window"],
87 | #context_openTabInWindow,
88 | #appMenu-new-window-button2,
89 | #appMenuRecentlyClosedWindows {
90 | background-image: url("chrome://browser/skin/window.svg");
91 | list-style-image: url("chrome://browser/skin/window.svg");
92 | }
93 |
94 | menuitem[data-l10n-id$="-private-window"],
95 | #appMenu-new-private-window-button2 {
96 | background-image: url("chrome://browser/skin/privateBrowsing.svg");
97 | list-style-image: url("chrome://browser/skin/privateBrowsing.svg");
98 | }
99 |
100 | .subviewbutton[data-l10n-id="library-bookmarks-menu"],
101 | #panelMenuBookmarkThisPage[starred],
102 | #sidebar-switcher-bookmarks {
103 | background-image: url("chrome://browser/skin/bookmark.svg");
104 | list-style-image: url("chrome://browser/skin/bookmark.svg");
105 | }
106 |
107 | menuitem[data-l10n-id*="bookmark-"]:not(.menuitem-iconic),
108 | #context-bookmarkframe,
109 | #placesContext_createBookmark ,
110 | #panelMenuBookmarkThisPage {
111 | background-image: url("chrome://browser/skin/bookmark-hollow.svg");
112 | list-style-image: url("chrome://browser/skin/bookmark-hollow.svg");
113 | }
114 |
115 | #appMenuSearchHistory,
116 | #menu_find,
117 | .findbar-textbox,
118 | #context-searchselect,
119 | #panelMenu_searchBookmarks,
120 | #appMenu-find-button2,
121 | #allTabsMenu-searchTabs {
122 | background-image: url("chrome://global/skin/icons/search-glass.svg");
123 | list-style-image: url("chrome://global/skin/icons/search-glass.svg");
124 | }
125 |
126 | #spell-dictionaries,
127 | #toggle_PersonalToolbar,
128 | #BMB_viewBookmarksToolbar,
129 | #panelMenu_viewBookmarksToolbar {
130 | background-image: url("chrome://browser/skin/bookmarks-toolbar.svg");
131 | list-style-image: url("chrome://browser/skin/bookmarks-toolbar.svg");
132 | }
133 |
134 | #menu_historySidebar:not([checked="true"]),
135 | .subviewbutton[id$="-history-button"],
136 | #sidebar-switcher-history {
137 | background-image: url("chrome://browser/skin/history.svg");
138 | list-style-image: url("chrome://browser/skin/history.svg");
139 | }
140 |
141 | #historyUndoMenu,
142 | #appMenuRecentlyClosedTabs {
143 | background-image: url("chrome://devtools/skin/images/debugging-tabs.svg");
144 | list-style-image: url("chrome://devtools/skin/images/debugging-tabs.svg");
145 | }
146 |
147 | #historyRestoreLastSession,
148 | #appMenuRestoreSession {
149 | background-image: url("chrome://userchrome/content/material/restore-session.svg");
150 | list-style-image: url("chrome://userchrome/content/material/restore-session.svg");
151 | }
152 |
153 | #sanitizeItem,
154 | #placesContext_deleteHost,
155 | #appMenuClearRecentHistory {
156 | background-image: url("chrome://browser/skin/forget.svg");
157 | list-style-image: url("chrome://browser/skin/forget.svg");
158 | }
159 |
160 | #menu_openDownloads,
161 | .subviewbutton[id$="-downloads-button"] {
162 | background-image: url("chrome://browser/skin/downloads/downloads.svg");
163 | list-style-image: url("chrome://browser/skin/downloads/downloads.svg");
164 | }
165 |
166 | #appMenu-passwords-button {
167 | background-image: url("chrome://browser/skin/login.svg");
168 | list-style-image: url("chrome://browser/skin/login.svg");
169 | }
170 |
171 | #menu_openAddons,
172 | #appMenu-extensions-themes-button {
173 | background-image: url("chrome://mozapps/skin/extensions/extension.svg");
174 | list-style-image: url("chrome://mozapps/skin/extensions/extension.svg");
175 | }
176 |
177 | menuitem[data-l10n-id*="-print"],
178 | #appMenu-print-button2 {
179 | background-image: url("chrome://global/skin/icons/print.svg");
180 | list-style-image: url("chrome://global/skin/icons/print.svg");
181 | }
182 |
183 | #context-saveimage,
184 | #context-savelink,
185 | #menu_savePage,
186 | #context-savepage,
187 | #appMenu-save-file-button2 {
188 | background-image: url("chrome://browser/skin/save.svg");
189 | list-style-image: url("chrome://browser/skin/save.svg");
190 | }
191 |
192 | menuitem[data-l10n-id*="-customize-toolbar"],
193 | .subviewbutton[command="cmd_CustomizeToolbars"] {
194 | background-image: url("chrome://browser/skin/customize.svg");
195 | list-style-image: url("chrome://browser/skin/customize.svg");
196 | }
197 |
198 | #menu_taskManager,
199 | .subviewbutton[label="Task Manager"],
200 | .subviewbutton[oncommand="switchToTabHavingURI('about:performance', true)"] {
201 | background-image: url("chrome://global/skin/icons/performance.svg");
202 | list-style-image: url("chrome://global/skin/icons/performance.svg");
203 | }
204 |
205 | #menu_browserToolbox,
206 | .subviewbutton[key="key_browserToolbox"] {
207 | background-image: url("chrome://devtools/skin/images/fox-smiling.svg");
208 | list-style-image: url("chrome://devtools/skin/images/fox-smiling.svg");
209 | }
210 |
211 | #menu_responsiveUI:not([checked="true"]),
212 | .subviewbutton[key="key_responsiveDesignMode"]:not([checked="true"]) {
213 | background-image: url("chrome://devtools/skin/images/command-responsivemode.svg");
214 | list-style-image: url("chrome://devtools/skin/images/command-responsivemode.svg");
215 | fill-opacity: 0;
216 | }
217 |
218 | .subviewbutton[key="key_responsiveDesignMode"]:not([checked="true"])
219 | > .menu-iconic-left::before {
220 | opacity: 0 !important;
221 | }
222 |
223 | #menu_eyedropper:not([checked="true"]),
224 | .subviewbutton[key="key_responsiveDesignMode"] + .subviewbutton {
225 | background-image: url("chrome://devtools/skin/images/command-eyedropper.svg");
226 | list-style-image: url("chrome://devtools/skin/images/command-eyedropper.svg");
227 | fill-opacity: 0;
228 | }
229 |
230 | #extensionsForDevelopers,
231 | .subviewbutton[data-l10n-id="appmenu-developer-tools-extensions"] {
232 | background-image: url("chrome://activity-stream/content/data/content/assets/glyph-webextension-16.svg");
233 | list-style-image: url("chrome://activity-stream/content/data/content/assets/glyph-webextension-16.svg");
234 | }
235 |
236 | #appMenu-help-button2 {
237 | background-image: url("chrome://global/skin/icons/help.svg");
238 | list-style-image: url("chrome://global/skin/icons/help.svg");
239 | }
240 |
241 | #appMenu-restart-button2 {
242 | background-image: url("chrome://userchrome/content/material/reload.svg");
243 | list-style-image: url("chrome://userchrome/content/material/reload.svg");
244 | }
245 |
246 | #appMenu-userChrome-button {
247 | background-image: url("chrome://browser/skin/trending.svg");
248 | list-style-image: url("chrome://browser/skin/trending.svg");
249 | }
250 |
251 | #menu_HelpPopup_reportPhishingtoolmenu,
252 | #appMenu_menu_HelpPopup_reportPhishingtoolmenu {
253 | background-image: url("chrome://global/skin/icons/lightbulb.svg");
254 | list-style-image: url("chrome://global/skin/icons/lightbulb.svg");
255 | }
256 |
257 | #aboutName,
258 | #appMenu_aboutName {
259 | background-image: url("chrome://devtools/skin/images/browsers/firefox.svg");
260 | list-style-image: url("chrome://devtools/skin/images/browsers/firefox.svg");
261 | }
262 |
263 | #menu_FileQuitItem,
264 | #appMenu-quit-button2 {
265 | background-image: url("chrome://userchrome/content/material/quit.svg");
266 | list-style-image: url("chrome://userchrome/content/material/quit.svg");
267 | }
268 |
269 | #menu_newUserContext,
270 | #allTabsMenu-containerTabsButton {
271 | background-image: url("chrome://userchrome/content/material/new-container.svg");
272 | list-style-image: url("chrome://userchrome/content/material/new-container.svg");
273 | }
274 |
275 | #PanelUI-fxa-menu-connect-device-button,
276 | #sidebar-switcher-tabs {
277 | background-image: url("chrome://browser/skin/synced-tabs.svg");
278 | list-style-image: url("chrome://browser/skin/synced-tabs.svg");
279 | }
280 |
281 | #sidebar-reverse-position[label="Move Sidebar to Right"],
282 | #sidebar-reverse-position[label="Kenar çubuğunu sağa taşı"] {
283 | background-image: url("chrome://browser/skin/sidebars-right.svg");
284 | list-style-image: url("chrome://browser/skin/sidebars-right.svg");
285 | }
286 |
287 | #viewSidebarMenuMenu,
288 | #BMB_viewBookmarksSidebar,
289 | #sidebar-reverse-position[label="Move Sidebar to Left"],
290 | #sidebar-reverse-position[label="Kenar çubuğunu sola taşı"] {
291 | background-image: url("chrome://browser/skin/sidebars.svg");
292 | list-style-image: url("chrome://browser/skin/sidebars.svg");
293 | }
294 |
295 | #toolbar-context-selectAllTabs[data-l10n-id="toolbar-context-menu-select-all-tabs"] {
296 | background-image: url("chrome://userchrome/content/material/select-all.svg");
297 | }
298 |
299 |
300 | #context_closeTab,
301 | #orgClose,
302 | menuitem[data-l10n-id="sidebar-menu-close"] {
303 | background-image: url("chrome://global/skin/icons/close.svg");
304 | list-style-image: url("chrome://global/skin/icons/close.svg");
305 | }
306 |
307 | #BMB_bookmarksPopup menuitem:not(.menuitem-iconic),
308 | #PlacesToolbar .openintabs-menuitem {
309 | list-style-image: url("chrome://userchrome/content/material/open_new_tabs.svg");
310 | background-image: url("chrome://userchrome/content/material/open_new_tabs.svg");
311 | }
312 |
313 | #menu_openFile {
314 | background-image: url("chrome://browser/skin/open.svg");
315 | }
316 |
317 | menuitem[data-l10n-id*="-email"] {
318 | background-image: url("chrome://browser/skin/mail.svg");
319 | }
320 |
321 | #menu_importFromAnotherBrowser,
322 | #browserImport {
323 | background-image: url("chrome://browser/skin/import.svg");
324 | }
325 |
326 | menuitem[data-l10n-id="text-action-undo"],
327 | menuitem[data-l10n-id$="-reopen-closed-tabs"] {
328 | background-image: url("chrome://global/skin/icons/undo.svg");
329 | }
330 |
331 | menuitem[data-l10n-id="text-action-redo"] {
332 | background-image: url("chrome://userchrome/content/material/redo.svg");
333 | }
334 |
335 | menuitem[data-l10n-id="text-action-cut"] {
336 | background-image: url("chrome://browser/skin/edit-cut.svg");
337 | }
338 |
339 | menuitem[data-l10n-id="text-action-copy"],
340 | #syncedTabsCopySelected {
341 | background-image: url("chrome://global/skin/icons/edit-copy.svg");
342 | }
343 |
344 | menuitem[data-l10n-id="text-action-paste"] {
345 | background-image: url("chrome://browser/skin/edit-paste.svg");
346 | }
347 |
348 | menuitem[data-l10n-id="text-action-delete"],
349 | menuitem[data-l10n-id="downloads-cmd-clear-list"],
350 | menuitem[data-l10n-id="downloads-cmd-delete-file"],
351 | .customize-context-removeExtension,
352 | menuitem[data-l10n-id="toolbar-context-menu-remove-from-toolbar"],
353 | .downloadRemoveFromHistoryMenuItem,
354 | menuitem[id^="placesContext_delete"] {
355 | background-image: url("chrome://global/skin/icons/delete.svg");
356 | }
357 |
358 | #menu_bookmarksSidebar:not([checked="true"]),
359 | menuitem[data-l10n-id="menu-bookmark-edit"] {
360 | background-image: url("chrome://browser/skin/bookmark.svg") !important;
361 | }
362 |
363 | #menu_bookmarksSidebar:not([checked="true"]) > .menu-iconic-left::before {
364 | opacity: 0 !important;
365 | }
366 |
367 | #menu_historySidebar:not([checked="true"]) > .menu-iconic-left::before {
368 | opacity: 0 !important;
369 | }
370 |
371 | #menu_tabsSidebar:not([checked="true"]),
372 | #sync-tabs-menuitem {
373 | background-image: url("chrome://browser/skin/tab.svg");
374 | }
375 |
376 | #menu_tabsSidebar:not([checked="true"]) > .menu-iconic-left::before {
377 | opacity: 0 !important;
378 | }
379 |
380 | #menu_zoomEnlarge {
381 | background-image: url("chrome://browser/skin/add-circle-fill.svg");
382 | }
383 |
384 | #menu_zoomReduce {
385 | background-image: url("chrome://browser/skin/subtract-circle-fill.svg");
386 | }
387 |
388 | #repair-text-encoding {
389 | background-image: url("chrome://browser/skin/characterEncoding.svg");
390 | }
391 |
392 | #fullScreenItem:not([checked="true"]) {
393 | background-image: url("chrome://browser/skin/fullscreen.svg");
394 | }
395 |
396 | #fullScreenItem:not([checked="true"]) > .menu-iconic-left::before {
397 | opacity: 0 !important;
398 | }
399 |
400 | #menu_readerModeItem {
401 | background-image: url("chrome://browser/skin/reader-mode.svg");
402 | }
403 |
404 | #sync-setup {
405 | background-image: var(--avatar-image-url);
406 | }
407 |
408 |
409 | #webDeveloperMenu {
410 | background-image: url("chrome://browser/skin/developer.svg");
411 | }
412 |
413 | #menu_responsiveUI:not([checked="true"]) > .menu-iconic-left::before {
414 | opacity: 0 !important;
415 | }
416 |
417 | #menu_eyedropper:not([checked="true"]) > .menu-iconic-left::before {
418 | opacity: 0 !important;
419 | }
420 |
421 |
422 | #menu_pageInfo,
423 | #context-viewframeinfo {
424 | background-image: url("chrome://global/skin/icons/info.svg");
425 | }
426 |
427 |
428 | menuitem[data-l10n-id*="reload-"],
429 | #context-reloadframe {
430 | background-image: url("chrome://global/skin/icons/reload.svg");
431 | }
432 |
433 | menuitem[id^="context_toggleMute"]:not([soundplaying], [muted]),
434 | menuitem[id^="context_toggleMute"][soundplaying]:not([muted]),
435 | #context-media-mute {
436 | background-image: url("chrome://global/skin/media/audio-muted.svg");
437 | }
438 |
439 | menuitem[id^="context_toggleMute"][muted],
440 | #context-media-unmute {
441 | background-image: url("chrome://global/skin/media/audio.svg");
442 | }
443 |
444 | menuitem[data-l10n-id^="pin-"],
445 | .customize-context-moveToPanel {
446 | background-image: url("chrome://activity-stream/content/data/content/assets/glyph-pin-16.svg");
447 | }
448 |
449 | menuitem[data-l10n-id^="unpin-"],
450 | .customize-context-moveToToolbar {
451 | background-image: url("chrome://activity-stream/content/data/content/assets/glyph-unpin-16.svg");
452 | }
453 |
454 | menuitem[id^="context_duplicateTab"] {
455 | background-image: url("chrome://userchrome/content/material/duplicate-tab.svg");
456 | }
457 |
458 | #context_moveTabOptions {
459 | background-image: url("chrome://userchrome/content/material/move-tab.svg");
460 | }
461 |
462 | menuitem.sendtab-target[clientType="desktop"] {
463 | background-image: url("chrome://browser/skin/device-desktop.svg");
464 | }
465 |
466 | menuitem.sendtab-target[clientType="phone"] {
467 | background-image: url("chrome://browser/skin/device-phone.svg");
468 | }
469 |
470 | menuitem.sendtab-target[clientType="tablet"] {
471 | background-image: url("chrome://browser/skin/device-tablet.svg");
472 | }
473 |
474 | menuitem.sendtab-target[clientType="tv"] {
475 | background-image: url("chrome://browser/skin/device-tv.svg");
476 | }
477 |
478 | menuitem.sendtab-target[clientType="vr"] {
479 | background-image: url("chrome://browser/skin/device-vr.svg");
480 | }
481 |
482 | .share-tab-url-item {
483 | background-image: url("chrome://userchrome/content/material/share-tab.svg");
484 | }
485 |
486 | #context-setDesktopBackground {
487 | background-image: url("chrome://userchrome/content/material/desktop-bg.svg");
488 | }
489 |
490 | #context_reopenInContainer,
491 | #context-openlinkinusercontext-menu {
492 | background-image: url("chrome://userchrome/content/material/move-container.svg");
493 | }
494 |
495 | #menu_selectAll,
496 | #context-selectall,
497 | #context_selectAllTabs {
498 | background-image: url("chrome://userchrome/content/material/select-all.svg");
499 | }
500 |
501 | #context-viewsource,
502 | #context-viewpartialsource-selection {
503 | background-image: url("chrome://userchrome/content/material/page-source.svg");
504 | }
505 |
506 | #context_closeTabOptions {
507 | background-image: url("chrome://userchrome/content/material/close-tab-option.svg");
508 | }
509 |
510 | #context_moveToStart {
511 | background-image: url("chrome://userchrome/content/material/move-start.svg");
512 | }
513 |
514 | #context_moveToEnd {
515 | background-image: url("chrome://userchrome/content/material/move-end.svg");
516 | }
517 |
518 | menuitem[data-l10n-id="full-screen-exit"] {
519 | background-image: url("chrome://browser/skin/fullscreen-exit.svg");
520 | }
521 |
522 | #paste-and-go {
523 | background-image: url("chrome://browser/skin/forward.svg");
524 | }
525 |
526 | #appMenu-report-broken-site-button {
527 | list-style-image: url("chrome://global/skin/icons/warning.svg");
528 | }
529 |
530 | .customize-context-reportExtension {
531 | background-image: url("chrome://global/skin/icons/warning.svg");
532 | }
533 |
534 | .downloadResumeMenuItem {
535 | background-image: url("chrome://userchrome/content/material/playButton.svg");
536 | }
537 |
538 | .downloadPauseMenuItem{
539 | background-image: url("chrome://userchrome/content/material/pause.svg");
540 | }
541 |
542 | .downloadShowMenuItem {
543 | background-image: url("chrome://global/skin/icons/folder.svg");
544 | }
545 |
546 | menuitem[id^="context-open"]:is([id$="intab"], [id$="incontainertab"]),
547 | menuitem[data-l10n-id$="-view-new-tab"],
548 | menuitem[data-l10n-id*="-open-in-"][data-l10n-id$="-tab"] {
549 | background-image: url("chrome://global/skin/icons/open-in-new.svg");
550 | }
551 |
552 | menuitem[oncommand^="Pocket.savePage"] {
553 | background-image: url("chrome://global/skin/icons/pocket-outline.svg");
554 | }
555 |
556 | menuitem[data-l10n-id$="-screenshot"] {
557 | background-image: url("chrome://browser/skin/screenshot.svg");
558 | }
559 |
560 | menuitem[data-l10n-id*="-copy-"][data-l10n-id*="-link"] {
561 | background-image: url("chrome://global/skin/icons/link.svg");
562 | }
563 |
564 | #context-searchselect[label^="Search Google for "] {
565 | background-image: url("chrome://activity-stream/content/data/content/tippytop/favicons/google-com.ico");
566 | }
567 |
568 | #context-searchselect[label^="Search Bing for "] {
569 | background-image: url("chrome://activity-stream/content/data/content/tippytop/favicons/bing-com.ico");
570 | }
571 |
572 | #PlacesToolbarItems .openintabs-menuitem
573 | #context-searchselect[label^="Search DuckDuckGo for "] {
574 | background-image: url("chrome://activity-stream/content/data/content/tippytop/favicons/duckduckgo-com.ico");
575 | }
576 |
577 | #context-inspect-a11y {
578 | background-image: url("chrome://devtools/skin/images/tool-accessibility.svg");
579 | }
580 |
581 | #appmenu-developer-tools-view .subviewbutton[key="key_viewSource"] {
582 | list-style-image: url("chrome://userchrome/content/material/web-page-source-code.svg");
583 | }
584 |
585 | #appmenu-developer-tools-view .subviewbutton[key="key_toggleToolbox"],
586 | #context-inspect {
587 | background-image: url("chrome://userchrome/content/material/command-pick.svg");
588 | list-style-image: url("chrome://userchrome/content/material/command-pick.svg");
589 | }
590 |
591 | #context-media-play {
592 | background-image: url("chrome://global/skin/media/play-fill.svg");
593 | }
594 |
595 | #context-media-pause,
596 | #doNotDisturbMenuItem {
597 | background-image: url("chrome://global/skin/media/pause-fill.svg");
598 | }
599 |
600 | #context-video-fullscreen {
601 | background-image: url("chrome://global/skin/media/fullscreenEnterButton.svg");
602 | }
603 |
604 | #context-leave-dom-fullscreen {
605 | background-image: url("chrome://global/skin/media/fullscreenExitButton.svg");
606 | }
607 |
608 | #context-video-pictureinpicture:not([checked="true"]) {
609 | background-image: url("chrome://global/skin/media/picture-in-picture-open.svg");
610 | }
611 |
612 | #context-video-pictureinpicture:not([checked="true"])
613 | > .menu-iconic-left::before {
614 | opacity: 0 !important;
615 | }
616 |
617 | #context-video-saveimage {
618 | background-image: url("chrome://devtools/skin/images/command-screenshot.svg");
619 | }
620 |
621 | #disableForOriginMenuItem {
622 | background-image: url("chrome://browser/skin/notification-icons/desktop-notification-blocked.svg");
623 | }
624 |
625 | menuitem[data-l10n-id^="places-edit-"] {
626 | background-image: url("chrome://global/skin/icons/edit.svg");
627 | }
628 |
629 | #appmenu-developer-tools-view .subviewbutton[key="key_aboutProcesses"] {
630 | list-style-image: url("chrome://global/skin/icons/performance.svg");
631 | background-image: url("chrome://global/skin/icons/performance.svg");
632 | }
633 |
634 | #context-copyimage-contents {
635 | background-image: url("chrome://devtools/skin/images/copy.svg");
636 | }
637 |
638 | #menu_openHelp,
639 | #appMenu_menu_openHelp {
640 | background-image: url("chrome://devtools/content/debugger/images/help.svg");
641 | list-style-image: url("chrome://devtools/content/debugger/images/help.svg");
642 | }
643 |
644 | #feedbackPage,
645 | #appMenu_feedbackPage {
646 | background-image: url("chrome://userchrome/content/material/ideas.svg");
647 | list-style-image: url("chrome://userchrome/content/material/ideas.svg");
648 | }
649 |
650 | #userScriptsMenu {
651 | background-image: url("chrome://userchrome/content/material/userScriptsMenu.svg");
652 | }
653 |
654 | #menu_devtools_remotedebugging,
655 | .subviewbutton[label="Remote Debugging"] {
656 | background-image: url("chrome://userchrome/content/material/remote-debug.svg");
657 | list-style-image: url("chrome://userchrome/content/material/remote-debug.svg");
658 | }
659 |
660 | #menu_browserConsole,
661 | .subviewbutton[key="key_browserConsole"] {
662 | background-image: url("chrome://userchrome/content/material/terminal.svg");
663 | list-style-image: url("chrome://userchrome/content/material/terminal.svg");
664 | }
665 |
666 | #placesContext_showAllBookmarks,
667 | #bookmarksShowAll,
668 | #panelMenu_showAllBookmarks {
669 | background-image: url("chrome://userchrome/content/material/bookmark-manage.svg");
670 | }
671 |
672 | #appMenu-restoreSession{
673 | list-style-image: url("chrome://userchrome/content/material/restore-session.svg");
674 | }
675 |
676 | #menu_showAllHistory {
677 | background-image: url("chrome://userchrome/content/material/all-history.svg");
678 | }
679 |
680 | #menu_zoomEnlarge {
681 | background-image: url("chrome://userchrome/content/material/zoom-in.svg");
682 | }
683 |
684 | #menu_zoomReduce {
685 | background-image: url("chrome://userchrome/content/material/zoom-out.svg");
686 | }
687 |
688 | #menu_zoomReset {
689 | background-image: url("chrome://userchrome/content/material/actual-zoom.svg");
690 | }
691 |
--------------------------------------------------------------------------------
/includes/realfire-inputs.css:
--------------------------------------------------------------------------------
1 | /*settings Inputs*/
2 | tree:hover,
3 | richlistbox:hover,
4 | #searchInput:hover,
5 | search-textbox:hover,
6 | input:is([type="email"], [type="tel"], [type="text"], [type="password"], [type="url"], [type="number"]):hover {
7 | outline: var(--settings-color) solid 1px !important;
8 | }
9 |
10 | tree:focus-visible,
11 | search-textbox[focused],
12 | richlistbox:focus-visible,
13 | #searchInput[focused="true"],
14 | input:is([type="email"], [type="tel"], [type="text"], [type="password"], [type="url"], [type="number"]):focus {
15 | transition: linear var(--uc-animation-duration) !important;
16 | outline: var(--settings-color) solid 2px !important;
17 | }
18 |
19 | #searchInput {
20 | transition: linear var(--uc-animation-duration) !important;
21 | border-radius: var(--uc-border-radius) !important;
22 | }
23 |
24 | /*popups*/
25 | search-textbox.tabsFilter:hover,
26 | search-textbox#search-box:hover,
27 | search-textbox#search-box:focus-within,
28 | search-textbox.tabsFilter:focus-within {
29 | transition: ease-in var(--uc-animation-duration);
30 | border: 1px solid var(--accent-color) !important;
31 | background-color: var(--uc-highlight-colour) !important;
32 | }
33 |
34 | image.textbox-search-sign {
35 | display: none !important;
36 | }
37 |
38 | search-textbox.tabsFilter,
39 | search-textbox#search-box {
40 | padding: 4px !important;
41 | transition: ease-out var(--uc-animation-duration);
42 | appearance: none !important;
43 | -moz-default-appearance: none !important;
44 | color: var(--uc-inverted-colour) !important;
45 | border-radius: var(--uc-border-radius) !important;
46 | background-color: var(--uc-base-colour) !important;
47 | border: 1px solid var(--uc-muted-colour) !important;
48 | }
--------------------------------------------------------------------------------
/includes/realfire-layout.css:
--------------------------------------------------------------------------------
1 | #nav-bar,
2 | #TabsToolbar,
3 | #main-window,
4 | #sidebar-box,
5 | #PersonalToolbar,
6 | #toolbar-menubar,
7 | #navigator-toolbox {
8 | box-shadow: none !important;
9 | border: none !important;
10 | }
11 |
12 | /* remove "padding" left and right from tabs */
13 | .titlebar-spacer {
14 | display: none !important;
15 | }
16 |
17 | /* fix Shield Icon padding */
18 | #urlbar-input-container[pageproxystate="valid"]
19 | > #tracking-protection-icon-container
20 | > #tracking-protection-icon-box
21 | > #tracking-protection-icon {
22 | padding-bottom: 1px;
23 | }
24 |
25 | #statuspanel #statuspanel-label {
26 | border: none !important;
27 | border-radius: var(--uc-border-radius) !important;
28 | }
29 |
--------------------------------------------------------------------------------
/includes/realfire-library.css:
--------------------------------------------------------------------------------
1 | @-moz-document url(chrome://browser/content/places/places.xhtml)
2 | {
3 | #PopupSearchAutoComplete > * {
4 | border-radius: 0 !important;
5 | }
6 |
7 | #PopupSearchAutoComplete > :first-child {
8 | border-radius: 4px 4px 0 0 !important;
9 | }
10 |
11 | #PopupSearchAutoComplete > :last-child {
12 | border-radius: 0 0 4px 4px !important;
13 | }
14 |
15 | /* autocomplete panel can't overlap the textbox, so shadow can't go up
16 | more than 1px */
17 | panel[type="autocomplete-richlistbox"] > .autocomplete-richlistbox {
18 | box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.03), 0 5px 5px -3px rgba(0, 0, 0, 0.2),
19 | 0 8px 10px -0px rgba(0, 0, 0, 0.14), 0 3px 14px -5px rgba(0, 0, 0, 0.12) !important;
20 | }
21 |
22 | /* search panel gets special treatment; it has multiple children */
23 | #PopupSearchAutoComplete > .autocomplete-richlistbox {
24 | box-shadow: none !important;
25 | }
26 |
27 | #PopupSearchAutoComplete {
28 | filter: drop-shadow(0 8px 6px rgba(0, 0, 0, 0.25))
29 | drop-shadow(0 1px 1px rgba(0, 0, 0, 0.125)) !important;
30 | }
31 |
32 | /* ============== Menus ============== */
33 |
34 | /* These change top bar background color */
35 | #placesToolbar {
36 | color: var(--uc-inverted-colour) !important;
37 | background-color: var(--uc-base-colour) !important;
38 | border-bottom: 1px solid var(--accent-color) !important;
39 | }
40 |
41 | /* These change the lists background color */
42 | /* This one changes the urlbar star bookmarking folder tree backgrund color */
43 | #placesView #placesView .scrollbox-innerbox,
44 | #infoPane,
45 | #placesList,
46 | #placeContent,
47 | #editBMPanel_folderTree {
48 | -moz-appearance: none !important;
49 | color: var(--uc-inverted-colour) !important;
50 | background: var(--uc-base-colour) !important;
51 | border-bottom: 1px solid var(--accent-color) !important;
52 | }
53 |
54 | /* These change the list header background and text colors */
55 | #placeContent treecol {
56 | -moz-appearance: none !important;
57 | color: var(--uc-inverted-colour) !important;
58 | background: var(--uc-base-colour) !important;
59 | }
60 |
61 | #placeContent treecol:hover {
62 | -moz-appearance: none !important;
63 | color: var(--uc-inverted-colour) !important;
64 | background: rgb(255, 255, 255, 0.15) !important;
65 | }
66 |
67 | /* This changes the right border on the left list panel */
68 | #placesView > splitter {
69 | border-inline-end: 1px solid var(--accent-color) !important;
70 | }
71 |
72 | /* These change the odd rows of the lists */
73 | #placeContent tree,
74 | treechildren::-moz-tree-row(odd) {
75 | color: var(--uc-inverted-colour) !important;
76 | }
77 |
78 | treechildren::-moz-tree-row(hover),
79 | treechildren::-moz-tree-row(selected, focus) {
80 | outline: none !important;
81 | color: var(--uc-inverted-colour) !important;
82 | background-color: var(--accent-color) !important;
83 | }
84 |
85 | treechildren::-moz-tree-cell {
86 | border-right: 0px dotted rgba(0, 0, 0, 0.4) !important;
87 | }
88 |
89 | #placeContent > splitter {
90 | border: 0px solid red !important;
91 | }
92 |
93 | /* This changes the forward and back buttons opacity when disabled */
94 | #placesToolbar > toolbarbutton[disabled] > .toolbarbutton-icon {
95 | opacity: 0.25 !important;
96 | }
97 |
98 | /* This changes the forward and back buttons color */
99 | #back-button > .toolbarbutton-icon,
100 | #forward-button > .toolbarbutton-icon {
101 | opacity: 1 !important;
102 | fill: var(--uc-inverted-colour) !important;
103 | }
104 |
105 | /* This deletes the leftover border when clicking one of the top buttons */
106 | #placesMenu > menu {
107 | margin-inline: 5px !important;
108 | border-radius: var(--uc-border-radius) !important;
109 | }
110 |
111 |
112 | #placesMenu > menu > .menubar-text {
113 | background: none !important;;
114 | }
115 |
116 | /* This changes the text color of the "clear downloads" button */
117 | #clearDownloadsButton {
118 | color: var(--uc-inverted-colour) !important;
119 | }
120 |
121 | #clearDownloadsButton[disabled] {
122 | color: var(--uc-base-colour) !important;
123 | }
124 |
125 | /* This themes the search box */
126 | #searchFilter {
127 | -moz-appearance: none !important;
128 | color: var(--uc-inverted-colour) !important;
129 | transition: all var(--uc-animation-duration) ease-in-out !important;
130 | border-radius: var(--uc-border-radius) !important;
131 | background-color: var(--uc-base-colour) !important;
132 | outline: 1px solid var(--uc-muted-colour) !important;
133 | }
134 |
135 | /* This themes the search box on hover */
136 | #searchFilter[focused="true"] {
137 | color: var(--uc-inverted-colour) !important;
138 | background-color: var(--uc-base-colour) !important;
139 | outline: 1.5px solid var(--accent-color) !important;
140 | box-shadow: var(--input-field-focus-shadow) !important;
141 | }
142 |
143 | /* This themes the information box on the lower part of the library menu */
144 | #detailsDeck {
145 | border-top: 2px solid #222 !important;
146 | color: var(--uc-inverted-colour) !important;
147 | background-color: var(--uc-base-colour) !important;
148 | }
149 |
150 | /* This changes the text boxes inside the library bottom information box */
151 | /* This changes the text boxes on the popup when bookmarking a page from the url box */
152 | #infoBox textbox,
153 | #infoBox listbox,
154 | #editBMPanel_namePicker,
155 | #editBMPanel_tagsField,
156 | #editBMPanel_tagsSelector,
157 | #editBMPanel_locationField,
158 | #editBMPanel_keywordField {
159 | -moz-appearance: none !important;
160 | color: var(--uc-inverted-colour) !important;
161 | transition: all var(--uc-animation-duration) ease-in-out !important;
162 | border-radius: var(--uc-border-radius) !important;
163 | border: 1px solid var(--uc-muted-colour) !important;
164 | }
165 |
166 | /* A fix for bookmark preferences... so that some boxes won't appear brighter than others */
167 | #bookmarkproperties #editBMPanel_namePicker,
168 | #bookmarkproperties #editBMPanel_tagsField,
169 | #bookmarkproperties #editBMPanel_tagsSelector {
170 | border: 1px solid var(--accent-color) !important;
171 | border-radius: var(--uc-border-radius) !important;
172 | }
173 |
174 |
175 |
176 | /* This changes the same text boxes on hover */
177 | /* This changes the same url bookmarking popup text boxes on hover */
178 | #infoBox textbox:hover,
179 | #infoBox listbox:hover,
180 | #editBMPanel_namePicker:hover,
181 | #editBMPanel_tagsField:hover,
182 | #editBMPanel_locationField:hover,
183 | #editBMPanel_keywordField:hover,
184 | #infoBox #bookmarkproperties #editBMPanel_namePicker:hover,
185 | #infoBox #bookmarkproperties #editBMPanel_tagsField:hover {
186 | color: var(--uc-inverted-colour) !important;
187 | border: 1.5px solid var(--accent-color) !important;
188 | background-color: var(--uc-base-colour) !important;
189 | box-shadow: var(--Input-field-focus-shadow) !important;
190 | }
191 |
192 | /* This changes the buttons inside the bookmarking popup at the url star */
193 | #editBMPanel_newFolderButton,
194 | #editBookmarkPanelDoneButton,
195 | #editBookmarkPanelRemoveButton,
196 | #identity-popup-popup-menulist,
197 | #tracking-action-unblock-private,
198 | #tracking-action-block,
199 | #tracking-action-unblock {
200 | padding: 0.3em !important;
201 | margin-top: 0.5em !important;
202 | margin-bottom: 0.5em !important;
203 | -moz-appearance: none !important;
204 | background: var(--uc-base-colour) !important;
205 | color: var(--uc-inverted-colour) !important;
206 | }
207 |
208 | #editBMPanel_newFolderButton:hover,
209 | #editBookmarkPanelDoneButton:hover,
210 | #editBookmarkPanelRemoveButton:hover,
211 | #tracking-action-unblock-private:hover,
212 | #identity-popup-popup-menulist:hover,
213 | #tracking-action-block:hover,
214 | #tracking-action-unblock:hover {
215 | color: var(--uc-inverted-colour) !important;
216 | background: var(--uc-muted-colour) !important;
217 | }
218 |
219 | #editBookmarkPanelBottomButtons {
220 | background: transparent !important;
221 | }
222 |
223 | /* These change the expander buttons on the library and bookmarking popup */
224 | #editBMPanel_folderMenuList,
225 | #editBMPanel_tagsSelectorExpander,
226 | #editBMPanel_foldersExpander,
227 | #detailsDeck button {
228 | -moz-appearance: none !important;
229 | color: var(--uc-inverted-colour) !important;
230 | background: var(--uc-base-colour) !important;
231 | border: 1px solid var(--uc-inverted-colour) !important;
232 | }
233 |
234 | #editBMPanel_folderMenuList:hover,
235 | #editBMPanel_foldersExpander:hover,
236 | #editBMPanel_tagsSelectorExpander:hover,
237 | #detailsDeck button:hover {
238 | background: var(--uc-muted-colour) !important;
239 | border: 1px solid var(--accent-color) !important;
240 | }
241 |
242 | #BMB_bookmarksPopup {
243 | margin-top: -9px !important;
244 | }
245 |
246 | #editBMPanel_folderMenuList {
247 | padding: 1px !important;
248 | color: var(--uc-inverted-colour) !important;
249 | }
250 |
251 | /* These change the downloads history list background */
252 | #downloadsRichListBox {
253 | color: var(--uc-inverted-colour) !important;
254 | background: var(--uc-base-colour) !important;
255 | }
256 |
257 | #detailsPane {
258 | border-top: none !important;
259 | background-color: var(--uc-base-colour) !important;
260 | }
261 |
262 |
263 | }
264 |
--------------------------------------------------------------------------------
/includes/realfire-nav-bar.css:
--------------------------------------------------------------------------------
1 | #navigator-toolbox:not(:-moz-lwtheme),
2 | .sidebar-panel:not(:-moz-lwtheme) {
3 | background: var(--uc-base-colour) !important;
4 | }
5 |
6 | #nav-bar {
7 | padding-block-start: 0px !important;
8 | border: none !important;
9 | box-shadow: none !important;
10 | background: transparent !important;
11 | }
12 |
13 | #nav-bar-toolbarbutton-slider-container {
14 | max-width: 64px !important;
15 | }
16 |
17 | ::-moz-selection {
18 | background-color: var(--accent-color) !important;
19 | }
20 |
21 |
22 | /*Dots in search bar*/
23 | #urlbar #identity-icon-box,
24 | #urlbar #identity-permission-box {
25 | opacity: 0 !important;
26 | margin-inline-start: calc(-16px - 2 * var(--urlbar-icon-padding));
27 | transition: margin-inline-start 100ms linear, opacity 200ms linear;
28 | }
29 |
30 | #urlbar #identity-box.notSecureText #identity-icon-box {
31 | margin-inline-start: initial !important;
32 | opacity: 1 !important;
33 | color: #e36f6f !important;
34 | }
35 |
36 | #urlbar #identity-box.extensionPage #identity-icon-box {
37 | margin-inline-start: initial !important;
38 | opacity: 1 !important;
39 | }
40 |
41 | #identity-box:hover #identity-icon-box,
42 | #identity-box:hover #identity-permission-box,
43 | #identity-box #identity-permission-box[open="true"] {
44 | opacity: 1 !important;
45 | margin-inline-start: initial !important;
46 | }
47 |
48 | #urlbar-input-container .urlbar-input-box {
49 | padding-inline-start: 2px !important;
50 | }
51 |
52 | #identity-box:hover~.urlbar-input-box>#urlbar-input {
53 | mask-image: linear-gradient(to right, transparent, black 3ch) !important;
54 | }
55 |
56 | #page-action-buttons {
57 | padding-inline-start: 8px;
58 | }
59 |
60 | #page-action-buttons .urlbar-page-action {
61 | margin-inline-end: calc(-16px - 2 * var(--urlbar-icon-padding));
62 | opacity: 0;
63 | transition: margin-inline-end 100ms linear, opacity 200ms linear;
64 | }
65 |
66 | #page-action-buttons:hover>.urlbar-page-action,
67 | .urlbar-page-action[open],
68 | .urlbar-page-action[open]~.urlbar-page-action {
69 | opacity: 1;
70 | margin-inline-end: 0px !important;
71 | }
72 |
73 | #identity-box.chromeUI #identity-icon-box {
74 | opacity: 1 !important;
75 | margin-inline-start: initial;
76 | }
77 |
78 | #identity-box.chromeUI::after,
79 | #identity-box.chromeUI:hover::after {
80 | opacity: 0 !important;
81 | }
82 |
83 | #page-action-buttons:not(:hover) #translations-button[translationsactive="true"]:not([open]) {
84 | visibility: collapse !important;
85 | }
86 |
87 | /* Create visual dots on both sides */
88 | /* left side identity-box dots modification */
89 | #identity-box::after,
90 | #page-action-buttons::before {
91 | position: relative;
92 | content: "•••";
93 | pointer-events: none;
94 | transition: opacity 100ms ease;
95 | align-self: center;
96 | font-size: 0.7em;
97 | }
98 |
99 | #identity-box::after,
100 | #page-action-buttons::before {
101 | opacity: 0.2;
102 | }
103 |
104 | #identity-box::after {
105 | transform: rotate(90deg);
106 | left: 4px;
107 | }
108 |
109 | #page-action-buttons::before {
110 | transform: rotate(-90deg);
111 | right: 4px;
112 | }
113 |
114 | #identity-box:hover::after,
115 | #page-action-buttons:hover::before {
116 | opacity: 0.5 !important;
117 | transition: opacity 50ms ease;
118 | pointer-events: none;
119 | }
120 |
121 | #identity-box[pageproxystate="invalid"]::after,
122 | #urlbar-input-container[pageproxystate="invalid"]>#page-action-buttons::before {
123 | opacity: 0 !important;
124 | transition: opacity 50ms ease;
125 | }
126 |
127 | /* Only show dots in search bar when hovered */
128 | #urlbar #identity-box::after,
129 | #urlbar #page-action-buttons::before {
130 | opacity: 0;
131 | }
132 |
133 | #urlbar:hover #identity-box::after,
134 | #urlbar:hover #page-action-buttons::before {
135 | opacity: 0.5;
136 | transition: opacity 100ms ease;
137 | }
138 |
139 | #urlbar-background {
140 | border: transparent !important;
141 | }
142 |
143 | #urlbar[focused="true"]>#urlbar-background,
144 | #urlbar:not([open])>#urlbar-background {
145 | background: var(--uc-base-colour) !important;
146 | }
147 |
148 | #urlbar[open]>#urlbar-background {
149 | background: var(--uc-base-colour) !important;
150 | }
151 |
152 | .urlbarView-row:hover>.urlbarView-row-inner,
153 | .urlbarView-row[selected]>.urlbarView-row-inner {
154 | background: var(--toolbar-field-focus-background-color) !important;
155 | color: var(--uc-inverted-colour) !important;
156 | }
157 |
158 | .urlbarView-url {
159 | color: var(--accent-color) !important;
160 | }
161 |
162 | .urlbar-icon,
163 | #urlbar-go-button {
164 | margin: auto;
165 | }
166 |
167 | .urlbar-icon[starred='true'] {
168 | fill: var(--accent-color) !important;
169 | }
170 |
171 | .urlbar-page-action {
172 | padding: 0 inherit !important;
173 | }
174 |
175 | #toolbar-menubar {
176 | min-width: 100% !important;
177 | }
--------------------------------------------------------------------------------
/includes/realfire-responsive.css:
--------------------------------------------------------------------------------
1 | @media (min-width: 1000px) {
2 | #navigator-toolbox {
3 | display: flex;
4 | flex-wrap: wrap;
5 | flex-direction: row;
6 | align-items: flex-end !important;
7 | }
8 |
9 | #nav-bar {
10 | order: var(--uc-urlbar-position) !important;
11 | width: var(--uc-urlbar-max-width) !important;
12 | }
13 |
14 | #urlbar-container {
15 | padding-left: 2px;
16 | width: auto !important;
17 | margin-inline: 6px !important;
18 | min-width: var(--uc-urlbar-min-width);
19 | max-width: var(--uc-urlbar-max-width) !important;
20 | }
21 |
22 | #TabsToolbar {
23 | order: 2 !important;
24 | }
25 |
26 | #PersonalToolbar {
27 | width: 100% !important;
28 | order: var(--uc-toolbar-position) !important;
29 | }
30 |
31 | :root:not([customizing])
32 | #nav-bar
33 | .customization-target
34 | > :not(#urlbar-container) {
35 | opacity: 0 !important;
36 | width: 0px !important;
37 | padding: 0px !important;
38 | min-width: 0px !important;
39 | transition: all var(--uc-animation-duration) !important;
40 | }
41 |
42 | :root:not([customizing])
43 | #nav-bar:hover
44 | .customization-target
45 | > :not(#urlbar-container,#nav-bar-toolbarbutton-slider-container),
46 | :root:not([customizing])
47 | #nav-bar:focus-within
48 | .customization-target
49 | > :not(#urlbar-container,#nav-bar-toolbarbutton-slider-container) {
50 | opacity: 1 !important;
51 | min-width: 28px !important;
52 | transition: all var(--uc-animation-duration) !important;
53 | }
54 |
55 | :root:not([customizing])
56 | #nav-bar:hover
57 | .customization-target
58 | > #nav-bar-toolbarbutton-slider-container,
59 | :root:not([customizing])
60 | #nav-bar:focus-within
61 | .customization-target
62 | > #nav-bar-toolbarbutton-slider-container {
63 | width: 100% !important;
64 | opacity: 1 !important;
65 | transition: all 200ms !important;
66 | }
67 |
68 | #back-button,
69 | #forward-button {
70 | transform: scale(1, 1) !important;
71 | transition: margin-left var(--uc-animation-duration) var(--animation-easing-function),
72 | transform var(--uc-animation-duration) var(--animation-easing-function) !important;
73 | }
74 |
75 | #forward-button[disabled="true"],
76 | #back-button[disabled="true"] {
77 | display: none;
78 | opacity: 0 !important;
79 | pointer-events: none !important;
80 | transform: scale(0.6, 0.6) !important;
81 | }
82 |
83 | #navigator-toolbox:focus-within #titlebar {
84 | width: auto !important;
85 | min-width: calc(100vw - var(--uc-urlbar-max-width) - 1px);
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/includes/realfire-settings-page.css:
--------------------------------------------------------------------------------
1 | @-moz-document url(chrome://browser/content/preferences/preferences.xhtml),
2 | url(about:preferences),
3 | url(about:preferences#home),
4 | url(about:preferences#general),
5 | url(about:preferences#search),
6 | url(about:preferences#privacy),
7 | url(about:preferences#sync),
8 | url(about:preferences#experimental),
9 | url(about:preferences#moreFromMozilla) {
10 |
11 | /* Navigation menu */
12 | .navigation {
13 | align-items: center !important;
14 | background-color: var(--uc-base-colour) !important;
15 | border-right: 2px solid var(--settings-color) !important;
16 | -moz-appearance: none !important;
17 | }
18 |
19 | .sticky-container {
20 | width: 100% !important;
21 | margin-inline: 0 !important;
22 | position: absolute !important;
23 | border-bottom: 2px solid var(--accent-color) !important;
24 | }
25 |
26 | .main-content {
27 | padding: 0 !important;
28 | background-color: var(--uc-base-colour) !important;
29 | -moz-appearance: none !important;
30 | }
31 |
32 | #mainPrefPane {
33 | padding: 90px 0 0 28px !important;
34 | }
35 |
36 | #categories {
37 | width: auto !important;
38 | }
39 |
40 | #categories richlistitem {
41 | color: var(--uc-inverted-colour) !important;
42 | border-radius: var(--uc-border-radius) !important;
43 | margin-inline: 20px !important;
44 | justify-content: center !important;
45 | }
46 |
47 | /* Sidebar footer */
48 | .sidebar-footer-list {
49 | margin-inline: 0 !important;
50 | margin-inline-start: 0 !important;
51 | }
52 |
53 | /* Selected category color */
54 | @media not (prefers-contrast) {
55 | #categories > .category[selected],
56 | #categories > .category.selected {
57 | color: var(--settings-color) !important;
58 | }
59 | }
60 |
61 | /* Selected privacy option background */
62 | .privacy-detailedoption.selected {
63 | border-color: var(--settings-color) !important;
64 | background-color: color-mix(var(--settings-color) 20%, transparent) !important;
65 | }
66 |
67 | /* Links */
68 | a,
69 | .text-link {
70 | color: var(--settings-color) !important;
71 | }
72 |
73 | a:hover,
74 | .text-link:hover,
75 | .text-link:is(:not([disabled="true"]), :enabled):hover {
76 | color: color-mix(var(--uc-inverted-colour), var(--settings-color)) !important;
77 | }
78 |
79 | /* Focus styles */
80 | input:is([type="email"], [type="tel"], [type="text"], [type="password"], [type="url"], [type="number"]):focus,
81 | search-textbox[focused],
82 | textarea:focus-visible,
83 | tree:focus-visible,
84 | richlistbox:focus-visible,
85 | #searchInput[focused="true"] {
86 | outline: 2px solid var(--settings-color) !important;
87 | }
88 |
89 | /* Search input */
90 | #searchInput {
91 | border-radius: var(--uc-border-radius) !important;
92 | }
93 |
94 | /* Buttons */
95 | button,
96 | #row-selector.selector {
97 | color: var(--uc-inverted-colour) !important;
98 | border-radius: var(--uc-border-radius) !important;
99 | }
100 |
101 | button.primary,
102 | button[default],
103 | button[autofocus],
104 | button[type="submit"],
105 | button:not([disabled])[default="true"] {
106 | color: var(--button-text-white) !important;
107 | border-color: var(--accent-color) !important;
108 | background-color: var(--accent-color) !important;
109 | }
110 |
111 | /* Focus styles for controls */
112 | select:focus-visible,
113 | button:focus-visible,
114 | menulist:focus-visible,
115 | radio[focused="true"] > .radio-check,
116 | tab:focus-visible > .tab-middle > .tab-text,
117 | checkbox:not([native]):focus-visible > .checkbox-check,
118 | input:is([type="checkbox"], [type="color"], [type="radio"]):focus-visible {
119 | outline: 2px solid var(--uc-inverted-colour) !important;
120 | outline-offset: 0 !important;
121 | }
122 |
123 | }
124 |
--------------------------------------------------------------------------------
/includes/realfire-side-bar.css:
--------------------------------------------------------------------------------
1 | #sidebar-search-container {
2 | justify-content: center !important;
3 | }
4 |
5 | .content-container {
6 | background-color: var(--uc-base-colour) !important;
7 | }
8 |
9 | .textbox-search-sign,
10 | .textbox-search-icon {
11 | background-repeat: no-repeat !important;
12 | background-color: transparent !important;
13 | background-position: 5px center !important;
14 | background-image: url(../icons/search.svg) !important;
15 | }
16 |
17 | #sidebar-header {
18 | background-color: var(--uc-base-colour) !important;
19 | border-bottom: 1.5px solid var(--accent-color) !important;
20 | }
21 |
22 | #sidebar-icon {
23 | fill: var(--accent-color) !important;
24 | }
25 |
--------------------------------------------------------------------------------
/includes/realfire-tabs.css:
--------------------------------------------------------------------------------
1 | /* Hides the list-all-tabs button */
2 | #alltabs-button {
3 | display: var(--uc-show-all-tabs-button) !important;
4 | }
5 |
6 | /* remove tab shadow */
7 | .tabbrowser-tab>.tab-stack>.tab-background {
8 | box-shadow: none !important;
9 | border-radius: var(--uc-border-radius) !important;
10 | margin-block: var(--uc-tab-block-margin) !important;
11 | }
12 |
13 | /* multi tab selection */
14 | #tabbrowser-tabs:not([noshadowfortests]) .tabbrowser-tab:is([multiselected])>.tab-stack>.tab-background:-moz-lwtheme {
15 | outline-color: var(--toolbarseparator-color) !important;
16 | }
17 |
18 | /* tab close button options */
19 | .tabbrowser-tab:not([pinned]) .tab-close-button {
20 | display: var(--show-tab-close-button) !important;
21 | }
22 |
23 | .tabbrowser-tab:not([pinned]):hover .tab-close-button {
24 | display: var(--show-tab-close-button-hover) !important;
25 | }
26 |
27 | /* Add animation for tab width change */
28 | .tabbrowser-tab[selected][fadein]:not([pinned]),
29 | .tabbrowser-tab[fadein]:not([selected]):not([pinned]) {
30 | transition: max-width var(--uc-animation-duration) ease-in-out !important;
31 | }
32 |
33 | /* adaptive tab width */
34 | .tabbrowser-tab[selected][fadein]:not([pinned]) {
35 | max-width: var(--uc-active-tab-width) !important;
36 | }
37 |
38 | .tabbrowser-tab[fadein]:not([selected]):not([pinned]) {
39 | max-width: var(--uc-inactive-tab-width) !important;
40 | }
41 |
42 | /* container tabs indicator */
43 | .tabbrowser-tab[usercontextid]>.tab-stack>.tab-background>.tab-context-line {
44 | height: 1px !important;
45 | box-shadow: var(--uc-identity-glow) var(--identity-tab-color) !important;
46 | margin: -1px var(--container-tabs-indicator-margin) 0 var(--container-tabs-indicator-margin) !important;
47 | }
48 |
49 | /* show favicon when media is playing but tab is hovered */
50 | .tab-icon-image:not([pinned]) {
51 | opacity: 1 !important;
52 | }
53 |
54 | /* Makes the speaker icon to always appear if the tab is playing (not only on hover) */
55 | .tab-icon-overlay:not([crashed]),
56 | .tab-icon-overlay[pinned][crashed][selected] {
57 | top: 5px !important;
58 | z-index: 1 !important;
59 | width: 16px !important;
60 | height: 16px !important;
61 | padding: 1.5px !important;
62 | inset-inline-end: -8px !important;
63 | border-radius: var(--uc-border-radius) !important;
64 | }
65 |
66 | /* style and position speaker icon */
67 | [muted],
68 | .tab-icon-overlay:not([sharing], [crashed]):is([soundplaying],
69 | [activemedia-blocked]) {
70 | opacity: 1 !important;
71 | fill-opacity: 0.8 !important;
72 | stroke: transparent !important;
73 | color: var(--accent-color) !important;
74 | stroke: var(--toolbar-bgcolor) !important;
75 | }
76 |
77 | /* change the colours of the speaker icon on active tab to match tab colours */
78 | .tabbrowser-tab[selected] .tab-icon-overlay:not([sharing], [crashed]):is([soundplaying],
79 | [muted],
80 | [activemedia-blocked]) {
81 | stroke: var(--toolbar-bgcolor) !important;
82 | }
83 |
84 | .tab-icon-overlay:not([pinned], [sharing], [crashed]):is([soundplaying],
85 | [muted],
86 | [activemedia-blocked]) {
87 | margin-inline-end: 9.5px !important;
88 | }
89 |
90 | .tabbrowser-tab:not([image]) .tab-icon-overlay:not([pinned], [sharing], [crashed]) {
91 | top: 0 !important;
92 | padding: 0 !important;
93 | inset-inline-end: 0 !important;
94 | margin-inline-end: 5.5px !important;
95 | }
96 |
97 | .tab-icon-overlay:not([crashed])[soundplaying]:hover,
98 | .tab-icon-overlay:not([crashed])[muted]:hover,
99 | .tab-icon-overlay:not([crashed])[activemedia-blocked]:hover {
100 | fill-opacity: 0.95 !important;
101 | color: var(--accent-color) !important;
102 | stroke: var(--toolbar-color) !important;
103 | background-color: var(--toolbar-color) !important;
104 | }
105 |
106 | .tabbrowser-tab[selected] .tab-icon-overlay:not([crashed])[muted]:hover,
107 | .tabbrowser-tab[selected] .tab-icon-overlay:not([crashed])[soundplaying]:hover,
108 | .tabbrowser-tab[selected] .tab-icon-overlay:not([crashed])[activemedia-blocked]:hover {
109 | fill-opacity: 0.95 !important;
110 | color: var(--accent-color) !important;
111 | stroke: var(--toolbar-color) !important;
112 | background-color: var(--toolbar-color) !important;
113 | }
114 |
115 | #PersonalToolbar:not([customizing]) {
116 | background-color: transparent !important;
117 | border-radius: var(--uc-border-radius) !important;
118 | /* border: 1.5px solid var(--accent-color) !important; */
119 | background-repeat: no-repeat, no-repeat, var(--lwt-background-tiling);
120 | --uc-bg-y: calc(-2 * (var(--tab-block-margin) + var(--toolbarbutton-inner-padding) + var(--toolbarbutton-outer-padding)) - var(--tab-min-height) - 16px - var(--bookmark-block-padding));
121 | background-position: top left, top left,
122 | var(--lwt-background-alignment, top left);
123 | margin-bottom: 4px;
124 | }
125 |
126 | /* #PersonalToolbar:not([customizing]):-moz-window-inactive {
127 | border: 1.5px solid var(--accent-field-color) !important;
128 | } */
129 |
130 | .tabbrowser-tab .tab-stack .tab-background:is([selected], [multiselected]) {
131 | outline: 2px solid var(--accent-color) !important;
132 | background-color: var(--uc-base-colour) !important;
133 | }
134 |
135 | /* Border for selected tab in inactive window */
136 | .tabbrowser-tab .tab-stack .tab-background[selected=]:-moz-window-inactive::after {
137 | content: "";
138 | display: block;
139 | height: 50%; /* Adjust this value to control the length of the border */
140 | width: 1.5px; /* Width of the border */
141 | position: absolute;
142 | right: 0;
143 | top: 25%; /* Adjust this value to control the vertical position */
144 | background-color: var(--accent-field-color);
145 | }
146 |
147 | /* Fixing Multiselect */
148 | .tab-background[multiselected="true"]:not([selected="true"])>.tab-background-inner {
149 | background: none !important;
150 | }
151 |
--------------------------------------------------------------------------------
/programs/install-curl.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | cd %TEMP%
4 |
5 | set "FILENAME=RealFire-main.zip"
6 | set "FOLDERPATH=RealFire-main"
7 |
8 | if exist "%FOLDERPATH%"\* (
9 | rd /s /q %FOLDERPATH%
10 | )
11 |
12 | curl -LJo %FILENAME% https://github.com/Hakanbaban53/RealFire/archive/refs/heads/main.zip || (echo Failed to fetch RealFire^! theme && echo Exiting... && goto :eof)
13 |
14 | tar -xvf %FILENAME% || echo.
15 |
16 | del %FILENAME%
17 |
18 | call "%FOLDERPATH%\programs\install.bat" %*
19 |
20 | REM if exist "%FOLDERPATH%"\* (
21 | REM rd /s /q %FOLDERPATH%
22 | REM )
23 |
24 | REM exit \B
25 |
--------------------------------------------------------------------------------
/programs/install-curl.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | FILENAME=RealFire-main.zip
4 | FOLDERPATH=$PWD/RealFire-main
5 |
6 | if [ -d "$FOLDERPATH" ]; then rm -Rf $FOLDERPATH; fi
7 |
8 | curl -LJo $FILENAME https://github.com/Hakanbaban53/RealFire/archive/refs/heads/main.zip
9 |
10 | unzip $FILENAME
11 |
12 | rm $FILENAME
13 |
14 | chmod +x "${FOLDERPATH}/programs/install.sh"
15 |
16 | "${FOLDERPATH}/programs/install.sh" "$@"
17 |
18 | # if [ -d "$FOLDERPATH" ]; then rm -Rf $FOLDERPATH; fi
19 |
--------------------------------------------------------------------------------
/programs/install.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | call :RequestAdminElevation "%~dpfs0" %* || goto:eof
4 |
5 | goto :init
6 |
7 | :header
8 | echo %__NAME% v%__VERSION%
9 | echo This is a sample batch file to install
10 | echo RealFire theme via Command Line Interface
11 | echo.
12 | goto :eof
13 |
14 | :usage
15 | echo USAGE:
16 | echo %__NAME% [ options ... ]"
17 | echo where options include:
18 | echo.
19 | echo. /b, -b ^ (Set custom Firefox binary folder path)
20 | echo. /f, -f ^ (Set custom Firefox folder path)
21 | echo. /p, -p ^ (Set custom profile name)
22 | echo. /e, -e (Default Enabled. Install fx-autoconfig - Runs as admin to copy mozilla.cfg and local-settings.js to Application Binary folder)
23 | echo. /v, -v, --version (Show script version)
24 | echo. /?, -h (Show help message)
25 | goto :eof
26 |
27 | :version
28 | if "%~1"=="full" call :header & goto :eof
29 | echo %__VERSION%
30 | goto :eof
31 |
32 | :init
33 | set "__NAME=%~nx0"
34 | set "__VERSION=4.0.0"
35 |
36 | for %%a in ("%~dp0.") do set "THEMEDIRECTORY=%%~dpa"
37 |
38 | set "APPLICATIONFOLDER=C:\Program Files\Mozilla Firefox"
39 | set "FIREFOXFOLDER=%APPDATA%\Mozilla\Firefox"
40 | set "PROFILENAME="
41 | set "FXACEXTRAS=yes"
42 | set "CHROMEFOLDER=chrome"
43 |
44 | :parse
45 | if "%~1"=="" goto :main
46 |
47 | if /i "%~1"=="/?" call :header & call :usage "%~2" & goto :end
48 | if /i "%~1"=="-h" call :header & call :usage "%~2" & goto :end
49 | if /i "%~1"=="--help" call :header & call :usage "%~2" & goto :end
50 |
51 | if /i "%~1"=="/v" call :version & goto :end
52 | if /i "%~1"=="-v" call :version & goto :end
53 | if /i "%~1"=="--version" call :version full & goto :end
54 |
55 | if /i "%~1"=="/b" set "APPLICATIONFOLDER=%~2" & shift & shift & goto :parse
56 | if /i "%~1"=="-b" set "APPLICATIONFOLDER=%~2" & shift & shift & goto :parse
57 |
58 | if /i "%~1"=="/f" set "FIREFOXFOLDER=%~2" & shift & shift & goto :parse
59 | if /i "%~1"=="-f" set "FIREFOXFOLDER=%~2" & shift & shift & goto :parse
60 |
61 | if /i "%~1"=="/p" set "PROFILENAME=%~2" & shift & shift & goto :parse
62 | if /i "%~1"=="-p" set "PROFILENAME=%~2" & shift & shift & goto :parse
63 |
64 | if /i "%~1"=="/e" set "FXACEXTRAS=" & shift & goto :parse
65 | if /i "%~1"=="-e" set "FXACEXTRAS=" & shift & goto :parse
66 |
67 | shift
68 | goto :parse
69 |
70 | :main
71 | setlocal enableDelayedExpansion
72 |
73 | REM Check if Firefox profiles.ini is installed or not
74 | set "PROFILES_FILE=%FIREFOXFOLDER%\profiles.ini"
75 | if not exist "%PROFILES_FILE%" (
76 | echo Failed to locate profiles.ini in %FIREFOXFOLDER%
77 | echo Exiting...
78 | goto :end
79 | )
80 | echo.
81 | echo Profiles file found...
82 |
83 | for /f "delims=" %%i in ('findstr /rc:"Default=.*" %PROFILES_FILE%') do (
84 | set "i=%%i"
85 | set "i=!i:/=\!"
86 | set "PROFILENAMEDEF=!i:~8!"
87 | goto :continue
88 | )
89 | :continue
90 |
91 | REM Define default Profile folder path else use -p option
92 | if defined PROFILENAME set "PROFILEFOLDER=%FIREFOXFOLDER%\%PROFILENAME%"
93 | if not defined PROFILENAME set "PROFILEFOLDER=%FIREFOXFOLDER%\%PROFILENAMEDEF%"
94 |
95 | REM Enter Firefox profile folder if it exists
96 | if not exist "%PROFILEFOLDER%"\* (
97 | echo Failed to locate Profile folder at %PROFILEFOLDER%
98 | echo Exiting...
99 | goto :end
100 | )
101 |
102 | cd %PROFILEFOLDER%
103 |
104 | REM Copy theme repository inside chrome folder
105 | echo.
106 | echo Installing RealFire UwU in %cd%
107 |
108 | if exist "%CHROMEFOLDER%"\* (
109 | echo Moving existing %CHROMEFOLDER% to %CHROMEFOLDER%_bak
110 | move %CHROMEFOLDER% %CHROMEFOLDER%_bak || (echo Rename or move the backup && goto :end)
111 | )
112 |
113 | mkdir %CHROMEFOLDER%
114 | cd %CHROMEFOLDER%
115 |
116 | robocopy %THEMEDIRECTORY% %cd% /COPY:DATS /E
117 |
118 | echo.
119 | echo Setting configuration user.js file...
120 |
121 | if exist ..\user.js (
122 | echo Moving existing user.js to user.js.bak
123 | move ..\user.js ..\user.js.bak || (echo Rename or move the user.js file && goto :end)
124 | )
125 | mklink ..\user.js "%cd%\programs\user.js"
126 |
127 | REM If FXACEXTRAS extras enabled, install necessary files
128 | if not defined FXACEXTRAS (
129 | goto :done
130 | )
131 |
132 | echo.
133 | echo Enabling userChrome.js manager (fx-autoconfig)...
134 | curl -sL "https://raw.githubusercontent.com/MrOtherGuy/fx-autoconfig/master/profile/chrome/utils/boot.sys.mjs" > "utils\boot.sys.mjs" || (echo Failed to fetch fx-autoconfig && echo Exiting... && goto :end)
135 |
136 | echo.
137 | echo Downloading config-pref.js (fx-autoconfig)...
138 | curl -sL "https://raw.githubusercontent.com/MrOtherGuy/fx-autoconfig/master/program/defaults/pref/config-prefs.js" > "programs\config-prefs.js" || (echo Failed to fetch fx-autoconfig config-prefs.js && echo Exiting... && goto :end)
139 | curl -sL "https://raw.githubusercontent.com/MrOtherGuy/fx-autoconfig/master/program/config.js" > "programs\config.js" || (echo Failed to fetch fx-autoconfig config.js && echo Exiting... && goto :end)
140 |
141 | echo.
142 | echo Copying mozilla.cfg and local-settings.js to %APPLICATIONFOLDER%
143 | copy .\programs\config.js "%APPLICATIONFOLDER%"
144 | copy .\programs\mozilla.cfg "%APPLICATIONFOLDER%"
145 | copy .\programs\config-prefs.js "%APPLICATIONFOLDER%\defaults\pref\"
146 | copy .\programs\local-settings.js "%APPLICATIONFOLDER%\defaults\pref\"
147 |
148 | goto :done
149 |
150 | :done
151 | echo.
152 | echo Done!
153 | echo Note: Restart twice to apply changes
154 |
155 | :end
156 | call :cleanup
157 | pause
158 | exit /B
159 |
160 | :cleanup
161 | REM The cleanup function is only really necessary if you
162 | REM are _not_ using SETLOCAL.
163 | set "__NAME="
164 | set "__VERSION="
165 |
166 | set "THEMEDIRECTORY="
167 | set "APPLICATIONFOLDER="
168 | set "FIREFOXFOLDER="
169 | set "PROFILENAME="
170 | set "FXACEXTRAS="
171 | set "CHROMEFOLDER="
172 |
173 | goto :eof
174 |
175 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
176 | :RequestAdminElevation FilePath %* || goto:eof
177 | ::
178 | :: By: Cyberponk, v1.5 - 10/06/2016 - Changed the admin rights test method from cacls to fltmc
179 | :: v1.4 - 17/05/2016 - Added instructions for arguments with ! char
180 | :: v1.3 - 01/08/2015 - Fixed not returning to original folder after elevation successful
181 | :: v1.2 - 30/07/2015 - Added error message when running from mapped drive
182 | :: v1.1 - 01/06/2015
183 | ::
184 | :: Func: opens an admin elevation prompt. If elevated, runs everything after the function call, with elevated rights.
185 | :: Returns: -1 if elevation was requested
186 | :: 0 if elevation was successful
187 | :: 1 if an error occured
188 | ::
189 | :: USAGE:
190 | :: If function is copied to a batch file:
191 | :: call :RequestAdminElevation "%~dpf0" %* || goto:eof
192 | ::
193 | :: If called as an external library (from a separate batch file):
194 | :: set "_DeleteOnExit=0" on Options
195 | :: (call :RequestAdminElevation "%~dpf0" %* || goto:eof) && CD /D %CD%
196 | ::
197 | :: If called from inside another CALL, you must set "_ThisFile=%~dpf0" at the beginning of the file
198 | :: call :RequestAdminElevation "%_ThisFile%" %* || goto:eof
199 | ::
200 | :: If you need to use the ! char in the arguments, the calling must be done like this, and afterwards you must use %args% to get the correct arguments:
201 | :: set "args=%* "
202 | :: call :RequestAdminElevation ..... use one of the above but replace the %* with %args:!={a)%
203 | :: set "args=%args:{a)=!%"
204 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
205 | setlocal ENABLEDELAYEDEXPANSION & set "_FilePath=%~1"
206 | if NOT EXIST "!_FilePath!" (echo/Read RequestAdminElevation usage information)
207 | :: UAC.ShellExecute only works with 8.3 filename, so use %~s1
208 | set "_FN=_%~ns1" & echo/%TEMP%| findstr /C:"(" >nul && (echo/ERROR: %%TEMP%% path can not contain parenthesis &pause &endlocal &fc;: 2>nul & goto:eof)
209 | :: Remove parenthesis from the temp filename
210 | set _FN=%_FN:(=%
211 | set _vbspath="%temp:~%\%_FN:)=%.vbs" & set "_batpath=%temp:~%\%_FN:)=%.bat"
212 |
213 | :: Test if we gave admin rights
214 | fltmc >nul 2>&1 || goto :_getElevation
215 |
216 | :: Elevation successful
217 | (if exist %_vbspath% ( del %_vbspath% )) & (if exist %_batpath% ( del %_batpath% ))
218 | :: Set ERRORLEVEL 0, set original folder and exit
219 | endlocal & CD /D "%~dp1" & ver >nul & goto:eof
220 |
221 | :_getElevation
222 | echo/Requesting elevation...
223 | :: Try to create %_vbspath% file. If failed, exit with ERRORLEVEL 1
224 | echo/Set UAC = CreateObject^("Shell.Application"^) > %_vbspath% || (echo/&echo/Unable to create %_vbspath% & endlocal &md; 2>nul &goto:eof)
225 | echo/UAC.ShellExecute "%_batpath%", "", "", "runas", 1 >> %_vbspath% & echo/wscript.Quit(1)>> %_vbspath%
226 | :: Try to create %_batpath% file. If failed, exit with ERRORLEVEL 1
227 | echo/@%* > "%_batpath%" || (echo/&echo/Unable to create %_batpath% & endlocal &md; 2>nul &goto:eof)
228 | echo/@if %%errorlevel%%==9009 (echo/^&echo/Admin user could not read the batch file. If running from a mapped drive or UNC path, check if Admin user can read it.)^&echo/^& @if %%errorlevel%% NEQ 0 pause >> "%_batpath%"
229 |
230 | :: Run %_vbspath%, that calls %_batpath%, that calls the original file
231 | %_vbspath% && (echo/&echo/Failed to run VBscript %_vbspath% &endlocal &md; 2>nul & goto:eof)
232 |
233 | :: Vbscript has been run, exit with ERRORLEVEL -1
234 | echo/&echo/Elevation was requested on a new CMD window &endlocal &fc;: 2>nul & goto:eof
235 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
236 |
--------------------------------------------------------------------------------
/programs/install.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | THEMEDIRECTORY=$(cd `dirname "$0"` && cd .. && pwd);
4 |
5 | os_type=$(uname -s)
6 |
7 | # Set default paths
8 | FIREFOXFOLDER=""
9 | APPLICATIONFOLDER=""
10 |
11 | # Check the operating system and set paths accordingly
12 | if [ "$os_type" == "Darwin" ]; then
13 | FIREFOXFOLDER=~/Library/Application\ Support/Firefox
14 | APPLICATIONFOLDER='/Applications/Firefox.app/Contents/MacOS/Firefox'
15 | else
16 | FIREFOXFOLDER=/home/$USER/.mozilla/firefox
17 | APPLICATIONFOLDER='/usr/lib64/firefox'
18 | fi
19 |
20 | PROFILENAME="";
21 | FXACEXTRAS=true;
22 | CHROMEFOLDER="chrome";
23 |
24 |
25 | # Get installation options
26 | while getopts 'b:f:p:eh' flag; do
27 | case "${flag}" in
28 | b) APPLICATIONFOLDER="${OPTARG}" ;;
29 | f) FIREFOXFOLDER="${OPTARG}" ;;
30 | p) PROFILENAME="${OPTARG}" ;;
31 | e) FXACEXTRAS=false ;;
32 | h)
33 | echo "RealFire! Install script usage: ./install.sh [ options ... ]"
34 | echo "where options include:"
35 | echo
36 | echo " -b (Set custom Firefox binary folder path)"
37 | echo " -f (Set custom Firefox folder path)"
38 | echo " -p (Set custom profile name)"
39 | echo " -e (Install fx-autoconfig - Runs sudo to copy mozilla.cfg and local-settings.js to Application Binary folder)"
40 | echo " -h (Show help message)"
41 | exit 0
42 | ;;
43 | esac
44 | done
45 |
46 |
47 | # Check if Firefox profiles.ini is installed or not
48 | PROFILES_FILE="${FIREFOXFOLDER}/profiles.ini"
49 | if [ ! -f "${PROFILES_FILE}" ]; then
50 | >&2 echo "Failed to locate profiles.ini in ${FIREFOXFOLDER}
51 | Exiting..."
52 | exit 1
53 | fi
54 |
55 | echo
56 | echo "Profiles file found..."
57 |
58 |
59 | # Define default Profile folder path else use -p option
60 | if [ -z "$PROFILENAME" ]; then
61 | PROFILEFOLDER="${FIREFOXFOLDER}/$(grep -zoP '\[Install.*?\]\nDefault=\K(.*?)\n' $PROFILES_FILE | tr -d '\0')"
62 | else
63 | PROFILEFOLDER="${FIREFOXFOLDER}/${PROFILENAME}"
64 | fi
65 |
66 |
67 | # Enter Firefox profile folder if it exists
68 | if [ ! -d "$PROFILEFOLDER" ]; then
69 | >&2 echo "Failed to locate Profile folder at ${PROFILEFOLDER}
70 | Exiting..."
71 | exit 1
72 | fi
73 |
74 | cd $PROFILEFOLDER
75 |
76 |
77 | # Copy theme repository inside chrome folder
78 | echo
79 | echo "Installing RealFire! in ${PWD}"
80 |
81 | # Create a chrome directory if it doesn't exist else take a backupold chrome folder
82 | if [ -d "$CHROMEFOLDER" ]; then
83 | echo "Moving existing $CHROMEFOLDER to ${CHROMEFOLDER}_bak"
84 | mv --backup=t $CHROMEFOLDER "${CHROMEFOLDER}_bak" || { exit 1; }
85 | fi
86 |
87 | mkdir -p $CHROMEFOLDER
88 | cd $CHROMEFOLDER
89 |
90 | cp -a "${THEMEDIRECTORY}/." $PWD
91 |
92 |
93 | # Symlink user.js to that of RealFire!
94 | echo
95 | echo "Setting configuration user.js file..."
96 |
97 | if [ -f ../user.js ]; then
98 | echo "Moving existing user.js to user.js.bak"
99 | mv --backup=t ../user.js ../user.js.bak || { exit 1; }
100 | fi
101 |
102 | ln -fs "`pwd`/programs/user.js" ../user.js
103 |
104 |
105 | # If FXACEXTRAS extras enabled, install necessary files
106 | if [ "$FXACEXTRAS" = true ] ; then
107 | echo
108 |
109 | echo "Enabling userChrome.js manager (fx-autoconfig)..."
110 | rm "./utils/boot.sys.mjs"
111 | curl -sL "https://raw.githubusercontent.com/MrOtherGuy/fx-autoconfig/master/profile/chrome/utils/boot.sys.mjs" > "./utils/boot.sys.mjs" || { echo "Failed to fetch boot.sys.mjs"; echo "Exiting..."; exit 1; }
112 |
113 | echo "Enabling config-prefs.js..."
114 | rm "./programs/config-prefs.js"
115 | curl -sL "https://raw.githubusercontent.com/MrOtherGuy/fx-autoconfig/master/program/defaults/pref/config-prefs.js" > "./programs/config-prefs.js" || { echo "Failed to fetch config-prefs.js"; echo "Exiting..."; exit 1; }
116 | echo "Enabling config.js..."
117 | rm "./programs/config.js"
118 | curl -sL "https://raw.githubusercontent.com/MrOtherGuy/fx-autoconfig/master/program/config.js" > "./programs/config.js" || { echo "Failed to fetch config.js"; echo "Exiting..."; exit 1; }
119 |
120 |
121 | echo
122 | echo "Copying mozilla.cfg, local-settings.js, config.js and config-pref.js to ${APPLICATIONFOLDER}"
123 |
124 | sudo cp ./programs/mozilla.cfg "${APPLICATIONFOLDER}/"
125 | sudo cp ./programs/config.js "${APPLICATIONFOLDER}/"
126 |
127 | sudo cp ./programs/config-prefs.js "${APPLICATIONFOLDER}/defaults/pref/"
128 | sudo cp ./programs/local-settings.js "${APPLICATIONFOLDER}/defaults/pref/"
129 | fi
130 |
131 | echo
132 | echo "Done!"
133 | echo "Note: Restart twice to apply changes"
--------------------------------------------------------------------------------
/programs/local-settings.js:
--------------------------------------------------------------------------------
1 | //
2 | pref("general.config.filename", "mozilla.cfg");
3 | pref("general.config.obscure_value", 0);
4 | pref("general.config.sandbox_enabled", false);
5 |
--------------------------------------------------------------------------------
/programs/mozilla.cfg:
--------------------------------------------------------------------------------
1 | // skip 1st line
2 | try {
3 |
4 | let {
5 | classes: Cc,
6 | interfaces: Ci,
7 | manager: Cm,
8 | utils: Cu
9 | } = Components;
10 |
11 | // set new tab page
12 | // Cu.import("resource:///modules/AboutNewTab.jsm");
13 | // var newTabURL_ = "file://";
14 | // AboutNewTab.newTabURL = newTabURL_;
15 |
16 | // set fx-autoconfig
17 | let cmanifest = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties).get('UChrm', Ci.nsIFile);
18 | cmanifest.append('utils');
19 | cmanifest.append('chrome.manifest');
20 |
21 | if(cmanifest.exists()){
22 | Cm.QueryInterface(Ci.nsIComponentRegistrar).autoRegister(cmanifest);
23 | Cu.import('chrome://userchromejs/content/boot.jsm');
24 | }
25 |
26 | } catch(ex) {Cu.reportError(ex)}; // report errors in the Browser Console
27 |
--------------------------------------------------------------------------------
/programs/uninstall.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | call :RequestAdminElevation "%~dpfs0" %* || goto:eof
4 |
5 | goto :init
6 |
7 | :init
8 | set "__NAME=RealFire Uninstaller"
9 | set "__VERSION=4.0.0"
10 |
11 | call :header
12 |
13 | set "APPLICATIONFOLDER=C:\Program Files\Mozilla Firefox"
14 | set "FIREFOXFOLDER=%APPDATA%\Mozilla\Firefox"
15 | set "CHROMEFOLDER=chrome"
16 | set "PROFILEFOLDER="
17 |
18 | REM Locate Firefox profiles.ini
19 | set "PROFILES_FILE=%FIREFOXFOLDER%\profiles.ini"
20 | if not exist "%PROFILES_FILE%" (
21 | echo Failed to locate profiles.ini in %FIREFOXFOLDER%
22 | echo Exiting...
23 | goto :end
24 | )
25 |
26 | echo.
27 | echo Profiles file found...
28 | for /f "delims=" %%i in ('findstr /rc:"Default=.*" %PROFILES_FILE%') do (
29 | set "i=%%i"
30 | set "i=!i:/=\!"
31 | set "PROFILENAMEDEF=!i:~8!"
32 | goto :continue
33 | )
34 | :continue
35 |
36 | REM Set profile folder
37 | set "PROFILEFOLDER=%FIREFOXFOLDER%\%PROFILENAMEDEF%"
38 |
39 | if not exist "%PROFILEFOLDER%" (
40 | echo Failed to locate Profile folder at %PROFILEFOLDER%
41 | echo Exiting...
42 | goto :end
43 | )
44 |
45 | cd "%PROFILEFOLDER%"
46 | echo.
47 | echo Uninstalling RealFire UwU from %cd%
48 |
49 | REM Remove chrome folder and restore backup if exists
50 | if exist "%CHROMEFOLDER%_bak" (
51 | echo Restoring backup folder %CHROMEFOLDER%_bak...
52 | rmdir /s /q "%CHROMEFOLDER%"
53 | move "%CHROMEFOLDER%_bak" "%CHROMEFOLDER%" || (
54 | echo Failed to restore backup folder %CHROMEFOLDER%_bak.
55 | goto :end
56 | )
57 | ) else (
58 | echo Removing %CHROMEFOLDER% folder...
59 | rmdir /s /q "%CHROMEFOLDER%"
60 | )
61 |
62 | REM Restore user.js backup if exists
63 | if exist "user.js.bak" (
64 | echo Restoring user.js.bak...
65 | move /y "user.js.bak" "user.js"
66 | ) else (
67 | echo Removing user.js link...
68 | del "user.js"
69 | )
70 |
71 | REM Optionally remove fx-autoconfig files
72 | set /p FXACREMOVE="Do you want to remove fx-autoconfig files? (Y/N): "
73 | if /i "%FXACREMOVE%"=="Y" (
74 | echo Removing fx-autoconfig files...
75 | rmdir /s /q "chrome\utils"
76 | del "programs\config.js"
77 | del "programs\mozilla.cfg"
78 | del "programs\config-prefs.js"
79 | del "programs\local-settings.js"
80 | )
81 |
82 | REM Optionally remove application files
83 | set /p APPREMOVE="Do you want to remove RealFire application files from %APPLICATIONFOLDER%? (Y/N): "
84 | if /i "%APPREMOVE%"=="Y" (
85 | echo Removing application files from %APPLICATIONFOLDER%...
86 | del "%APPLICATIONFOLDER%\config.js"
87 | del "%APPLICATIONFOLDER%\mozilla.cfg"
88 | del "%APPLICATIONFOLDER%\defaults\pref\config-prefs.js"
89 | del "%APPLICATIONFOLDER%\defaults\pref\local-settings.js"
90 | )
91 |
92 | echo.
93 | echo Uninstallation complete!
94 |
95 | :end
96 | pause
97 | exit /B
98 |
99 | :header
100 | echo %__NAME% v%__VERSION%
101 | echo This uninstaller will remove RealFire theme
102 | echo and restore your Firefox profile to its
103 | echo previous state.
104 | echo.
105 | goto :eof
106 |
107 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
108 | :RequestAdminElevation FilePath %* || goto:eof
109 | ::
110 | :: By: Cyberponk, v1.5 - 10/06/2016 - Changed the admin rights test method from cacls to fltmc
111 | :: v1.4 - 17/05/2016 - Added instructions for arguments with ! char
112 | :: v1.3 - 01/08/2015 - Fixed not returning to original folder after elevation successful
113 | :: v1.2 - 30/07/2015 - Added error message when running from mapped drive
114 | :: v1.1 - 01/06/2015
115 | ::
116 | :: Func: opens an admin elevation prompt. If elevated, runs everything after the function call, with elevated rights.
117 | :: Returns: -1 if elevation was requested
118 | :: 0 if elevation was successful
119 | :: 1 if an error occured
120 | ::
121 | :: USAGE:
122 | :: If function is copied to a batch file:
123 | :: call :RequestAdminElevation "%~dpf0" %* || goto:eof
124 | ::
125 | :: If called as an external library (from a separate batch file):
126 | :: set "_DeleteOnExit=0" on Options
127 | :: (call :RequestAdminElevation "%~dpf0" %* || goto:eof) && CD /D %CD%
128 | ::
129 | :: If called from inside another CALL, you must set "_ThisFile=%~dpf0" at the beginning of the file
130 | :: call :RequestAdminElevation "%_ThisFile%" %* || goto:eof
131 | ::
132 | :: If you need to use the ! char in the arguments, the calling must be done like this, and afterwards you must use %args% to get the correct arguments:
133 | :: set "args=%* "
134 | :: call :RequestAdminElevation ..... use one of the above but replace the %* with %args:!={a)%
135 | :: set "args=%args:{a)=!%"
136 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
137 | setlocal ENABLEDELAYEDEXPANSION & set "_FilePath=%~1"
138 | if NOT EXIST "!_FilePath!" (echo/Read RequestAdminElevation usage information)
139 | :: UAC.ShellExecute only works with 8.3 filename, so use %~s1
140 | set "_FN=_%~ns1" & echo/%TEMP%| findstr /C:"(" >nul && (echo/ERROR: %%TEMP%% path can not contain parenthesis &pause &endlocal &fc;: 2>nul & goto:eof)
141 | :: Remove parenthesis from the temp filename
142 | set _FN=%_FN:(=%
143 | set _vbspath="%temp:~%\%_FN:)=%.vbs" & set "_batpath=%temp:~%\%_FN:)=%.bat"
144 |
145 | :: Test if we gave admin rights
146 | fltmc >nul 2>&1 || goto :_getElevation
147 |
148 | :: Elevation successful
149 | (if exist %_vbspath% ( del %_vbspath% )) & (if exist %_batpath% ( del %_batpath% ))
150 | :: Set ERRORLEVEL 0, set original folder and exit
151 | endlocal & CD /D "%~dp1" & ver >nul & goto:eof
152 |
153 | :_getElevation
154 | echo/Requesting elevation...
155 | :: Try to create %_vbspath% file. If failed, exit with ERRORLEVEL 1
156 | echo/Set UAC = CreateObject^("Shell.Application"^) > %_vbspath% || (echo/&echo/Unable to create %_vbspath% & endlocal &md; 2>nul &goto:eof)
157 | echo/UAC.ShellExecute "%_batpath%", "", "", "runas", 1 >> %_vbspath% & echo/wscript.Quit(1)>> %_vbspath%
158 | :: Try to create %_batpath% file. If failed, exit with ERRORLEVEL 1
159 | echo/@%* > "%_batpath%" || (echo/&echo/Unable to create %_batpath% & endlocal &md; 2>nul &goto:eof)
160 | echo/@if %%errorlevel%%==9009 (echo/^&echo/Admin user could not read the batch file. If running from a mapped drive or UNC path, check if Admin user can read it.)^&echo/^& @if %%errorlevel%% NEQ 0 pause >> "%_batpath%"
161 |
162 | :: Run %_vbspath%, that calls %_batpath%, that calls the original file
163 | %_vbspath% && (echo/&echo/Failed to run VBscript %_vbspath% &endlocal &md; 2>nul & goto:eof)
164 |
165 | :: Vbscript has been run, exit with ERRORLEVEL -1
166 | echo/&echo/Elevation was requested on a new CMD window &endlocal &fc;: 2>nul & goto:eof
167 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
168 |
--------------------------------------------------------------------------------
/programs/uninstall.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Set theme directory
4 | THEMEDIRECTORY=$(cd `dirname "$0"` && cd .. && pwd);
5 |
6 | # Default paths
7 | FIREFOXFOLDER=""
8 | APPLICATIONFOLDER=""
9 |
10 | # Determine operating system
11 | os_type=$(uname -s)
12 |
13 | # Set paths based on operating system
14 | if [ "$os_type" == "Darwin" ]; then
15 | FIREFOXFOLDER=~/Library/Application\ Support/Firefox
16 | APPLICATIONFOLDER='/Applications/Firefox.app/Contents/MacOS/Firefox'
17 | else
18 | FIREFOXFOLDER=/home/$USER/.mozilla/firefox
19 | APPLICATIONFOLDER='/usr/lib64/firefox'
20 | fi
21 |
22 | CHROMEFOLDER="chrome";
23 |
24 | # Get installation options
25 | while getopts 'b:f:p:eh' flag; do
26 | case "${flag}" in
27 | b) APPLICATIONFOLDER="${OPTARG}" ;;
28 | f) FIREFOXFOLDER="${OPTARG}" ;;
29 | p) PROFILENAME="${OPTARG}" ;;
30 | e) FXACEXTRAS=false ;;
31 | h)
32 | echo "RealFire! Uninstall script usage: ./uninstall.sh [ options ... ]"
33 | echo "where options include:"
34 | echo
35 | echo " -b (Set custom Firefox binary folder path)"
36 | echo " -f (Set custom Firefox folder path)"
37 | echo " -p (Set custom profile name)"
38 | echo " -e (Install fx-autoconfig - Runs sudo to copy mozilla.cfg and local-settings.js to Application Binary folder)"
39 | echo " -h (Show help message)"
40 | exit 0
41 | ;;
42 | esac
43 | done
44 |
45 | # Check if Firefox profiles.ini is installed or not
46 | PROFILES_FILE="${FIREFOXFOLDER}/profiles.ini"
47 | if [ ! -f "${PROFILES_FILE}" ]; then
48 | >&2 echo "Failed to locate profiles.ini in ${FIREFOXFOLDER}
49 | Exiting..."
50 | exit 1
51 | fi
52 |
53 | echo
54 | echo "Profiles file found..."
55 |
56 |
57 | # Define default Profile folder path else use -p option
58 | if [ -z "$PROFILENAME" ]; then
59 | PROFILEFOLDER="${FIREFOXFOLDER}/$(grep -zoP '\[Install.*?\]\nDefault=\K(.*?)\n' $PROFILES_FILE | tr -d '\0')"
60 | else
61 | PROFILEFOLDER="${FIREFOXFOLDER}/${PROFILENAME}"
62 | fi
63 |
64 |
65 | # Enter Firefox profile folder if it exists
66 | if [ ! -d "$PROFILEFOLDER" ]; then
67 | >&2 echo "Failed to locate Profile folder at ${PROFILEFOLDER}
68 | Exiting..."
69 | exit 1
70 | fi
71 |
72 | cd $PROFILEFOLDER
73 |
74 | # Confirm uninstallation
75 | read -p "This will remove RealFire! theme and associated configuration files. Are you sure? (y/n): " -n 1 -r
76 | echo
77 | if [[ $REPLY =~ ^[Yy]$ ]]; then
78 |
79 |
80 | # Remove RealFire! theme folder if it exists
81 | if [ -d "${CHROMEFOLDER}" ]; then
82 | rm -rf "${CHROMEFOLDER}"
83 | fi
84 |
85 | # Remove user.js symbolic link
86 | if [ -f "../user.js" ]; then
87 | rm "../user.js"
88 | fi
89 |
90 | # Restore backup of user.js if exists
91 | if [ -f "../user.js.bak" ]; then
92 | mv ../user.js.bak ../user.js || { exit 1; }
93 | fi
94 |
95 | echo "Removing mozilla.cfg, local-settings.js, config.js and config-pref.js from ${APPLICATIONFOLDER}"
96 |
97 | sudo rm -f "${APPLICATIONFOLDER}/mozilla.cfg"
98 | sudo rm -f "${APPLICATIONFOLDER}/config.js"
99 | sudo rm -f "${APPLICATIONFOLDER}/defaults/pref/config-prefs.js"
100 | sudo rm -f "${APPLICATIONFOLDER}/defaults/pref/local-settings.js"
101 |
102 | echo "RealFire! theme and associated configuration files have been removed."
103 | else
104 | echo "Uninstallation aborted."
105 | fi
106 |
--------------------------------------------------------------------------------
/programs/user.js:
--------------------------------------------------------------------------------
1 | user_pref("toolkit.legacyUserProfileCustomizations.stylesheets", true);
2 | user_pref("svg.context-properties.content.enabled", true);
3 | user_pref("browser.tabs.tabMinWidth", 76);
4 | user_pref("browser.compactmode.show", true);
5 | user_pref("browser.proton.enabled", false);
6 | user_pref("ui.popup.disable_autohide", false);
7 | user_pref("browser.startup.preXulSkeletonUI", false);
8 | // user_pref("browser.uidensity", 1);
9 | user_pref("userChrome.toolbarSlider.width", 2);
10 | user_pref("layout.css.has-selector.enabled", true);
11 | user_pref("userChromeJS.scriptsDisabled", "macosTheme.uc.js");
12 |
--------------------------------------------------------------------------------
/resources/material/actual-zoom.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/material/all-history.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/material/bookmark-manage.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/material/checked copy.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/resources/material/checked.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/material/close-hover.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/material/close-tab-option.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/resources/material/close.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/material/command-pick.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/material/desktop-bg.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/material/duplicate-tab.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/resources/material/experiments.svg:
--------------------------------------------------------------------------------
1 |
4 |
7 |
--------------------------------------------------------------------------------
/resources/material/ideas.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/material/inactive.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/material/maximize-hover.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/material/maximize-restore.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/material/maximize-svg.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/material/maximize.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/material/minimize-hover.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/material/minimize.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/material/move-container.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/resources/material/move-end.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/material/move-start.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/material/move-tab.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/resources/material/new-container.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/resources/material/open_new_tabs.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/material/page-source.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/material/pause.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/material/playButton.svg:
--------------------------------------------------------------------------------
1 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/resources/material/quit.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/material/radio-checked.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/material/radio-unchecked.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/material/redo.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/material/reload.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/resources/material/remote-debug.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/material/restore-session.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/material/select-all.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/material/send-tab.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/resources/material/share-tab.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/resources/material/signout.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/material/terminal.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/material/toolbox.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/material/translate.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/material/unchecked.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/resources/material/userScriptsMenu.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/material/web-page-source-code.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/material/zoom-in.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/material/zoom-out.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/userChrome.css:
--------------------------------------------------------------------------------
1 | @import 'includes/realfire-config.css';
2 | @import 'includes/realfire-colours.css';
3 |
4 | @import 'includes/realfire-layout.css';
5 | @import 'includes/realfire-responsive.css';
6 |
7 | @import "includes/realfire-findbar.css";
8 | @import "includes/realfire-icons.css";
9 | @import "includes/realfire-popups.css";
10 | @import "includes/realfire-checkbox.css";
11 |
12 | @import 'includes/realfire-nav-bar.css';
13 | @import 'includes/realfire-tabs.css';
14 | @import 'includes/realfire-side-bar.css';
15 | @import 'includes/realfire-library.css';
16 | @import 'includes/realfire-button.css';
17 | @import 'includes/realfire-inputs.css';
18 |
19 | notification-message.infobar {
20 | background:var(--uc-base-colour) !important;
21 | outline: 2px solid var(--accent-color) !important;
22 | border-radius: var(--uc-border-radius) !important;
23 | }
24 |
25 | notification-message.infobar::before {
26 | background-image: none !important;
27 | }
--------------------------------------------------------------------------------
/userContent.css:
--------------------------------------------------------------------------------
1 | @import 'includes/realfire-config.css';
2 | @import 'includes/realfire-colours.css';
3 | @import 'includes/realfire-settings-page.css';
4 | @import "includes/realfire-popups.css";
5 | @import "includes/realfire-checkbox.css";
6 | @import 'includes/realfire-library.css';
7 | @import 'includes/realfire-addons-page.css';
8 |
9 | @-moz-document url(about:home), url(about:newtab), url(about:privatebrowsing) {
10 |
11 | .search-wrapper:not(.search.disabled) .search-handoff-button {
12 | transition: all var(--uc-animation-duration) ease-out;
13 | }
14 |
15 | .search-wrapper.fake-focus:not(.search.disabled) .search-handoff-button {
16 | transition: all var(--uc-animation-duration) ease-in;
17 | }
18 |
19 | div.title span {
20 | background-color: var(--uc-base-colour);
21 | border-radius: var(--uc-border-radius);
22 | white-space: nowrap !important;
23 | padding: 2px 4px !important;
24 | min-height: auto !important;
25 | width: 9vh !important;
26 | }
27 |
28 | .top-site-outer {
29 | transition: all var(--uc-animation-duration) ease-out;
30 | }
31 |
32 | .top-site-outer .top-site-icon,
33 | .outer-wrapper .ds-top-sites .top-sites .top-site-outer .top-site-inner > a .tile {
34 | transition: all var(--uc-animation-duration) ease-out;
35 | background-color: var(--uc-base-colour) !important;
36 | }
37 |
38 | .top-sites-list:not(.dnd-active) .top-site-outer:is(.active, :focus, :hover),
39 | .outer-wrapper .ds-top-sites .top-sites .top-site-outer .top-site-inner > a:is(.active, :focus, :hover) {
40 | transition: all var(--uc-animation-duration) ease-in;
41 | outline: 2px solid var(--accent-color);
42 | }
43 |
44 | .top-sites-list:not(.dnd-active) .top-site-outer:is(.active, :focus, :hover) {
45 | transition: all var(--uc-animation-duration) ease-in;
46 | background: var(--uc-base-colour) !important;
47 | }
48 |
49 | .click-target-container *,
50 | .top-sites-list * {
51 | color: var(--uc-inverted-colour) !important;
52 | }
53 |
54 | body::before {
55 | content: "";
56 | z-index: -1;
57 | position: fixed;
58 | top: 0;
59 | left: 0;
60 | background: url(img/new_tab_wallpaper.jpg) center no-repeat;
61 | background-size: cover;
62 | width: 100vw;
63 | height: 100vh;
64 | }
65 |
66 | .neterror {
67 | background-color: var(--uc-base-colour) !important;
68 | }
69 |
70 | #neterrorTryAgainButton {
71 | background-color: var(--accent-color) !important;
72 | color: var(--uc-inverted-colour) !important;
73 | }
74 |
75 | #neterrorTryAgainButton:hover {
76 | background-color: var(--accent-hover-color) !important;
77 | }
78 |
79 | .home-section .section input:checked + .slider {
80 | background-color: var(--accent-color) !important;
81 | }
82 |
83 | .home-section .section .slider {
84 | background-color: var(--uc-inverted-colour) !important;
85 | }
86 | .weatherCard {
87 | background-color: var(--uc-base-colour) !important;
88 | border-radius: var(--uc-border-radius);
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/utils/boot.sys.mjs:
--------------------------------------------------------------------------------
1 | import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
2 | import { loaderModuleLink, Pref, FileSystem, windowUtils, showNotification, startupFinished, restartApplication, escapeXUL, toggleScript } from "chrome://userchromejs/content/utils.sys.mjs";
3 |
4 | const FX_AUTOCONFIG_VERSION = "0.10.4";
5 | console.warn( "Browser is executing custom scripts via autoconfig" );
6 |
7 | const APP_VARIANT = (() => {
8 | let is_tb = AppConstants.BROWSER_CHROME_URL.startsWith("chrome://messenger");
9 | return {
10 | THUNDERBIRD: is_tb,
11 | FIREFOX: !is_tb
12 | }
13 | })();
14 | const BRAND_NAME = AppConstants.MOZ_APP_DISPLAYNAME_DO_NOT_USE;
15 |
16 | const BROWSERCHROME = (() => {
17 | if(APP_VARIANT.FIREFOX){
18 | return AppConstants.BROWSER_CHROME_URL
19 | }
20 | return "chrome://messenger/content/messenger.xhtml"
21 | })();
22 |
23 | const PREF_ENABLED = 'userChromeJS.enabled';
24 | const PREF_SCRIPTSDISABLED = 'userChromeJS.scriptsDisabled';
25 |
26 | function getDisabledScripts(){
27 | return Services.prefs.getStringPref(PREF_SCRIPTSDISABLED,"").split(",")
28 | }
29 |
30 | class ScriptData {
31 | #preCompiledESM;
32 | #preCompileFailed;
33 | #preCompiling;
34 | #preLoadedStyle;
35 | #chromeURI;
36 | #isRunning = false;
37 | #injectionFailed = false;
38 | constructor(leafName, headerText, noExec, isStyle){
39 | const hasLongDescription = (/^\/\/\ @long-description/im).test(headerText);
40 | this.filename = leafName;
41 | this.name = headerText.match(/\/\/ @name\s+(.+)\s*$/im)?.[1];
42 | this.charset = headerText.match(/\/\/ @charset\s+(.+)\s*$/im)?.[1];
43 | this.description = hasLongDescription
44 | ? headerText.match(/\/\/ @description\s+.*?\/\*\s*(.+?)\s*\*\//is)?.[1]
45 | : headerText.match(/\/\/ @description\s+(.+)\s*$/im)?.[1];
46 | this.version = headerText.match(/\/\/ @version\s+(.+)\s*$/im)?.[1];
47 | this.author = headerText.match(/\/\/ @author\s+(.+)\s*$/im)?.[1];
48 | this.icon = headerText.match(/\/\/ @icon\s+(.+)\s*$/im)?.[1];
49 | this.homepageURL = headerText.match(/\/\/ @homepageURL\s+(.+)\s*$/im)?.[1];
50 | this.downloadURL = headerText.match(/\/\/ @downloadURL\s+(.+)\s*$/im)?.[1];
51 | this.updateURL = headerText.match(/\/\/ @updateURL\s+(.+)\s*$/im)?.[1];
52 | this.optionsURL = headerText.match(/\/\/ @optionsURL\s+(.+)\s*$/im)?.[1];
53 | this.id = headerText.match(/\/\/ @id\s+(.+)\s*$/im)?.[1]
54 | || `${leafName.split('.uc.js')[0]}@${this.author||'userChromeJS'}`;
55 | this.isESM = this.filename.endsWith(".mjs");
56 | this.onlyonce = /\/\/ @onlyonce\b/.test(headerText);
57 | this.inbackground = this.filename.endsWith(".sys.mjs") || /\/\/ @backgroundmodule\b/.test(headerText);
58 | this.ignoreCache = /\/\/ @ignorecache\b/.test(headerText);
59 | this.manifest = headerText.match(/\/\/ @manifest\s+(.+)\s*$/im)?.[1];
60 | this.type = isStyle ? "style" : "script";
61 | this.styleSheetMode = isStyle
62 | ? headerText.match(/\/\/ @stylemode\s+(.+)\s*$/im)?.[1] === "agent_sheet"
63 | ? "agent" : "author"
64 | : null;
65 | this.useFileURI = /\/\/ @usefileuri\b/.test(headerText);
66 | this.noExec = isStyle || noExec;
67 |
68 | if(this.inbackground || this.styleSheetMode === "agent" || (!isStyle && noExec)){
69 | this.regex = null;
70 | this.loadOrder = -1;
71 | }else{
72 | // Construct regular expression to use to match target document
73 | let match, rex = {
74 | include: [],
75 | exclude: []
76 | };
77 | let findNextRe = /^\/\/ @(include|exclude)\s+(.+)\s*$/gm;
78 | while (match = findNextRe.exec(headerText)) {
79 | rex[match[1]].push(
80 | match[2].replace(/^main$/i, BROWSERCHROME).replace(/\*/g, '.*?')
81 | );
82 | }
83 | if (!rex.include.length) {
84 | rex.include.push(BROWSERCHROME);
85 | }
86 | let exclude = rex.exclude.length ? `(?!${rex.exclude.join('$|')}$)` : '';
87 | this.regex = new RegExp(`^${exclude}(${rex.include.join('|') || '.*'})$`,'i');
88 | let loadOrder = headerText.match(/\/\/ @loadOrder\s+(\d+)\s*$/im)?.[1];
89 | this.loadOrder = Number.parseInt(loadOrder) || 10;
90 | }
91 |
92 | Object.freeze(this);
93 | }
94 | get isEnabled() {
95 | return getDisabledScripts().indexOf(this.filename) === -1;
96 | }
97 | get injectionFailed(){
98 | return this.#injectionFailed
99 | }
100 | get isRunning(){
101 | return this.#isRunning
102 | }
103 | get chromeURI(){
104 | if(!this.#chromeURI){
105 | this.#chromeURI = this.type === "style"
106 | ? Services.io.newURI(`chrome://userstyles/skin/${this.filename}`)
107 | : Services.io.newURI(`chrome://userscripts/content/${this.filename}`)
108 | }
109 | return this.#chromeURI
110 | }
111 | get referenceURI(){
112 | return this.useFileURI && this.type === "style"
113 | ? FileSystem.convertChromeURIToFileURI(this.chromeURI)
114 | : this.chromeURI
115 | }
116 | get preLoadedStyle(){
117 | return this.#preLoadedStyle
118 | }
119 | static preCompileMJS(aScript){
120 | if(aScript.#preCompiledESM){
121 | return Promise.resolve(aScript.#preCompiledESM)
122 | }
123 | if(aScript.#preCompileFailed){
124 | return Promise.resolve(null);
125 | }
126 | if(aScript.#preCompiling){
127 | return aScript.#preCompiling
128 | }
129 | aScript.#preCompiling = new Promise(resolve => {
130 | ChromeUtils.compileScript(
131 | `data:,"use strict";
132 | import("${aScript.chromeURI.spec}")
133 | .catch(e=>{ throw new Error(e.message,"${aScript.filename}",e.lineNumber) })`
134 | )
135 | .then( script => {
136 | aScript.#preCompiledESM = script;
137 | resolve(script);
138 | })
139 | .catch( (ex) => resolve(ScriptData.onCompileRejection(ex,aScript)) )
140 | .finally(()=>{aScript.#preCompiling = null})
141 | });
142 | return aScript.#preCompiling
143 | }
144 | static onCompileRejection(ex,script){
145 | script.#preCompileFailed = true;
146 | console.error(`@ ${script.filename}: script couldn't be compiled because:`,ex);
147 | return null
148 | }
149 | static preLoadAuthorStyle(aStyle){
150 | if(aStyle.#injectionFailed){
151 | console.warn(`ignoring style preload for ${aStyle.filename} because it has already failed`);
152 | return false
153 | }
154 | let sss = Cc['@mozilla.org/content/style-sheet-service;1'].getService(Ci.nsIStyleSheetService);
155 | try{
156 | // Try to preload the file and store it
157 | aStyle.#preLoadedStyle = sss.preloadSheet(aStyle.referenceURI, sss.AUTHOR_SHEET);
158 | }catch(e){
159 | console.error(`Could not pre-load ${aStyle.filename}: ${e.name}`)
160 | return false
161 | }
162 | aStyle.#isRunning = true;
163 | return true
164 | }
165 |
166 | static tryLoadScriptIntoWindow(aScript,win){
167 | if(aScript.regex === null || !aScript.regex.test(win.location.href)){
168 | return
169 | }
170 | if(aScript.type === "style" && aScript.styleSheetMode === "author"){
171 | if(!aScript.#preLoadedStyle){
172 | let success = ScriptData.preLoadAuthorStyle(aScript);
173 | if(!success){
174 | return
175 | }
176 | }
177 | win.windowUtils.addSheet(aScript.#preLoadedStyle,Ci.nsIDOMWindowUtils.AUTHOR_SHEET);
178 | return
179 | }
180 | if (aScript.inbackground || aScript.noExec) {
181 | return
182 | }
183 | if(aScript.onlyonce && aScript.#isRunning) {
184 | return
185 | }
186 |
187 | const injection = aScript.isESM
188 | ? ScriptData.injectESMIntoGlobal(aScript,win)
189 | : ScriptData.injectClassicScriptIntoGlobal(aScript,win);
190 | injection
191 | .catch(ex => {
192 | console.error(new Error(`@ ${aScript.filename}:${ex.lineNumber}`,{cause:ex}));
193 | })
194 | }
195 | static markScriptRunning(aScript){
196 | aScript.#isRunning = true;
197 | }
198 | static injectESMIntoGlobal(aScript,aGlobal){
199 | return new Promise((resolve,reject) => {
200 | ScriptData.preCompileMJS(aScript)
201 | .then(script => {
202 | if(script){
203 | script.executeInGlobal(aGlobal);
204 | aScript.#isRunning = true;
205 | }
206 | })
207 | .then(resolve)
208 | .catch( ex => {
209 | aScript.#injectionFailed = true;
210 | reject(ex)
211 | })
212 | })
213 | }
214 | static injectClassicScriptIntoGlobal(aScript,aGlobal){
215 | try{
216 | Services.scriptloader.loadSubScriptWithOptions(
217 | aScript.chromeURI.spec,
218 | {
219 | target: aGlobal,
220 | ignoreCache: aScript.ignoreCache
221 | }
222 | )
223 | aScript.#isRunning = true;
224 | return Promise.resolve(1)
225 | }catch(ex){
226 | aScript.#injectionFailed = true;
227 | return Promise.reject(ex)
228 | }
229 | }
230 | static registerScriptManifest(aScript){
231 | if(aScript.#isRunning){
232 | return
233 | }
234 | let cmanifest = FileSystem.getEntry(FileSystem.convertChromeURIToFileURI(`chrome://userscripts/content/${aScript.manifest}.manifest`));
235 | if(cmanifest.isFile()){
236 | Components.manager
237 | .QueryInterface(Ci.nsIComponentRegistrar).autoRegister(cmanifest.entry());
238 | }else{
239 | console.warn(`Script '${aScript.filename}' tried to register a manifest but requested file '${aScript.manifest}' doesn't exist`);
240 | }
241 | }
242 | static extractScriptHeader(aFSResult){
243 | return aFSResult.content()
244 | .match(/^\/\/ ==UserScript==\s*[\n\r]+(?:.*[\n\r]+)*?\/\/ ==\/UserScript==\s*/m)?.[0] || ""
245 | }
246 | static extractStyleHeader(aFSResult){
247 | return aFSResult.content()
248 | .match(/^\/\* ==UserScript==\s*[\n\r]+(?:.*[\n\r]+)*?\/\/ ==\/UserScript==\s*\*\//m)?.[0] || ""
249 | }
250 | static fromScriptFile(aFile){
251 | if(aFile.fileSize < 24){
252 | // Smaller files can't possibly have a valid header
253 | // This also means that we successfully generate a ScriptData for *folders* named "xx.uc.js"...
254 | return new ScriptData(aFile.leafName,"",aFile.fileSize === 0,false)
255 | }
256 | const result = FileSystem.readNSIFileSyncUncheckedWithOptions(aFile,{ metaOnly: true });
257 | const headerText = this.extractScriptHeader(result);
258 | // If there are less than 2 bytes after the header then we mark the script as non-executable. This means that if the file only has a header then we don't try to inject it to any windows, since it wouldn't do anything.
259 | return new ScriptData(aFile.leafName, headerText, headerText.length > aFile.fileSize - 2,false);
260 | }
261 | static fromStyleFile(aFile){
262 | if(aFile.fileSize < 24){
263 | // Smaller files can't possibly have a valid header
264 | return new ScriptData(aFile.leafName,"",true,true)
265 | }
266 | const result = FileSystem.readNSIFileSyncUncheckedWithOptions(aFile,{ metaOnly: true });
267 | return new ScriptData(aFile.leafName, this.extractStyleHeader(result), true,true);
268 | }
269 | }
270 |
271 | Pref.setIfUnset(PREF_ENABLED,true);
272 | Pref.setIfUnset(PREF_SCRIPTSDISABLED,"");
273 |
274 | // This is called if _previous_ startup was broken
275 | function showgBrowserNotification(){
276 | Services.prefs.setBoolPref('userChromeJS.gBrowser_hack.enabled',true);
277 | showNotification(
278 | {
279 | label : "fx-autoconfig: Something was broken in last startup",
280 | type : "fx-autoconfig-gbrowser-notification",
281 | priority: "critical",
282 | buttons: [{
283 | label: "Why am I seeing this?",
284 | callback: (notification) => {
285 | notification.ownerGlobal.openWebLinkIn(
286 | "https://github.com/MrOtherGuy/fx-autoconfig#startup-error",
287 | "tab"
288 | );
289 | return false
290 | }
291 | }]
292 | }
293 | )
294 | }
295 |
296 | // This is called if startup somehow takes over 5 seconds
297 | function maybeShowBrokenNotification(window){
298 | if(window.isFullyOccluded && "gBrowser" in window){
299 | console.log("Window was fully occluded, no need to panic")
300 | return
301 | }
302 | let aNotificationBox = window.gNotificationBox;
303 | aNotificationBox.appendNotification(
304 | "fx-autoconfig-broken-notification",
305 | {
306 | label: "fx-autoconfig: Startup might be broken",
307 | image: "chrome://browser/skin/notification-icons/popup.svg",
308 | priority: "critical"
309 | }
310 | );
311 | }
312 |
313 |
314 |
315 | function updateMenuStatus(event){
316 | const menu = event.target;
317 | if(!menu.id === "menuUserScriptsPopup"){
318 | return
319 | }
320 | let disabledScripts = getDisabledScripts();
321 | for(let item of menu.children){
322 | if(item.getAttribute("type") != "checkbox"){
323 | continue
324 | }
325 | if (disabledScripts.includes(item.dataset.filename)){
326 | item.removeAttribute("checked");
327 | }else{
328 | item.setAttribute("checked","true");
329 | }
330 | }
331 | }
332 |
333 | class UserChrome_js{
334 | constructor(){
335 | this.scripts = [];
336 | this.styles = [];
337 | this.SESSION_RESTORED = false;
338 | this.IS_ENABLED = Services.prefs.getBoolPref(PREF_ENABLED,false);
339 | this.isInitialWindow = true;
340 | this.initialized = false;
341 | this.init();
342 | }
343 | registerScript(aScript,isDisabled){
344 | if(aScript.type === "script"){
345 | this.scripts.push(aScript);
346 | }else{
347 | this.styles.push(aScript);
348 | }
349 | if(!isDisabled && aScript.manifest){
350 | try{
351 | ScriptData.registerScriptManifest(aScript);
352 | }catch(ex){
353 | console.error(new Error(`@ ${aScript.filename}`,{cause:ex}));
354 | }
355 | }
356 | return isDisabled
357 | }
358 | init(){
359 | if(this.initialized){
360 | return
361 | }
362 | loaderModuleLink.setup(this,FX_AUTOCONFIG_VERSION,AppConstants.MOZ_APP_DISPLAYNAME_DO_NOT_USE,APP_VARIANT,ScriptData);
363 |
364 | if(!this.IS_ENABLED){
365 | Services.obs.addObserver(this, 'domwindowopened', false);
366 | this.initialized = true;
367 | return
368 | }
369 | // gBrowserHack setup
370 | this.GBROWSERHACK_ENABLED =
371 | (Services.prefs.getBoolPref("userChromeJS.gBrowser_hack.required",false) ? 2 : 0)
372 | + (Services.prefs.getBoolPref("userChromeJS.gBrowser_hack.enabled",false) ? 1 : 0);
373 | this.PERSISTENT_DOMCONTENT_CALLBACK = Services.prefs.getBoolPref("userChromeJS.persistent_domcontent_callback",false);
374 | const disabledScripts = getDisabledScripts();
375 | // load script data
376 | const scriptDir = FileSystem.getScriptDir();
377 | if(scriptDir.isDirectory()){
378 | for(let entry of scriptDir){
379 | if (/^[A-Za-z0-9]+.*(\.uc\.js|\.uc\.mjs|\.sys\.mjs)$/i.test(entry.leafName)) {
380 | let script = ScriptData.fromScriptFile(entry);
381 | if(this.registerScript(script,disabledScripts.includes(script.filename))){
382 | continue // script is disabled
383 | }
384 | if(script.inbackground){
385 | try{
386 | if(script.isESM){
387 | ChromeUtils.importESModule( script.chromeURI.spec );
388 | ScriptData.markScriptRunning(script);
389 | }else{
390 | console.warn(`Refusing to import legacy jsm style backgroundmodule script: ${script.filename} - convert to ES6 modules instead`);
391 | }
392 | }catch(ex){
393 | console.error(new Error(`@ ${script.filename}:${ex.lineNumber}`,{cause:ex}));
394 | }
395 | }
396 | if(script.isESM && !script.inbackground){
397 | ScriptData.preCompileMJS(script);
398 | }
399 | }
400 | }
401 | }
402 | const styleDir = FileSystem.getStyleDir();
403 | if(styleDir.isDirectory()){
404 | for(let entry of styleDir){
405 | if (/^[A-Za-z0-9]+.*\.uc\.css$/i.test(entry.leafName)) {
406 | let style = ScriptData.fromStyleFile(entry);
407 | this.registerScript(style,!disabledScripts.includes(style.filename));
408 | }
409 | }
410 | this.addAgentStyles(this.styles.filter(style => style.styleSheetMode === "agent" && !disabledScripts.includes(style.filename)));
411 | }
412 | this.scripts.sort((a,b) => a.loadOrder - b.loadOrder);
413 | this.styles.sort((a,b) => a.loadOrder - b.loadOrder);
414 | Services.obs.addObserver(this, 'domwindowopened', false);
415 | this.initialized = true;
416 |
417 | }
418 | addAgentStyles(agentStyles){
419 | if(agentStyles.length > 0){
420 | let sss = Cc['@mozilla.org/content/style-sheet-service;1'].getService(Ci.nsIStyleSheetService);
421 | for(let style of agentStyles){
422 | try{
423 | sss.loadAndRegisterSheet(style.referenceURI, sss.AGENT_SHEET);
424 | ScriptData.markScriptRunning(style);
425 | }catch(e){
426 | console.error(`Could not load ${style.filename}: ${e.name}`);
427 | }
428 | }
429 | }
430 | }
431 | onDOMContent(document){
432 | const window = document.defaultView;
433 | if(!(/^chrome:(?!\/\/global\/content\/(commonDialog|alerts\/alert)\.xhtml)|about:(?!blank)/i).test(window.location.href)){
434 | // Don't inject scripts to modal prompt windows or notifications
435 | if(this.IS_ENABLED && this.styles.length > 0){
436 | const disabledScripts = getDisabledScripts();
437 | for(let style of this.styles){
438 | if(!disabledScripts.includes(style.filename)){
439 | ScriptData.tryLoadScriptIntoWindow(style,window)
440 | }
441 | }
442 | }
443 | return
444 | }
445 | ChromeUtils.defineLazyGetter(window,"UC_API",() =>
446 | ChromeUtils.importESModule("chrome://userchromejs/content/uc_api.sys.mjs")
447 | )
448 | if(this.IS_ENABLED){
449 | document.allowUnsafeHTML = false; // https://bugzilla.mozilla.org/show_bug.cgi?id=1432966
450 |
451 | // This is a hack to make gBrowser available for scripts.
452 | // Without it, scripts would need to check if gBrowser exists and deal
453 | // with it somehow. See bug 1443849
454 | const _gb = APP_VARIANT.FIREFOX && "_gBrowser" in window;
455 | if(this.GBROWSERHACK_ENABLED && _gb){
456 | window.gBrowser = window._gBrowser;
457 | }else if(_gb && this.isInitialWindow){
458 | this.isInitialWindow = false;
459 | let timeout = window.setTimeout(() => {
460 | maybeShowBrokenNotification(window);
461 | },5000);
462 | windowUtils.waitWindowLoading(window)
463 | .then(() => {
464 | // startup is fine, clear timeout
465 | window.clearTimeout(timeout);
466 | })
467 | }
468 | // Inject scripts to window
469 | const disabledScripts = getDisabledScripts();
470 | for(let script of this.scripts){
471 | if(script.inbackground || script.injectionFailed){
472 | continue
473 | }
474 | if(!disabledScripts.includes(script.filename)){
475 | ScriptData.tryLoadScriptIntoWindow(script,window)
476 | }
477 | }
478 | for(let style of this.styles){
479 | if(!disabledScripts.includes(style.filename)){
480 | ScriptData.tryLoadScriptIntoWindow(style,window)
481 | }
482 | }
483 | }
484 | if(window.isChromeWindow){
485 | const menu = document.querySelector(
486 | APP_VARIANT.FIREFOX ? "#menu_openDownloads" : "menuitem#addressBook");
487 | if(menu){
488 | menu.parentNode.addEventListener("popupshown",
489 | (ev) => this.generateScriptMenuItemsIfNeeded(ev.target.ownerDocument),
490 | {once: true}
491 | );
492 | }
493 | }
494 | }
495 |
496 | // Add simple script menu to menubar tools popup
497 | generateScriptMenuItemsIfNeeded(aDoc){
498 | {
499 | let menu = aDoc.getElementById("userScriptsMenu");
500 | if(menu){
501 | return menu
502 | }
503 | }
504 | const popup = aDoc.querySelector(
505 | APP_VARIANT.FIREFOX ? "#menu_openDownloads" : "menuitem#addressBook")?.parentNode;
506 |
507 | if(aDoc.location.href !== BROWSERCHROME || !popup){
508 | return null
509 | }
510 | const window = aDoc.ownerGlobal;
511 |
512 | window.MozXULElement.insertFTLIfNeeded("toolkit/about/aboutSupport.ftl");
513 | let menuFragment = window.MozXULElement.parseXULToFragment(`
514 |
522 | `);
523 | const itemsFragment = window.MozXULElement.parseXULToFragment("");
524 | for(let script of this.scripts){
525 | UserChrome_js.appendScriptMenuitemToFragment(window,itemsFragment,script);
526 | }
527 | if(this.styles.length){
528 | itemsFragment.append(aDoc.createXULElement("menuseparator"));
529 | for(let style of this.styles){
530 | UserChrome_js.appendScriptMenuitemToFragment(window,itemsFragment,style);
531 | }
532 | }
533 | if(!this.IS_ENABLED){
534 | itemsFragment.append(window.MozXULElement.parseXULToFragment(''));
535 | }
536 | let menupopup = menuFragment.getElementById("menuUserScriptsPopup");
537 | menupopup.prepend(itemsFragment);
538 | popup.prepend(menuFragment);
539 | menupopup.addEventListener("popupshown",updateMenuStatus);
540 | menupopup.addEventListener("command",ev => {
541 | switch(ev.target.id){
542 | case "userScriptsMenu-OpenFolder":
543 | FileSystem.getScriptDir().showInFileManager();
544 | break;
545 | case "userScriptsMenu-Restart":
546 | restartApplication(false);
547 | break;
548 | case "userScriptsMenu-ClearCache":
549 | restartApplication(true);
550 | break;
551 | default:
552 | if(ev.target.dataset.filename){
553 | toggleScript(ev.target.dataset.filename);
554 | }
555 | }
556 | });
557 | aDoc.l10n.formatValues(["restart-button-label","clear-startup-cache-label","show-dir-label"])
558 | .then(values => {
559 | let baseTitle = `${values[0]} ${BRAND_NAME}`;
560 | aDoc.getElementById("userScriptsMenu-Restart").setAttribute("label", baseTitle);
561 | aDoc.getElementById("userScriptsMenu-ClearCache").setAttribute("label", values[1].replace("…","") + " & " + baseTitle);
562 | aDoc.getElementById("userScriptsMenu-OpenFolder").setAttribute("label",values[2])
563 | });
564 | return popup.querySelector("#userScriptsMenu");
565 | }
566 | static appendScriptMenuitemToFragment(aWindow,aFragment,aScript){
567 | aFragment.append(
568 | aWindow.MozXULElement.parseXULToFragment(`
569 |
574 | `)
575 | );
576 | return
577 | }
578 | observe(aSubject, aTopic, aData) {
579 | aSubject.addEventListener('DOMContentLoaded', this, {once: !this.PERSISTENT_DOMCONTENT_CALLBACK, capture: true});
580 | }
581 |
582 | handleEvent(aEvent){
583 | switch (aEvent.type){
584 | case "DOMContentLoaded":
585 | this.onDOMContent(aEvent.originalTarget);
586 | break;
587 | default:
588 | console.warn(new Error("unexpected event received",{cause:aEvent}));
589 | }
590 | }
591 |
592 | }
593 |
594 | const _ucjs = !Services.appinfo.inSafeMode && new UserChrome_js();
595 | _ucjs && startupFinished().then(() => {
596 | _ucjs.SESSION_RESTORED = true;
597 | _ucjs.GBROWSERHACK_ENABLED === 2 && showgBrowserNotification();
598 | if(Pref.setIfUnset("userChromeJS.firstRunShown",true)){
599 | showNotification({
600 | type: "fx-autoconfig-installed",
601 | label: `fx-autoconfig: ${BRAND_NAME} is being modified with custom autoconfig scripting`
602 | });
603 | }
604 | });
605 |
--------------------------------------------------------------------------------
/utils/chrome.manifest:
--------------------------------------------------------------------------------
1 | content userchromejs ./
2 | content userscripts ../JS/
3 | skin userstyles classic/1.0 ../CSS/
4 | content userchrome ../resources/
5 |
--------------------------------------------------------------------------------
/utils/fs.sys.mjs:
--------------------------------------------------------------------------------
1 | export class FileSystem{
2 | static RESULT_CONTENT = Symbol("Content");
3 | static RESULT_DIRECTORY = Symbol("Directory");
4 | static RESULT_ERROR = Symbol("Error");
5 | static RESULT_FILE = Symbol("File");
6 |
7 | static getFileURIForFile(aEntry, type){
8 | let qi = Services.io.getProtocolHandler('file').QueryInterface(Ci.nsIFileProtocolHandler);
9 | if(type === FileSystem.RESULT_DIRECTORY){
10 | return qi.getURLSpecFromDir(aEntry)
11 | }
12 | if(type === FileSystem.RESULT_FILE){
13 | return qi.getURLSpecFromActualFile(aEntry)
14 | }
15 | throw ResultError.fromKind(FileSystem.ERROR_KIND_INVALID_ARGUMENT,{expected: "FileSystem.RESULT_FILE | FileSystem.RESULT_DIRECTORY"})
16 | }
17 |
18 | static convertChromeURIToFileURI(aURI){
19 | const registry = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIChromeRegistry);
20 | return registry.convertChromeURL(
21 | aURI instanceof Ci.nsIURI
22 | ? aURI
23 | : Services.io.newURI(aURI)
24 | );
25 | }
26 | // Call to .parent is needed because chrome urls get implicit "filename" based on the provider
27 | static #SCRIPT_URI;
28 | static #STYLE_URI;
29 | static #RESOURCE_URI;
30 | static{
31 | this.#RESOURCE_URI = FileSystem.getFileURIForFile(
32 | FileSystem.convertChromeURIToFileURI('chrome://userchrome/content/')
33 | .QueryInterface(Ci.nsIFileURL).file.parent,
34 | FileSystem.RESULT_DIRECTORY
35 | );
36 | this.#SCRIPT_URI = FileSystem.getFileURIForFile(
37 | FileSystem.convertChromeURIToFileURI('chrome://userscripts/content/')
38 | .QueryInterface(Ci.nsIFileURL).file.parent,
39 | FileSystem.RESULT_DIRECTORY
40 | );
41 | this.#STYLE_URI = FileSystem.getFileURIForFile(
42 | FileSystem.convertChromeURIToFileURI('chrome://userstyles/skin/')
43 | .QueryInterface(Ci.nsIFileURL).file.parent,
44 | FileSystem.RESULT_DIRECTORY
45 | );
46 | }
47 |
48 | static get SCRIPT_URI(){
49 | return Services.io.newURI(FileSystem.#SCRIPT_URI)
50 | }
51 |
52 | static get STYLE_URI(){
53 | return Services.io.newURI(FileSystem.#STYLE_URI)
54 | }
55 |
56 | static get RESOURCE_URI(){
57 | return Services.io.newURI(FileSystem.#RESOURCE_URI)
58 | }
59 |
60 | static getResourceDir(){
61 | return FileSystemResult.fromNsIFile(FileSystem.RESOURCE_URI.QueryInterface(Ci.nsIFileURL).file)
62 | }
63 |
64 | static getScriptDir(){
65 | return FileSystemResult.fromNsIFile(FileSystem.SCRIPT_URI.QueryInterface(Ci.nsIFileURL).file)
66 | }
67 |
68 | static getStyleDir(){
69 | return FileSystemResult.fromNsIFile(FileSystem.STYLE_URI.QueryInterface(Ci.nsIFileURL).file)
70 | }
71 |
72 | static #getEntryFromString(aFilename, baseFileURI){
73 | let baseDirectory = baseFileURI.QueryInterface(Ci.nsIFileURL).file;
74 | if(typeof aFilename !== "string"){
75 | return FileSystemResult.fromErrorKind(FileSystem.ERROR_KIND_INVALID_ARGUMENT,{expected:"String"});
76 | }
77 | const parts = aFilename.replace("\\","/").split("/").filter(a => a.length > 0);
78 | while(parts[0] === ".."){
79 | baseDirectory = baseDirectory.parent;
80 | parts.shift();
81 | }
82 | try{
83 | for(let part of parts){
84 | baseDirectory.append(part)
85 | }
86 | }catch(ex){
87 | return FileSystemResult.fromErrorKind(FileSystem.ERROR_KIND_INVALID_ARGUMENT,{type:"Invalid path"})
88 | }
89 | return FileSystemResult.fromNsIFile(baseDirectory)
90 | }
91 |
92 | static getEntry(aFilename, options = {}){
93 | if(aFilename instanceof Ci.nsIURI){
94 | if(aFilename.scheme === "chrome"){
95 | return FileSystemResult.fromNsIFile(FileSystem.convertChromeURIToFileURI(aFilename).QueryInterface(Ci.nsIFileURL).file)
96 | }
97 | if(aFilename.scheme === "file"){
98 | return FileSystemResult.fromNsIFile(aFilename.QueryInterface(Ci.nsIFileURL).file)
99 | }
100 | throw new Error("unsupported nsIURI conversion")
101 | }
102 | return FileSystem.#getEntryFromString(aFilename, options.baseDirectory || FileSystem.RESOURCE_URI)
103 | }
104 | static readNSIFileSyncUncheckedWithOptions(aFile,options){
105 | let stream = Cc['@mozilla.org/network/file-input-stream;1'].createInstance(Ci.nsIFileInputStream);
106 | let cvstream = Cc['@mozilla.org/intl/converter-input-stream;1'].createInstance(Ci.nsIConverterInputStream);
107 | try{
108 | stream.init(aFile, 0x01, 0, 0);
109 | cvstream.init(stream, 'UTF-8', 1024, Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
110 | }catch(e){
111 | console.error(e);
112 | cvstream.close();
113 | stream.close();
114 | return FileSystemResult.fromErrorKind(FileSystem.ERROR_KIND_NOT_READABLE,{cause: e, filename: aFile.leafName})
115 | }
116 | let rv = {content:'',path: FileSystem.getFileURIForFile(aFile,FileSystem.RESULT_FILE)};
117 | let data = {};
118 | const metaOnly = !!options.metaOnly;
119 | while (cvstream.readString(4096, data)) {
120 | rv.content += data.value;
121 | if (metaOnly && rv.content.indexOf('// ==/UserScript==') > 0) {
122 | break;
123 | }
124 | }
125 | cvstream.close();
126 | stream.close();
127 |
128 | return FileSystemResult.fromContent(rv)
129 | }
130 | static readFileSync(aFile, options = {}) {
131 | if(typeof aFile === "string"){
132 | const fsResult = FileSystem.#getEntryFromString(aFile, FileSystem.RESOURCE_URI);
133 | if(fsResult.isFile()){
134 | return FileSystem.readNSIFileSyncUncheckedWithOptions(fsResult.entry(),options);
135 | }
136 | return fsResult.isError()
137 | ? fsResult
138 | : FileSystemResult.fromErrorKind(FileSystem.ERROR_KIND_NOT_FILE,{topic: aFile})
139 | }
140 | if(aFile instanceof Ci.nsIFile){
141 | return FileSystem.readNSIFileSyncUncheckedWithOptions(aFile,options);
142 | }
143 | throw ResultError.fromKind(FileSystem.ERROR_KIND_INVALID_ARGUMENT,{expected: "string | Ci.nsIFile"})
144 | }
145 | static async readFile(aPath){
146 | if(typeof aPath !== "string"){
147 | throw ResultError.fromKind(FileSystem.ERROR_KIND_INVALID_ARGUMENT,{expected: "string"})
148 | }
149 | try{
150 | let path = FileSystem.#appendToBaseURI(aPath);
151 | return FileSystemResult.fromContent({ content: await IOUtils.readUTF8(path), path: PathUtils.toFileURI(path) })
152 | }catch(ex){
153 | return FileSystemResult.fromErrorKind(FileSystem.ERROR_KIND_NOT_READABLE,{cause: ex})
154 | }
155 | }
156 | static async readJSON(path){
157 | try{
158 | let result = await FileSystem.readFile(path);
159 | return result.isError()
160 | ? null
161 | : JSON.parse(result.content())
162 | }catch(ex){
163 | console.error(ex)
164 | }
165 | return null
166 | }
167 | static #appendToBaseURI(aPath,aFileURI){
168 | // Normally, this API can only write into resources directory
169 | // Writing outside of resources can be enabled using following pref
170 | const disallowUnsafeWrites = !Services.prefs.getBoolPref("userChromeJS.allowUnsafeWrites",false);
171 |
172 | const baseURI = aFileURI || FileSystem.RESOURCE_URI;
173 | let baseParts = PathUtils.split(baseURI.QueryInterface(Ci.nsIFileURL).file.path);
174 | let pathParts = aPath.split(/[\\\/]/);
175 | while(pathParts[0] === ".."){
176 | baseParts.pop();
177 | pathParts.shift();
178 | if(disallowUnsafeWrites){
179 | throw ResultError.fromKind(FileSystem.ERROR_KIND_NOT_ALLOWED)
180 | }
181 | }
182 | return PathUtils.join(...baseParts.concat(pathParts))
183 | }
184 | static async writeFile(path, content, options = {}){
185 | if(!path || typeof path !== "string"){
186 | throw ResultError.fromKind(FileSystem.ERROR_KIND_INVALID_ARGUMENT,{expected: "string"})
187 | }
188 | if(typeof content !== "string"){
189 | throw ResultError.fromKind(FileSystem.ERROR_KIND_INVALID_ARGUMENT,{expected: "string"})
190 | }
191 | const fileName = FileSystem.#appendToBaseURI(path);
192 | if(!options.tmpPath){
193 | options.tmpPath = fileName + ".tmp";
194 | }
195 | return IOUtils.writeUTF8( fileName, content, options );
196 | }
197 | static createFileURI(fileName){
198 | if(!fileName){
199 | return FileSystem.#RESOURCE_URI
200 | }
201 | return FileSystem.convertChromeURIToFileURI(`chrome://userchrome/content/${fileName}`).spec
202 | }
203 | static chromeDir(){
204 | return FileSystemResult.fromDirectory(Services.dirsvc.get('UChrm',Ci.nsIFile))
205 | }
206 | static StringContent(obj){
207 | return FileSystemResult.fromContent(obj)
208 | }
209 | static ERROR_KIND_NOT_EXIST = 1;
210 | static ERROR_KIND_NOT_DIRECTORY = 2;
211 | static ERROR_KIND_NOT_FILE = 3;
212 | static ERROR_KIND_NOT_CONTENT = 4;
213 | static ERROR_KIND_UNKNOWN_RESULT = 5;
214 | static ERROR_KIND_INVALID_ARGUMENT = 6;
215 | static ERROR_KIND_NOT_READABLE = 7;
216 | static ERROR_KIND_NOT_ALLOWED = 8;
217 | }
218 |
219 | class ResultError extends Error{
220 |
221 | constructor(kind,options,info = {}){
222 | super(ResultError.toMessage(kind,info),options);
223 | this.kind = kind;
224 | this.name = "ResultError";
225 | }
226 | static toMessage(kind,info){
227 | const strInfo = ResultError.parseInfo(info);
228 | switch(kind){
229 | case FileSystem.ERROR_KIND_NOT_EXIST:
230 | return `Entry doesn't exist: ${strInfo}`
231 | case FileSystem.ERROR_KIND_NOT_DIRECTORY:
232 | return `Result is not a directory: ${strInfo}`
233 | case FileSystem.ERROR_KIND_NOT_FILE:
234 | return `Result is not a file: ${strInfo}`
235 | case FileSystem.ERROR_KIND_NOT_CONTENT:
236 | return `Result is not content: ${strInfo}`
237 | case FileSystem.ERROR_KIND_UNKNOWN_RESULT:
238 | return `Unknown result type: ${strInfo}`
239 | case FileSystem.ERROR_KIND_INVALID_ARGUMENT:
240 | return `Invalid argument: ${strInfo}`
241 | case FileSystem.ERROR_KIND_NOT_READABLE:
242 | return `File stream is not readable: ${strInfo}`
243 | case FileSystem.ERROR_KIND_NOT_ALLOWED:
244 | return "Writing outside of resources directory is not allowed"
245 | default:
246 | return "Unknown error"
247 | }
248 | }
249 | static parseInfo(aInfo){
250 | return Object.entries(aInfo).map(a => `${a[0]}: ${a[1]}`).join("; ")
251 | }
252 | static fromKind(aKind,info){
253 | return info instanceof ResultError
254 | ? info
255 | : new ResultError(aKind,{},info)
256 | }
257 | }
258 |
259 | class FileSystemResult{
260 | #result;
261 | #type;
262 | #fileuri;
263 | constructor(data,resultType){
264 | this.#result = data;
265 | this.#type = resultType;
266 | }
267 |
268 | get fileURI(){
269 | if(this.isError()){
270 | return null
271 | }
272 | if(!this.#fileuri){
273 | this.#fileuri = FileSystemResult.#getFileURI(this)
274 | }
275 | return this.#fileuri
276 | }
277 | content(replaceNewlines){
278 | if(this.isContent()){
279 | return replaceNewlines
280 | ? this.#result.content.replace(/\r\n?/g, '\n')
281 | : this.#result.content
282 | }
283 | throw ResultError.fromKind(FileSystem.ERROR_KIND_NOT_CONTENT,{type:this.#type.description})
284 | }
285 | get size(){
286 | return this.isContent()
287 | ? this.#result.content.length
288 | : this.#result.fileSize
289 | }
290 | entry(){
291 | if(this.isDirectory() || this.isFile()){
292 | return this.#result
293 | }
294 | throw ResultError.fromKind(FileSystem.ERROR_KIND_NOT_EXIST,FileSystemResult.#generateErrorInfo(this))
295 | }
296 | error(){
297 | return this.isError()
298 | ? this.#result
299 | : null
300 | }
301 | readSync(){
302 | if(!this.isFile()){
303 | throw ResultError.fromKind(FileSystem.ERROR_KIND_NOT_FILE,FileSystemResult.#generateErrorInfo(this))
304 | }
305 | return FileSystem.readNSIFileSyncUncheckedWithOptions(this.#result,{}).content()
306 | }
307 | read(){
308 | if(!this.isFile()){
309 | return Promise.reject(ResultError.fromKind(FileSystem.ERROR_KIND_NOT_FILE,FileSystemResult.#generateErrorInfo(this)))
310 | }
311 | return IOUtils.readUTF8(this.#result.path)
312 | }
313 | get type(){
314 | return this.#type
315 | }
316 | isContent(){
317 | return this.#type === FileSystem.RESULT_CONTENT
318 | }
319 | isFile(){
320 | return this.#type === FileSystem.RESULT_FILE
321 | }
322 | isDirectory(){
323 | return this.#type === FileSystem.RESULT_DIRECTORY
324 | }
325 | isError(){
326 | return this.#type === FileSystem.RESULT_ERROR
327 | }
328 | [Symbol.iterator](){
329 | try{
330 | return this.entries()
331 | }catch(e){
332 | console.warn(e)
333 | }
334 | return { next() { return { done: true } } }
335 | };
336 | entries(){
337 | if(!this.isDirectory()){
338 | throw ResultError.fromKind(FileSystem.ERROR_KIND_NOT_DIRECTORY,FileSystemResult.#generateErrorInfo(this))
339 | }
340 | let enumerator = this.#result.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);
341 | return {
342 | next() {
343 | return enumerator.hasMoreElements()
344 | ? {
345 | value: enumerator.getNext().QueryInterface(Ci.nsIFile),
346 | done: false
347 | }
348 | : { done: true }
349 | },
350 | [Symbol.iterator]() {
351 | return this;
352 | },
353 | };
354 | }
355 | showInFileManager(){
356 | try{
357 | if(this.isFile()){
358 | this.#result.reveal();
359 | return true
360 | }
361 | if(this.isDirectory()){
362 | this.#result.launch();
363 | return true
364 | }
365 | }catch(ex){
366 | console.error("Could not open file manager for: " + this.#result.leafName);
367 | }
368 | return false
369 | }
370 | static #generateErrorInfo(aResult){
371 | if(aResult.isError()){
372 | return aResult.#result
373 | }
374 | return {
375 | topic: aResult.isContent()
376 | ? aResult.#result.path
377 | : aResult.#result.leafName
378 | }
379 | }
380 | static #getFileURI(aResult){
381 | if(aResult.isContent()){
382 | return aResult.#result.path
383 | }
384 | return FileSystem.getFileURIForFile(aResult.#result,aResult.#type)
385 | }
386 | static fromDirectory(dir){
387 | return new FileSystemResult(dir, FileSystem.RESULT_DIRECTORY)
388 | }
389 | static fromContent(content){
390 | return new FileSystemResult(content, FileSystem.RESULT_CONTENT)
391 | }
392 | static fromErrorKind(aKind,aErrorDescription){
393 | return new FileSystemResult(ResultError.fromKind(aKind,aErrorDescription), FileSystem.RESULT_ERROR)
394 | }
395 | static fromFile(file){
396 | return new FileSystemResult(file, FileSystem.RESULT_FILE)
397 | }
398 | static fromNsIFile(entry){
399 | if(!entry.exists()){
400 | return FileSystemResult.fromErrorKind(FileSystem.ERROR_KIND_NOT_EXIST,{topic: entry.leafName})
401 | }
402 | if(entry.isDirectory()){
403 | return FileSystemResult.fromDirectory(entry)
404 | }else if(entry.isFile()){
405 | return FileSystemResult.fromFile(entry)
406 | }
407 | return FileSystemResult.fromErrorKind(FileSystem.ERROR_KIND_UNKNOWN_RESULT,{topic: entry.leafName})
408 | }
409 | }
410 |
--------------------------------------------------------------------------------
/utils/uc_api.sys.mjs:
--------------------------------------------------------------------------------
1 | const {
2 | Hotkey,
3 | windowUtils,
4 | SharedGlobal,
5 | Pref,
6 | FileSystem,
7 | restartApplication,
8 | startupFinished,
9 | createElement,
10 | createWidget,
11 | escapeXUL,
12 | loadURI,
13 | loaderModuleLink,
14 | getScriptData,
15 | getStyleData,
16 | parseStringAsScriptInfo,
17 | toggleScript,
18 | updateStyleSheet,
19 | showNotification
20 | } = ChromeUtils.importESModule("chrome://userchromejs/content/utils.sys.mjs");
21 |
22 | export {
23 | FileSystem,
24 | Hotkey as Hotkeys,
25 | Pref as Prefs,
26 | SharedGlobal as SharedStorage,
27 | windowUtils as Windows
28 | }
29 |
30 | export const Runtime = Object.freeze({
31 | appVariant: loaderModuleLink.variant.THUNDERBIRD
32 | ? "Thunderbird"
33 | : "Firefox",
34 | brandName: loaderModuleLink.brandName,
35 | config: null,
36 | restart: restartApplication,
37 | startupFinished: startupFinished,
38 | loaderVersion: loaderModuleLink.version
39 | });
40 |
41 | export const Utils = Object.freeze({
42 | createElement: createElement,
43 | createWidget: createWidget,
44 | escapeXUL: escapeXUL,
45 | loadURI: loadURI
46 | });
47 |
48 | export const Scripts = Object.freeze({
49 | getScriptData: getScriptData,
50 | getStyleData: getStyleData,
51 | getScriptMenuForDocument(doc){
52 | return doc.getElementById("userScriptsMenu") || loaderModuleLink.getScriptMenu(doc)
53 | },
54 | openScriptDir(){
55 | FileSystem.getScriptDir().showInFileManager()
56 | },
57 | openStyleDir(){
58 | FileSystem.getStyleDir().showInFileManager()
59 | },
60 | parseStringAsScriptInfo: parseStringAsScriptInfo,
61 | toggleScript: toggleScript,
62 | reloadStyleSheet: updateStyleSheet
63 | });
64 |
65 | export const Notifications = Object.freeze({
66 | show(def){
67 | showNotification(def)
68 | }
69 | });
--------------------------------------------------------------------------------