Last active
February 26, 2024 04:18
-
-
Save dstensnes/1e87ed55dfbe5cca329e9cd5eb579064 to your computer and use it in GitHub Desktop.
Firefox profile wrapper script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /bin/sh | |
##### DESCRIPTION ##### | |
# This is a small wrapper script for running firefox with multiple profiles. | |
# By default it just wraps the normal firefox executable functionality, but | |
# appends a path to a profile named "default". | |
# | |
# You can create additional profiles like this: | |
# firefox normal netflix 'https://www.netflix.com/' | |
# | |
# It also has support for creating profiles somewhat similar to | |
# google chrome's app-mode functionality (which works | |
# great for netflix by the way!). All it does is hide | |
# the URL-bar and tabs, but keyboard shortcuts still works | |
# (like Ctrl+T for new tab, and Ctrl+Tab to cycle tabs, | |
# Ctrl+W to close a tab). Create an app profile like this: | |
# firefox app netflix 'https://www.netflix.com/' | |
# | |
# Everything else is passed along to the real firefox | |
# executable like normal, so options etc should work | |
# | |
# Notes: | |
# * I preseed a lot of settings in new profiles to prevent UI tours | |
# and data sharing popups. I have however tried to disable all kind | |
# of datasharing and telemetry, but further updates to firefox may | |
# require additional settings to turn them off in the future. | |
# * To delete a profile, delete the folder inside "$HOME/$PROFILEFOLDERDIR" | |
# and the corresponding wrapper script created inside "$SCRIPTPATH" | |
# * Clicking the Alt button once allows access to preferences and addons | |
# from the old application menu, in case you need to install additional | |
# addons or do other tweaks. | |
# | |
# Licence: Public domain without restrictions. | |
# | |
# Warnings: | |
# * As usual, use at your own risk. It works for me, it should hopefully | |
# work for you if you follow the instructions above. I accept no | |
# responsibility for bugs here. | |
# | |
# Enjoy! | |
# | |
# - Daniel Stensnes | |
# | |
# | |
# | |
##### CONFIGURATION ##### | |
# | |
# Path to Firefox executable | |
FIREFOXEXECUTABLE="$HOME/.local/apps/firefox/firefox" | |
# Folder to hold all firefox profiles. Always relative to home directory! No absolute urls! No trailing slash! | |
PROFILEFOLDERDIR=".firefox-profiles" | |
# Space separated URLs to extensions to install in all profiles | |
EXTENSIONURLS='https://addons.mozilla.org/en-US/firefox/addon/ublock-origin/' | |
# Path where a wrapper script for starting this profile will be created | |
SCRIPTPATH="$HOME/.local/bin" | |
# | |
# | |
##### SCRIPT CODE ##### | |
# | |
syntax () { | |
echo "$0 \"normal\" <appname> <url>" | |
echo "$0 \"app\" <appname> <url>" | |
echo "$0 <url>" | |
} | |
# Validate that "$1" looks somewhat like a valid URL | |
checkIsUrl () { | |
if [ -z "$(echo "$1" | grep "://")" ] ; then | |
echo "No URL given. Follow the syntax!" | |
syntax | |
exit 1 | |
fi | |
} | |
# Preseed some settings in new profiles, to prevent | |
# UI tours and other popups on every new profile. | |
mkUserPref () { | |
echo ' | |
pref("app.shield.optoutstudies.enabled", true); | |
pref("browser.bookmarks.restore_default_bookmarks", false); | |
pref("browser.contentblocking.introCount", 20); | |
pref("browser.newtabpage.activity-stream.feeds.telemetry", false); | |
pref("browser.newtabpage.activity-stream.telemetry", false); | |
pref("browser.newtabpage.activity-stream.telemetry.ping.endpoint", ""); | |
pref("browser.newtabpage.enabled", false); | |
pref("browser.newtabpage.enhanced", false); | |
pref("browser.newtabpage.storageVersion", 1); | |
pref("browser.onboarding.enabled", false); | |
pref("browser.onboarding.notification.finished", true); | |
pref("browser.onboarding.state", "watermark"); | |
pref("browser.onboarding.notification.finished", true); | |
pref("browser.onboarding.tour-type", "none"); | |
pref("browser.onboarding.tour.onboarding-tour-addons.completed", true); | |
pref("browser.onboarding.tour.onboarding-tour-customize.completed", true); | |
pref("browser.onboarding.tour.onboarding-tour-default-browser.completed", true); | |
pref("browser.onboarding.tour.onboarding-tour-performance.completed", true); | |
pref("browser.onboarding.tour.onboarding-tour-private-browsing.completed", true); | |
pref("browser.onboarding.tour.onboarding-tour-screenshots.completed", true); | |
pref("browser.link.open_newwindow.restriction", 0); | |
pref("browser.ping-centre.telemetry", false); | |
pref("browser.shell.checkDefaultBrowser", false); | |
pref("browser.shell.didSkipDefaultBrowserCheckOnFirstRun", true); | |
pref("browser.startup.homepage_override.mstone", "ignore"); | |
pref("browser.uitour.enabled", false); | |
pref("datareporting.healthreport.uploadEnabled", false); | |
pref("extensions.pocket.enabled", false); | |
pref("extensions.shield-recipe-client.enabled", false); | |
pref("extensions.shield-recipe-client.first_run", false); | |
pref("extensions.shield-recipe-client.startupExperimentPrefs.browser.newtabpage.activity-stream.enabled", false); | |
pref("extensions.ui.dictionary.hidden", true); | |
pref("extensions.ui.experiment.hidden", true); | |
pref("extensions.ui.locale.hidden", true); | |
pref("network.cookie.cookieBehavior", 3); | |
pref("network.dns.disablePrefetch", true); | |
pref("privacy.donottrackheader.enabled", true); | |
pref("privacy.clearOnShutdown.cookies", false); | |
pref("privacy.clearOnShutdown.downloads", false); | |
pref("privacy.clearOnShutdown.formdata", false); | |
pref("privacy.clearOnShutdown.history", false); | |
pref("privacy.clearOnShutdown.sessions", false); | |
pref("privacy.donottrackheader.enabled", true); | |
pref("privacy.history.custom", true); | |
pref("privacy.sanitize.didShutdownSanitize", true); | |
pref("privacy.sanitize.sanitizeOnShutdown", true); | |
pref("security.ssl.errorReporting.url", ""); | |
pref("toolkit.telemetry.archive.enabled", false); | |
pref("toolkit.telemetry.bhrPing.enabled", false); | |
pref("toolkit.telemetry.enabled", false); | |
pref("toolkit.telemetry.firstShutdownPing.enabled", false); | |
pref("toolkit.telemetry.newProfilePing.enabled", false); | |
pref("toolkit.telemetry.reportingpolicy.firstRun", false); | |
pref("toolkit.telemetry.server", ""); | |
pref("toolkit.telemetry.shutdownPingSender.enabled", false); | |
pref("toolkit.telemetry.unified", false); | |
pref("toolkit.telemetry.updatePing.enabled", false); | |
pref("browser.uidensity", 1); | |
pref("lightweightThemes.selectedThemeID", "firefox-compact-dark@mozilla.org"); | |
pref("toolkit.cosmeticAnimations.enabled", false); | |
pref("datareporting.policy.dataSubmissionPolicyAcceptedVersion", 20); | |
pref("datareporting.policy.dataSubmissionPolicyNotifiedTime", "1"); | |
' > $1 | |
} | |
mkProfilePath () { | |
if [ "$1" != 'app' -a "$1" != 'normal' ] ; then | |
echo "ERROR: No app-mode given to mkProfilePath" | |
exit 1 | |
fi | |
if [ -z "$2" -o -n "$(echo "$2" | grep '://')" ] ; then | |
echo "ERROR: No profile name given to mkProfilePath" | |
exit 1 | |
fi | |
if [ -z "$3" ] ; then | |
echo "WARNING: No default URL given to mkProfilePath. Not setting a default" | |
fi | |
PROFILEPATH="$HOME/$PROFILEFOLDERDIR/$2" | |
if [ ! -d "$PROFILEPATH" ] ; then | |
mkdir -p "${PROFILEPATH}" | |
fi | |
if [ ! -f "$PROFILEPATH/user.js" ] ; then | |
mkUserPref "$PROFILEPATH/user.js" | |
fi | |
if [ "$1" = "app" ] ; then | |
mkdir -p "${PROFILEPATH}/chrome" | |
chmod og-rwx -R "${PROFILEPATH}" | |
echo $ECHOESCAPECHAROPTION '#TabsToolbar,#nav-bar { visibility: collapse !important; }'>"${PROFILEPATH}/chrome/userChrome.css" | |
echo $ECHOESCAPECHAROPTION '@-moz-document url-prefix("about:") { * { color: #F9F9FA !important; background-color: #0C0C0C !important; } }'>${PROFILEPATH}/chrome/userContent.css | |
fi | |
if [ -n "$SCRIPTPATH" -a ! -f "$HOME/$SCRIPTPATH/$2" -a "$3" != 'no-script' ] ; then | |
if [ -n "$3" -a "$3" != 'none' ] ; then | |
echo $ECHOESCAPECHAROPTION '#! /bin/sh\nexport GTK_THEME=Adwaita:light\nexec $HOME/.local/apps/firefox/firefox --class="'$2'" -profile "$HOME/'"$PROFILEFOLDERDIR/$2"'" -no-remote "'"$3"'" &> $HOME/.output.firefox-'"$2"'' > "$SCRIPTPATH/$2" | |
else | |
echo $ECHOESCAPECHAROPTION '#! /bin/sh\nexport GTK_THEME=Adwaita:light\nexec $HOME/.local/apps/firefox/firefox --class="'$2'" -profile "$HOME/'"$PROFILEFOLDERDIR/$2"'" -no-remote $* &> $HOME/.output.firefox-'"$2"'' > "$SCRIPTPATH/$2" | |
fi | |
chmod 755 "$SCRIPTPATH/$2" | |
fi | |
} | |
installExtensions () { | |
if [ -n "$EXTENSIONURLS" ] ; then | |
for EXTURL in $EXTENSIONURLS ; do | |
$FIREFOXEXECUTABLE -profile "$1" -no-remote "${EXTURL}" &> /dev/null | |
done | |
fi | |
} | |
if [ -n "$(readlink "/proc/$$/exe" | grep '/bash')" ] ; then | |
ECHOESCAPECHAROPTION="-e" | |
else | |
ECHOESCAPECHAROPTION="" | |
fi | |
if [ ! -x "$FIREFOXEXECUTABLE" ] ; then | |
echo "FIREFOXEXECUTABLE does not point to an executable file (firefox executable)" | |
exit 1 | |
fi | |
[ -n "$SCRIPTPATH" -a ! -d "$SCRIPTPATH" ] && mkdir -p "$SCRIPTPATH" | |
umask 077 | |
case "$1" in | |
app|normal) | |
PROFILEPATH="$HOME/$PROFILEFOLDERDIR/$2/" | |
checkIsUrl "$3" | |
mkProfilePath "$1" "$2" "$3" | |
installExtensions "$PROFILEPATH" | |
;; | |
help) | |
syntax | |
;; | |
*) | |
PROFILEPATH="$HOME/$PROFILEFOLDERDIR/default/" | |
if [ ! -d "$PROFILEPATH" ] ; then | |
mkProfilePath normal "$PROFILEPATH" no-script | |
fi | |
export GTK_THEME=Adwaita:light | |
exec ${FIREFOXEXECUTABLE} -profile "${PROFILEPATH}" $* &> $HOME/.output.firefox-default | |
;; | |
esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment