Merge branch 'autostart-dropins'

Conflicts:
	misc/qubes-trigger-desktop-file-install

Fixes qubesos/qubes-issues#1151
This commit is contained in:
Marek Marczykowski-Górecki 2015-09-02 01:16:19 +02:00
commit c8ac55b179
37 changed files with 205 additions and 522 deletions

View File

@ -8,6 +8,9 @@ SBINDIR ?= /usr/sbin
LIBDIR ?= /usr/lib LIBDIR ?= /usr/lib
SYSLIBDIR ?= /lib SYSLIBDIR ?= /lib
PYTHON = /usr/bin/python2
PYTHON_SITEARCH = `python2 -c 'import distutils.sysconfig; print distutils.sysconfig.get_python_lib(1)'`
# This makefile uses some bash-isms, make uses /bin/sh by default. # This makefile uses some bash-isms, make uses /bin/sh by default.
SHELL = /bin/bash SHELL = /bin/bash
@ -109,7 +112,6 @@ install-rh: install-systemd install-systemd-dropins install-sysvinit
touch $(DESTDIR)/etc/yum.conf.d/qubes-proxy.conf touch $(DESTDIR)/etc/yum.conf.d/qubes-proxy.conf
install -D -m 0644 misc/qubes-trigger-sync-appmenus.action $(DESTDIR)/etc/yum/post-actions/qubes-trigger-sync-appmenus.action install -D -m 0644 misc/qubes-trigger-sync-appmenus.action $(DESTDIR)/etc/yum/post-actions/qubes-trigger-sync-appmenus.action
install -D -m 0644 misc/qubes-trigger-desktop-file-install.action $(DESTDIR)/etc/yum/post-actions/qubes-trigger-desktop-file-install.action
install -D -m 0644 misc/serial.conf $(DESTDIR)/usr/share/qubes/serial.conf install -D -m 0644 misc/serial.conf $(DESTDIR)/usr/share/qubes/serial.conf
install -D misc/qubes-serial-login $(DESTDIR)/$(SBINDIR)/qubes-serial-login install -D misc/qubes-serial-login $(DESTDIR)/$(SBINDIR)/qubes-serial-login
@ -118,6 +120,7 @@ install-rh: install-systemd install-systemd-dropins install-sysvinit
install -m 0400 -D network/ip6tables $(DESTDIR)/usr/lib/qubes/init/ip6tables install -m 0400 -D network/ip6tables $(DESTDIR)/usr/lib/qubes/init/ip6tables
install-common: install-common:
$(MAKE) -C autostart-dropins install
install -m 0644 -D misc/fstab $(DESTDIR)/etc/fstab install -m 0644 -D misc/fstab $(DESTDIR)/etc/fstab
install -D -m 0440 misc/qubes.sudoers $(DESTDIR)/etc/sudoers.d/qubes install -D -m 0440 misc/qubes.sudoers $(DESTDIR)/etc/sudoers.d/qubes
@ -169,8 +172,7 @@ install-common:
install network/qubes-netwatcher $(DESTDIR)/$(SBINDIR)/ install network/qubes-netwatcher $(DESTDIR)/$(SBINDIR)/
install -d $(DESTDIR)/usr/bin install -d $(DESTDIR)/usr/bin
install -m 0755 misc/qubes-desktop-file-install $(DESTDIR)/usr/bin/qubes-desktop-file-install install -m 0755 misc/qubes-session-autostart $(DESTDIR)/usr/bin/qubes-session-autostart
install -m 0755 misc/qubes-trigger-desktop-file-install $(DESTDIR)$(LIBDIR)/qubes/qubes-trigger-desktop-file-install
install qubes-rpc/{qvm-open-in-dvm,qvm-open-in-vm,qvm-copy-to-vm,qvm-move-to-vm,qvm-run,qvm-mru-entry} $(DESTDIR)/usr/bin install qubes-rpc/{qvm-open-in-dvm,qvm-open-in-vm,qvm-copy-to-vm,qvm-move-to-vm,qvm-run,qvm-mru-entry} $(DESTDIR)/usr/bin
install qubes-rpc/wrap-in-html-if-url.sh $(DESTDIR)$(LIBDIR)/qubes install qubes-rpc/wrap-in-html-if-url.sh $(DESTDIR)$(LIBDIR)/qubes
@ -202,6 +204,13 @@ install-common:
install -D -m 0755 misc/qubes-desktop-run $(DESTDIR)/usr/bin/qubes-desktop-run install -D -m 0755 misc/qubes-desktop-run $(DESTDIR)/usr/bin/qubes-desktop-run
mkdir -p $(DESTDIR)/$(PYTHON_SITEARCH)/qubes/
ifeq (1,${DEBIANBUILD})
install -m 0644 misc/xdg.py $(DESTDIR)/$(PYTHON_SITEARCH)/qubes/
else
install -m 0644 misc/xdg.py* $(DESTDIR)/$(PYTHON_SITEARCH)/qubes/
endif
install -d $(DESTDIR)/mnt/removable install -d $(DESTDIR)/mnt/removable
install -D -m 0644 misc/xorg-preload-apps.conf $(DESTDIR)/etc/X11/xorg-preload-apps.conf install -D -m 0644 misc/xorg-preload-apps.conf $(DESTDIR)/etc/X11/xorg-preload-apps.conf

View File

@ -0,0 +1,6 @@
DROPINS_DIR = /etc/qubes/autostart
install:
for f in *.desktop; do install -m 0644 -D $$f $(DESTDIR)$(DROPINS_DIR)/$$f.d/30_qubes.conf; done
install -m 0644 README.txt $(DESTDIR)$(DROPINS_DIR)/

View File

@ -0,0 +1,20 @@
This directory (/etc/qubes/autostart) is used to override parts of files in
/etc/xdg/autostart. For each desktop file there, you can create directory named
after the file plus ".d", then place files there. All such files will be read
(in lexicographical order) and lines specified there will override respective
entries in the original file. This can be used for example to enable or disable
specific application in particular VM type.
For example, you can extend `/etc/xdg/autostart/gnome-keyring-ssh.desktop` by
creating `/etc/qubes/autostart/gnome-keyring-ssh.desktop.d/50_user.conf` with:
```
[Desktop Entry]
OnlyShowIn=X-AppVM;
```
This would mean that `OnlyShowIn` key would be read as `X-AppVM;`, regardless
of original entry in `/etc/xdg/autostart/gnome-keyring-ssh.desktop`.
This mechanism overrides only content of /etc/xdg/autostart, files placed in
~/.config/autostart are unaffected, so can be used to override settings per-VM
basis.

View File

@ -0,0 +1,2 @@
[Desktop Entry]
NotShowIn=X-QUBES;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
NotShowIn=X-DisposableVM;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
OnlyShowIn=GNOME;X-AppVM;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
OnlyShowIn=GNOME;X-AppVM;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
OnlyShowIn=GNOME;X-AppVM;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
OnlyShowIn=GNOME;X-AppVM;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
NotShowIn=X-QUBES;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
NotShowIn=X-QUBES;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
OnlyShowIn=GNOME;X-AppVM;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
NotShowIn=X-QUBES;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
OnlyShowIn=GNOME;X-UpdateableVM;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
OnlyShowIn=GNOME;X-AppVM;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
NotShowIn=X-QUBES;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
NotShowIn=X-QUBES;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
OnlyShowIn=GNOME;X-QUBES

View File

@ -0,0 +1,2 @@
[Desktop Entry]
NotShowIn=X-QUBES;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
NotShowIn=X-QUBES;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
NotShowIn=X-QUBES;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
NotShowIn=X-QUBES;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
NotShowIn=X-QUBES;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
NotShowIn=X-QUBES;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
NotShowIn=X-QUBES;

View File

@ -0,0 +1,2 @@
[Desktop Entry]
OnlyShowIn=GNOME;X-AppVM;

View File

@ -143,10 +143,6 @@ case "${1}" in
# Update Qubes App Menus" # Update Qubes App Menus"
/usr/lib/qubes/qubes-trigger-sync-appmenus.sh || true /usr/lib/qubes/qubes-trigger-sync-appmenus.sh || true
## Update all xdg autostart desktop entries
/usr/lib/qubes/qubes-trigger-desktop-file-install clean || true
;; ;;
abort-upgrade|abort-remove|abort-deconfigure) abort-upgrade|abort-remove|abort-deconfigure)
@ -160,14 +156,6 @@ case "${1}" in
/usr/share/applications) /usr/share/applications)
debug "Updating Qubes App Menus..." debug "Updating Qubes App Menus..."
/usr/lib/qubes/qubes-trigger-sync-appmenus.sh || true /usr/lib/qubes/qubes-trigger-sync-appmenus.sh || true
debug "Updating XDG Config..."
/usr/lib/qubes/qubes-trigger-desktop-file-install || true
;;
/etc/xdg)
debug "Updating XDG Config..."
/usr/lib/qubes/qubes-trigger-desktop-file-install || true
;; ;;
# Install overridden serial.conf init script # Install overridden serial.conf init script

View File

@ -64,6 +64,8 @@ if [ "$1" = "upgrade" ] ; then
if grep -q ^qubes:x:98: /etc/group ; then if grep -q ^qubes:x:98: /etc/group ; then
if ! grep -q :980: /etc/group ; then if ! grep -q :980: /etc/group ; then
if groupmod -g 980 qubes ; then if groupmod -g 980 qubes ; then
# make sure that vchan will still work until VM start
chmod 666 /dev/xen/* /proc/xen/privcmd
find / -gid 98 ! -type l -exec chgrp --verbose qubes {} \; 2>/dev/null || true find / -gid 98 ! -type l -exec chgrp --verbose qubes {} \; 2>/dev/null || true
fi fi
fi fi

View File

@ -1,3 +1,2 @@
interest-noawait /usr/share/applications interest-noawait /usr/share/applications
interest-noawait /etc/xdg
interest-noawait /etc/init/serial.conf interest-noawait /etc/init/serial.conf

View File

@ -1,367 +0,0 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim: set ft=python ts=4 sw=4 sts=4 et :
# Copyright (C) 2015 Jason Mehring <nrgaway@gmail.com>
# License: GPL-2+
# Authors: Jason Mehring
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
'''Installation and edition of desktop files.
Description:
The desktop-file-install program is a tool to install, and optionally edit,
desktop files. They are mostly useful for developers and packagers.
Various options are available to edit the desktop files. The edit options can
be specified more than once and will be processed in the same order as the
options passed to the program.
The original .desktop files are left untouched and left in place.
Qubes modifies the XDG_CONFIG_DIRS to first include the `/var/lib/qubes/xdg`
directory (XDG_CONFIG_DIRS=/var/lib/qubes/xdg:/etc/xdg).
Usage:
qubes-desktop-file-install [--dir DIR] [--force]
[--remove-show-in]
[--remove-key KEY]
[--remove-only-show-in ENVIRONMENT]
[--add-only-show-in ENVIRONMENT]
[--remove-not-show-in ENVIRONMENT]
[--add-not-show-in ENVIRONMENT]
[(--set-key KEY VALUE)]
FILE
qubes-desktop-file-install -h | --help
qubes-desktop-file-install --version
Examples:
qubes-desktop-file-install --dir /var/lib/qubes/xdg/autostart --add-only-show-in X-QUBES /etc/xdg/autostart/pulseaudio.desktop
Arguments:
FILE Path to desktop entry file
Help Options:
-h, --help show this help message and exit
Installation options for desktop file:
--dir DIR Install desktop files to the DIR directory (default: <FILE>)
--force Force overwrite of existing desktop files (default: False)
Edition options for desktop file:
--remove-show-in Remove the "OnlyShowIn" and "NotShowIn" entries from the desktop file (default: False)
--remove-key KEY Remove the KEY key from the desktop files, if present
--set-key (KEY VALUE) Set the KEY key to VALUE
--remove-only-show-in ENVIRONMENT Remove ENVIRONMENT from the list of desktop environment where the desktop files should be displayed
--add-only-show-in ENVIRONMENT Add ENVIRONMENT to the list of desktop environment where the desktop files should be displayed
--remove-not-show-in ENVIRONMENT Remove ENVIRONMENT from the list of desktop environment where the desktop files should not be displayed
--add-not-show-in ENVIRONMENT Add ENVIRONMENT to the list of desktop environment where the desktop files should not be displayed
'''
import argparse
import codecs
import io
import locale
import os
import sys
try:
import ConfigParser as configparser
except ImportError:
import configparser
from collections import OrderedDict
# Third party libs
import xdg.DesktopEntry
__all__ = []
__version__ = '1.0.0'
# This is almost always a good thing to do at the beginning of your programs.
locale.setlocale(locale.LC_ALL, '')
# Default Qubes directory that modified desktop entry config files are stored in
QUBES_XDG_CONFIG_DIR = '/vat/lib/qubes/xdg'
class DesktopEntry(xdg.DesktopEntry.DesktopEntry):
'''Class to parse and validate Desktop Entries (OVERRIDE).
xdg.DesktopEntry.DesktopEntry does not maintain order of content
'''
defaultGroup = 'Desktop Entry'
def __init__(self, filename=None):
"""Create a new DesktopEntry
If filename exists, it will be parsed as a desktop entry file. If not,
or if filename is None, a blank DesktopEntry is created.
"""
self.content = OrderedDict()
if filename and os.path.exists(filename):
self.parse(filename)
elif filename:
self.new(filename)
def parse(self, filename):
'''Parse a desktop entry file.'''
headers = [u'Desktop Entry', u'KDE Desktop Entry']
cfgparser = configparser.RawConfigParser()
cfgparser.optionxform = unicode
try:
cfgparser.readfp(codecs.open(filename, 'r', 'utf8'))
except configparser.MissingSectionHeaderError:
sys.exit('{0} missing header!'.format(filename, headers[0]))
self.filename = filename
self.tainted = False
for header in headers:
if cfgparser.has_section(header):
self.content[header] = OrderedDict(cfgparser.items(header))
if not self.defaultGroup:
self.defaultGroup = header
if not self.defaultGroup:
sys.exit('{0} missing header!'.format(filename, headers[0]))
# Write support broken in Wheezy; override here
def write(self, filename=None, trusted=False):
if not filename and not self.filename:
raise ParsingError("File not found", "")
if filename:
self.filename = filename
else:
filename = self.filename
if os.path.dirname(filename) and not os.path.isdir(os.path.dirname(filename)):
os.makedirs(os.path.dirname(filename))
with io.open(filename, 'w', encoding='utf-8') as fp:
# An executable bit signifies that the desktop file is
# trusted, but then the file can be executed. Add hashbang to
# make sure that the file is opened by something that
# understands desktop files.
if trusted:
fp.write(u("#!/usr/bin/env xdg-open\n"))
if self.defaultGroup:
fp.write(unicode("[%s]\n") % self.defaultGroup)
for (key, value) in self.content[self.defaultGroup].items():
fp.write(unicode("%s=%s\n") % (key, value))
fp.write(unicode("\n"))
for (name, group) in self.content.items():
if name != self.defaultGroup:
fp.write(unicode("[%s]\n") % name)
for (key, value) in group.items():
fp.write(unicode("%s=%s\n") % (key, value))
fp.write(unicode("\n"))
# Add executable bits to the file to show that it's trusted.
if trusted:
oldmode = os.stat(filename).st_mode
mode = oldmode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
os.chmod(filename, mode)
self.tainted = False
def delete(path):
'''Delete a file.
'''
if os.path.exists(path):
try:
os.unlink(os.path.abspath(path))
except IOError as error:
sys.exit('Unable to delete file: {0}\n{1}'.format(path, error))
def set_key(entry, key, value):
'''Set a key with value within an desktop-file entry object.
'''
key = unicode(key)
if isinstance(value, list):
entry.set(key, u';'.join(value))
else:
entry.set(key, unicode(value))
def remove_key(entry, key):
'''Remove a key within an desktop-file entry object.
'''
entry.removeKey(unicode(key))
def add_value(entry, key, value):
'''Add a value to a desktop-file entry object.
'''
values = entry.getList(unicode(value))
for value in values:
entry_values = entry.get(key, list=True)
if value not in entry_values:
entry_values.append(value)
set_key(entry, key, entry_values)
def remove_value(entry, key, value):
'''Remove a value to a desktop-file entry object.
'''
value = unicode(value)
entry_values = entry.get(key, list=True)
if value in entry_values:
entry_values.remove(value)
if entry_values:
set_key(entry, key, entry_values)
else:
remove_key(entry, key)
def install(**kwargs):
'''Install a copy of a desktop-file entry file to a new location and
optionally edit it.
'''
paths = kwargs.get('path', [])
for path in paths:
if not path:
sys.exit('No path selected!')
filename, extension = os.path.splitext(path)
if extension.lower() not in ['.desktop']:
sys.exit("Invalid desktop extenstion '{0}'! Was expecting '.desktop'.".format(extension))
new_path = os.path.join(kwargs['dir'], os.path.basename(path))
if os.path.exists(path) and os.path.isfile(path):
stat_info = os.stat(path)
# Don't update if file has previously been updated unless force is True
if os.path.exists(new_path) and not kwargs['force']:
if os.stat(new_path).st_mtime == stat_info.st_mtime:
continue
else:
if os.path.exists(new_path) and os.path.isfile(new_path):
delete(new_path)
continue
entry = DesktopEntry(path)
if kwargs['remove_show_in']:
kwargs['remove_key'].append(u'OnlyShowIn')
kwargs['remove_key'].append(u'NotShowIn')
if kwargs['remove_key']:
for value in kwargs['remove_key']:
remove_key(entry, value)
if kwargs['remove_only_show_in']:
for value in kwargs['remove_only_show_in']:
remove_value(entry, u'OnlyShowIn', value)
if kwargs['add_only_show_in']:
for value in kwargs['add_only_show_in']:
add_value(entry, u'OnlyShowIn', value)
if kwargs['remove_not_show_in']:
for value in kwargs['remove_not_show_in']:
remove_value(entry, u'NotShowIn', value)
if kwargs['add_not_show_in']:
for value in kwargs['add_not_show_in']:
add_value(entry, u'NotShowIn', value)
if kwargs['set_key']:
for key, value in kwargs['set_key']:
set_key(entry, key, value)
entry.write(new_path)
if stat_info:
os.utime(new_path, (stat_info.st_atime, stat_info.st_mtime))
def parse(args):
'''Argparse configuration.
'''
parser = argparse.ArgumentParser()
parser.add_argument('--version', action='version', version='%(prog)s (version {0})'.format(__version__))
parser.add_argument('--force', action='store_true', default=False, help='\
Force overwrite of existing desktop files.')
parser.add_argument('--dir', default=QUBES_XDG_CONFIG_DIR, help='\
Install desktop files to the DIR directory.')
parser.add_argument('--remove-show-in', action='store_true', default=False, help='\
Remove the "OnlyShowIn" and "NotShowIn" entries from the desktop file')
parser.add_argument('--remove-key', action='append', metavar='KEY', default=[], help='\
Remove the KEY key from the desktop file')
parser.add_argument('--remove-only-show-in', action='append', metavar='ENVIRONMENT', default=[], help='\
Remove ENVIRONMENT from the list of desktop environments where the\
desktop files should be displayed (key OnlyShowIn). If ENVIRONMENT was\
not present in the list, this operation is a no-op.')
parser.add_argument('--add-only-show-in', action='append', metavar='ENVIRONMENT', default=[], help='\
Add ENVIRONMENT to the list of desktop environments where the desktop\
files should be displayed (key OnlyShowIn). If ENVIRONMENT was already\
present in the list, this operation is a no-op. A non-registered desktop\
environment should be prefixed with X-. Note that an empty OnlyShowIn\
key in a desktop file means that the desktop file will be displayed in\
all environments.')
parser.add_argument('--remove-not-show-in', action='append', metavar='ENVIRONMENT', default=[], help='\
Remove ENVIRONMENT from the list of desktop environments where the\
desktop files should not be displayed (key NotShowIn). If\
ENVIRONMENT was not present in the list, this operation is a no-op.')
parser.add_argument('--add-not-show-in', action='append', metavar='ENVIRONMENT', default=[], help='\
Add ENVIRONMENT to the list of desktop environments where the desktop\
files should not be displayed (key NotShowIn). If ENVIRONMENT was\
already present in the list, this operation is a no-op. A non-registered\
desktop environment should be prefixed with X-. Note that an empty\
NotShowIn key in a desktop file means that the desktop file will be\
displayed in all environments.')
parser.add_argument('--set-key', action='append', nargs=2, metavar=('KEY', 'VALUE'), default=[], help='\
Set the KEY key to the VALUE passed.')
parser.add_argument('path', action='store', nargs='+', metavar='FILE', default=None,
help='Path to desktop entry file')
args = parser.parse_args(args)
if not os.path.isabs(args.dir):
args.dir = os.path.join(QUBES_XDG_CONFIG_DIR, args.dir)
return args
def main(argv):
'''Main function.
'''
args = parse(argv[1:])
install(**vars(args))
if __name__ == '__main__':
main(sys.argv)
sys.exit(0)

View File

@ -1,19 +1,7 @@
#!/usr/bin/python #!/usr/bin/python
from gi.repository import Gio from qubes.xdg import launch
import sys import sys
import dbus
def main(myname, desktop, *files): if __name__ == '__main__':
launcher = Gio.DesktopAppInfo.new_from_filename(desktop) launch(*sys.argv[1:])
activatable = launcher.get_boolean('DBusActivatable')
if activatable:
bus = dbus.SessionBus()
service_id = launcher.get_id()
# cut the .desktop suffix
service_id = service_id[:-8]
bus.start_service_by_name(service_id)
launcher.launch(files, None)
if __name__ == "__main__":
main(*sys.argv)

View File

@ -0,0 +1,89 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2015 Marek Marczykowski-Górecki
# <marmarek@invisiblethingslab.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
#
import subprocess
import sys
from xdg.DesktopEntry import DesktopEntry
from qubes.xdg import launch
import xdg.BaseDirectory
import os
QUBES_XDG_CONFIG_DROPINS = '/etc/qubes/autostart'
def open_desktop_entry_and_dropins(filename):
desktop_entry = DesktopEntry(filename)
dropins_dir = os.path.join(QUBES_XDG_CONFIG_DROPINS,
os.path.basename(filename) + '.d')
if os.path.isdir(dropins_dir):
for dropin in sorted(os.listdir(dropins_dir)):
dropin_content = DesktopEntry(os.path.join(dropins_dir, dropin))
desktop_entry.content.update(dropin_content.content)
return desktop_entry
def entry_should_be_started(entry, environments):
"""
:type entry: DesktopEntry
"""
if entry.getHidden():
return False
if entry.getOnlyShowIn():
return bool(set(entry.getOnlyShowIn()).intersection(environments))
if entry.getNotShowIn():
return not bool(set(entry.getNotShowIn()).intersection(environments))
return True
def process_autostart(environments):
# handle only "most important" entry
processed_entries = {}
for path in xdg.BaseDirectory.load_config_paths('autostart'):
for entry_name in os.listdir(path):
if entry_name in processed_entries:
continue
# make the entry as processed, even if not actually started
processed_entries[entry_name] = True
try:
entry_path = os.path.join(path, entry_name)
# files in $HOME have higher priority than dropins
if not path.startswith(xdg.BaseDirectory.xdg_config_home):
entry = open_desktop_entry_and_dropins(entry_path)
else:
entry = DesktopEntry(entry_path)
if entry_should_be_started(entry, environments):
launch(entry_path)
except Exception as e:
print >>sys.stderr, "Failed to process '{}': {}".format(
entry_name, str(e)
)
def main():
process_autostart(sys.argv[1:])
if __name__ == '__main__':
main()

View File

@ -1,96 +0,0 @@
#!/bin/bash -e
# vim: set ts=4 sw=4 sts=4 et :
#
# qubes-trigger-desktop-file-install
#
# This trigger script calls qubes-desktop-file-install to installation and edit
# desktop file overrides, leaving the original desktop file in-place and
# untouched.
#
# 'qubes-desktop-file-install' options:
# --dir DIR Install desktop files to the DIR directory (default: <FILE>)
# --force Force overwrite of existing desktop files (default: False)
# --remove-show-in Remove the "OnlyShowIn" and "NotShowIn" entries from the desktop file (default: False)
# --remove-key KEY Remove the KEY key from the desktop files, if present
# --set-key (KEY VALUE) Set the KEY key to VALUE
# --remove-only-show-in ENVIRONMENT Remove ENVIRONMENT from the list of desktop environment where the desktop files should be displayed
# --add-only-show-in ENVIRONMENT Add ENVIRONMENT to the list of desktop environment where the desktop files should be displayed
# --remove-not-show-in ENVIRONMENT Remove ENVIRONMENT from the list of desktop environment where the desktop files should not be displayed
# --add-not-show-in ENVIRONMENT Add ENVIRONMENT to the list of desktop environment where the desktop files should not be displayed
QUBES_DESKTOP_FILE_INSTALL='/usr/bin/qubes-desktop-file-install'
QUBES_XDG_CONFIG_DIR=/var/lib/qubes/xdg/autostart
XDG_CONFIG_DIR=/etc/xdg/autostart
INSTALL_CMD=""${QUBES_DESKTOP_FILE_INSTALL}" --force --dir "${QUBES_XDG_CONFIG_DIR}""
# Remove all current Qubes desktop entry files
if [ "${1}" == "clean" ]; then
rm -f "${QUBES_XDG_CONFIG_DIR}"/*
fi
generatePath () {
echo "${XDG_CONFIG_DIR}/${1}.desktop"
}
generateFileList () {
for key in "${!FILES[@]}"; do
FILES[${key}]="$(generatePath ${FILES[key]})"
done
}
install () {
local options="${@}"
# Install an edited version of desktop file in $QUBES_XDG_CONFIG_DIR
generateFileList
$INSTALL_CMD "${@}" "${FILES[@]}" || true
}
# Desktop Entry Modification - NotShowIn=QUBES
FILES=(
'pulseaudio'
'pulseaudio-kde'
'deja-dup-monitor'
'imsettings-start'
'krb5-auth-dialog'
'restorecond'
'sealertauto'
'spice-vdagent'
'gnome-power-manager'
'gnome-sound-applet'
'gnome-screensaver'
'orca-autostart'
'notify-osd'
); install --remove-show-in --add-not-show-in X-QUBES
# Desktop Entry Modification - NotShowIn=DisposableVM
FILES=('gcm-apply')
install --remove-show-in --add-not-show-in X-DisposableVM
# Desktop Entry Modification - OnlyShowIn=GNOME;AppVM;
FILES=(
'gnome-keyring-gpg'
'gnome-keyring-pkcs11'
'gnome-keyring-secrets'
'gnome-keyring-ssh'
'gnome-settings-daemon'
'user-dirs-update-gtk'
'gsettings-data-convert'
); install --remove-show-in --add-only-show-in 'GNOME;X-AppVM'
# Desktop Entry Modification - OnlyShowIn=GNOME;UpdateableVM
FILES=('gpk-update-icon')
install --remove-show-in --add-only-show-in 'GNOME;X-UpdateableVM'
# Desktop Entry Modification - OnlyShowIn=GNOME;QUBES
FILES=('nm-applet')
install --remove-show-in --add-only-show-in 'GNOME;X-QUBES'
# Desktop Entry Modification - Remove existing rules
FILES=(
'abrt-applet'
); install --remove-show-in

View File

@ -1 +0,0 @@
*:any:/usr/lib/qubes/qubes-trigger-desktop-file-install

20
misc/xdg.py Executable file
View File

@ -0,0 +1,20 @@
#!/usr/bin/python
from gi.repository import Gio
import sys
import dbus
def launch(desktop, *files):
launcher = Gio.DesktopAppInfo.new_from_filename(desktop)
if hasattr(launcher, 'get_boolean'):
activatable = launcher.get_boolean('DBusActivatable')
if activatable:
bus = dbus.SessionBus()
service_id = launcher.get_id()
# cut the .desktop suffix
service_id = service_id[:-8]
bus.start_service_by_name(service_id)
launcher.launch(files, None)
if __name__ == "__main__":
launch(*sys.argv[1:])

View File

@ -51,7 +51,7 @@ Requires: qubes-utils
Requires: initscripts Requires: initscripts
# for qubes-desktop-run # for qubes-desktop-run
Requires: pygobject3-base Requires: pygobject3-base
# for qubes-desktop-file-install # for qubes-session-autostart
Requires: pyxdg Requires: pyxdg
%if %{fedora} >= 20 %if %{fedora} >= 20
# gpk-update-viewer required by qubes-manager # gpk-update-viewer required by qubes-manager
@ -128,9 +128,6 @@ if [ -e /etc/init/serial.conf ]; then
cp /usr/share/qubes/serial.conf /etc/init/serial.conf cp /usr/share/qubes/serial.conf /etc/init/serial.conf
fi fi
%triggerin -- pulseaudio-module-x11
/usr/bin/qubes-desktop-file-install --force --dir /var/lib/qubes/xdg/autostart --remove-show-in --add-not-show-in X-QUBES /etc/xdg/autostart/pulseaudio.desktop
%triggerin -- iptables %triggerin -- iptables
if ! grep -q IPTABLES_DATA /etc/sysconfig/iptables-config; then if ! grep -q IPTABLES_DATA /etc/sysconfig/iptables-config; then
cat <<EOF >>/etc/sysconfig/iptables-config cat <<EOF >>/etc/sysconfig/iptables-config
@ -159,10 +156,6 @@ for F in plymouth-shutdown prefdm splash-manager start-ttys tty ; do
fi fi
done done
# Update all autostart xdg desktop configuration files (modified copies are
# placed in /var/lib/qubes/xdg/autostart)
/usr/lib/qubes/qubes-trigger-desktop-file-install clean
# Create NetworkManager configuration if we do not have it # Create NetworkManager configuration if we do not have it
if ! [ -e /etc/NetworkManager/NetworkManager.conf ]; then if ! [ -e /etc/NetworkManager/NetworkManager.conf ]; then
echo '[main]' > /etc/NetworkManager/NetworkManager.conf echo '[main]' > /etc/NetworkManager/NetworkManager.conf
@ -356,6 +349,9 @@ rm -f %{name}-%{version}
%config(noreplace) /etc/qubes-rpc/qubes.SelectDirectory %config(noreplace) /etc/qubes-rpc/qubes.SelectDirectory
%config(noreplace) /etc/qubes-rpc/qubes.GetImageRGBA %config(noreplace) /etc/qubes-rpc/qubes.GetImageRGBA
%config(noreplace) /etc/qubes-rpc/qubes.SetDateTime %config(noreplace) /etc/qubes-rpc/qubes.SetDateTime
%dir /etc/qubes/autostart
/etc/qubes/autostart/README.txt
%config /etc/qubes/autostart/*.desktop.d/30_qubes.conf
%config(noreplace) /etc/sudoers.d/qubes %config(noreplace) /etc/sudoers.d/qubes
%config(noreplace) /etc/sudoers.d/qt_x11_no_mitshm %config(noreplace) /etc/sudoers.d/qt_x11_no_mitshm
%config(noreplace) /etc/sysconfig/iptables.qubes %config(noreplace) /etc/sysconfig/iptables.qubes
@ -372,7 +368,6 @@ rm -f %{name}-%{version}
%config(noreplace) /etc/yum.repos.d/qubes-r3.repo %config(noreplace) /etc/yum.repos.d/qubes-r3.repo
/etc/yum/pluginconf.d/yum-qubes-hooks.conf /etc/yum/pluginconf.d/yum-qubes-hooks.conf
/etc/yum/post-actions/qubes-trigger-sync-appmenus.action /etc/yum/post-actions/qubes-trigger-sync-appmenus.action
/etc/yum/post-actions/qubes-trigger-desktop-file-install.action
/usr/lib/systemd/system/user@.service.d/90-session-stop-timeout.conf /usr/lib/systemd/system/user@.service.d/90-session-stop-timeout.conf
/usr/sbin/qubes-serial-login /usr/sbin/qubes-serial-login
/usr/bin/qvm-copy-to-vm /usr/bin/qvm-copy-to-vm
@ -385,7 +380,7 @@ rm -f %{name}-%{version}
/usr/bin/qubes-desktop-run /usr/bin/qubes-desktop-run
/usr/bin/qrexec-fork-server /usr/bin/qrexec-fork-server
/usr/bin/qrexec-client-vm /usr/bin/qrexec-client-vm
/usr/bin/qubes-desktop-file-install /usr/bin/qubes-session-autostart
%dir /usr/lib/qubes %dir /usr/lib/qubes
/usr/lib/qubes/vusb-ctl.py* /usr/lib/qubes/vusb-ctl.py*
/usr/lib/qubes/dispvm-prerun.sh /usr/lib/qubes/dispvm-prerun.sh
@ -415,8 +410,8 @@ rm -f %{name}-%{version}
/usr/lib/qubes/wrap-in-html-if-url.sh /usr/lib/qubes/wrap-in-html-if-url.sh
/usr/lib/qubes/iptables-updates-proxy /usr/lib/qubes/iptables-updates-proxy
/usr/lib/qubes/close-window /usr/lib/qubes/close-window
/usr/lib/qubes/qubes-trigger-desktop-file-install
/usr/lib/yum-plugins/yum-qubes-hooks.py* /usr/lib/yum-plugins/yum-qubes-hooks.py*
/usr/lib64/python2.7/site-packages/qubes/xdg.py*
/usr/sbin/qubes-firewall /usr/sbin/qubes-firewall
/usr/sbin/qubes-netwatcher /usr/sbin/qubes-netwatcher
/usr/share/qubes/serial.conf /usr/share/qubes/serial.conf

View File

@ -26,25 +26,10 @@ INTERFACE=eth0 /usr/lib/qubes/setup-ip
# Start services which haven't own proper systemd unit: # Start services which haven't own proper systemd unit:
# Start AppVM specific services if [ ! -f /usr/lib/systemd/system/cups.service ]; then
INSTALL_CMD='/usr/bin/qubes-desktop-file-install --force --dir /var/lib/qubes/xdg/autostart'
if [ ! -f /etc/systemd/system/cups.service ]; then
if [ -f /var/run/qubes-service/cups ]; then if [ -f /var/run/qubes-service/cups ]; then
/usr/sbin/service cups start /usr/sbin/service cups start
# Allow also notification icon
$INSTALL_CMD --remove-not-show-in X-QUBES /etc/xdg/autostart/print-applet.desktop
else
# Disable notification icon
$INSTALL_CMD --add-not-show-in X-QUBES /etc/xdg/autostart/print-applet.desktop
fi fi
fi fi
if [ -f /var/run/qubes-service/network-manager ]; then
# Allow also notification icon
$INSTALL_CMD --remove-not-show-in X-QUBES --add-only-show-in X-QUBES /etc/xdg/autostart/nm-applet.desktop
else
# Disable notification icon
$INSTALL_CMD --remove-only-show-in X-QUBES --add-not-show-in X-QUBES /etc/xdg/autostart/nm-applet.desktop
fi
exit 0 exit 0