Skip to content

Instantly share code, notes, and snippets.

@tsbertalan
Last active March 4, 2024 14:35
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tsbertalan/5773a35403052578340c5bf5e28c6675 to your computer and use it in GitHub Desktop.
Save tsbertalan/5773a35403052578340c5bf5e28c6675 to your computer and use it in GitHub Desktop.
Largely automate the process of making a special-purpose Firefox profile without window chrome.
#!/usr/bin/env python
from __future__ import print_function
import argparse
from os import system
from glob import glob
from os.path import join, expanduser
HOME = expanduser('~')
def sanitize(s, alpha=True, ALPHA=True, num=True, extra='_'):
allowed = str(extra)
abc = 'abcdefghijklmnopqrstuvwxyz'
if alpha:
allowed += abc.lower()
if ALPHA:
allowed += abc.upper()
if num:
allowed += '1234567890'
return ''.join([
c for c in s if c in allowed
])
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('URL', type=str, help='Homepage to be used when opening new windows in the profile via the .desktop file.')
parser.add_argument('icon_name', type=str, help='Icon name to use in .desktop file. An explicit path can be given, or something that resolves using the regular icon search path (however that works; e.g., for ~/.local/share/icons/gmail.svg, you could enter just gmail.svg).')
parser.add_argument('--app_name', type=str, default=None, help='Name for the generated "app" to use in the .desktop file. If not given, a santized version of the URL will be used instead.')
parser.add_argument('--hide_user_chrome', type=bool, default=True, help='Whether to generate userChrome.css file that will hide window chrome in all windows created in the new profile. Useful to make web-apps seem more app-y.')
parser.add_argument('--run_after_creating', type=bool, default=True, help='Whether we should start the new app after creating it.')
args = parser.parse_args()
tag = sanitize(args.URL)
if tag.startswith('https'):
tag = tag[5:]
elif tag.startswith('http'):
tag = tag[4:]
if args.app_name is None:
args.app_name = args.icon_name.replace('_', ' ').title()
def run_and_speak(cmd, instructions):
print()
for l in instructions.split('\n'):
print(l)
print()
print('$ %s' % cmd)
return system(cmd)
run_and_speak('firefox -P',
'''Create Firefox profile with name "%s" (without quotes) now.
1. Be sure not to check the box setting this to the default.
2. Optionally, open the new profile and set the home page to "%s".''' % (tag, args.URL)
)
execline = '/usr/bin/firefox -new-window -P "%s" --class="%s" "%s"' % (tag, tag, args.URL)
desktopfile = '''#!/usr/bin/env xdg-open
[Desktop Entry]
Version=1.0
Terminal=false
Type=Application
Name=%s
Exec=%s
Icon=%s
StartupWMClass=%s''' % (
args.app_name,
execline,
args.icon_name,
tag,
)
desktopfile_path = join(HOME, '.local', 'share', 'applications', '%s.desktop' % tag)
print('Creating "%s" with contents:\n>>>>\n%s\n<<<<' % (desktopfile_path, desktopfile))
with open(desktopfile_path, 'w') as fp:
fp.write(desktopfile)
system('chmod +x "%s"' % desktopfile_path)
# Find profile dir.
print('Searching for profile folder:')
found = None
for folder in glob(join(HOME, '.mozilla', 'firefox', '*')):
if tag in folder:
print('>>>>', end=' ')
found = folder
else:
print(' ', end=' ')
print(folder)
if found is None:
print('Couldn\'t find profile "%s". Did you create it?' % tag)
exit(1)
else:
userChrome_path = join(found, 'chrome', 'userChrome.css')
print('Found profile folder at "%s"; creating userChrome.css file:\n%s' % (found, userChrome_path))
if args.hide_user_chrome:
system('mkdir -p "%s/chrome/"' % found)
with open(userChrome_path, 'a') as fp:
fp.write('''/*
* Do not remove the @namespace line -- it's required for correct functioning
*/
@namespace URL("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* set default namespace to XUL */
/*
* Hide tab bar, navigation bar and scrollbars
* !important may be added to force override, but not necessary
* #content is not necessary to hide scroll bars
*/
#TabsToolbar {visibility: collapse;}
#navigator-toolbox {visibility: collapse;}
browser {margin-right: -14px; margin-bottom: -14px;}''')
if args.run_after_creating:
run_and_speak(execline, 'Starting new app.')
@gusbemacbe
Copy link

Hi @tsbertalan, does this script work with any non-Firefox? For example, I want to two Dolphin apps, one Dolphin with Meld whose WM CLASS would be dolphin-meld and another Dolphin with Beyond Compare whose WM Class would be dolphin-bcompare.

@tsbertalan
Copy link
Author

tsbertalan commented Dec 1, 2019 via email

@gusbemacbe
Copy link

Too bad, @tsbertalan! Thank you for your answer! I have to duplicate the source code, modify and compile.

@rodrigomb81
Copy link

rodrigomb81 commented Mar 4, 2024

Thanks for uploading this! It helped me separate my work Firefox from my personal Firefox :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment